8223306: Remove threads linked list (use ThreadsList's array in SA)

Reviewed-by: coleenp, dholmes, dcubed
This commit is contained in:
Robbin Ehn 2019-05-21 10:34:57 +02:00
parent a165ef39c6
commit 1645161cad
21 changed files with 133 additions and 117 deletions

View file

@ -1613,7 +1613,6 @@ void JavaThread::initialize() {
set_deopt_compiled_method(NULL); set_deopt_compiled_method(NULL);
clear_must_deopt_id(); clear_must_deopt_id();
set_monitor_chunks(NULL); set_monitor_chunks(NULL);
set_next(NULL);
_on_thread_list = false; _on_thread_list = false;
set_thread_state(_thread_new); set_thread_state(_thread_new);
_terminated = _not_terminated; _terminated = _not_terminated;
@ -3457,7 +3456,6 @@ void CodeCacheSweeperThread::nmethods_do(CodeBlobClosure* cf) {
// would like. We are actively migrating Threads_lock uses to other // would like. We are actively migrating Threads_lock uses to other
// mechanisms in order to reduce Threads_lock contention. // mechanisms in order to reduce Threads_lock contention.
JavaThread* Threads::_thread_list = NULL;
int Threads::_number_of_threads = 0; int Threads::_number_of_threads = 0;
int Threads::_number_of_non_daemon_threads = 0; int Threads::_number_of_non_daemon_threads = 0;
int Threads::_return_code = 0; int Threads::_return_code = 0;
@ -3764,7 +3762,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) {
} }
// Initialize Threads state // Initialize Threads state
_thread_list = NULL;
_number_of_threads = 0; _number_of_threads = 0;
_number_of_non_daemon_threads = 0; _number_of_non_daemon_threads = 0;
@ -4423,9 +4420,6 @@ void Threads::add(JavaThread* p, bool force_daemon) {
BarrierSet::barrier_set()->on_thread_attach(p); BarrierSet::barrier_set()->on_thread_attach(p);
p->set_next(_thread_list);
_thread_list = p;
// Once a JavaThread is added to the Threads list, smr_delete() has // Once a JavaThread is added to the Threads list, smr_delete() has
// to be used to delete it. Otherwise we can just delete it directly. // to be used to delete it. Otherwise we can just delete it directly.
p->set_on_thread_list(); p->set_on_thread_list();
@ -4463,20 +4457,6 @@ void Threads::remove(JavaThread* p, bool is_daemon) {
// Maintain fast thread list // Maintain fast thread list
ThreadsSMRSupport::remove_thread(p); ThreadsSMRSupport::remove_thread(p);
JavaThread* current = _thread_list;
JavaThread* prev = NULL;
while (current != p) {
prev = current;
current = current->next();
}
if (prev) {
prev->set_next(current->next());
} else {
_thread_list = p->next();
}
_number_of_threads--; _number_of_threads--;
if (!is_daemon) { if (!is_daemon) {
_number_of_non_daemon_threads--; _number_of_non_daemon_threads--;

View file

@ -983,7 +983,6 @@ class JavaThread: public Thread {
friend class JVMCIVMStructs; friend class JVMCIVMStructs;
friend class WhiteBox; friend class WhiteBox;
private: private:
JavaThread* _next; // The next thread in the Threads list
bool _on_thread_list; // Is set when this JavaThread is added to the Threads list bool _on_thread_list; // Is set when this JavaThread is added to the Threads list
oop _threadObj; // The Java level thread object oop _threadObj; // The Java level thread object
@ -1247,10 +1246,6 @@ class JavaThread: public Thread {
virtual bool is_Java_thread() const { return true; } virtual bool is_Java_thread() const { return true; }
virtual bool can_call_java() const { return true; } virtual bool can_call_java() const { return true; }
// Thread chain operations
JavaThread* next() const { return _next; }
void set_next(JavaThread* p) { _next = p; }
// Thread oop. threadObj() can be NULL for initial JavaThread // Thread oop. threadObj() can be NULL for initial JavaThread
// (or for threads attached via JNI) // (or for threads attached via JNI)
oop threadObj() const { return _threadObj; } oop threadObj() const { return _threadObj; }
@ -2213,7 +2208,6 @@ inline CompilerThread* CompilerThread::current() {
class Threads: AllStatic { class Threads: AllStatic {
friend class VMStructs; friend class VMStructs;
private: private:
static JavaThread* _thread_list;
static int _number_of_threads; static int _number_of_threads;
static int _number_of_non_daemon_threads; static int _number_of_non_daemon_threads;
static int _return_code; static int _return_code;

View file

@ -86,6 +86,7 @@ class ThreadClosure;
// SMR Support for the Threads class. // SMR Support for the Threads class.
// //
class ThreadsSMRSupport : AllStatic { class ThreadsSMRSupport : AllStatic {
friend class VMStructs;
friend class SafeThreadsListPtr; // for _nested_thread_list_max, delete_notify(), release_stable_list_wake_up() access friend class SafeThreadsListPtr; // for _nested_thread_list_max, delete_notify(), release_stable_list_wake_up() access
// The coordination between ThreadsSMRSupport::release_stable_list() and // The coordination between ThreadsSMRSupport::release_stable_list() and
@ -158,6 +159,7 @@ class ThreadsSMRSupport : AllStatic {
// A fast list of JavaThreads. // A fast list of JavaThreads.
// //
class ThreadsList : public CHeapObj<mtThread> { class ThreadsList : public CHeapObj<mtThread> {
friend class VMStructs;
friend class SafeThreadsListPtr; // for {dec,inc}_nested_handle_cnt() access friend class SafeThreadsListPtr; // for {dec,inc}_nested_handle_cnt() access
friend class ThreadsSMRSupport; // for _nested_handle_cnt, {add,remove}_thread(), {,set_}next_list() access friend class ThreadsSMRSupport; // for _nested_handle_cnt, {add,remove}_thread(), {,set_}next_list() access

View file

@ -94,6 +94,7 @@
#include "runtime/sharedRuntime.hpp" #include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp" #include "runtime/stubRoutines.hpp"
#include "runtime/thread.inline.hpp" #include "runtime/thread.inline.hpp"
#include "runtime/threadSMR.hpp"
#include "runtime/vframeArray.hpp" #include "runtime/vframeArray.hpp"
#include "runtime/vmStructs.hpp" #include "runtime/vmStructs.hpp"
#include "utilities/globalDefinitions.hpp" #include "utilities/globalDefinitions.hpp"
@ -740,10 +741,13 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
/* Threads (NOTE: incomplete) */ \ /* Threads (NOTE: incomplete) */ \
/******************************/ \ /******************************/ \
\ \
static_field(Threads, _thread_list, JavaThread*) \ static_field(Threads, _number_of_threads, int) \
static_field(Threads, _number_of_threads, int) \ static_field(Threads, _number_of_non_daemon_threads, int) \
static_field(Threads, _number_of_non_daemon_threads, int) \ static_field(Threads, _return_code, int) \
static_field(Threads, _return_code, int) \ \
static_ptr_volatile_field(ThreadsSMRSupport, _java_thread_list, ThreadsList*) \
nonstatic_field(ThreadsList, _length, const uint) \
nonstatic_field(ThreadsList, _threads, JavaThread *const *const) \
\ \
nonstatic_field(ThreadShadow, _pending_exception, oop) \ nonstatic_field(ThreadShadow, _pending_exception, oop) \
nonstatic_field(ThreadShadow, _exception_file, const char*) \ nonstatic_field(ThreadShadow, _exception_file, const char*) \
@ -757,7 +761,6 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
nonstatic_field(Thread, _current_waiting_monitor, ObjectMonitor*) \ nonstatic_field(Thread, _current_waiting_monitor, ObjectMonitor*) \
nonstatic_field(NamedThread, _name, char*) \ nonstatic_field(NamedThread, _name, char*) \
nonstatic_field(NamedThread, _processed_thread, JavaThread*) \ nonstatic_field(NamedThread, _processed_thread, JavaThread*) \
nonstatic_field(JavaThread, _next, JavaThread*) \
nonstatic_field(JavaThread, _threadObj, oop) \ nonstatic_field(JavaThread, _threadObj, oop) \
nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \ nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \
nonstatic_field(JavaThread, _vm_result, oop) \ nonstatic_field(JavaThread, _vm_result, oop) \
@ -1371,6 +1374,9 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
declare_toplevel_type(OSThread) \ declare_toplevel_type(OSThread) \
declare_toplevel_type(JavaFrameAnchor) \ declare_toplevel_type(JavaFrameAnchor) \
\ \
declare_toplevel_type(ThreadsSMRSupport) \
declare_toplevel_type(ThreadsList) \
\
/***************/ \ /***************/ \
/* Interpreter */ \ /* Interpreter */ \
/***************/ \ /***************/ \
@ -1964,6 +1970,7 @@ typedef PaddedEnd<ObjectMonitor> PaddedObjectMonitor;
declare_toplevel_type(intptr_t*) \ declare_toplevel_type(intptr_t*) \
declare_unsigned_integer_type(InvocationCounter) /* FIXME: wrong type (not integer) */ \ declare_unsigned_integer_type(InvocationCounter) /* FIXME: wrong type (not integer) */ \
declare_toplevel_type(JavaThread*) \ declare_toplevel_type(JavaThread*) \
declare_toplevel_type(JavaThread *const *const) \
declare_toplevel_type(java_lang_Class) \ declare_toplevel_type(java_lang_Class) \
declare_integer_type(JavaThread::AsyncRequests) \ declare_integer_type(JavaThread::AsyncRequests) \
declare_integer_type(JavaThread::TerminatedTypes) \ declare_integer_type(JavaThread::TerminatedTypes) \

View file

@ -536,7 +536,8 @@ public class CommandProcessor {
// Not an address // Not an address
boolean all = name.equals("-a"); boolean all = name.equals("-a");
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos)); thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) { if (all || bos.toString().equals(name)) {
@ -898,7 +899,8 @@ public class CommandProcessor {
String name = t.nextToken(); String name = t.nextToken();
boolean all = name.equals("-a"); boolean all = name.equals("-a");
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos)); thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) { if (all || bos.toString().equals(name)) {
@ -927,7 +929,8 @@ public class CommandProcessor {
String name = t.nextToken(); String name = t.nextToken();
boolean all = name.equals("-a"); boolean all = name.equals("-a");
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos)); thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) { if (all || bos.toString().equals(name)) {
@ -954,7 +957,8 @@ public class CommandProcessor {
String name = t.nextToken(); String name = t.nextToken();
boolean all = name.equals("-a"); boolean all = name.equals("-a");
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos)); thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) { if (all || bos.toString().equals(name)) {
@ -1437,7 +1441,8 @@ public class CommandProcessor {
final long stride = VM.getVM().getAddressSize(); final long stride = VM.getVM().getAddressSize();
if (type.equals("threads")) { if (type.equals("threads")) {
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
Address base = thread.getStackBase(); Address base = thread.getStackBase();
Address end = thread.getLastJavaSP(); Address end = thread.getLastJavaSP();
if (end == null) continue; if (end == null) continue;
@ -1561,7 +1566,8 @@ public class CommandProcessor {
String name = t.nextToken(); String name = t.nextToken();
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
boolean all = name.equals("-a"); boolean all = name.equals("-a");
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos)); thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) { if (all || bos.toString().equals(name)) {
@ -1590,7 +1596,8 @@ public class CommandProcessor {
String name = t.nextToken(); String name = t.nextToken();
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
boolean all = name.equals("-a"); boolean all = name.equals("-a");
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos)); thread.printThreadIDOn(new PrintStream(bos));
if (all || bos.toString().equals(name)) { if (all || bos.toString().equals(name)) {
@ -1613,7 +1620,8 @@ public class CommandProcessor {
usage(); usage();
} else { } else {
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
thread.printThreadIDOn(out); thread.printThreadIDOn(out);
out.println(" " + thread.getThreadName()); out.println(" " + thread.getThreadName());
thread.printInfoOn(out); thread.printInfoOn(out);
@ -1631,7 +1639,8 @@ public class CommandProcessor {
ArrayList nmethods = new ArrayList(); ArrayList nmethods = new ArrayList();
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
HTMLGenerator gen = new HTMLGenerator(false); HTMLGenerator gen = new HTMLGenerator(false);
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
try { try {
for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { for (JavaVFrame vf = thread.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {
if (vf instanceof CompiledVFrame) { if (vf instanceof CompiledVFrame) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -619,10 +619,10 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
int len = threads.getNumberOfThreads(); int len = threads.getNumberOfThreads();
long[] result = new long[len * 3]; // triple long[] result = new long[len * 3]; // triple
JavaThread t = threads.first();
long beg, end; long beg, end;
int i = 0; int i = 0;
while (t != null) { for (int k = 0; k < threads.getNumberOfThreads(); k++) {
JavaThread t = threads.getJavaThreadAt(k);
end = t.getStackBaseValue(); end = t.getStackBaseValue();
beg = end - t.getStackSize(); beg = end - t.getStackSize();
BsdThread bsdt = (BsdThread)t.getThreadProxy(); BsdThread bsdt = (BsdThread)t.getThreadProxy();
@ -631,7 +631,6 @@ public class BsdDebuggerLocal extends DebuggerBase implements BsdDebugger {
result[i] = uid; result[i] = uid;
result[i + 1] = beg; result[i + 1] = beg;
result[i + 2] = end; result[i + 2] = end;
t = t.next();
i += 3; i += 3;
} }
return result; return result;

View file

@ -357,7 +357,9 @@ public class ObjectHeap {
// end. // end.
if (VM.getVM().getUseTLAB()) { if (VM.getVM().getUseTLAB()) {
for (JavaThread thread = VM.getVM().getThreads().first(); thread != null; thread = thread.next()) { Threads threads = VM.getVM().getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
ThreadLocalAllocBuffer tlab = thread.tlab(); ThreadLocalAllocBuffer tlab = thread.tlab();
if (tlab.start() != null) { if (tlab.start() != null) {
if ((tlab.top() == null) || (tlab.end() == null)) { if ((tlab.top() == null) || (tlab.end() == null)) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -146,7 +146,9 @@ public class DeadlockDetector {
private static void createThreadTable() { private static void createThreadTable() {
threadTable = new HashMap(); threadTable = new HashMap();
for (JavaThread cur = threads.first(); cur != null; cur = cur.next()) { Threads threads = VM.getVM().getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread cur = threads.getJavaThreadAt(i);
// initialize dfn for each thread to -1 // initialize dfn for each thread to -1
threadTable.put(cur, new Integer(-1)); threadTable.put(cur, new Integer(-1));
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -41,7 +41,6 @@ import sun.jvm.hotspot.utilities.*;
public class JavaThread extends Thread { public class JavaThread extends Thread {
private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.JavaThread.DEBUG") != null; private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.JavaThread.DEBUG") != null;
private static AddressField nextField;
private static sun.jvm.hotspot.types.OopField threadObjField; private static sun.jvm.hotspot.types.OopField threadObjField;
private static AddressField anchorField; private static AddressField anchorField;
private static AddressField lastJavaSPField; private static AddressField lastJavaSPField;
@ -84,7 +83,6 @@ public class JavaThread extends Thread {
Type type = db.lookupType("JavaThread"); Type type = db.lookupType("JavaThread");
Type anchorType = db.lookupType("JavaFrameAnchor"); Type anchorType = db.lookupType("JavaFrameAnchor");
nextField = type.getAddressField("_next");
threadObjField = type.getOopField("_threadObj"); threadObjField = type.getOopField("_threadObj");
anchorField = type.getAddressField("_anchor"); anchorField = type.getAddressField("_anchor");
lastJavaSPField = anchorType.getAddressField("_last_Java_sp"); lastJavaSPField = anchorType.getAddressField("_last_Java_sp");
@ -120,15 +118,6 @@ public class JavaThread extends Thread {
this.access = access; this.access = access;
} }
public JavaThread next() {
Address threadAddr = nextField.getValue(addr);
if (threadAddr == null) {
return null;
}
return VM.getVM().getThreads().createJavaThreadWrapper(threadAddr);
}
/** NOTE: for convenience, this differs in definition from the underlying VM. /** NOTE: for convenience, this differs in definition from the underlying VM.
Only "pure" JavaThreads return true; CompilerThreads, the CodeCacheSweeperThread, Only "pure" JavaThreads return true; CompilerThreads, the CodeCacheSweeperThread,
JVMDIDebuggerThreads return false. JVMDIDebuggerThreads return false.

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -42,12 +42,41 @@ import sun.jvm.hotspot.runtime.bsd_x86.BsdX86JavaThreadPDAccess;
import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess; import sun.jvm.hotspot.runtime.bsd_amd64.BsdAMD64JavaThreadPDAccess;
import sun.jvm.hotspot.utilities.*; import sun.jvm.hotspot.utilities.*;
class ThreadsList extends VMObject {
private static AddressField threadsField;
private static CIntegerField lengthField;
static {
VM.registerVMInitializedObserver((o, d) -> initialize(VM.getVM().getTypeDataBase()));
}
private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("ThreadsList");
lengthField = type.getCIntegerField("_length");
threadsField = type.getAddressField("_threads");
}
public Address getJavaThreadAddressAt(int i) {
Address threadAddr = threadsField.getValue(addr);
Address at = threadAddr.getAddressAt(VM.getVM().getAddressSize() * i);
return at;
}
public long length() {
return lengthField.getValue(addr);
}
public ThreadsList(Address addr) {
super(addr);
}
}
public class Threads { public class Threads {
private static JavaThreadFactory threadFactory; private static JavaThreadFactory threadFactory;
private static AddressField threadListField; private static AddressField threadListField;
private static CIntegerField numOfThreadsField;
private static VirtualConstructor virtualConstructor; private static VirtualConstructor virtualConstructor;
private static JavaThreadPDAccess access; private static JavaThreadPDAccess access;
private static ThreadsList _list;
static { static {
VM.registerVMInitializedObserver(new Observer() { VM.registerVMInitializedObserver(new Observer() {
@ -58,10 +87,8 @@ public class Threads {
} }
private static synchronized void initialize(TypeDataBase db) { private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("Threads"); Type type = db.lookupType("ThreadsSMRSupport");
threadListField = type.getAddressField("_java_thread_list");
threadListField = type.getAddressField("_thread_list");
numOfThreadsField = type.getCIntegerField("_number_of_threads");
// Instantiate appropriate platform-specific JavaThreadFactory // Instantiate appropriate platform-specific JavaThreadFactory
String os = VM.getVM().getOS(); String os = VM.getVM().getOS();
@ -134,6 +161,7 @@ public class Threads {
} }
public Threads() { public Threads() {
_list = VMObjectFactory.newObject(ThreadsList.class, threadListField.getValue());
} }
/** NOTE: this returns objects of type JavaThread, CompilerThread, /** NOTE: this returns objects of type JavaThread, CompilerThread,
@ -147,17 +175,15 @@ public class Threads {
false for the three subclasses. FIXME: should reconsider the false for the three subclasses. FIXME: should reconsider the
inheritance hierarchy; see {@link inheritance hierarchy; see {@link
sun.jvm.hotspot.runtime.JavaThread#isJavaThread}. */ sun.jvm.hotspot.runtime.JavaThread#isJavaThread}. */
public JavaThread first() { public JavaThread getJavaThreadAt(int i) {
Address threadAddr = threadListField.getValue(); if (i < _list.length()) {
if (threadAddr == null) { return createJavaThreadWrapper(_list.getJavaThreadAddressAt(i));
return null;
} }
return null;
return createJavaThreadWrapper(threadAddr);
} }
public int getNumberOfThreads() { public int getNumberOfThreads() {
return (int) numOfThreadsField.getValue(); return (int) _list.length();
} }
/** Routine for instantiating appropriately-typed wrapper for a /** Routine for instantiating appropriately-typed wrapper for a
@ -177,7 +203,9 @@ public class Threads {
/** Memory operations */ /** Memory operations */
public void oopsDo(AddressVisitor oopVisitor) { public void oopsDo(AddressVisitor oopVisitor) {
// FIXME: add more of VM functionality // FIXME: add more of VM functionality
for (JavaThread thread = first(); thread != null; thread = thread.next()) { Threads threads = VM.getVM().getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
thread.oopsDo(oopVisitor); thread.oopsDo(oopVisitor);
} }
} }
@ -185,15 +213,17 @@ public class Threads {
// refer to Threads::owning_thread_from_monitor_owner // refer to Threads::owning_thread_from_monitor_owner
public JavaThread owningThreadFromMonitor(Address o) { public JavaThread owningThreadFromMonitor(Address o) {
if (o == null) return null; if (o == null) return null;
for (JavaThread thread = first(); thread != null; thread = thread.next()) { for (int i = 0; i < getNumberOfThreads(); i++) {
JavaThread thread = getJavaThreadAt(i);
if (o.equals(thread.threadObjectAddress())) { if (o.equals(thread.threadObjectAddress())) {
return thread; return thread;
} }
} }
for (JavaThread thread = first(); thread != null; thread = thread.next()) { for (int i = 0; i < getNumberOfThreads(); i++) {
if (thread.isLockOwned(o)) JavaThread thread = getJavaThreadAt(i);
return thread; if (thread.isLockOwned(o))
return thread;
} }
return null; return null;
} }
@ -206,7 +236,8 @@ public class Threads {
// Get list of Java threads that are waiting to enter the specified monitor. // Get list of Java threads that are waiting to enter the specified monitor.
public List getPendingThreads(ObjectMonitor monitor) { public List getPendingThreads(ObjectMonitor monitor) {
List pendingThreads = new ArrayList(); List pendingThreads = new ArrayList();
for (JavaThread thread = first(); thread != null; thread = thread.next()) { for (int i = 0; i < getNumberOfThreads(); i++) {
JavaThread thread = getJavaThreadAt(i);
if (thread.isCompilerThread() || thread.isCodeCacheSweeperThread()) { if (thread.isCompilerThread() || thread.isCodeCacheSweeperThread()) {
continue; continue;
} }
@ -221,7 +252,8 @@ public class Threads {
// Get list of Java threads that have called Object.wait on the specified monitor. // Get list of Java threads that have called Object.wait on the specified monitor.
public List getWaitingThreads(ObjectMonitor monitor) { public List getWaitingThreads(ObjectMonitor monitor) {
List pendingThreads = new ArrayList(); List pendingThreads = new ArrayList();
for (JavaThread thread = first(); thread != null; thread = thread.next()) { for (int i = 0; i < getNumberOfThreads(); i++) {
JavaThread thread = getJavaThreadAt(i);
ObjectMonitor waiting = thread.getCurrentWaitingMonitor(); ObjectMonitor waiting = thread.getCurrentWaitingMonitor();
if (monitor.equals(waiting)) { if (monitor.equals(waiting)) {
pendingThreads.add(thread); pendingThreads.add(thread);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -201,7 +201,8 @@ public class PStack extends Tool {
jframeCache = new HashMap(); jframeCache = new HashMap();
proxyToThread = new HashMap(); proxyToThread = new HashMap();
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
for (JavaThread cur = threads.first(); cur != null; cur = cur.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread cur = threads.getJavaThreadAt(i);
List tmp = new ArrayList(10); List tmp = new ArrayList(10);
try { try {
for (JavaVFrame vf = cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) { for (JavaVFrame vf = cur.getLastJavaVFrameDbg(); vf != null; vf = vf.javaSender()) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -71,8 +71,8 @@ public class StackTrace extends Tool {
concLocksPrinter = new ConcurrentLocksPrinter(); concLocksPrinter = new ConcurrentLocksPrinter();
} }
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
int i = 1; for (int i = 0; i < threads.getNumberOfThreads(); i++) {
for (JavaThread cur = threads.first(); cur != null; cur = cur.next(), i++) { JavaThread cur = threads.getJavaThreadAt(i);
if (cur.isJavaThread()) { if (cur.isJavaThread()) {
cur.printThreadInfoOn(tty); cur.printThreadInfoOn(tty);
try { try {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -459,12 +459,13 @@ public class JavaThreadsPanel extends SAPanel implements ActionListener {
} }
private void cache() { private void cache() {
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
for (JavaThread t = threads.first(); t != null; t = t.next()) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
if (t.isJavaThread()) { JavaThread t = threads.getJavaThreadAt(i);
cachedThreads.add(new CachedThread(t)); if (t.isJavaThread()) {
} cachedThreads.add(new CachedThread(t));
} }
}
} }
private void decache() { private void decache() {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -129,15 +129,12 @@ public abstract class AbstractHeapGraphWriter implements HeapGraphWriter {
protected void writeJavaThreads() throws IOException { protected void writeJavaThreads() throws IOException {
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
JavaThread jt = threads.first(); for (int i = 0; i < threads.getNumberOfThreads(); i++) {
int index = 1; JavaThread jt = threads.getJavaThreadAt(i);
while (jt != null) {
if (jt.getThreadObj() != null) { if (jt.getThreadObj() != null) {
// Note that the thread serial number range is 1-to-N // Note that the thread serial number range is 1-to-N
writeJavaThread(jt, index); writeJavaThread(jt, i + 1);
index++;
} }
jt = jt.next();
} }
} }

View file

@ -708,8 +708,8 @@ public class HeapHprofBinWriter extends AbstractHeapGraphWriter {
int frameSerialNum = 0; int frameSerialNum = 0;
int numThreads = 0; int numThreads = 0;
Threads threads = VM.getVM().getThreads(); Threads threads = VM.getVM().getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) { JavaThread thread = threads.getJavaThreadAt(i);
Oop threadObj = thread.getThreadObj(); Oop threadObj = thread.getThreadObj();
if (threadObj != null && !thread.isExiting() && !thread.isHiddenFromExternalView()) { if (threadObj != null && !thread.isExiting() && !thread.isHiddenFromExternalView()) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -56,7 +56,9 @@ public class PointerFinder {
if (VM.getVM().getUseTLAB()) { if (VM.getVM().getUseTLAB()) {
// Try to find thread containing it // Try to find thread containing it
for (JavaThread t = VM.getVM().getThreads().first(); t != null; t = t.next()) { Threads threads = VM.getVM().getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread t = threads.getJavaThreadAt(i);
ThreadLocalAllocBuffer tlab = t.tlab(); ThreadLocalAllocBuffer tlab = t.tlab();
if (tlab.contains(a)) { if (tlab.contains(a)) {
loc.inTLAB = true; loc.inTLAB = true;
@ -125,7 +127,9 @@ public class PointerFinder {
return loc; return loc;
} }
// Look in thread-local handles // Look in thread-local handles
for (JavaThread t = VM.getVM().getThreads().first(); t != null; t = t.next()) { Threads threads = VM.getVM().getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread t = threads.getJavaThreadAt(i);
JNIHandleBlock handleBlock = t.activeHandles(); JNIHandleBlock handleBlock = t.activeHandles();
if (handleBlock != null) { if (handleBlock != null) {
handleBlock = handleBlock.blockContainingHandle(a); handleBlock = handleBlock.blockContainingHandle(a);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -92,9 +92,9 @@ public class ReversePtrsAnalysis {
heap = vm.getObjectHeap(); heap = vm.getObjectHeap();
// Do each thread's roots // Do each thread's roots
for (JavaThread thread = VM.getVM().getThreads().first(); Threads threads = VM.getVM().getThreads();
thread != null; for (int i = 0; i < threads.getNumberOfThreads(); i++) {
thread = thread.next()) { JavaThread thread = threads.getJavaThreadAt(i);
ByteArrayOutputStream bos = new ByteArrayOutputStream(); ByteArrayOutputStream bos = new ByteArrayOutputStream();
thread.printThreadIDOn(new PrintStream(bos)); thread.printThreadIDOn(new PrintStream(bos));
String threadDesc = String threadDesc =

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -189,12 +189,12 @@ public class JSJavaVM extends DefaultScriptObject {
private synchronized JSList getThreads() { private synchronized JSList getThreads() {
if (threadsCache == null) { if (threadsCache == null) {
List threads = new ArrayList(0); List threadsList = new ArrayList(0);
threadsCache = factory.newJSList(threads); threadsCache = factory.newJSList(threadsList);
JavaThread jthread = vm.getThreads().first(); Threads threads = VM.getVM().getThreads();
while (jthread != null) { for (int i = 0; i < threads.getNumberOfThreads(); i++) {
threads.add(jthread); JavaThread thread = threads.getJavaThreadAt(i);
jthread = jthread.next(); threadsList.add(thread);
} }
} }
return threadsCache; return threadsCache;

View file

@ -55,7 +55,6 @@ public class ClhsdbField {
"field InstanceKlass _methods Array<Method*>*", "field InstanceKlass _methods Array<Method*>*",
"field InstanceKlass _constants ConstantPool*", "field InstanceKlass _constants ConstantPool*",
"field Klass _name Symbol*", "field Klass _name Symbol*",
"field JavaThread _next JavaThread*",
"field JavaThread _osthread OSThread*", "field JavaThread _osthread OSThread*",
"field JVMState _bci", "field JVMState _bci",
"field TenuredGeneration _the_space ContiguousSpace*", "field TenuredGeneration _the_space ContiguousSpace*",

View file

@ -68,8 +68,7 @@ public class ClhsdbPrintStatics {
"SystemDictionary::Object_klass_knum")); "SystemDictionary::Object_klass_knum"));
expStrMap.put("printstatics Threads", List.of( expStrMap.put("printstatics Threads", List.of(
"Static fields of Threads", "Static fields of Threads",
"_number_of_threads", "_number_of_non_daemon_threads", "_number_of_threads", "_number_of_non_daemon_threads"));
"JavaThread\\* Threads"));
expStrMap.put("printstatics Universe", List.of( expStrMap.put("printstatics Universe", List.of(
"Static fields of Universe", "Static fields of Universe",
"uintptr_t Universe::_verify_oop_mask", "uintptr_t Universe::_verify_oop_mask",

View file

@ -57,7 +57,6 @@ public class ClhsdbVmStructsDump {
"field Klass _name Symbol*", "field Klass _name Symbol*",
"type ClassLoaderData* null", "type ClassLoaderData* null",
"type DictionaryEntry KlassHashtableEntry", "type DictionaryEntry KlassHashtableEntry",
"field JavaThread _next JavaThread*",
"field JavaThread _osthread OSThread*", "field JavaThread _osthread OSThread*",
"type TenuredGeneration CardGeneration", "type TenuredGeneration CardGeneration",
"field JVMState _bci", "field JVMState _bci",