This commit is contained in:
Andrew Haley 2020-05-29 13:16:30 -04:00
commit d101efc16b
155 changed files with 2699 additions and 8128 deletions
.hgtags
make
CompileJavaModules.gmk
hotspot/lib
modules/jdk.jdwp.agent
src/classes/build/tools/jfr
src
hotspot
java.base/share/classes/java/net
java.net.http/share/classes
jdk.compiler/share/classes/com/sun
source/util
tools
jdk.hotspot.agent
jdk.incubator.foreign/share/classes/jdk/internal/foreign
jdk.internal.vm.compiler/share/classes
org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test
org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot
jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html

@ -636,3 +636,5 @@ dd5198db2e5b1ebcafe065d987c03ba9fcb50fc3 jdk-15+17
f143729ca00ec14a98ea5c7f73acba88da97746e jdk-15+23
497fd9f9129c4928fd5a876dd55e0daf6298b511 jdk-15+24
58833044988772ca06c97ab2f142474a8627af80 jdk-15+25
58833044988772ca06c97ab2f142474a8627af80 jdk-15+25
90b266a84c06f1b3dc0ed8767856793e8c1c357e jdk-15+25

@ -315,7 +315,7 @@ jdk.compiler_CLEAN_FILES += $(wildcard \
jdk.hotspot.agent_DISABLED_WARNINGS += rawtypes serial cast static overrides \
fallthrough
jdk.hotspot.agent_COPY += .gif .png sa.js .properties
jdk.hotspot.agent_COPY += .gif .png .properties
################################################################################

@ -81,7 +81,7 @@ DISABLED_WARNINGS_gcc := parentheses comment unknown-pragmas address \
delete-non-virtual-dtor char-subscripts array-bounds int-in-bool-context \
ignored-qualifiers missing-field-initializers implicit-fallthrough \
empty-body strict-overflow sequence-point maybe-uninitialized \
misleading-indentation cast-function-type
misleading-indentation cast-function-type shift-negative-value
ifeq ($(call check-jvm-feature, zero), true)
DISABLED_WARNINGS_gcc += return-type switch clobbered
@ -90,7 +90,8 @@ endif
DISABLED_WARNINGS_clang := tautological-compare \
undefined-var-template sometimes-uninitialized unknown-pragmas \
delete-non-virtual-dtor missing-braces char-subscripts \
ignored-qualifiers missing-field-initializers mismatched-tags
ignored-qualifiers missing-field-initializers mismatched-tags \
shift-negative-value
DISABLED_WARNINGS_xlc := tautological-compare shift-negative-value

@ -64,7 +64,6 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \
LIBS_linux := $(LIBDL), \
LIBS_macosx := -liconv, \
LIBS_aix := -liconv, \
LIBS_windows := $(WIN_JAVA_LIB), \
))
$(BUILD_LIBJDWP): $(call FindLib, java.base, java)

@ -7,10 +7,10 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringJoiner;
import java.util.function.Predicate;
@ -43,10 +43,11 @@ public class GenerateJfrFiles {
metadata.verify();
metadata.wireUpTypes();
TypeCounter typeCounter = new TypeCounter();
printJfrEventIdsHpp(metadata, typeCounter, outputDirectory);
printJfrTypesHpp(metadata, typeCounter, outputDirectory);
printJfrPeriodicHpp(metadata, outputDirectory);
printJfrEventIdsHpp(metadata, outputDirectory);
printJfrEventControlHpp(metadata, outputDirectory);
printJfrTypesHpp(metadata, outputDirectory);
printJfrEventControlHpp(metadata, typeCounter, outputDirectory);
printJfrEventClassesHpp(metadata, outputDirectory);
} catch (Exception e) {
@ -55,12 +56,78 @@ public class GenerateJfrFiles {
}
}
static class TypeCounter {
final static long RESERVED_EVENT_COUNT = 2;
long typeId = -1;
long eventId = -1;
long eventCount = 0;
String firstTypeName;
String lastTypeName;
String firstEventName;
String lastEventname;
public long nextEventId(String name) {
eventCount++;
if (eventId == -1) {
eventId = firstEventId();
firstEventName = lastEventname = name;
return eventId;
}
lastEventname = name;
return ++eventId;
}
public long nextTypeId(String typeName) {
if (typeId == -1) {
lastTypeName = firstTypeName = typeName;
typeId = lastEventId();
}
lastTypeName = typeName;
return ++typeId;
}
public long firstEventId() {
return RESERVED_EVENT_COUNT;
}
public long lastEventId() {
return eventId == -1 ? firstEventId() : eventId;
}
public long eventCount() {
return eventCount;
}
public String firstTypeName() {
return firstTypeName;
}
public String lastTypeName() {
return lastTypeName;
}
public String firstEventName() {
return firstEventName;
}
public String lastEventName() {
return lastEventname;
}
}
static class XmlType {
final String name;
final String fieldType;
final String parameterType;
XmlType(String fieldType, String parameterType) {
final String javaType;
final boolean unsigned;
XmlType(String name, String fieldType, String parameterType, String javaType, boolean unsigned) {
this.name = name;
this.fieldType = fieldType;
this.parameterType = parameterType;
this.javaType = javaType;
this.unsigned = unsigned;
}
}
@ -74,7 +141,7 @@ public class GenerateJfrFiles {
static class Metadata {
final Map<String, TypeElement> types = new LinkedHashMap<>();
final Map<String, XmlType> xmlTypes = new HashMap<>();
final Map<String, XmlType> xmlTypes = new LinkedHashMap<>();
Metadata(File metadataXml, File metadataSchema) throws ParserConfigurationException, SAXException, FileNotFoundException, IOException {
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
SAXParserFactory factory = SAXParserFactory.newInstance();
@ -110,12 +177,8 @@ public class GenerateJfrFiles {
return getList(t -> t.getClass() == EventElement.class && ((EventElement) t).periodic);
}
List<TypeElement> getNonEventsAndNonStructs() {
return getList(t -> t.getClass() != EventElement.class && !t.supportStruct);
}
List<TypeElement> getTypes() {
return getList(t -> t.getClass() == TypeElement.class && !t.supportStruct);
return getList(t -> t.getClass() == TypeElement.class);
}
List<TypeElement> getStructs() {
@ -213,8 +276,11 @@ public class GenerateJfrFiles {
String name = attributes.getValue("name");
String parameterType = attributes.getValue("parameterType");
String fieldType = attributes.getValue("fieldType");
metadata.xmlTypes.put(name, new XmlType(fieldType, parameterType));
String javaType = attributes.getValue("javaType");
boolean unsigned = getBoolean(attributes, "unsigned", false);
metadata.xmlTypes.put(name, new XmlType(name, fieldType, parameterType, javaType, unsigned));
break;
case "Relation":
case "Type":
currentType = new TypeElement();
currentType.name = attributes.getValue("name");
@ -247,6 +313,7 @@ public class GenerateJfrFiles {
@Override
public void endElement(String uri, String localName, String qName) {
switch (qName) {
case "Relation":
case "Type":
case "Event":
metadata.types.put(currentType.name, currentType);
@ -318,7 +385,7 @@ public class GenerateJfrFiles {
}
}
private static void printJfrEventControlHpp(Metadata metadata, File outputDirectory) throws Exception {
private static void printJfrEventControlHpp(Metadata metadata, TypeCounter typeCounter, File outputDirectory) throws Exception {
try (Printer out = new Printer(outputDirectory, "jfrEventControl.hpp")) {
out.write("#ifndef JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
out.write("#define JFRFILES_JFR_NATIVE_EVENTSETTING_HPP");
@ -342,11 +409,11 @@ public class GenerateJfrFiles {
out.write("");
out.write("union JfrNativeSettings {");
out.write(" // Array version.");
out.write(" jfrNativeEventSetting bits[MaxJfrEventId];");
out.write(" jfrNativeEventSetting bits[NUMBER_OF_EVENTS];");
out.write(" // Then, to make it easy to debug,");
out.write(" // add named struct members also.");
out.write(" struct {");
out.write(" jfrNativeEventSetting pad[NUM_RESERVED_EVENTS];");
out.write(" jfrNativeEventSetting pad[NUMBER_OF_RESERVED_EVENTS];");
for (TypeElement t : metadata.getEventsAndStructs()) {
out.write(" jfrNativeEventSetting " + t.name + ";");
}
@ -358,53 +425,34 @@ public class GenerateJfrFiles {
}
}
private static void printJfrEventIdsHpp(Metadata metadata, File outputDirectory) throws Exception {
private static void printJfrEventIdsHpp(Metadata metadata, TypeCounter typeCounter, File outputDirectory) throws Exception {
try (Printer out = new Printer(outputDirectory, "jfrEventIds.hpp")) {
out.write("#ifndef JFRFILES_JFREVENTIDS_HPP");
out.write("#define JFRFILES_JFREVENTIDS_HPP");
out.write("");
out.write("#include \"utilities/macros.hpp\"");
out.write("#if INCLUDE_JFR");
out.write("#include \"jfrfiles/jfrTypes.hpp\"");
out.write("");
out.write("/**");
out.write(" * Enum of the event types in the JVM");
out.write(" */");
out.write("enum JfrEventId {");
out.write(" _jfreventbase = (NUM_RESERVED_EVENTS-1), // Make sure we start at right index.");
out.write(" ");
out.write(" // Events -> enum entry");
for (TypeElement t : metadata.getEventsAndStructs()) {
out.write(" Jfr" + t.name + "Event,");
out.write(" JfrMetadataEvent = 0,");
out.write(" JfrCheckpointEvent = 1,");
for (TypeElement t : metadata.getEvents()) {
String name = "Jfr" + t.name +"Event";
out.write(" " + name + " = " + typeCounter.nextEventId(name) + ",");
}
out.write("");
out.write(" MaxJfrEventId");
out.write("};");
out.write("");
out.write("/**");
out.write(" * Struct types in the JVM");
out.write(" */");
out.write("enum JfrStructId {");
for (TypeElement t : metadata.getNonEventsAndNonStructs()) {
out.write(" Jfr" + t.name + "Struct,");
}
for (TypeElement t : metadata.getEventsAndStructs()) {
out.write(" Jfr" + t.name + "Struct,");
}
out.write("");
out.write(" MaxJfrStructId");
out.write("};");
out.write("");
out.write("typedef enum JfrEventId JfrEventId;");
out.write("typedef enum JfrStructId JfrStructId;");
out.write("");
out.write("static const JfrEventId FIRST_EVENT_ID = " + typeCounter.firstEventName() + ";");
out.write("static const JfrEventId LAST_EVENT_ID = " + typeCounter.lastEventName() + ";");
out.write("static const int NUMBER_OF_EVENTS = " + typeCounter.eventCount() + ";");
out.write("static const int NUMBER_OF_RESERVED_EVENTS = " + TypeCounter.RESERVED_EVENT_COUNT + ";");
out.write("#endif // INCLUDE_JFR");
out.write("#endif // JFRFILES_JFREVENTIDS_HPP");
}
}
private static void printJfrTypesHpp(Metadata metadata, File outputDirectory) throws Exception {
List<String> knownTypes = List.of("Thread", "StackTrace", "Class", "StackFrame");
private static void printJfrTypesHpp(Metadata metadata, TypeCounter typeCounter, File outputDirectory) throws Exception {
try (Printer out = new Printer(outputDirectory, "jfrTypes.hpp")) {
out.write("#ifndef JFRFILES_JFRTYPES_HPP");
out.write("#define JFRFILES_JFRTYPES_HPP");
@ -412,41 +460,54 @@ public class GenerateJfrFiles {
out.write("#include \"utilities/macros.hpp\"");
out.write("#if INCLUDE_JFR");
out.write("");
out.write("#include <string.h>");
out.write("#include \"memory/allocation.hpp\"");
out.write("");
out.write("enum JfrTypeId {");
out.write(" TYPE_NONE = 0,");
out.write(" TYPE_CLASS = 20,");
out.write(" TYPE_STRING = 21,");
out.write(" TYPE_THREAD = 22,");
out.write(" TYPE_STACKTRACE = 23,");
out.write(" TYPE_BYTES = 24,");
out.write(" TYPE_EPOCHMILLIS = 25,");
out.write(" TYPE_MILLIS = 26,");
out.write(" TYPE_NANOS = 27,");
out.write(" TYPE_TICKS = 28,");
out.write(" TYPE_ADDRESS = 29,");
out.write(" TYPE_PERCENTAGE = 30,");
out.write(" TYPE_DUMMY,");
out.write(" TYPE_DUMMY_1,");
for (TypeElement type : metadata.getTypes()) {
if (!knownTypes.contains(type.name)) {
out.write(" TYPE_" + type.name.toUpperCase() + ",");
Map<String, XmlType> javaTypes = new LinkedHashMap<>();
for (var t : metadata.xmlTypes.entrySet()) {
String name = t.getKey();
XmlType xmlType = t.getValue();
if (xmlType.javaType != null && !xmlType.unsigned) {
String typeName = "TYPE_" + name.toUpperCase();
long typeId = typeCounter.nextTypeId(typeName);
out.write(" " + typeName + " = " + typeId + ",");
javaTypes.put(name, xmlType);
}
}
for (TypeElement type : metadata.getTypes()) {
String name = type.name;
if (!javaTypes.containsKey(name)) {
String typeName = "TYPE_" + name.toUpperCase();
long typeId = typeCounter.nextTypeId(typeName);
out.write(" " + typeName + " = " + typeId + ",");
}
}
out.write("");
out.write(" NUM_JFR_TYPES,");
out.write(" TYPES_END = 255");
out.write("};");
out.write("");
out.write("enum ReservedEvent {");
out.write(" EVENT_METADATA,");
out.write(" EVENT_CHECKPOINT,");
out.write(" EVENT_BUFFERLOST,");
out.write(" NUM_RESERVED_EVENTS = TYPES_END");
out.write("static const JfrTypeId FIRST_TYPE_ID = " + typeCounter.firstTypeName() + ";");
out.write("static const JfrTypeId LAST_TYPE_ID = " + typeCounter.lastTypeName() + ";");
out.write("");
out.write("class JfrType : public AllStatic {");
out.write(" public:");
out.write(" static jlong name_to_id(const char* type_name) {");
for (Entry<String, XmlType> m : javaTypes.entrySet()) {
XmlType xmlType = m.getValue();
String javaName = xmlType.javaType;
String typeName = xmlType.name.toUpperCase();
out.write(" if (strcmp(type_name, \"" + javaName + "\") == 0) {");
out.write(" return TYPE_" + typeName + ";");
out.write(" }");
}
out.write(" return -1;");
out.write(" }");
out.write("};");
out.write("");
out.write("#endif // INCLUDE_JFR");
out.write("#endif // JFRFILES_JFRTYPES_HPP");
};
}
;
}
private static void printJfrEventClassesHpp(Metadata metadata, File outputDirectory) throws Exception {

@ -61,7 +61,6 @@ define_pd_global(bool, CICompileOSR, true );
#endif // !TIERED
define_pd_global(bool, UseTypeProfile, false);
define_pd_global(bool, LIRFillDelaySlots, false);
define_pd_global(bool, OptimizeSinglePrecision, true );
define_pd_global(bool, CSEArrayLength, false);
define_pd_global(bool, TwoOperandLIRForm, false );

@ -62,7 +62,6 @@ define_pd_global(bool, CICompileOSR, true );
#endif // COMPILER2
define_pd_global(bool, UseTypeProfile, false);
define_pd_global(bool, LIRFillDelaySlots, false);
define_pd_global(bool, OptimizeSinglePrecision, true);
define_pd_global(bool, CSEArrayLength, true);
define_pd_global(bool, TwoOperandLIRForm, false);

@ -62,7 +62,6 @@ define_pd_global(uintx, InitialCodeCacheSize, 160*K);
define_pd_global(bool, UseTypeProfile, false);
define_pd_global(bool, LIRFillDelaySlots, false);
define_pd_global(bool, OptimizeSinglePrecision, false);
define_pd_global(bool, CSEArrayLength, true);
define_pd_global(bool, TwoOperandLIRForm, false);

@ -63,7 +63,6 @@ define_pd_global(uintx, InitialCodeCacheSize, 160*K);
define_pd_global(bool, UseTypeProfile, false);
define_pd_global(bool, LIRFillDelaySlots, false);
define_pd_global(bool, OptimizeSinglePrecision, false);
define_pd_global(bool, CSEArrayLength, true);
define_pd_global(bool, TwoOperandLIRForm, true);

@ -60,7 +60,6 @@ define_pd_global(bool, CICompileOSR, true );
#endif // !TIERED
define_pd_global(bool, UseTypeProfile, false);
define_pd_global(bool, LIRFillDelaySlots, false);
define_pd_global(bool, OptimizeSinglePrecision, true );
define_pd_global(bool, CSEArrayLength, false);
define_pd_global(bool, TwoOperandLIRForm, true );

@ -1376,18 +1376,35 @@ double os::elapsedVTime() {
}
jlong os::javaTimeMillis() {
timeval time;
int status = gettimeofday(&time, NULL);
assert(status != -1, "linux error");
return jlong(time.tv_sec) * 1000 + jlong(time.tv_usec / 1000);
if (os::Posix::supports_clock_gettime()) {
struct timespec ts;
int status = os::Posix::clock_gettime(CLOCK_REALTIME, &ts);
assert_status(status == 0, status, "gettime error");
return jlong(ts.tv_sec) * MILLIUNITS +
jlong(ts.tv_nsec) / NANOUNITS_PER_MILLIUNIT;
} else {
timeval time;
int status = gettimeofday(&time, NULL);
assert(status != -1, "linux error");
return jlong(time.tv_sec) * MILLIUNITS +
jlong(time.tv_usec) / (MICROUNITS / MILLIUNITS);
}
}
void os::javaTimeSystemUTC(jlong &seconds, jlong &nanos) {
timeval time;
int status = gettimeofday(&time, NULL);
assert(status != -1, "linux error");
seconds = jlong(time.tv_sec);
nanos = jlong(time.tv_usec) * 1000;
if (os::Posix::supports_clock_gettime()) {
struct timespec ts;
int status = os::Posix::clock_gettime(CLOCK_REALTIME, &ts);
assert_status(status == 0, status, "gettime error");
seconds = jlong(ts.tv_sec);
nanos = jlong(ts.tv_nsec);
} else {
timeval time;
int status = gettimeofday(&time, NULL);
assert(status != -1, "linux error");
seconds = jlong(time.tv_sec);
nanos = jlong(time.tv_usec) * (NANOUNITS / MICROUNITS);
}
}
void os::Linux::fast_thread_clock_init() {

@ -1638,6 +1638,8 @@ void os::Posix::save_preinstalled_handler(int sig, struct sigaction& oldAct) {
int (*os::Posix::_clock_gettime)(clockid_t, struct timespec *) = NULL;
int (*os::Posix::_clock_getres)(clockid_t, struct timespec *) = NULL;
bool os::Posix::_supports_monotonic_clock = false;
static int (*_pthread_condattr_setclock)(pthread_condattr_t *, clockid_t) = NULL;
static bool _use_clock_monotonic_condattr = false;
@ -1653,7 +1655,7 @@ void os::Posix::init(void) {
void* handle = NULL;
// For linux we need librt, for other OS we can find
// For older linux we need librt, for other OS we can find
// this function in regular libc.
#ifdef NEEDS_LIBRT
// We do dlopen's in this particular order due to bug in linux
@ -1673,6 +1675,8 @@ void os::Posix::init(void) {
int (*clock_gettime_func)(clockid_t, struct timespec*) =
(int(*)(clockid_t, struct timespec*))dlsym(handle, "clock_gettime");
if (clock_getres_func != NULL && clock_gettime_func != NULL) {
_clock_gettime = clock_gettime_func;
_clock_getres = clock_getres_func;
// We assume that if both clock_gettime and clock_getres support
// CLOCK_MONOTONIC then the OS provides true high-res monotonic clock.
struct timespec res;
@ -1680,15 +1684,7 @@ void os::Posix::init(void) {
if (clock_getres_func(CLOCK_MONOTONIC, &res) == 0 &&
clock_gettime_func(CLOCK_MONOTONIC, &tp) == 0) {
// Yes, monotonic clock is supported.
_clock_gettime = clock_gettime_func;
_clock_getres = clock_getres_func;
} else {
#ifdef NEEDS_LIBRT
// Close librt if there is no monotonic clock.
if (handle != RTLD_DEFAULT) {
dlclose(handle);
}
#endif
_supports_monotonic_clock = true;
}
}

@ -128,18 +128,18 @@ public:
#ifdef SUPPORTS_CLOCK_MONOTONIC
private:
static bool _supports_monotonic_clock;
// These need to be members so we can access them from inline functions
static int (*_clock_gettime)(clockid_t, struct timespec *);
static int (*_clock_getres)(clockid_t, struct timespec *);
public:
static bool supports_monotonic_clock();
static bool supports_clock_gettime();
static int clock_gettime(clockid_t clock_id, struct timespec *tp);
static int clock_getres(clockid_t clock_id, struct timespec *tp);
#else
static bool supports_monotonic_clock() { return false; }
static bool supports_clock_gettime() { return false; }
#endif
static void to_RTC_abstime(timespec* abstime, int64_t millis);

@ -32,6 +32,10 @@
// Exported clock functionality
inline bool os::Posix::supports_monotonic_clock() {
return _supports_monotonic_clock;
}
inline bool os::Posix::supports_clock_gettime() {
return _clock_gettime != NULL;
}

@ -366,24 +366,30 @@ void AOTCodeHeap::publish_aot(const methodHandle& mh, AOTMethodData* method_data
}
}
void AOTCodeHeap::link_primitive_array_klasses() {
void AOTCodeHeap::link_klass(const Klass* klass) {
ResourceMark rm;
assert(klass != NULL, "Should be given a klass");
AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), klass->signature_name());
if (klass_data != NULL) {
// Set both GOT cells, resolved and initialized klass pointers.
// _got_index points to second cell - resolved klass pointer.
_klasses_got[klass_data->_got_index-1] = (Metadata*)klass; // Initialized
_klasses_got[klass_data->_got_index ] = (Metadata*)klass; // Resolved
if (PrintAOT) {
tty->print_cr("[Found %s in %s]", klass->internal_name(), _lib->name());
}
}
}
void AOTCodeHeap::link_known_klasses() {
for (int i = T_BOOLEAN; i <= T_CONFLICT; i++) {
BasicType t = (BasicType)i;
if (is_java_primitive(t)) {
const Klass* arr_klass = Universe::typeArrayKlassObj(t);
AOTKlassData* klass_data = (AOTKlassData*) os::dll_lookup(_lib->dl_handle(), arr_klass->signature_name());
if (klass_data != NULL) {
// Set both GOT cells, resolved and initialized klass pointers.
// _got_index points to second cell - resolved klass pointer.
_klasses_got[klass_data->_got_index-1] = (Metadata*)arr_klass; // Initialized
_klasses_got[klass_data->_got_index ] = (Metadata*)arr_klass; // Resolved
if (PrintAOT) {
tty->print_cr("[Found %s in %s]", arr_klass->internal_name(), _lib->name());
}
}
link_klass(arr_klass);
}
}
link_klass(SystemDictionary::Reference_klass());
}
void AOTCodeHeap::register_stubs() {
@ -590,9 +596,7 @@ void AOTCodeHeap::link_global_lib_symbols() {
link_stub_routines_symbols();
link_os_symbols();
link_graal_runtime_symbols();
// Link primitive array klasses.
link_primitive_array_klasses();
link_known_klasses();
}
}

@ -217,7 +217,8 @@ class AOTCodeHeap : public CodeHeap {
void link_graal_runtime_symbols();
void link_global_lib_symbols();
void link_primitive_array_klasses();
void link_klass(const Klass* klass);
void link_known_klasses();
void publish_aot(const methodHandle& mh, AOTMethodData* method_data, int code_id);

@ -1805,7 +1805,7 @@ class LIR_OpDelay: public LIR_Op {
LIR_OpDelay(LIR_Op* op, CodeEmitInfo* info):
LIR_Op(lir_delay_slot, LIR_OprFact::illegalOpr, info),
_op(op) {
assert(op->code() == lir_nop || LIRFillDelaySlots, "should be filling with nops");
assert(op->code() == lir_nop, "should be filling with nops");
}
virtual void emit_code(LIR_Assembler* masm);
virtual LIR_OpDelay* as_OpDelay() { return this; }

@ -211,9 +211,6 @@
develop(bool, LIRTraceExecution, false, \
"add LIR code which logs the execution of blocks") \
\
product_pd(bool, LIRFillDelaySlots, \
"fill delays on on SPARC with LIR") \
\
develop_pd(bool, CSEArrayLength, \
"Create separate nodes for length in array accesses") \
\

@ -45,18 +45,6 @@ void EpsilonArguments::initialize() {
FLAG_SET_DEFAULT(ExitOnOutOfMemoryError, true);
}
// Warn users that non-resizable heap might be better for some configurations.
// We are not adjusting the heap size by ourselves, because it affects startup time.
if (InitialHeapSize != MaxHeapSize) {
log_warning(gc)("Consider setting -Xms equal to -Xmx to avoid resizing hiccups");
}
// Warn users that AlwaysPreTouch might be better for some configurations.
// We are not turning this on by ourselves, because it affects startup time.
if (FLAG_IS_DEFAULT(AlwaysPreTouch) && !AlwaysPreTouch) {
log_warning(gc)("Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups");
}
if (EpsilonMaxTLABSize < MinTLABSize) {
log_warning(gc)("EpsilonMaxTLABSize < MinTLABSize, adjusting it to " SIZE_FORMAT, MinTLABSize);
EpsilonMaxTLABSize = MinTLABSize;

@ -24,6 +24,7 @@
#include "precompiled.hpp"
#include "gc/epsilon/epsilonHeap.hpp"
#include "gc/epsilon/epsilonInitLogger.hpp"
#include "gc/epsilon/epsilonMemoryPool.hpp"
#include "gc/epsilon/epsilonThreadLocalData.hpp"
#include "gc/shared/gcArguments.hpp"
@ -67,24 +68,7 @@ jint EpsilonHeap::initialize() {
BarrierSet::set_barrier_set(new EpsilonBarrierSet());
// All done, print out the configuration
if (init_byte_size != max_byte_size) {
log_info(gc)("Resizeable heap; starting at " SIZE_FORMAT "M, max: " SIZE_FORMAT "M, step: " SIZE_FORMAT "M",
init_byte_size / M, max_byte_size / M, EpsilonMinHeapExpand / M);
} else {
log_info(gc)("Non-resizeable heap; start/max: " SIZE_FORMAT "M", init_byte_size / M);
}
if (UseTLAB) {
log_info(gc)("Using TLAB allocation; max: " SIZE_FORMAT "K", _max_tlab_size * HeapWordSize / K);
if (EpsilonElasticTLAB) {
log_info(gc)("Elastic TLABs enabled; elasticity: %.2fx", EpsilonTLABElasticity);
}
if (EpsilonElasticTLABDecay) {
log_info(gc)("Elastic TLABs decay enabled; decay time: " SIZE_FORMAT "ms", EpsilonTLABDecayTime);
}
} else {
log_info(gc)("Not using TLAB allocation");
}
EpsilonInitLogger::print();
return JNI_OK;
}

@ -0,0 +1,63 @@
/*
* Copyright (c) 2020, Red Hat, Inc. 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 "gc/epsilon/epsilonHeap.hpp"
#include "gc/epsilon/epsilonInitLogger.hpp"
#include "logging/log.hpp"
#include "runtime/globals.hpp"
#include "utilities/globalDefinitions.hpp"
void EpsilonInitLogger::print_gc_specific() {
// Warn users that non-resizable heap might be better for some configurations.
// We are not adjusting the heap size by ourselves, because it affects startup time.
if (InitialHeapSize != MaxHeapSize) {
log_warning(gc, init)("Consider setting -Xms equal to -Xmx to avoid resizing hiccups");
}
// Warn users that AlwaysPreTouch might be better for some configurations.
// We are not turning this on by ourselves, because it affects startup time.
if (FLAG_IS_DEFAULT(AlwaysPreTouch) && !AlwaysPreTouch) {
log_warning(gc, init)("Consider enabling -XX:+AlwaysPreTouch to avoid memory commit hiccups");
}
if (UseTLAB) {
size_t max_tlab = EpsilonHeap::heap()->max_tlab_size() * HeapWordSize;
log_info(gc, init)("TLAB Size Max: " SIZE_FORMAT "%s",
byte_size_in_exact_unit(max_tlab), exact_unit_for_byte_size(max_tlab));
if (EpsilonElasticTLAB) {
log_info(gc, init)("TLAB Size Elasticity: %.2fx", EpsilonTLABElasticity);
}
if (EpsilonElasticTLABDecay) {
log_info(gc, init)("TLAB Size Decay Time: " SIZE_FORMAT "ms", EpsilonTLABDecayTime);
}
} else {
log_info(gc, init)("TLAB: Disabled");
}
}
void EpsilonInitLogger::print() {
EpsilonInitLogger init_log;
init_log.print_all();
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, Red Hat, Inc. 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
@ -22,18 +22,17 @@
*
*/
package sun.jvm.hotspot.utilities.soql;
#ifndef SHARE_GC_EPSILON_EPSILONINITLOGGER_HPP
#define SHARE_GC_EPSILON_EPSILONINITLOGGER_HPP
public class SOQLException extends Exception {
public SOQLException(String msg) {
super(msg);
}
#include "gc/shared/gcInitLogger.hpp"
public SOQLException(String msg, Throwable cause) {
super(msg, cause);
}
class EpsilonInitLogger : public GCInitLogger {
protected:
virtual void print_gc_specific();
public SOQLException(Throwable cause) {
super(cause);
}
}
public:
static void print();
};
#endif // SHARE_GC_EPSILON_EPSILONINITLOGGER_HPP

@ -167,7 +167,7 @@
product(bool, UseZGC, false, \
"Use the Z garbage collector") \
\
experimental(bool, UseShenandoahGC, false, \
product(bool, UseShenandoahGC, false, \
"Use the Shenandoah garbage collector") \
\
product(uint, ParallelGCThreads, 0, \

@ -154,17 +154,8 @@ public:
assert(decode_pow(encode_pow(pow)) == pow, "pow can be encoded: %d", pow);
_obj = encode_oop(o) | encode_chunk(chunk) | encode_pow(pow);
}
ObjArrayChunkedTask(const ObjArrayChunkedTask& t): _obj(t._obj) { }
ObjArrayChunkedTask& operator =(const ObjArrayChunkedTask& t) {
_obj = t._obj;
return *this;
}
volatile ObjArrayChunkedTask&
operator =(const volatile ObjArrayChunkedTask& t) volatile {
(void)const_cast<uintptr_t&>(_obj = t._obj);
return *this;
}
// Trivially copyable.
inline oop decode_oop(uintptr_t val) const {
return (oop) reinterpret_cast<void*>((val >> oop_shift) & right_n_bits(oop_bits));
@ -223,21 +214,8 @@ public:
_chunk = chunk;
_pow = pow;
}
ObjArrayChunkedTask(const ObjArrayChunkedTask& t): _obj(t._obj), _chunk(t._chunk), _pow(t._pow) { }
ObjArrayChunkedTask& operator =(const ObjArrayChunkedTask& t) {
_obj = t._obj;
_chunk = t._chunk;
_pow = t._pow;
return *this;
}
volatile ObjArrayChunkedTask&
operator =(const volatile ObjArrayChunkedTask& t) volatile {
(void)const_cast<oop&>(_obj = t._obj);
_chunk = t._chunk;
_pow = t._pow;
return *this;
}
// Trivially copyable.
inline oop obj() const { return _obj; }
inline int chunk() const { return _chunk; }

@ -63,14 +63,14 @@
"This also caps the maximum TLAB size.") \
range(1, 100) \
\
experimental(ccstr, ShenandoahGCMode, "satb", \
product(ccstr, ShenandoahGCMode, "satb", \
"GC mode to use. Among other things, this defines which " \
"barriers are in in use. Possible values are:" \
" satb - snapshot-at-the-beginning concurrent GC (three pass mark-evac-update);" \
" iu - incremental-update concurrent GC (three pass mark-evac-update);" \
" passive - stop the world GC only (either degenerated or full)") \
\
experimental(ccstr, ShenandoahGCHeuristics, "adaptive", \
product(ccstr, ShenandoahGCHeuristics, "adaptive", \
"GC heuristics to use. This fine-tunes the GC mode selected, " \
"by choosing when to start the GC, how much to process on each " \
"cycle, and what other features to automatically enable. " \

@ -49,6 +49,7 @@
#include "jfr/utilities/jfrTime.hpp"
#include "jfr/writers/jfrJavaEventWriter.hpp"
#include "jfrfiles/jfrPeriodic.hpp"
#include "jfrfiles/jfrTypes.hpp"
#include "logging/log.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/interfaceSupport.inline.hpp"
@ -349,4 +350,10 @@ JVM_ENTRY_NO_ENV(jboolean, jfr_set_handler(JNIEnv * env, jobject jvm, jobject cl
return JfrJavaSupport::set_handler(clazz, handler, thread);
JVM_END
NO_TRANSITION(jlong, jfr_get_type_id_from_string(JNIEnv * env, jobject jvm, jstring type))
const char* type_name= env->GetStringUTFChars(type, NULL);
jlong id = JfrType::name_to_id(type_name);
env->ReleaseStringUTFChars(type, type_name);
return id;
NO_TRANSITION_END

@ -148,6 +148,7 @@ jobject JNICALL jfr_get_handler(JNIEnv* env, jobject jvm, jobject clazz);
jboolean JNICALL jfr_set_handler(JNIEnv* env, jobject jvm, jobject clazz, jobject handler);
jlong JNICALL jfr_get_type_id_from_string(JNIEnv* env, jobject jvm, jstring type);
#ifdef __cplusplus
}

@ -88,7 +88,8 @@ JfrJniMethodRegistration::JfrJniMethodRegistration(JNIEnv* env) {
(char*)"isExcluded", (char*)"(Ljava/lang/Thread;)Z", (void*)jfr_is_thread_excluded,
(char*)"getChunkStartNanos", (char*)"()J", (void*)jfr_chunk_start_nanos,
(char*)"getHandler", (char*)"(Ljava/lang/Class;)Ljava/lang/Object;", (void*)jfr_get_handler,
(char*)"setHandler", (char*)"(Ljava/lang/Class;Ljdk/jfr/internal/handlers/EventHandler;)Z", (void*)jfr_set_handler
(char*)"setHandler", (char*)"(Ljava/lang/Class;Ljdk/jfr/internal/handlers/EventHandler;)Z", (void*)jfr_set_handler,
(char*)"getTypeId", (char*)"(Ljava/lang/String;)J", (void*)jfr_get_type_id_from_string
};
const size_t method_array_length = sizeof(method) / sizeof(JNINativeMethod);

@ -1304,8 +1304,8 @@
<XmlType name="ClassLoader" parameterType="const ClassLoaderData*" fieldType="const ClassLoaderData*"/>
<XmlType name="Method" parameterType="const Method*" fieldType="const Method*"/>
<XmlType name="Thread" javaType="java.lang.Thread" parameterType="u8" fieldType="u8"/>
<XmlType name="Tickspan" contentType="tickspan" javaType="long" parameterType="const Tickspan&amp;" fieldType="Tickspan"/>
<XmlType name="Ticks" contentType="tickstamp" javaType="long" parameterType="const Ticks&amp;" fieldType="Ticks"/>
<XmlType name="Tickspan" contentType="tickspan" unsigned="true" javaType="long" parameterType="const Tickspan&amp;" fieldType="Tickspan"/>
<XmlType name="Ticks" contentType="tickstamp" unsigned="true" javaType="long" parameterType="const Ticks&amp;" fieldType="Ticks"/>
<XmlType name="ulong" javaType="long" unsigned="true" parameterType="u8" fieldType="u8"/>
<XmlType name="uint" javaType="int" unsigned="true" parameterType="unsigned" fieldType="unsigned"/>
<XmlType name="ushort" javaType="short" unsigned="true" parameterType="u2" fieldType="u2"/>
@ -1319,6 +1319,7 @@
<XmlType name="boolean" javaType="boolean" parameterType="bool" fieldType="bool"/>
<XmlType name="char" javaType="char" parameterType="char" fieldType="char"/>
<XmlType name="string" javaType="java.lang.String" parameterType="const char*" fieldType="const char*"/>
<XmlType name="StackTrace" javaType="jdk.types.StackTrace" parameterType="u8" fieldType="u8"/>
<XmlContentType name="bytes" annotation="jdk.jfr.DataAmount(BYTES)" />
<XmlContentType name="tickstamp" annotation="jdk.jfr.Timestamp(TICKS)" />

@ -126,7 +126,8 @@ void JfrCheckpointWriter::release() {
}
void JfrCheckpointWriter::write_type(JfrTypeId type_id) {
assert(type_id < TYPES_END, "invariant");
assert(type_id <= LAST_TYPE_ID, "type id overflow invariant");
assert(type_id >= FIRST_TYPE_ID, "type id underflow invariant");
write<u8>(type_id);
increment();
}

@ -27,6 +27,7 @@
#include "classfile/javaClasses.inline.hpp"
#include "classfile/symbolTable.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "jfrfiles/jfrTypes.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#include "oops/arrayKlass.inline.hpp"
#include "oops/klass.inline.hpp"
@ -52,7 +53,7 @@ static traceid atomic_inc(traceid volatile* const dest) {
}
static traceid next_class_id() {
static volatile traceid class_id_counter = MaxJfrEventId + 100;
static volatile traceid class_id_counter = LAST_TYPE_ID + 1;
return atomic_inc(&class_id_counter) << TRACE_ID_SHIFT;
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, 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
@ -55,7 +55,10 @@ void JfrEventSetting::set_enabled(jlong id, bool enabled) {
#ifdef ASSERT
bool JfrEventSetting::bounds_check_event(jlong id) {
if ((unsigned)id < NUM_RESERVED_EVENTS || (unsigned)id >= MaxJfrEventId) {
if ((unsigned)id < FIRST_EVENT_ID) {
return false;
}
if ((unsigned)id > LAST_EVENT_ID) {
return false;
}
return true;

@ -23,6 +23,7 @@
*/
#include "precompiled.hpp"
#include "jfrfiles/jfrTypes.hpp"
#include "jfr/recorder/repository/jfrChunk.hpp"
#include "jfr/recorder/repository/jfrChunkWriter.hpp"
#include "jfr/utilities/jfrTime.hpp"

@ -192,8 +192,8 @@ class JfrEvent {
JfrEventVerifier _verifier;
void assert_precondition() {
assert(T::eventId >= (JfrEventId)NUM_RESERVED_EVENTS, "event id underflow invariant");
assert(T::eventId < MaxJfrEventId, "event id overflow invariant");
assert(T::eventId >= FIRST_EVENT_ID, "event id underflow invariant");
assert(T::eventId <= LAST_EVENT_ID, "event id overflow invariant");
DEBUG_ONLY(static_cast<T*>(this)->verify());
}

@ -26,6 +26,7 @@
#define SHARE_JFR_UTILITIES_JFRTYPES_HPP
#include "jfrfiles/jfrEventIds.hpp"
#include "jfrfiles/jfrTypes.hpp"
#include "utilities/globalDefinitions.hpp"
typedef u8 traceid;
@ -46,6 +47,11 @@ inline int sort_traceid(traceid* lhs, traceid* rhs) {
return compare_traceid(*lhs, *rhs);
}
enum ReservedEvent {
EVENT_METADATA = 0,
EVENT_CHECKPOINT = 1
};
enum EventStartTime {
UNTIMED,
TIMED

@ -357,10 +357,6 @@
"Limit of ops to make speculative when using CMOVE") \
range(0, max_jint) \
\
/* Set BranchOnRegister == false. See 4965987. */ \
product(bool, BranchOnRegister, false, \
"Use Sparc V9 branch-on-register opcodes") \
\
product(bool, UseRDPCForConstantTableBase, false, \
"Use Sparc RDPC instruction for the constant table base.") \
\

@ -1497,8 +1497,6 @@ JVM_END
/// JVM_RegisterMethodHandleMethods
#undef CS // Solaris builds complain
#define LANG "Ljava/lang/"
#define JLINV "Ljava/lang/invoke/"

@ -564,6 +564,8 @@ static SpecialFlag const special_jvm_flags[] = {
{ "UseBarriersForVolatile", JDK_Version::undefined(), JDK_Version::jdk(15), JDK_Version::jdk(16) },
#endif
{ "UseLWPSynchronization", JDK_Version::undefined(), JDK_Version::jdk(15), JDK_Version::jdk(16) },
{ "BranchOnRegister", JDK_Version::undefined(), JDK_Version::jdk(15), JDK_Version::jdk(16) },
{ "LIRFillDelaySlots", JDK_Version::undefined(), JDK_Version::jdk(15), JDK_Version::jdk(16) },
#ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS
// These entries will generate build errors. Their purpose is to test the macros.

@ -188,6 +188,8 @@ public class DatagramSocket implements java.io.Closeable {
* or the socket could not bind to the specified local port.
* @throws SecurityException if a security manager exists and its
* {@code checkListen} method doesn't allow the operation.
* @throws IllegalArgumentException if bindaddr is a
* SocketAddress subclass not supported by this socket.
*
* @see SecurityManager#checkListen
* @since 1.4
@ -208,11 +210,13 @@ public class DatagramSocket implements java.io.Closeable {
* as its argument to ensure the operation is allowed.
* This could result in a SecurityException.
*
* @param port port to use.
* @param port local port to use in the bind operation.
* @throws SocketException if the socket could not be opened,
* or the socket could not bind to the specified local port.
* @throws SecurityException if a security manager exists and its
* {@code checkListen} method doesn't allow the operation.
* @throws IllegalArgumentException if port is <a href="#PortRange">
* out of range.</a>
*
* @see SecurityManager#checkListen
*/
@ -222,7 +226,11 @@ public class DatagramSocket implements java.io.Closeable {
/**
* Creates a datagram socket, bound to the specified local
* address. The local port must be between 0 and 65535 inclusive.
* address.
* <p><a id="PortRange"></a>The local port must be between 0 and
* 65535 inclusive. A port number of {@code zero} will let the system pick
* up an ephemeral port in a {@code bind} operation.
* <p>
* If the IP address is 0.0.0.0, the socket will be bound to the
* {@link InetAddress#isAnyLocalAddress wildcard} address,
* an IP address chosen by the kernel.
@ -233,13 +241,15 @@ public class DatagramSocket implements java.io.Closeable {
* as its argument to ensure the operation is allowed.
* This could result in a SecurityException.
*
* @param port local port to use
* @param port local port to use in the bind operation.
* @param laddr local address to bind
*
* @throws SocketException if the socket could not be opened,
* or the socket could not bind to the specified local port.
* @throws SecurityException if a security manager exists and its
* {@code checkListen} method doesn't allow the operation.
* @throws IllegalArgumentException if port is <a href="#PortRange">
* out of range.</a>
*
* @see SecurityManager#checkListen
* @since 1.1
@ -311,7 +321,8 @@ public class DatagramSocket implements java.io.Closeable {
* @param port the remote port for the socket.
*
* @throws IllegalArgumentException
* if the address is null, or the port is out of range.
* if the address is null, or the port is <a href="#PortRange">
* out of range.</a>
*
* @throws SecurityException
* if a security manager has been installed and it does
@ -504,7 +515,8 @@ public class DatagramSocket implements java.io.Closeable {
* @throws IllegalArgumentException if the socket is connected,
* and connected address and packet address differ, or
* if the socket is not connected and the packet address
* is not set or if its port is out of range.
* is not set or if its port is <a href="#PortRange">out of
* range.</a>
*
* @see java.net.DatagramPacket
* @see SecurityManager#checkMulticast(InetAddress)

@ -1,5 +1,5 @@
/*
* Copyright (c) 1995, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1995, 2020, 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,11 +25,11 @@
package java.net;
import java.util.List;
import java.util.NavigableSet;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Scanner;
import java.security.AccessController;
import java.io.File;
import java.io.ObjectStreamException;
import java.io.ObjectStreamField;
@ -954,29 +954,18 @@ public class InetAddress implements java.io.Serializable {
*/
private static final class HostsFileNameService implements NameService {
private static final InetAddress[] EMPTY_ARRAY = new InetAddress[0];
// Specify if only IPv4 addresses should be returned by HostsFileService implementation
private static final boolean preferIPv4Stack = Boolean.parseBoolean(
GetPropertyAction.privilegedGetProperty("java.net.preferIPv4Stack"));
private final String hostsFile;
public HostsFileNameService (String hostsFileName) {
public HostsFileNameService(String hostsFileName) {
this.hostsFile = hostsFileName;
}
private String addrToString(byte addr[]) {
String stringifiedAddress = null;
if (addr.length == Inet4Address.INADDRSZ) {
stringifiedAddress = Inet4Address.numericToTextFormat(addr);
} else { // treat as an IPV6 jobby
byte[] newAddr
= IPAddressUtil.convertFromIPv4MappedAddress(addr);
if (newAddr != null) {
stringifiedAddress = Inet4Address.numericToTextFormat(addr);
} else {
stringifiedAddress = Inet6Address.numericToTextFormat(addr);
}
}
return stringifiedAddress;
}
/**
* Lookup the host name corresponding to the IP address provided.
* Search the configured host file a host name corresponding to
@ -1037,15 +1026,15 @@ public class InetAddress implements java.io.Serializable {
public InetAddress[] lookupAllHostAddr(String host)
throws UnknownHostException {
String hostEntry;
String addrStr = null;
InetAddress[] res = null;
byte addr[] = new byte[4];
ArrayList<InetAddress> inetAddresses = null;
String addrStr;
byte addr[];
List<InetAddress> inetAddresses = new ArrayList<>();
List<InetAddress> inet4Addresses = new ArrayList<>();
List<InetAddress> inet6Addresses = new ArrayList<>();
// lookup the file and create a list InetAddress for the specified host
try (Scanner hostsFileScanner = new Scanner(new File(hostsFile),
UTF_8.INSTANCE))
{
UTF_8.INSTANCE)) {
while (hostsFileScanner.hasNextLine()) {
hostEntry = hostsFileScanner.nextLine();
if (!hostEntry.startsWith("#")) {
@ -1054,11 +1043,15 @@ public class InetAddress implements java.io.Serializable {
addrStr = extractHostAddr(hostEntry, host);
if ((addrStr != null) && (!addrStr.isEmpty())) {
addr = createAddressByteArray(addrStr);
if (inetAddresses == null) {
inetAddresses = new ArrayList<>(1);
}
if (addr != null) {
inetAddresses.add(InetAddress.getByAddress(host, addr));
InetAddress address = InetAddress.getByAddress(host, addr);
inetAddresses.add(address);
if (address instanceof Inet4Address) {
inet4Addresses.add(address);
}
if (address instanceof Inet6Address) {
inet6Addresses.add(address);
}
}
}
}
@ -1069,13 +1062,32 @@ public class InetAddress implements java.io.Serializable {
+ " as hosts file " + hostsFile + " not found ");
}
if (inetAddresses != null) {
res = inetAddresses.toArray(new InetAddress[inetAddresses.size()]);
List<InetAddress> res;
// If "preferIPv4Stack" system property is set to "true" then return
// only IPv4 addresses
if (preferIPv4Stack) {
res = inet4Addresses;
} else {
// Otherwise, analyse "preferIPv6Addresses" value
res = switch (preferIPv6Address) {
case PREFER_IPV4_VALUE -> concatAddresses(inet4Addresses, inet6Addresses);
case PREFER_IPV6_VALUE -> concatAddresses(inet6Addresses, inet4Addresses);
default -> inetAddresses;
};
}
if (res.isEmpty()) {
throw new UnknownHostException("Unable to resolve host " + host
+ " in hosts file " + hostsFile);
}
return res;
return res.toArray(EMPTY_ARRAY);
}
private static List<InetAddress> concatAddresses(List<InetAddress> firstPart,
List<InetAddress> secondPart) {
List<InetAddress> result = new ArrayList<>(firstPart);
result.addAll(secondPart);
return result;
}
private String removeComments(String hostsEntry) {

@ -506,18 +506,24 @@ public interface HttpResponse<T> {
* been completely written to the file, and {@link #body()} returns a
* reference to its {@link Path}.
*
* <p> Security manager permission checks are performed in this factory
* method, when the {@code BodyHandler} is created. Care must be taken
* that the {@code BodyHandler} is not shared with untrusted code.
* <p> In the case of the default file system provider, security manager
* permission checks are performed in this factory method, when the
* {@code BodyHandler} is created. Otherwise,
* {@linkplain FileChannel#open(Path, OpenOption...) permission checks}
* may be performed asynchronously against the caller's context
* at file access time.
* Care must be taken that the {@code BodyHandler} is not shared with
* untrusted code.
*
* @param file the file to store the body in
* @param openOptions any options to use when opening/creating the file
* @param file the file to store the body in
* @param openOptions any options to use when opening/creating the file
* @return a response body handler
* @throws IllegalArgumentException if an invalid set of open options
* are specified
* @throws SecurityException If a security manager has been installed
* and it denies {@linkplain SecurityManager#checkWrite(String)
* write access} to the file.
* are specified
* @throws SecurityException in the case of the default file system
* provider, and a security manager is installed,
* {@link SecurityManager#checkWrite(String) checkWrite}
* is invoked to check write access to the given file
*/
public static BodyHandler<Path> ofFile(Path file, OpenOption... openOptions) {
Objects.requireNonNull(file);
@ -535,15 +541,21 @@ public interface HttpResponse<T> {
*
* <p> Equivalent to: {@code ofFile(file, CREATE, WRITE)}
*
* <p> Security manager permission checks are performed in this factory
* method, when the {@code BodyHandler} is created. Care must be taken
* that the {@code BodyHandler} is not shared with untrusted code.
* <p> In the case of the default file system provider, security manager
* permission checks are performed in this factory method, when the
* {@code BodyHandler} is created. Otherwise,
* {@linkplain FileChannel#open(Path, OpenOption...) permission checks}
* may be performed asynchronously against the caller's context
* at file access time.
* Care must be taken that the {@code BodyHandler} is not shared with
* untrusted code.
*
* @param file the file to store the body in
* @param file the file to store the body in
* @return a response body handler
* @throws SecurityException If a security manager has been installed
* and it denies {@linkplain SecurityManager#checkWrite(String)
* write access} to the file.
* @throws SecurityException in the case of the default file system
* provider, and a security manager is installed,
* {@link SecurityManager#checkWrite(String) checkWrite}
* is invoked to check write access to the given file
*/
public static BodyHandler<Path> ofFile(Path file) {
return BodyHandlers.ofFile(file, CREATE, WRITE);
@ -570,20 +582,22 @@ public interface HttpResponse<T> {
* method, when the {@code BodyHandler} is created. Care must be taken
* that the {@code BodyHandler} is not shared with untrusted code.
*
* @param directory the directory to store the file in
* @param openOptions open options used when opening the file
* @param directory the directory to store the file in
* @param openOptions open options used when opening the file
* @return a response body handler
* @throws IllegalArgumentException if the given path does not exist,
* is not a directory, is not writable, or if an invalid set
* of open options are specified
* @throws SecurityException If a security manager has been installed
* and it denies
* {@linkplain SecurityManager#checkRead(String) read access}
* to the directory, or it denies
* {@linkplain SecurityManager#checkWrite(String) write access}
* to the directory, or it denies
* {@linkplain SecurityManager#checkWrite(String) write access}
* to the files within the directory.
* is not of the default file system, is not a directory,
* is not writable, or if an invalid set of open options
* are specified
* @throws SecurityException in the case of the default file system
* provider and a security manager has been installed,
* and it denies
* {@linkplain SecurityManager#checkRead(String) read access}
* to the directory, or it denies
* {@linkplain SecurityManager#checkWrite(String) write access}
* to the directory, or it denies
* {@linkplain SecurityManager#checkWrite(String) write access}
* to the files within the directory.
*/
public static BodyHandler<Path> ofFileDownload(Path directory,
OpenOption... openOptions) {
@ -1068,18 +1082,24 @@ public interface HttpResponse<T> {
* <p> The {@link HttpResponse} using this subscriber is available after
* the entire response has been read.
*
* <p> Security manager permission checks are performed in this factory
* method, when the {@code BodySubscriber} is created. Care must be taken
* that the {@code BodyHandler} is not shared with untrusted code.
* <p> In the case of the default file system provider, security manager
* permission checks are performed in this factory method, when the
* {@code BodySubscriber} is created. Otherwise,
* {@linkplain FileChannel#open(Path, OpenOption...) permission checks}
* may be performed asynchronously against the caller's context
* at file access time.
* Care must be taken that the {@code BodySubscriber} is not shared with
* untrusted code.
*
* @param file the file to store the body in
* @param openOptions the list of options to open the file with
* @param file the file to store the body in
* @param openOptions the list of options to open the file with
* @return a body subscriber
* @throws IllegalArgumentException if an invalid set of open options
* are specified
* @throws SecurityException if a security manager has been installed
* and it denies {@linkplain SecurityManager#checkWrite(String)
* write access} to the file
* are specified
* @throws SecurityException in the case of the default file system
* provider, and a security manager is installed,
* {@link SecurityManager#checkWrite(String) checkWrite}
* is invoked to check write access to the given file
*/
public static BodySubscriber<Path> ofFile(Path file, OpenOption... openOptions) {
Objects.requireNonNull(file);
@ -1097,15 +1117,21 @@ public interface HttpResponse<T> {
*
* <p> Equivalent to: {@code ofFile(file, CREATE, WRITE)}
*
* <p> Security manager permission checks are performed in this factory
* method, when the {@code BodySubscriber} is created. Care must be taken
* that the {@code BodyHandler} is not shared with untrusted code.
* <p> In the case of the default file system provider, security manager
* permission checks are performed in this factory method, when the
* {@code BodySubscriber} is created. Otherwise,
* {@linkplain FileChannel#open(Path, OpenOption...) permission checks}
* may be performed asynchronously against the caller's context
* at file access time.
* Care must be taken that the {@code BodySubscriber} is not shared with
* untrusted code.
*
* @param file the file to store the body in
* @param file the file to store the body in
* @return a body subscriber
* @throws SecurityException if a security manager has been installed
* and it denies {@linkplain SecurityManager#checkWrite(String)
* write access} to the file
* @throws SecurityException in the case of the default file system
* provider, and a security manager is installed,
* {@link SecurityManager#checkWrite(String) checkWrite}
* is invoked to check write access to the given file
*/
public static BodySubscriber<Path> ofFile(Path file) {
return ofFile(file, CREATE, WRITE);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, 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
@ -34,11 +34,12 @@ import java.nio.file.Files;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Function;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpResponse.BodyHandler;
@ -63,6 +64,7 @@ public final class ResponseBodyHandlers {
public static class PathBodyHandler implements BodyHandler<Path>{
private final Path file;
private final List<OpenOption> openOptions; // immutable list
private final AccessControlContext acc;
private final FilePermission filePermission;
/**
@ -77,25 +79,34 @@ public final class ResponseBodyHandlers {
FilePermission filePermission = null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
String fn = pathForSecurityCheck(file);
FilePermission writePermission = new FilePermission(fn, "write");
sm.checkPermission(writePermission);
filePermission = writePermission;
try {
String fn = pathForSecurityCheck(file);
FilePermission writePermission = new FilePermission(fn, "write");
sm.checkPermission(writePermission);
filePermission = writePermission;
} catch (UnsupportedOperationException ignored) {
// path not associated with the default file system provider
}
}
return new PathBodyHandler(file, openOptions, filePermission);
assert filePermission == null || filePermission.getActions().equals("write");
var acc = sm != null ? AccessController.getContext() : null;
return new PathBodyHandler(file, openOptions, acc, filePermission);
}
private PathBodyHandler(Path file,
List<OpenOption> openOptions,
AccessControlContext acc,
FilePermission filePermission) {
this.file = file;
this.openOptions = openOptions;
this.acc = acc;
this.filePermission = filePermission;
}
@Override
public BodySubscriber<Path> apply(ResponseInfo responseInfo) {
return new PathSubscriber(file, openOptions, filePermission);
return new PathSubscriber(file, openOptions, acc, filePermission);
}
}
@ -149,6 +160,7 @@ public final class ResponseBodyHandlers {
public static class FileDownloadBodyHandler implements BodyHandler<Path> {
private final Path directory;
private final List<OpenOption> openOptions;
private final AccessControlContext acc;
private final FilePermission[] filePermissions; // may be null
/**
@ -160,10 +172,17 @@ public final class ResponseBodyHandlers {
*/
public static FileDownloadBodyHandler create(Path directory,
List<OpenOption> openOptions) {
String fn;
try {
fn = pathForSecurityCheck(directory);
} catch (UnsupportedOperationException uoe) {
// directory not associated with the default file system provider
throw new IllegalArgumentException("invalid path: " + directory, uoe);
}
FilePermission filePermissions[] = null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
String fn = pathForSecurityCheck(directory);
FilePermission writePermission = new FilePermission(fn, "write");
String writePathPerm = fn + File.separatorChar + "*";
FilePermission writeInDirPermission = new FilePermission(writePathPerm, "write");
@ -184,15 +203,19 @@ public final class ResponseBodyHandlers {
if (!Files.isWritable(directory))
throw new IllegalArgumentException("non-writable directory: " + directory);
return new FileDownloadBodyHandler(directory, openOptions, filePermissions);
assert filePermissions == null || (filePermissions[0].getActions().equals("write")
&& filePermissions[1].getActions().equals("write"));
var acc = sm != null ? AccessController.getContext() : null;
return new FileDownloadBodyHandler(directory, openOptions, acc, filePermissions);
}
private FileDownloadBodyHandler(Path directory,
List<OpenOption> openOptions,
AccessControlContext acc,
FilePermission... filePermissions) {
this.directory = directory;
this.openOptions = openOptions;
this.acc = acc;
this.filePermissions = filePermissions;
}
@ -273,7 +296,7 @@ public final class ResponseBodyHandlers {
"Resulting file, " + file.toString() + ", outside of given directory");
}
return new PathSubscriber(file, openOptions, filePermissions);
return new PathSubscriber(file, openOptions, acc, filePermissions);
}
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2016, 2020, 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
@ -35,7 +35,9 @@ import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
@ -172,7 +174,9 @@ public class ResponseSubscribers {
private final Path file;
private final OpenOption[] options;
private final AccessControlContext acc;
private final FilePermission[] filePermissions;
private final boolean isDefaultFS;
private final CompletableFuture<Path> result = new MinimalFuture<>();
private final AtomicBoolean subscribed = new AtomicBoolean();
@ -192,25 +196,44 @@ public class ResponseSubscribers {
*/
public static PathSubscriber create(Path file,
List<OpenOption> options) {
FilePermission filePermission = null;
SecurityManager sm = System.getSecurityManager();
FilePermission filePermission = null;
if (sm != null) {
String fn = pathForSecurityCheck(file);
FilePermission writePermission = new FilePermission(fn, "write");
sm.checkPermission(writePermission);
filePermission = writePermission;
try {
String fn = pathForSecurityCheck(file);
FilePermission writePermission = new FilePermission(fn, "write");
sm.checkPermission(writePermission);
filePermission = writePermission;
} catch (UnsupportedOperationException ignored) {
// path not associated with the default file system provider
}
}
return new PathSubscriber(file, options, filePermission);
assert filePermission == null || filePermission.getActions().equals("write");
AccessControlContext acc = sm != null ? AccessController.getContext() : null;
return new PathSubscriber(file, options, acc, filePermission);
}
// pp so handler implementations in the same package can construct
/*package-private*/ PathSubscriber(Path file,
List<OpenOption> options,
AccessControlContext acc,
FilePermission... filePermissions) {
this.file = file;
this.options = options.stream().toArray(OpenOption[]::new);
this.filePermissions =
filePermissions == null ? EMPTY_FILE_PERMISSIONS : filePermissions;
this.acc = acc;
this.filePermissions = filePermissions == null || filePermissions[0] == null
? EMPTY_FILE_PERMISSIONS : filePermissions;
this.isDefaultFS = isDefaultFS(file);
}
private static boolean isDefaultFS(Path file) {
try {
file.toFile();
return true;
} catch (UnsupportedOperationException uoe) {
return false;
}
}
@Override
@ -222,23 +245,30 @@ public class ResponseSubscribers {
}
this.subscription = subscription;
if (System.getSecurityManager() == null) {
if (acc == null) {
try {
out = FileChannel.open(file, options);
} catch (IOException ioe) {
result.completeExceptionally(ioe);
subscription.cancel();
return;
}
} else {
try {
PrivilegedExceptionAction<FileChannel> pa =
() -> FileChannel.open(file, options);
out = AccessController.doPrivileged(pa, null, filePermissions);
out = isDefaultFS
? AccessController.doPrivileged(pa, acc, filePermissions)
: AccessController.doPrivileged(pa, acc);
} catch (PrivilegedActionException pae) {
Throwable t = pae.getCause() != null ? pae.getCause() : pae;
result.completeExceptionally(t);
subscription.cancel();
return;
} catch (Exception e) {
result.completeExceptionally(e);
subscription.cancel();
return;
}
}
subscription.request(1);
@ -249,7 +279,7 @@ public class ResponseSubscribers {
try {
out.write(items.toArray(Utils.EMPTY_BB_ARRAY));
} catch (IOException ex) {
Utils.close(out);
close();
subscription.cancel();
result.completeExceptionally(ex);
}
@ -259,12 +289,12 @@ public class ResponseSubscribers {
@Override
public void onError(Throwable e) {
result.completeExceptionally(e);
Utils.close(out);
close();
}
@Override
public void onComplete() {
Utils.close(out);
close();
result.complete(file);
}
@ -272,6 +302,22 @@ public class ResponseSubscribers {
public CompletionStage<Path> getBody() {
return result;
}
private void close() {
if (acc == null) {
Utils.close(out);
} else {
PrivilegedAction<Void> pa = () -> {
Utils.close(out);
return null;
};
if (isDefaultFS) {
AccessController.doPrivileged(pa, acc, filePermissions);
} else {
AccessController.doPrivileged(pa, acc);
}
}
}
}
public static class ByteArraySubscriber<T> implements TrustedSubscriber<T> {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2020, 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
@ -32,6 +32,7 @@ import java.util.List;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.element.PackageElement;
import javax.lang.model.type.TypeMirror;
import javax.tools.Diagnostic;
import javax.tools.FileObject;
import javax.tools.JavaCompiler.CompilationTask;
@ -152,6 +153,21 @@ public abstract class DocTrees extends Trees {
*/
public abstract Element getElement(DocTreePath path);
/**
* Returns the language model type referred to by the leaf node of the given
* {@link DocTreePath}, or {@code null} if unknown. This method usually
* returns the same value as {@code getElement(path).asType()} for a
* {@code path} argument for which {@link #getElement(DocTreePath)} returns
* a non-null value, but may return a type that includes additional
* information, such as a parameterized generic type instead of a raw type.
*
* @param path the path for the tree node
* @return the referenced type, or null
*
* @since 15
*/
public abstract TypeMirror getType(DocTreePath path);
/**
* Returns the list of {@link DocTree} representing the first sentence of
* a comment.

@ -915,14 +915,9 @@ public class Checker extends DocTreePathScanner<Void, Void> {
@Override @DefinedBy(Api.COMPILER_TREE)
public Void visitReference(ReferenceTree tree, Void ignore) {
String sig = tree.getSignature();
if (sig.contains("<") || sig.contains(">")) {
env.messages.error(REFERENCE, tree, "dc.type.arg.not.allowed");
} else {
Element e = env.trees.getElement(getCurrentPath());
if (e == null)
env.messages.error(REFERENCE, tree, "dc.ref.not.found");
}
Element e = env.trees.getElement(getCurrentPath());
if (e == null)
env.messages.error(REFERENCE, tree, "dc.ref.not.found");
return super.visitReference(tree, ignore);
}

@ -80,7 +80,6 @@ dc.tag.start.unmatched = end tag missing: </{0}>
dc.tag.unknown = unknown tag: {0}
dc.tag.not.supported = tag not supported in the generated HTML version: {0}
dc.text.not.allowed = text not allowed in <{0}> element
dc.type.arg.not.allowed = type arguments not allowed here
dc.unexpected.comment=documentation comment not expected here
dc.value.not.allowed.here='{@value}' not allowed here
dc.value.not.a.constant=value does not refer to a constant

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2020, 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
@ -431,6 +431,31 @@ public class JavacTrees extends DocTrees {
return null;
}
@Override @DefinedBy(Api.COMPILER_TREE)
public TypeMirror getType(DocTreePath path) {
DocTree tree = path.getLeaf();
if (tree instanceof DCReference) {
JCTree qexpr = ((DCReference)tree).qualifierExpression;
if (qexpr != null) {
Log.DeferredDiagnosticHandler deferredDiagnosticHandler =
new Log.DeferredDiagnosticHandler(log);
try {
Env<AttrContext> env = getAttrContext(path.getTreePath());
Type t = attr.attribType(((DCReference) tree).qualifierExpression, env);
if (t != null && !t.isErroneous()) {
return t;
}
} catch (Abort e) { // may be thrown by Check.completionError in case of bad class file
return null;
} finally {
log.popDiagnosticHandler(deferredDiagnosticHandler);
}
}
}
Element e = getElement(path);
return e == null ? null : e.asType();
}
@Override @DefinedBy(Api.COMPILER_TREE)
public java.util.List<DocTree> getFirstSentence(java.util.List<? extends DocTree> list) {
return docTreeMaker.getFirstSentence(list);
@ -721,78 +746,15 @@ public class JavacTrees extends DocTrees {
if (method.params().size() != paramTypes.size())
return false;
List<Type> methodParamTypes = types.erasureRecursive(method.asType()).getParameterTypes();
List<Type> methodParamTypes = method.asType().getParameterTypes();
if (!Type.isErroneous(paramTypes) && types.isSubtypes(paramTypes, methodParamTypes)) {
return true;
}
return (Type.isErroneous(paramTypes))
? fuzzyMatch(paramTypes, methodParamTypes)
: types.isSameTypes(paramTypes, methodParamTypes);
methodParamTypes = types.erasureRecursive(methodParamTypes);
return types.isSameTypes(paramTypes, methodParamTypes);
}
boolean fuzzyMatch(List<Type> paramTypes, List<Type> methodParamTypes) {
List<Type> l1 = paramTypes;
List<Type> l2 = methodParamTypes;
while (l1.nonEmpty()) {
if (!fuzzyMatch(l1.head, l2.head))
return false;
l1 = l1.tail;
l2 = l2.tail;
}
return true;
}
boolean fuzzyMatch(Type paramType, Type methodParamType) {
Boolean b = fuzzyMatcher.visit(paramType, methodParamType);
return (b == Boolean.TRUE);
}
TypeRelation fuzzyMatcher = new TypeRelation() {
@Override
public Boolean visitType(Type t, Type s) {
if (t == s)
return true;
if (s.isPartial())
return visit(s, t);
switch (t.getTag()) {
case BYTE: case CHAR: case SHORT: case INT: case LONG: case FLOAT:
case DOUBLE: case BOOLEAN: case VOID: case BOT: case NONE:
return t.hasTag(s.getTag());
default:
throw new AssertionError("fuzzyMatcher " + t.getTag());
}
}
@Override
public Boolean visitArrayType(ArrayType t, Type s) {
if (t == s)
return true;
if (s.isPartial())
return visit(s, t);
return s.hasTag(ARRAY)
&& visit(t.elemtype, types.elemtype(s));
}
@Override
public Boolean visitClassType(ClassType t, Type s) {
if (t == s)
return true;
if (s.isPartial())
return visit(s, t);
return t.tsym == s.tsym;
}
@Override
public Boolean visitErrorType(ErrorType t, Type s) {
return s.hasTag(CLASS)
&& t.tsym.name == ((ClassType) s).tsym.name;
}
};
@Override @DefinedBy(Api.COMPILER_TREE)
public TypeMirror getTypeMirror(TreePath path) {
Tree t = path.getLeaf();

@ -192,18 +192,6 @@ This is cross platform Solaris pmap-like utility.
</td>
</tr>
<tr>
<td>
soqlproc.sh,
soqlproc64.sh,
soqlwindbg.bat
soqlwindbg64.bat
</td>
<td>
This is command line SOQL - Simple Object Query Language tool.
SOQL is SQL-like query language to query Java heap.
</td>
<tr>
<td>
start-debug-server-proc.sh,
start-debug-server-proc64.sh,

File diff suppressed because it is too large Load Diff

@ -104,9 +104,6 @@ import sun.jvm.hotspot.utilities.ReversePtrs;
import sun.jvm.hotspot.utilities.ReversePtrsAnalysis;
import sun.jvm.hotspot.utilities.RobustOopDeterminator;
import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
import sun.jvm.hotspot.utilities.soql.JSJavaFactory;
import sun.jvm.hotspot.utilities.soql.JSJavaFactoryImpl;
import sun.jvm.hotspot.utilities.soql.JSJavaScriptEngine;
public class CommandProcessor {
@ -1846,7 +1843,6 @@ public class CommandProcessor {
private DebuggerInterface debugger;
private HotSpotAgent agent;
private JSJavaScriptEngine jsengine;
private BufferedReader in;
private PrintStream out;
private PrintStream err;
@ -1858,65 +1854,7 @@ public class CommandProcessor {
// called after debuggee attach
private void postAttach() {
/*
* JavaScript engine no longer works. For now disable it. Eventually we will remove it.
// create JavaScript engine and start it
try {
jsengine = new JSJavaScriptEngine() {
private ObjectReader reader = new ObjectReader();
private JSJavaFactory factory = new JSJavaFactoryImpl();
public ObjectReader getObjectReader() {
return reader;
}
public JSJavaFactory getJSJavaFactory() {
return factory;
}
protected void quit() {
debugger.detach();
quit = true;
}
protected BufferedReader getInputReader() {
return in;
}
protected PrintStream getOutputStream() {
return out;
}
protected PrintStream getErrorStream() {
return err;
}
};
try {
jsengine.defineFunction(this,
this.getClass().getMethod("registerCommand",
new Class[] {
String.class, String.class, String.class
}));
} catch (NoSuchMethodException exp) {
// should not happen, see below...!!
exp.printStackTrace();
}
jsengine.start();
}
catch (Exception ex) {
System.out.println("Warning! JS Engine can't start, some commands will not be available.");
if (verboseExceptions) {
ex.printStackTrace(out);
}
}
*/
}
public void registerCommand(String cmd, String usage, final String func) {
commands.put(cmd, new Command(cmd, usage, false) {
public void doit(Tokens t) {
final int len = t.countTokens();
Object[] args = new Object[len];
for (int i = 0; i < len; i++) {
args[i] = t.nextToken();
}
jsengine.call(func, args);
}
});
// nothing for now..
}
public void setOutput(PrintStream o) {

@ -276,15 +276,6 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
item.setMnemonic(KeyEvent.VK_D);
toolsMenu.add(item);
item = createMenuItem("Find Object by Query",
new ActionListener() {
public void actionPerformed(ActionEvent e) {
showFindByQueryPanel();
}
});
item.setMnemonic(KeyEvent.VK_Q);
toolsMenu.add(item);
item = createMenuItem("Find Pointer",
new ActionListener() {
@ -1531,10 +1522,6 @@ public class HSDB implements ObjectHistogramPanel.Listener, SAListener {
showPanel("Command Line", new CommandProcessorPanel(new CommandProcessor(di, null, null, null)));
}
private void showFindByQueryPanel() {
showPanel("Find Object by Query", new FindByQueryPanel());
}
private void showFindPanel() {
showPanel("Find Pointer", new FindPanel());
}

@ -1,97 +0,0 @@
/*
* Copyright (c) 2003, 2020, 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 sun.jvm.hotspot.memory;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.types.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.utilities.Observable;
import sun.jvm.hotspot.utilities.Observer;
public class FreeChunk extends VMObject {
static {
VM.registerVMInitializedObserver(new Observer() {
public void update(Observable o, Object data) {
initialize(VM.getVM().getTypeDataBase());
}
});
}
private static synchronized void initialize(TypeDataBase db) {
Type type = db.lookupType("FreeChunk");
nextField = type.getAddressField("_next");
prevField = type.getAddressField("_prev");
sizeField = type.getAddressField("_size");
}
// Fields
private static AddressField nextField;
private static AddressField prevField;
private static AddressField sizeField;
// Accessors
public FreeChunk next() {
return (FreeChunk) VMObjectFactory.newObject(FreeChunk.class, nextField.getValue(addr));
}
public FreeChunk prev() {
Address prev = prevField.getValue(addr).andWithMask(~0x3);
return (FreeChunk) VMObjectFactory.newObject(FreeChunk.class, prev);
}
public long size() {
if (VM.getVM().isCompressedOopsEnabled()) {
Mark mark = new Mark(addr.addOffsetTo(sizeField.getOffset()));
return mark.getSize();
} else {
Address size = sizeField.getValue(addr);
Debugger dbg = VM.getVM().getDebugger();
return dbg.getAddressValue(size);
}
}
public FreeChunk(Address addr) {
super(addr);
}
public static boolean indicatesFreeChunk(Address cur) {
FreeChunk f = new FreeChunk(cur);
return f.isFree();
}
public boolean isFree() {
if (VM.getVM().isCompressedOopsEnabled()) {
Mark mark = new Mark(addr.addOffsetTo(sizeField.getOffset()));
return mark.isCmsFreeChunk();
} else {
Address prev = prevField.getValue(addr);
Debugger dbg = VM.getVM().getDebugger();
long word = dbg.getAddressValue(prev);
return (word & 0x1L) == 0x1L;
}
}
}

@ -238,10 +238,5 @@ public class Mark extends VMObject {
}
}
// Copy markWord methods for CMS here.
public boolean isCmsFreeChunk() {
return isUnlocked() &&
(Bits.maskBitsLong(value() >> cmsShift, cmsMask) & 0x1L) == 0x1L;
}
public long getSize() { return (long)(value() >> sizeShift); }
}

@ -1,63 +0,0 @@
/*
* Copyright (c) 2004, 2013, 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 sun.jvm.hotspot.tools.soql;
import sun.jvm.hotspot.debugger.JVMDebugger;
import sun.jvm.hotspot.tools.*;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.utilities.soql.*;
/** This is command line JavaScript debugger console */
public class JSDB extends Tool {
public JSDB() {
super();
}
public JSDB(JVMDebugger d) {
super(d);
}
public static void main(String[] args) {
JSDB jsdb = new JSDB();
jsdb.execute(args);
}
public void run() {
JSJavaScriptEngine engine = new JSJavaScriptEngine() {
private ObjectReader objReader = new ObjectReader();
private JSJavaFactory factory = new JSJavaFactoryImpl();
public ObjectReader getObjectReader() {
return objReader;
}
public JSJavaFactory getJSJavaFactory() {
return factory;
}
};
engine.startConsole();
}
}

@ -1,223 +0,0 @@
/*
* Copyright (c) 2003, 2013, 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 sun.jvm.hotspot.tools.soql;
import java.io.*;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.tools.*;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.utilities.soql.*;
/**
This is command line SOQL (Simple Object Query Language) interpreter.
*/
public class SOQL extends Tool {
public static void main(String[] args) {
SOQL soql = new SOQL();
soql.execute(args);
}
public SOQL() {
super();
}
public SOQL(JVMDebugger d) {
super(d);
}
protected SOQLEngine soqlEngine;
protected BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
protected PrintStream out = System.out;
static protected String prompt = "soql> ";
static protected String secondPrompt = "> ";
public void run() {
soqlEngine = SOQLEngine.getEngine();
while (true) {
try {
out.print(prompt);
String line = in.readLine();
if (line == null) {
return;
}
StringTokenizer st = new StringTokenizer(line);
if (st.hasMoreTokens()) {
String cmd = st.nextToken();
if (cmd.equals("select")) {
handleSelect(line);
} else if (cmd.equals("classes")) {
handleClasses(line);
} else if (cmd.equals("class")) {
handleClass(line);
} else if (cmd.equals("object")) {
handleObject(line);
} else if (cmd.equals("quit")) {
out.println("Bye!");
return;
} else if (cmd.equals("")) {
// do nothing ...
} else {
handleUnknown(line);
}
}
} catch (IOException e) {
e.printStackTrace();
return;
}
}
}
protected void handleSelect(String query) {
StringBuffer buf = new StringBuffer(query);
String tmp = null;
while (true) {
out.print(secondPrompt);
try {
tmp = in.readLine();
} catch (IOException ioe) {
break;
}
if (tmp.equals("") || tmp.equals("go"))
break;
buf.append('\n');
buf.append(tmp);
}
query = buf.toString();
try {
soqlEngine.executeQuery(query,
new ObjectVisitor() {
public void visit(Object o) {
if (o != null && o instanceof JSJavaObject) {
String oopAddr = ((JSJavaObject)o).getOop().getHandle().toString();
out.println(oopAddr);
} else {
out.println((o == null)? "null" : o.toString());
}
}
});
} catch (SOQLException se) {
se.printStackTrace();
}
}
protected void handleClasses(String line) {
// just list all InstanceKlasses
InstanceKlass[] klasses = SystemDictionaryHelper.getAllInstanceKlasses();
for (int i = 0; i < klasses.length; i++) {
out.print(klasses[i].getName().asString().replace('/', '.'));
out.print(" @");
out.println(klasses[i].getAddress());
}
}
protected void handleClass(String line) {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // ignore "class"
if (st.hasMoreTokens()) {
String className = st.nextToken();
InstanceKlass klass = SystemDictionaryHelper.findInstanceKlass(className);
if (klass == null) {
out.println("class " + className + " not found");
} else {
// klass.iterate(new OopPrinter(out), true);
// base class
InstanceKlass base = (InstanceKlass) klass.getSuper();
if (base != null) {
out.println("super");
out.print("\t");
out.println(base.getName().asString().replace('/', '.'));
}
// list immediate fields only
U2Array fields = klass.getFields();
int numFields = (int) fields.length();
ConstantPool cp = klass.getConstants();
out.println("fields");
if (numFields != 0) {
for (int f = 0; f < numFields; f++){
Symbol f_name = klass.getFieldName(f);
Symbol f_sig = klass.getFieldSignature(f);
StringBuffer sigBuf = new StringBuffer();
new SignatureConverter(f_sig, sigBuf).dispatchField();
out.print('\t');
out.print(sigBuf.toString().replace('/', '.'));
out.print(' ');
out.println(f_name.asString());
}
} else {
out.println("\tno fields in this class");
}
}
} else {
out.println("usage: class <name of the class>");
}
}
protected Oop getOopAtAddress(Address addr) {
OopHandle oopHandle = addr.addOffsetToAsOopHandle(0);
return VM.getVM().getObjectHeap().newOop(oopHandle);
}
protected void handleObject(String line) {
StringTokenizer st = new StringTokenizer(line);
st.nextToken(); // ignore "object"
if (st.hasMoreTokens()) {
String addrStr = st.nextToken();
Address addr = null;
Debugger dbg = VM.getVM().getDebugger();
try {
addr = dbg.parseAddress(addrStr);
} catch (Exception e) {
out.println("invalid address : " + e.getMessage());
return;
}
Oop oop = null;
try {
oop = getOopAtAddress(addr);
} catch (Exception e) {
out.println("invalid object : " + e.getMessage());
}
if (oop != null) {
oop.iterate(new OopPrinter(out), true);
} else {
out.println("null object!");
}
} else {
out.println("usage: object <address>");
}
}
protected void handleUnknown(String line) {
out.println("Unknown command!");
}
}

@ -1,111 +0,0 @@
/*
* Copyright (c) 2003, 2007, 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 sun.jvm.hotspot.ui;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.ui.tree.*;
import sun.jvm.hotspot.utilities.soql.*;
public class FindByQueryPanel extends SAPanel {
private JTextArea queryEditor;
private JEditorPane objectsEditor;
private SOQLEngine queryEngine;
public FindByQueryPanel() {
queryEngine = SOQLEngine.getEngine();
HyperlinkListener hyperListener = new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
VM vm = VM.getVM();
OopHandle handle = vm.getDebugger().parseAddress(e.getDescription()).addOffsetToAsOopHandle(0);
showInspector(vm.getObjectHeap().newOop(handle));
}
}
};
objectsEditor = new JEditorPane();
objectsEditor.setContentType("text/html");
objectsEditor.setEditable(false);
objectsEditor.addHyperlinkListener(hyperListener);
queryEditor = new JTextArea();
JButton queryButton = new JButton("Execute");
queryButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
final StringBuffer buf = new StringBuffer();
buf.append("<html><body>");
try {
queryEngine.executeQuery(queryEditor.getText(),
new ObjectVisitor() {
public void visit(Object o) {
if (o != null && o instanceof JSJavaObject) {
String oopAddr = ((JSJavaObject)o).getOop().getHandle().toString();
buf.append("<a href='");
buf.append(oopAddr);
buf.append("'>");
buf.append(oopAddr);
buf.append("</a>");
} else {
buf.append((o == null)? "null" : o.toString());
}
buf.append("<br>");
}
});
} catch (Exception e) {
e.printStackTrace();
buf.append("<b>");
buf.append(e.getMessage());
buf.append("</b>");
}
buf.append("</body></html>");
objectsEditor.setText(buf.toString());
}
});
JPanel topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
topPanel.add(new JLabel("SOQL Query :"), BorderLayout.WEST);
topPanel.add(new JScrollPane(queryEditor), BorderLayout.CENTER);
topPanel.add(queryButton, BorderLayout.EAST);
JPanel bottomPanel = new JPanel();
bottomPanel.setLayout(new BorderLayout());
bottomPanel.add(new JScrollPane(objectsEditor), BorderLayout.CENTER);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, topPanel, bottomPanel);
splitPane.setDividerLocation(0.3);
setLayout(new BorderLayout());
add(splitPane, BorderLayout.CENTER);
}
}

@ -1,38 +0,0 @@
/*
* Copyright (c) 2007, 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 sun.jvm.hotspot.utilities.soql;
import javax.script.ScriptException;
/**
* This interface is used to represent "function" valued
* properties in ScriptObjects.
*/
public interface Callable {
/**
* Call the underlying function passing the given
* arguments and return the result.
*/
public Object call(Object[] args) throws ScriptException;
}

@ -1,68 +0,0 @@
/*
* Copyright (c) 2007, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
/**
* Dummy implementation for ScriptObject interface. This class
* supports empty set of named and indexed properties. Returns
* false always for "has" calls. And ignores "delete" and "put"
* calls.
*/
public class DefaultScriptObject implements ScriptObject {
public Object[] getIds() {
return EMPTY_ARRAY;
}
public Object get(String name) {
return UNDEFINED;
}
public Object get(int index) {
return UNDEFINED;
}
public void put(String name, Object value) {
}
public void put(int index, Object value) {
}
public boolean has(String name) {
return false;
}
public boolean has(int index) {
return false;
}
public boolean delete(String name) {
return false;
}
public boolean delete(int index) {
return false;
}
}

@ -1,58 +0,0 @@
/*
* Copyright (c) 2007, 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 sun.jvm.hotspot.utilities.soql;
import javax.script.Invocable;
import javax.script.ScriptException;
/**
* This Callable implementation invokes a script
* function of given name when called. If the target
* object is non-null, script "method" is invoked, else
* a "global" script function is invoked.
*/
public class InvocableCallable implements Callable {
private Object target;
private String name;
private Invocable invocable;
public InvocableCallable(Object target, String name,
Invocable invocable) {
this.target = target;
this.name = name;
this.invocable = invocable;
}
public Object call(Object[] args) throws ScriptException {
try {
if (target == null) {
return invocable.invokeFunction(name, args);
} else {
return invocable.invokeMethod(target, name, args);
}
} catch (NoSuchMethodException nme) {
throw new ScriptException(nme);
}
}
}

@ -1,105 +0,0 @@
/*
* Copyright (c) 2003, 2020, 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 sun.jvm.hotspot.utilities.soql;
import sun.jvm.hotspot.oops.*;
/**
This is JavaScript wrapper for Java Array.
*/
public abstract class JSJavaArray extends JSJavaObject {
public JSJavaArray(Array array, JSJavaFactory fac) {
super(array, fac);
type = (JSJavaArrayKlass) fac.newJSJavaKlass(array.getKlass());
}
public final Array getArray() {
return (Array) getOop();
}
public final JSJavaClass getJSJavaClass() {
return type.getJSJavaClass();
}
public Object get(String name) {
if (name.equals("length")) {
return (int) getArray().getLength();
} else {
return super.get(name);
}
}
public Object get(int index) {
return (isInRange(index)) ? type.getFieldValue(index, getArray())
: super.get(index);
}
public Object[] getIds() {
Object[] superFields = super.getIds();
final int len = (int) getArray().getLength();
Object[] res = new Object[superFields.length + len];
for (int i = 0; i < len; i++) {
res[i] = i;
}
System.arraycopy(superFields, 0, res, len, superFields.length);
return res;
}
public boolean has(String name) {
if (name.equals("length")) {
return true;
} else {
return super.has(name);
}
}
public boolean has(int index) {
if (isInRange(index)) {
return true;
} else {
return super.has(index);
}
}
public void put(String name, Object value) {
if (! name.equals("length")) {
super.put(name, value);
}
}
public void put(int index, Object value) {
if (! isInRange(index)) {
super.put(index, value);
}
}
//-- Internals only below this point
private boolean isInRange(int index) {
return index >= 0 && index < getArray().getLength();
}
private JSJavaArrayKlass type;
}

@ -1,72 +0,0 @@
/*
* Copyright (c) 2003, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
/**
This is JavaScript wrapper for Java ArrayKlass.
*/
public abstract class JSJavaArrayKlass extends JSJavaKlass {
public JSJavaArrayKlass(ArrayKlass kls, JSJavaFactory fac) {
super(kls, fac);
}
public final ArrayKlass getArrayKlass() {
return (ArrayKlass) getKlass();
}
public Object getMetaClassFieldValue(String name) {
if (name.equals("dimension")) {
return getArrayKlass().getDimension();
} else {
return super.getMetaClassFieldValue(name);
}
}
public boolean hasMetaClassField(String name) {
if (name.equals("dimension")) {
return true;
} else {
return super.hasMetaClassField(name);
}
}
public boolean isArray() {
return true;
}
public String[] getMetaClassFieldNames() {
String[] superFields = super.getMetaClassFieldNames();
String[] res = new String[superFields.length + 1];
System.arraycopy(superFields, 0, res, 0, superFields.length);
res[superFields.length] = "dimension";
return res;
}
public abstract Object getFieldValue(int index, Array array);
}

@ -1,64 +0,0 @@
/*
* Copyright (c) 2004, 2007, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.utilities.*;
public class JSJavaClass extends JSJavaInstance {
public JSJavaClass(Instance instance, JSJavaKlass jk, JSJavaFactory fac) {
super(instance, fac);
this.jklass = jk;
}
public JSJavaKlass getJSJavaKlass() {
return jklass;
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Class (address=");
buf.append(getOop().getHandle());
buf.append(", name=");
buf.append(jklass.getName());
buf.append(')');
return buf.toString();
}
protected Object getFieldValue(String name) {
return jklass.getMetaClassFieldValue(name);
}
protected String[] getFieldNames() {
return jklass.getMetaClassFieldNames();
}
protected boolean hasField(String name) {
return jklass.hasMetaClassField(name);
}
private JSJavaKlass jklass;
}

@ -1,44 +0,0 @@
/*
* Copyright (c) 2003, 2012, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
public interface JSJavaFactory {
public JSJavaObject newJSJavaObject(Oop oop);
public JSJavaKlass newJSJavaKlass(Klass klass);
public JSJavaField newJSJavaField(Field f);
public JSJavaThread newJSJavaThread(JavaThread jt);
public JSJavaFrame newJSJavaFrame(JavaVFrame vf);
public JSJavaMethod newJSJavaMethod(Method m);
public JSList newJSList(List l);
public JSMap newJSMap(Map m);
public JSJavaHeap newJSJavaHeap();
public JSJavaVM newJSJavaVM();
// checks for one of the above special cases
public Object newJSJavaWrapper(Object o);
}

@ -1,197 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.lang.ref.*;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
public class JSJavaFactoryImpl implements JSJavaFactory {
public JSJavaObject newJSJavaObject(Oop oop) {
if (oop == null) return null;
SoftReference sref = (SoftReference) om.get(oop);
JSJavaObject res = (sref != null)? (JSJavaObject) sref.get() : null;
if (res == null) {
if (oop instanceof TypeArray) {
res = new JSJavaTypeArray((TypeArray)oop, this);
} else if (oop instanceof ObjArray) {
res = new JSJavaObjArray((ObjArray)oop, this);
} else if (oop instanceof Instance) {
res = newJavaInstance((Instance) oop);
}
}
if (res != null) {
om.put(oop, new SoftReference<>(res));
}
return res;
}
public JSJavaKlass newJSJavaKlass(Klass klass) {
JSJavaKlass res = null;
if (klass instanceof InstanceKlass) {
res = new JSJavaInstanceKlass((InstanceKlass) klass, this);
} else if (klass instanceof ObjArrayKlass) {
res = new JSJavaObjArrayKlass((ObjArrayKlass) klass, this);
} else if (klass instanceof TypeArrayKlass) {
res = new JSJavaTypeArrayKlass((TypeArrayKlass) klass, this);
}
if (res != null) {
om.put(klass, new SoftReference<>(res));
}
return res;
}
public JSJavaMethod newJSJavaMethod(Method method) {
JSJavaMethod res = new JSJavaMethod(method, this);
if (res != null) {
om.put(method, new SoftReference<>(res));
}
return res;
}
public JSJavaField newJSJavaField(Field field) {
if (field == null) return null;
return new JSJavaField(field, this);
}
public JSJavaThread newJSJavaThread(JavaThread jthread) {
if (jthread == null) return null;
return new JSJavaThread(jthread, this);
}
public JSJavaFrame newJSJavaFrame(JavaVFrame jvf) {
if (jvf == null) return null;
return new JSJavaFrame(jvf, this);
}
public JSList newJSList(List list) {
if (list == null) return null;
return new JSList(list, this);
}
public JSMap newJSMap(Map map) {
if (map == null) return null;
return new JSMap(map, this);
}
public Object newJSJavaWrapper(Object item) {
if (item == null) return null;
if (item instanceof Oop) {
return newJSJavaObject((Oop) item);
} else if (item instanceof Field) {
return newJSJavaField((Field) item);
} else if (item instanceof JavaThread) {
return newJSJavaThread((JavaThread) item);
} else if (item instanceof JavaVFrame) {
return newJSJavaFrame((JavaVFrame) item);
} else if (item instanceof List) {
return newJSList((List) item);
} else if (item instanceof Map) {
return newJSMap((Map) item);
} else {
// not-a-special-type, just return the input item
return item;
}
}
public JSJavaHeap newJSJavaHeap() {
return new JSJavaHeap(this);
}
public JSJavaVM newJSJavaVM() {
return new JSJavaVM(this);
}
// -- Internals only below this point
private String javaLangString() {
if (javaLangString == null) {
javaLangString = "java/lang/String";
}
return javaLangString;
}
private String javaLangThread() {
if (javaLangThread == null) {
javaLangThread = "java/lang/Thread";
}
return javaLangThread;
}
private String javaLangClass() {
if (javaLangClass == null) {
javaLangClass = "java/lang/Class";
}
return javaLangClass;
}
private JSJavaObject newJavaInstance(Instance instance) {
// look for well-known classes
Symbol className = instance.getKlass().getName();
if (Assert.ASSERTS_ENABLED) {
Assert.that(className != null, "Null class name");
}
JSJavaObject res = null;
if (className.equals(javaLangString())) {
res = new JSJavaString(instance, this);
} else if (className.equals(javaLangThread())) {
res = new JSJavaThread(instance, this);
} else if (className.equals(javaLangClass())) {
Klass reflectedType = java_lang_Class.asKlass(instance);
if (reflectedType != null) {
JSJavaKlass jk = newJSJavaKlass(reflectedType);
// we don't support mirrors of VM internal Klasses
if (jk == null) return null;
res = new JSJavaClass(instance, jk, this);
} else {
// for primitive Classes, the reflected type is null
return null;
}
} else {
// not a well-known class. But the base class may be
// one of the known classes.
Klass kls = instance.getKlass().getSuper();
while (kls != null) {
className = kls.getName();
// java.lang.Class and java.lang.String are final classes
if (className.equals(javaLangThread())) {
res = new JSJavaThread(instance, this);
break;
}
kls = kls.getSuper();
}
}
if (res == null) {
res = new JSJavaInstance(instance, this);
}
return res;
}
private Map<Object, SoftReference<?>> om = new HashMap<>();
private String javaLangString;
private String javaLangThread;
private String javaLangClass;
}

@ -1,161 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
public class JSJavaField extends DefaultScriptObject {
private static final int FIELD_NAME = 0;
private static final int FIELD_SIGNATURE = 1;
private static final int FIELD_HOLDER = 2;
private static final int FIELD_IS_PRIVATE = 3;
private static final int FIELD_IS_PUBLIC = 4;
private static final int FIELD_IS_PROTECTED = 5;
private static final int FIELD_IS_PACKAGE_PRIVATE = 6;
private static final int FIELD_IS_STATIC = 7;
private static final int FIELD_IS_FINAL = 8;
private static final int FIELD_IS_VOLATILE = 9;
private static final int FIELD_IS_TRANSIENT = 10;
private static final int FIELD_IS_SYNTHETIC = 11;
private static final int FIELD_UNDEFINED = -1;
public JSJavaField(Field f, JSJavaFactory fac) {
this.field = f;
this.factory = fac;
}
public Object get(String name) {
int fieldID = getFieldID(name);
switch (fieldID) {
case FIELD_NAME:
return field.getID().getName();
case FIELD_SIGNATURE:
return field.getSignature().asString();
case FIELD_HOLDER:
return getFieldHolder();
case FIELD_IS_PRIVATE:
return Boolean.valueOf(field.isPrivate());
case FIELD_IS_PUBLIC:
return Boolean.valueOf(field.isPublic());
case FIELD_IS_PROTECTED:
return Boolean.valueOf(field.isProtected());
case FIELD_IS_PACKAGE_PRIVATE:
return Boolean.valueOf(field.isPackagePrivate());
case FIELD_IS_STATIC:
return Boolean.valueOf(field.isStatic());
case FIELD_IS_FINAL:
return Boolean.valueOf(field.isFinal());
case FIELD_IS_VOLATILE:
return Boolean.valueOf(field.isVolatile());
case FIELD_IS_TRANSIENT:
return Boolean.valueOf(field.isTransient());
case FIELD_IS_SYNTHETIC:
return Boolean.valueOf(field.isSynthetic());
case FIELD_UNDEFINED:
default:
return super.get(name);
}
}
public Object[] getIds() {
Object[] fieldNames = fields.keySet().toArray();
Object[] superFields = super.getIds();
Object[] res = new Object[fieldNames.length + superFields.length];
System.arraycopy(fieldNames, 0, res, 0, fieldNames.length);
System.arraycopy(superFields, 0, res, fieldNames.length, superFields.length);
return res;
}
public boolean has(String name) {
if (getFieldID(name) != FIELD_UNDEFINED) {
return true;
} else {
return super.has(name);
}
}
public void put(String name, Object value) {
if (getFieldID(name) == FIELD_UNDEFINED) {
super.put(name, value);
}
}
public boolean equals(Object o) {
if (o == null || !(o instanceof JSJavaField)) {
return false;
}
JSJavaField other = (JSJavaField) o;
return field.equals(other.field);
}
public int hashCode() {
return field.hashCode();
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Field ");
buf.append(field.getFieldHolder().getName().asString().replace('/', '.'));
buf.append('.');
buf.append(field.getID().getName());
return buf.toString();
}
//-- Internals only below this point
private JSJavaObject getFieldHolder() {
return factory.newJSJavaKlass(field.getFieldHolder()).getJSJavaClass();
}
private static Map<String, Integer> fields = new HashMap<>();
private static void addField(String name, int fieldId) {
fields.put(name, fieldId);
}
private static int getFieldID(String name) {
Integer res = (Integer) fields.get(name);
return (res != null)? res.intValue() : FIELD_UNDEFINED;
}
static {
addField("name", FIELD_NAME);
addField("signature", FIELD_SIGNATURE);
addField("holder", FIELD_HOLDER);
addField("isPrivate", FIELD_IS_PRIVATE);
addField("isPublic", FIELD_IS_PUBLIC);
addField("isProtected", FIELD_IS_PROTECTED);
addField("isPackagePrivate", FIELD_IS_PACKAGE_PRIVATE);
addField("isStatic", FIELD_IS_STATIC);
addField("isFinal", FIELD_IS_FINAL);
addField("isVolatile", FIELD_IS_VOLATILE);
addField("isTransient", FIELD_IS_TRANSIENT);
addField("isSynthetic", FIELD_IS_SYNTHETIC);
}
private final Field field;
private final JSJavaFactory factory;
}

@ -1,225 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
public class JSJavaFrame extends DefaultScriptObject {
private static final int FIELD_METHOD = 0;
private static final int FIELD_BCI = 1;
private static final int FIELD_LINE_NUMBER = 2;
private static final int FIELD_LOCALS = 3;
private static final int FIELD_THIS_OBJECT = 4;
private static final int FIELD_THREAD = 5;
private static final int FIELD_UNDEFINED = -1;
public JSJavaFrame(JavaVFrame jvf, JSJavaFactory fac) {
this.jvf = jvf;
this.factory = fac;
}
public Object get(String name) {
int fieldID = getFieldID(name);
switch (fieldID) {
case FIELD_METHOD:
return getMethod();
case FIELD_BCI:
return getBCI();
case FIELD_LINE_NUMBER:
return getLineNumber();
case FIELD_LOCALS:
return getLocals();
case FIELD_THIS_OBJECT:
return getThisObject();
case FIELD_THREAD:
return getThread();
case FIELD_UNDEFINED:
default:
return super.get(name);
}
}
public Object[] getIds() {
Object[] fieldNames = fields.keySet().toArray();
Object[] superFields = super.getIds();
Object[] res = new Object[fieldNames.length + superFields.length];
System.arraycopy(fieldNames, 0, res, 0, fieldNames.length);
System.arraycopy(superFields, 0, res, fieldNames.length, superFields.length);
return res;
}
public boolean has(String name) {
if (getFieldID(name) != FIELD_UNDEFINED) {
return true;
} else {
return super.has(name);
}
}
public void put(String name, Object value) {
if (getFieldID(name) == FIELD_UNDEFINED) {
super.put(name, value);
}
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Frame (method=");
buf.append(jvf.getMethod().externalNameAndSignature());
buf.append(", bci=");
buf.append(getBCI());
buf.append(", line=");
buf.append(getLineNumber());
buf.append(')');
return buf.toString();
}
//-- Internals only below this point
private static Map<String, Integer> fields = new HashMap<>();
private static void addField(String name, int fieldId) {
fields.put(name, fieldId);
}
private static int getFieldID(String name) {
Integer res = (Integer) fields.get(name);
return (res != null)? res.intValue() : FIELD_UNDEFINED;
}
static {
addField("method", FIELD_METHOD);
addField("bci", FIELD_BCI);
addField("line", FIELD_LINE_NUMBER);
addField("locals", FIELD_LOCALS);
addField("thisObject", FIELD_THIS_OBJECT);
addField("thread", FIELD_THREAD);
}
private JSJavaMethod getMethod() {
return factory.newJSJavaMethod(jvf.getMethod());
}
private int getBCI() {
return jvf.getBCI();
}
private int getLineNumber() {
int bci = jvf.getBCI();
if (bci == -1) {
return 0;
} else {
int lineNum = jvf.getMethod().getLineNumberFromBCI(bci);
return (lineNum <= 0)? 0 : lineNum;
}
}
private synchronized JSMap getLocals() {
if (localsCache == null) {
Map<String, Object> map = new HashMap<>();
localsCache = factory.newJSMap(map);
StackValueCollection values = jvf.getLocals();
Method method = jvf.getMethod();
if (method.isNative() || ! method.hasLocalVariableTable() ||
values == null) {
return localsCache;
}
LocalVariableTableElement[] localVars = method.getLocalVariableTable();
int bci = getBCI();
List<LocalVariableTableElement> visibleVars = new ArrayList<>(0);
for (int i = 0; i < localVars.length; i++) {
LocalVariableTableElement cur = localVars[i];
int startBCI = cur.getStartBCI();
if (startBCI <= bci && bci < startBCI + cur.getLength()) {
visibleVars.add(cur);
}
}
OopHandle handle = null;
ObjectHeap heap = VM.getVM().getObjectHeap();
for (Iterator varItr = visibleVars.iterator(); varItr.hasNext();) {
LocalVariableTableElement cur = (LocalVariableTableElement) varItr.next();
String name = method.getConstants().getSymbolAt(cur.getNameCPIndex()).asString();
int slot = cur.getSlot();
String signature = method.getConstants().getSymbolAt(cur.getDescriptorCPIndex()).asString();
BasicType variableType = BasicType.charToBasicType(signature.charAt(0));
Object value = null;
if (variableType == BasicType.T_BOOLEAN) {
value = values.booleanAt(slot);
} else if (variableType == BasicType.T_CHAR) {
value = values.charAt(slot);
} else if (variableType == BasicType.T_FLOAT) {
value = values.floatAt(slot);
} else if (variableType == BasicType.T_DOUBLE) {
value = values.doubleAt(slot);
} else if (variableType == BasicType.T_BYTE) {
value = values.byteAt(slot);
} else if (variableType == BasicType.T_SHORT) {
value = values.shortAt(slot);
} else if (variableType == BasicType.T_INT) {
value = values.intAt(slot);
} else if (variableType == BasicType.T_LONG) {
value = values.longAt(slot);
} else if (variableType == BasicType.T_OBJECT ||
variableType == BasicType.T_ARRAY) {
handle = values.oopHandleAt(slot);
value = factory.newJSJavaObject(heap.newOop(handle));
} else {
// ignore
}
map.put(name, value);
}
}
return localsCache;
}
private JSJavaObject getThisObject() {
Method method = jvf.getMethod();
if (method.isStatic()) {
return null;
}
StackValueCollection values = jvf.getLocals();
if (values != null) {
// 'this' at index 0.
OopHandle handle = values.oopHandleAt(0);
ObjectHeap heap = VM.getVM().getObjectHeap();
return factory.newJSJavaObject(heap.newOop(handle));
} else {
// can't get locals, return null.
return null;
}
}
private JSJavaThread getThread() {
return factory.newJSJavaThread(jvf.getThread());
}
private final JavaVFrame jvf;
private final JSJavaFactory factory;
private JSMap localsCache;
}

@ -1,265 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import javax.script.ScriptException;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.classfile.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
import java.lang.reflect.Method;
public class JSJavaHeap extends DefaultScriptObject {
private static final int FIELD_CAPACITY = 0;
private static final int FIELD_USED = 1;
private static final int FIELD_FOR_EACH_OBJECT = 2;
private static final int FIELD_FOR_EACH_CLASS = 3;
private static final int FIELD_UNDEFINED = -1;
public JSJavaHeap(JSJavaFactory fac) {
this.factory = fac;
}
public Object get(String name) {
int fieldID = getFieldID(name);
switch (fieldID) {
case FIELD_CAPACITY:
return getCapacity();
case FIELD_USED:
return getUsed();
case FIELD_FOR_EACH_OBJECT:
return new MethodCallable(this, forEachObjectMethod);
case FIELD_FOR_EACH_CLASS:
return new MethodCallable(this, forEachClassMethod);
case FIELD_UNDEFINED:
default:
return super.get(name);
}
}
public Object[] getIds() {
Object[] superIds = super.getIds();
Object[] tmp = fields.keySet().toArray();
Object[] res = new Object[superIds.length + tmp.length];
System.arraycopy(tmp, 0, res, 0, tmp.length);
System.arraycopy(superIds, 0, res, tmp.length, superIds.length);
return res;
}
public boolean has(String name) {
if (getFieldID(name) != FIELD_UNDEFINED) {
return true;
} else {
return super.has(name);
}
}
public void put(String name, Object value) {
if (getFieldID(name) == FIELD_UNDEFINED) {
super.put(name, value);
}
}
public void forEachObject(Object[] args) {
boolean subtypes = true;
Klass kls = null;
Callable func = null;
switch (args.length) {
case 3: {
Object b = args[2];
if (b != null && b instanceof Boolean) {
subtypes = ((Boolean)b).booleanValue();
}
}
case 2: {
Object k = args[1];
if (k == null) return;
if (k instanceof JSJavaKlass) {
kls = ((JSJavaKlass)k).getKlass();
} else if (k instanceof String) {
kls = SystemDictionaryHelper.findInstanceKlass((String)k);
if (kls == null) return;
}
}
case 1: {
Object f = args[0];
if (f != null && f instanceof Callable) {
func = (Callable) f;
} else {
// unknown target - just return
return ;
}
}
break;
default:
return;
}
final Callable finalFunc = func;
HeapVisitor visitor = new DefaultHeapVisitor() {
public boolean doObj(Oop oop) {
JSJavaObject jo = factory.newJSJavaObject(oop);
if (jo != null) {
try {
finalFunc.call(new Object[] { jo });
} catch (ScriptException exp) {
throw new RuntimeException(exp);
}
}
return false;
}
};
ObjectHeap heap = VM.getVM().getObjectHeap();
if (kls == null) {
kls = SystemDictionaryHelper.findInstanceKlass("java.lang.Object");
}
heap.iterateObjectsOfKlass(visitor, kls, subtypes);
}
public void forEachClass(Object[] args) {
boolean withLoader = false;
Callable func = null;
switch (args.length) {
case 2: {
Object b = args[1];
if (b instanceof Boolean) {
withLoader = ((Boolean)b).booleanValue();
}
}
case 1: {
Object f = args[0];
if (f instanceof Callable) {
func = (Callable) f;
} else {
return;
}
}
break;
default:
return;
}
final Callable finalFunc = func;
ClassLoaderDataGraph cldg = VM.getVM().getClassLoaderDataGraph();
if (withLoader) {
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass kls) {
JSJavaKlass jk = factory.newJSJavaKlass(kls);
Oop loader = kls.getClassLoader();
if (jk == null) {
return;
}
JSJavaObject k = jk.getJSJavaClass();
JSJavaObject l = factory.newJSJavaObject(loader);
if (k != null) {
if (l != null) {
try {
finalFunc.call(new Object[] { k, l });
} catch (ScriptException exp) {
throw new RuntimeException(exp);
}
}
}
}
});
} else {
cldg.classesDo(new ClassLoaderDataGraph.ClassVisitor() {
public void visit(Klass kls) {
JSJavaKlass jk = factory.newJSJavaKlass(kls);
if (jk == null) {
return;
}
JSJavaClass k = jk.getJSJavaClass();
if (k != null) {
if (k != null) {
try {
finalFunc.call(new Object[] { k });
} catch (ScriptException exp) {
throw new RuntimeException(exp);
}
}
}
}
});
}
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Java Heap (capacity=");
buf.append(getCapacity());
buf.append(", used=");
buf.append(getUsed());
buf.append(")");
return buf.toString();
}
//-- Internals only below this point
private static Map<String, Integer> fields = new HashMap<>();
private static void addField(String name, int fieldId) {
fields.put(name, fieldId);
}
private static int getFieldID(String name) {
Integer res = (Integer) fields.get(name);
return (res != null)? res.intValue() : FIELD_UNDEFINED;
}
static {
addField("capacity", FIELD_CAPACITY);
addField("used", FIELD_USED);
addField("forEachObject", FIELD_FOR_EACH_OBJECT);
addField("forEachClass", FIELD_FOR_EACH_CLASS);
try {
Class<?> myClass = JSJavaHeap.class;
forEachObjectMethod = myClass.getMethod("forEachObject",
new Class[] { Object[].class });
forEachClassMethod = myClass.getMethod("forEachClass",
new Class[] {Object[].class });
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
private long getCapacity() {
return VM.getVM().getUniverse().heap().capacity();
}
private long getUsed() {
return VM.getVM().getUniverse().heap().used();
}
private final JSJavaFactory factory;
private static Method forEachObjectMethod;
private static Method forEachClassMethod;
}

@ -1,93 +0,0 @@
/*
* Copyright (c) 2003, 2007, 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 sun.jvm.hotspot.utilities.soql;
import sun.jvm.hotspot.oops.*;
/** This is JavaScript wrapper for Java Instance in debuggee.*/
public class JSJavaInstance extends JSJavaObject {
public JSJavaInstance(Instance instance, JSJavaFactory fac) {
super(instance, fac);
this.type = (JSJavaInstanceKlass) fac.newJSJavaKlass(instance.getKlass());
}
public final Instance getInstance() {
return (Instance) getOop();
}
public final JSJavaClass getJSJavaClass() {
return type.getJSJavaClass();
}
public Object get(String name) {
if (hasField(name)) {
return getFieldValue(name);
} else {
return super.get(name);
}
}
public Object[] getIds() {
String[] fieldNames = getFieldNames();
Object[] superFields = super.getIds();
Object[] res = new Object[fieldNames.length + superFields.length];
System.arraycopy(fieldNames, 0, res, 0, fieldNames.length);
System.arraycopy(superFields, 0, res, fieldNames.length, superFields.length);
return res;
}
public boolean has(String name) {
if (hasField(name)) {
return true;
} else {
return super.has(name);
}
}
public void put(String name, Object value) {
if (! hasField(name)) {
super.put(name, value);
}
}
protected Object getFieldValue(String name) {
try {
return type.getInstanceFieldValue(name, getInstance());
} catch (NoSuchFieldException exp) {
return UNDEFINED;
}
}
protected String[] getFieldNames() {
return type.getInstanceFieldNames();
}
protected boolean hasField(String name) {
return type.hasInstanceField(name);
}
protected final JSJavaInstanceKlass type;
}

@ -1,381 +0,0 @@
/*
* Copyright (c) 2003, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.utilities.*;
/**
This is JavaScript wrapper for InstanceKlass.
*/
public class JSJavaInstanceKlass extends JSJavaKlass {
private static final int FIELD_SOURCE_FILE = 1;
private static final int FIELD_INTERFACES = 2;
private static final int FIELD_FIELDS = 3;
private static final int FIELD_METHODS = 4;
private static final int FIELD_IS_PRIVATE = 5;
private static final int FIELD_IS_PUBLIC = 6;
private static final int FIELD_IS_PROTECTED = 7;
private static final int FIELD_IS_PACKAGE_PRIVATE = 8;
private static final int FIELD_IS_STATIC = 9;
private static final int FIELD_IS_FINAL = 10;
private static final int FIELD_IS_ABSTRACT = 11;
private static final int FIELD_IS_STRICT = 12;
private static final int FIELD_IS_SYNTHETIC = 13;
private static final int FIELD_IS_INTERFACE = 14;
private static final int FIELD_CLASS_LOADER = 15;
private static final int FIELD_STATICS = 18;
private static final int FIELD_UNDEFINED = -1;
public JSJavaInstanceKlass(InstanceKlass kls, JSJavaFactory fac) {
super(kls, fac);
this.instanceFields = new HashMap<>();
this.staticFields = new HashMap<>();
}
public final InstanceKlass getInstanceKlass() {
return (InstanceKlass) getKlass();
}
public Object getMetaClassFieldValue(String name) {
int fieldID = getFieldID(name);
InstanceKlass ik = getInstanceKlass();
switch (fieldID) {
case FIELD_SOURCE_FILE: {
Symbol sourceFile = ik.getSourceFileName();
return (sourceFile != null)? sourceFile.asString() : "<unknown>";
}
case FIELD_INTERFACES:
return getInterfaces();
case FIELD_FIELDS:
return factory.newJSList(ik.getImmediateFields());
case FIELD_METHODS:
return factory.newJSList(ik.getImmediateMethods());
case FIELD_IS_PRIVATE:
return Boolean.valueOf(getAccessFlags().isPrivate());
case FIELD_IS_PUBLIC:
return Boolean.valueOf(getAccessFlags().isPublic());
case FIELD_IS_PROTECTED:
return Boolean.valueOf(getAccessFlags().isProtected());
case FIELD_IS_PACKAGE_PRIVATE: {
AccessFlags acc = getAccessFlags();
return Boolean.valueOf(!acc.isPrivate() && !acc.isPublic() && !acc.isProtected());
}
case FIELD_IS_STATIC:
return Boolean.valueOf(getAccessFlags().isStatic());
case FIELD_IS_FINAL:
return Boolean.valueOf(getAccessFlags().isFinal());
case FIELD_IS_ABSTRACT:
return Boolean.valueOf(getAccessFlags().isAbstract());
case FIELD_IS_STRICT:
return Boolean.valueOf(getAccessFlags().isStrict());
case FIELD_IS_SYNTHETIC:
return Boolean.valueOf(getAccessFlags().isSynthetic());
case FIELD_IS_INTERFACE:
return Boolean.valueOf(ik.isInterface());
case FIELD_CLASS_LOADER:
return factory.newJSJavaObject(ik.getClassLoader());
case FIELD_STATICS:
return getStatics();
case FIELD_UNDEFINED:
default:
return super.getMetaClassFieldValue(name);
}
}
public boolean hasMetaClassField(String name) {
if (getFieldID(name) != FIELD_UNDEFINED) {
return true;
} else {
return super.hasMetaClassField(name);
}
}
public String getName() {
return getInstanceKlass().getName().asString().replace('/', '.');
}
public boolean isArray() {
return false;
}
public String[] getMetaClassFieldNames() {
String[] superFields = super.getMetaClassFieldNames();
Set k = fields.keySet();
String[] res = new String[k.size() + superFields.length];
System.arraycopy(superFields, 0, res, 0, superFields.length);
int i = superFields.length;
for (Iterator itr = k.iterator(); itr.hasNext();) {
res[i] = (String) itr.next();
i++;
}
return res;
}
public Object getInstanceFieldValue(String name, Instance instance) throws NoSuchFieldException {
Field fld = findInstanceField(name);
if (fld != null) {
return getFieldValue(fld, name, instance);
} else {
throw new NoSuchFieldException(name + " is not field of "
+ getInstanceKlass().getName().asString().replace('/', '.'));
}
}
public Object getStaticFieldValue(String name) throws NoSuchFieldException {
Field fld = findStaticField(name);
if (fld != null) {
return getFieldValue(fld, name, getInstanceKlass());
} else {
throw new NoSuchFieldException(name + " is not field of "
+ getInstanceKlass().getName().asString().replace('/', '.'));
}
}
public String[] getInstanceFieldNames() {
if (instanceFieldNames == null) {
InstanceKlass current = getInstanceKlass();
while (current != null) {
List<Field> tmp = current.getImmediateFields();
for (Iterator<Field> itr = tmp.iterator(); itr.hasNext();) {
Field fld = itr.next();
if (!fld.isStatic()) {
String name = fld.getID().getName();
if (instanceFields.get(name) == null) {
instanceFields.put(name, fld);
}
}
}
current = (InstanceKlass) current.getSuper();
}
Set s = instanceFields.keySet();
instanceFieldNames = new String[s.size()];
int i = 0;
for (Iterator itr = s.iterator(); itr.hasNext(); i++) {
instanceFieldNames[i] = (String) itr.next();
}
}
return instanceFieldNames;
}
public boolean hasInstanceField(String name) {
Field fld = findInstanceField(name);
return (fld != null)? true: false;
}
public String[] getStaticFieldNames() {
if (staticFieldNames == null) {
InstanceKlass current = getInstanceKlass();
List<Field> tmp = current.getImmediateFields();
for (Iterator<Field> itr = tmp.iterator(); itr.hasNext();) {
Field fld = itr.next();
if (fld.isStatic()) {
staticFields.put(fld.getID().getName(), fld);
}
}
Set s = staticFields.keySet();
staticFieldNames = new String[s.size()];
int i = 0;
for (Iterator itr = s.iterator(); itr.hasNext(); i++) {
staticFieldNames[i] = (String) itr.next();
}
}
return staticFieldNames;
}
public boolean hasStaticField(String name) {
Field fld = findStaticField(name);
return (fld != null)? true: false;
}
//-- Intenals only below this point
private static Map<String, Integer> fields = new HashMap<>();
private static void addField(String name, int fieldId) {
fields.put(name, fieldId);
}
private static int getFieldID(String name) {
Integer res = (Integer) fields.get(name);
return (res != null)? res.intValue() : FIELD_UNDEFINED;
}
static {
addField("sourceFile", FIELD_SOURCE_FILE);
addField("interfaces", FIELD_INTERFACES);
addField("fields", FIELD_FIELDS);
addField("methods", FIELD_METHODS);
addField("isPrivate", FIELD_IS_PRIVATE);
addField("isPublic", FIELD_IS_PUBLIC);
addField("isProtected", FIELD_IS_PROTECTED);
addField("isPackagePrivate", FIELD_IS_PACKAGE_PRIVATE);
addField("isStatic", FIELD_IS_STATIC);
addField("isFinal", FIELD_IS_FINAL);
addField("isAbstract", FIELD_IS_ABSTRACT);
addField("isStrict", FIELD_IS_STRICT);
addField("isSynthetic", FIELD_IS_SYNTHETIC);
addField("isInterface", FIELD_IS_INTERFACE);
addField("classLoader", FIELD_CLASS_LOADER);
addField("statics", FIELD_STATICS);
}
private AccessFlags getAccessFlags() {
if (accFlags == null) {
accFlags = new AccessFlags(getInstanceKlass().computeModifierFlags());
}
return accFlags;
}
private Object getFieldValue(Field fld, String name, Oop oop) {
FieldType fd = fld.getFieldType();
if (fd.isObject() || fd.isArray()) {
return factory.newJSJavaObject(((OopField)fld).getValue(oop));
} else if (fd.isByte()) {
return ((ByteField) fld).getValue(oop);
} else if (fd.isChar()) {
return new String(new char[] { ((CharField)fld).getValue(oop) });
} else if (fd.isDouble()) {
return ((DoubleField) fld).getValue(oop);
} else if (fd.isFloat()) {
return ((FloatField) fld).getValue(oop);
} else if (fd.isInt()) {
return ((IntField) fld).getValue(oop);
} else if (fd.isLong()) {
return ((LongField) fld).getValue(oop);
} else if (fd.isShort()) {
return ((ShortField) fld).getValue(oop);
} else if (fd.isBoolean()) {
return ((BooleanField) fld).getValue(oop);
} else {
if (Assert.ASSERTS_ENABLED) {
Assert.that(false, "invalid field type for " + name);
}
return null;
}
}
private Object getFieldValue(Field fld, String name, InstanceKlass oop) {
FieldType fd = fld.getFieldType();
if (fd.isObject() || fd.isArray()) {
return factory.newJSJavaObject(((OopField)fld).getValue(oop));
} else if (fd.isByte()) {
return ((ByteField) fld).getValue(oop);
} else if (fd.isChar()) {
return new String(new char[] { ((CharField)fld).getValue(oop) });
} else if (fd.isDouble()) {
return ((DoubleField) fld).getValue(oop);
} else if (fd.isFloat()) {
return ((FloatField) fld).getValue(oop);
} else if (fd.isInt()) {
return ((IntField) fld).getValue(oop);
} else if (fd.isLong()) {
return ((LongField) fld).getValue(oop);
} else if (fd.isShort()) {
return ((ShortField) fld).getValue(oop);
} else if (fd.isBoolean()) {
return ((BooleanField) fld).getValue(oop);
} else {
if (Assert.ASSERTS_ENABLED) {
Assert.that(false, "invalid field type for " + name);
}
return null;
}
}
private Field findInstanceField(String name) {
Field fld = (Field) instanceFields.get(name);
if (fld != null) {
return fld;
} else {
InstanceKlass current = getInstanceKlass();
while (current != null) {
List<Field> tmp = current.getImmediateFields();
for (Iterator<Field> itr = tmp.iterator(); itr.hasNext();) {
fld = itr.next();
if (fld.getID().getName().equals(name) && !fld.isStatic()) {
instanceFields.put(name, fld);
return fld;
}
}
// lookup in super class.
current = (InstanceKlass) current.getSuper();
}
}
// no match
return null;
}
private Field findStaticField(String name) {
Field fld = (Field) staticFields.get(name);
if (fld != null) {
return fld;
} else {
// static fields are searched only in current.
// Direct/indirect super classes and interfaces
// are not included in search.
InstanceKlass current = getInstanceKlass();
List<Field> tmp = current.getImmediateFields();
for (Iterator<Field> itr = tmp.iterator(); itr.hasNext();) {
fld = itr.next();
if (fld.getID().getName().equals(name) && fld.isStatic()) {
staticFields.put(name, fld);
return fld;
}
}
// no match
return null;
}
}
private JSList getInterfaces() {
InstanceKlass ik = getInstanceKlass();
List<Klass> intfs = ik.getDirectImplementedInterfaces();
List<Instance> res = new ArrayList<>(0);
for (Iterator<Klass> itr = intfs.iterator(); itr.hasNext();) {
Klass k = itr.next();
res.add(k.getJavaMirror());
}
return factory.newJSList(res);
}
private JSMap getStatics() {
String[] names = getStaticFieldNames();
Map<String, Object> map = new HashMap<>();
for (int i=0; i < names.length; i++) {
try {
map.put(names[i], getStaticFieldValue(names[i]));
} catch (NoSuchFieldException exp) {}
}
return factory.newJSMap(map);
}
private Map<String, Field> instanceFields;
private Map<String, Field> staticFields;
private String[] instanceFieldNames;
private String[] staticFieldNames;
private AccessFlags accFlags;
}

@ -1,104 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.utilities.*;
/**
This is JavaScript wrapper for Klass.
*/
public abstract class JSJavaKlass {
private static final int FIELD_SUPER_CLASS = 0;
private static final int FIELD_NAME = 1;
private static final int FIELD_IS_ARRAY_CLASS = 2;
private static final int FIELD_UNDEFINED = -1;
public JSJavaKlass(Klass klass, JSJavaFactory factory) {
this.factory = factory;
this.klass = klass;
}
public final Klass getKlass() {
return klass;
}
public JSJavaClass getJSJavaClass() {
return (JSJavaClass) factory.newJSJavaObject(getKlass().getJavaMirror());
}
public Object getMetaClassFieldValue(String name) {
int fieldID = getFieldID(name);
switch (fieldID) {
case FIELD_SUPER_CLASS: {
JSJavaKlass jk = factory.newJSJavaKlass(getKlass().getSuper());
return (jk != null) ? jk.getJSJavaClass() : null;
}
case FIELD_NAME:
return getName();
case FIELD_IS_ARRAY_CLASS:
return Boolean.valueOf(isArray());
case FIELD_UNDEFINED:
default:
return ScriptObject.UNDEFINED;
}
}
public boolean hasMetaClassField(String name) {
return getFieldID(name) != FIELD_UNDEFINED;
}
public String[] getMetaClassFieldNames() {
String[] res = { "name", "superClass", "isArrayClass" };
return res;
}
public abstract String getName();
public abstract boolean isArray();
//-- Internals only below this point
private static Map<String, Integer> fields = new HashMap<>();
private static void addField(String name, int fieldId) {
fields.put(name, fieldId);
}
private static int getFieldID(String name) {
Integer res = (Integer) fields.get(name);
return (res != null)? res.intValue() : FIELD_UNDEFINED;
}
static {
addField("base", FIELD_SUPER_CLASS);
addField("baseClass", FIELD_SUPER_CLASS);
addField("superClass", FIELD_SUPER_CLASS);
addField("name", FIELD_NAME);
addField("isArrayClass", FIELD_IS_ARRAY_CLASS);
}
protected final JSJavaFactory factory;
private final Klass klass;
}

@ -1,165 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
/**
* Wraps a Method* from the debuggee VM.
*/
public class JSJavaMethod extends JSMetadata {
private static final int FIELD_NAME = 0;
private static final int FIELD_SIGNATURE = 1;
private static final int FIELD_HOLDER = 2;
private static final int FIELD_IS_PRIVATE = 3;
private static final int FIELD_IS_PUBLIC = 4;
private static final int FIELD_IS_PROTECTED = 5;
private static final int FIELD_IS_PACKAGE_PRIVATE = 6;
private static final int FIELD_IS_STATIC = 7;
private static final int FIELD_IS_FINAL = 8;
private static final int FIELD_IS_SYNCHRONIZED = 9;
private static final int FIELD_IS_NATIVE = 10;
private static final int FIELD_IS_ABSTRACT = 11;
private static final int FIELD_IS_STRICT = 12;
private static final int FIELD_IS_SYNTHETIC = 13;
private static final int FIELD_IS_OBSOLETE = 14;
private static final int FIELD_UNDEFINED = -1;
public JSJavaMethod(Method m, JSJavaFactory fac) {
super(m, fac);
}
public final Method getMethod() {
return (Method) getMetadata();
}
public Object get(String name) {
int fieldID = getFieldID(name);
Method method = getMethod();
switch (fieldID) {
case FIELD_NAME:
return method.getName().asString();
case FIELD_SIGNATURE:
return method.getSignature().asString();
case FIELD_HOLDER:
return getMethodHolder();
case FIELD_IS_PRIVATE:
return Boolean.valueOf(method.isPrivate());
case FIELD_IS_PUBLIC:
return Boolean.valueOf(method.isPublic());
case FIELD_IS_PROTECTED:
return Boolean.valueOf(method.isProtected());
case FIELD_IS_PACKAGE_PRIVATE:
return Boolean.valueOf(method.isPackagePrivate());
case FIELD_IS_STATIC:
return Boolean.valueOf(method.isStatic());
case FIELD_IS_FINAL:
return Boolean.valueOf(method.isFinal());
case FIELD_IS_SYNCHRONIZED:
return Boolean.valueOf(method.isSynchronized());
case FIELD_IS_NATIVE:
return Boolean.valueOf(method.isNative());
case FIELD_IS_ABSTRACT:
return Boolean.valueOf(method.isAbstract());
case FIELD_IS_STRICT:
return Boolean.valueOf(method.isStrict());
case FIELD_IS_SYNTHETIC:
return Boolean.valueOf(method.isSynthetic());
case FIELD_IS_OBSOLETE:
return Boolean.valueOf(method.isObsolete());
case FIELD_UNDEFINED:
default:
return super.get(name);
}
}
public Object[] getIds() {
Object[] fieldNames = fields.keySet().toArray();
Object[] superFields = super.getIds();
Object[] res = new Object[fieldNames.length + superFields.length];
System.arraycopy(fieldNames, 0, res, 0, fieldNames.length);
System.arraycopy(superFields, 0, res, fieldNames.length, superFields.length);
return res;
}
public boolean has(String name) {
if (getFieldID(name) != FIELD_UNDEFINED) {
return true;
} else {
return super.has(name);
}
}
public void put(String name, Object value) {
if (getFieldID(name) != FIELD_UNDEFINED) {
return;
} else {
super.put(name, value);
}
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Method ");
buf.append(getMethod().externalNameAndSignature());
return buf.toString();
}
//-- Internals only below this point
private JSJavaObject getMethodHolder() {
Klass k = getMethod().getMethodHolder();
return factory.newJSJavaKlass(k).getJSJavaClass();
}
private static Map<String, Integer> fields = new HashMap<>();
private static void addField(String name, int fieldId) {
fields.put(name, fieldId);
}
private static int getFieldID(String name) {
Integer res = (Integer) fields.get(name);
return (res != null)? res.intValue() : FIELD_UNDEFINED;
}
static {
addField("name", FIELD_NAME);
addField("signature", FIELD_SIGNATURE);
addField("holder", FIELD_HOLDER);
addField("isPrivate", FIELD_IS_PRIVATE);
addField("isPublic", FIELD_IS_PUBLIC);
addField("isProtected", FIELD_IS_PROTECTED);
addField("isPackagePrivate", FIELD_IS_PACKAGE_PRIVATE);
addField("isStatic", FIELD_IS_STATIC);
addField("isFinal", FIELD_IS_FINAL);
addField("isSynchronized", FIELD_IS_SYNCHRONIZED);
addField("isNative", FIELD_IS_NATIVE);
addField("isAbstract", FIELD_IS_ABSTRACT);
addField("isStrict", FIELD_IS_STRICT);
addField("isSynthetic", FIELD_IS_SYNTHETIC);
addField("isObsolete", FIELD_IS_OBSOLETE);
}
}

@ -1,41 +0,0 @@
/*
* Copyright (c) 2004, 2007, 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 sun.jvm.hotspot.utilities.soql;
import sun.jvm.hotspot.oops.ObjArray;
/**
This is JavaScript wrapper for Java Object Array.
*/
public class JSJavaObjArray extends JSJavaArray {
public JSJavaObjArray(ObjArray array, JSJavaFactory fac) {
super(array, fac);
}
public final ObjArray getObjArray() {
return (ObjArray) getArray();
}
}

@ -1,61 +0,0 @@
/*
* Copyright (c) 2003, 2007, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
/**
This is JavaScript wrapper for ObjArrayKlass.
*/
public class JSJavaObjArrayKlass extends JSJavaArrayKlass {
public JSJavaObjArrayKlass(ObjArrayKlass kls, JSJavaFactory fac) {
super(kls, fac);
}
public ObjArrayKlass getObjArrayKlass() {
return (ObjArrayKlass) getArrayKlass();
}
public String getName() {
Klass botKls = getObjArrayKlass().getBottomKlass();
int dimension = (int) getObjArrayKlass().getDimension();
StringBuffer buf = new StringBuffer();
if (botKls instanceof TypeArrayKlass) {
dimension--;
}
buf.append(factory.newJSJavaKlass(botKls).getName());
for (int i = 0; i < dimension; i++) {
buf.append("[]");
}
return buf.toString();
}
public Object getFieldValue(int index, Array array) {
Oop obj = ((ObjArray)array).getObjAt(index);
return factory.newJSJavaObject(obj);
}
}

@ -1,60 +0,0 @@
/*
* Copyright (c) 2003, 2007, 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 sun.jvm.hotspot.utilities.soql;
import sun.jvm.hotspot.oops.Oop;
/** This is JavaScript wrapper for a Java Object in debuggee.*/
public abstract class JSJavaObject extends DefaultScriptObject {
public JSJavaObject(Oop oop, JSJavaFactory factory) {
this.oop = oop;
this.factory = factory;
}
public final Oop getOop() {
return oop;
}
public boolean equals(Object o) {
if (o == null || !(o instanceof JSJavaObject)) {
return false;
}
JSJavaObject other = (JSJavaObject) o;
return oop.equals(other.oop);
}
public int hashCode() {
return oop.hashCode();
}
public String toString() {
return "Object " + oop.getHandle().toString();
}
private final Oop oop;
protected final JSJavaFactory factory;
}

@ -1,653 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.io.*;
import java.util.*;
import javax.script.Invocable;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
import sun.jvm.hotspot.tools.*;
import sun.jvm.hotspot.tools.jcore.*;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* Simple wrapper around jsr-223 JavaScript script engine.
* In addition to wrapping useful functionality of jsr-223 engine,
* this class exposed certain "global" functions to the script.
*/
public abstract class JSJavaScriptEngine extends MapScriptObject {
/**
* Start a read-eval-print loop with this engine.
*/
public void startConsole() {
start(true);
}
/**
* Initialize the engine so that we can "eval" strings
* and files later.
*/
public void start() {
start(false);
}
/**
* Define a global function that invokes given Method.
*/
public void defineFunction(Object target, Method method) {
putFunction(target, method, false);
}
/**
* Call the script function of given name passing the
* given arguments.
*/
public Object call(String name, Object[] args) {
Invocable invocable = (Invocable)engine;
try {
return invocable.invokeFunction(name, args);
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new RuntimeException(exp);
}
}
/**
address function returns address of JSJavaObject as String. For other
type of objects, the result is undefined.
*/
public Object address(Object[] args) {
if (args.length != 1) return UNDEFINED;
Object o = args[0];
if (o != null && o instanceof JSJavaObject) {
return ((JSJavaObject)o).getOop().getHandle().toString();
} else {
return UNDEFINED;
}
}
/**
classof function gets type of given JSJavaInstance or JSJavaArray. Or
given a string class name, this function gets the class object. For
other type of objects, the result is undefined.
*/
public Object classof(Object[] args) {
if (args.length != 1) {
return UNDEFINED;
}
Object o = args[0];
if (o != null) {
if (o instanceof JSJavaObject) {
if (o instanceof JSJavaInstance) {
return ((JSJavaInstance)o).getJSJavaClass();
} else if (o instanceof JSJavaArray) {
return ((JSJavaArray)o).getJSJavaClass();
} else {
return UNDEFINED;
}
} else if (o instanceof String) {
InstanceKlass ik = SystemDictionaryHelper.findInstanceKlass((String) o);
return getJSJavaFactory().newJSJavaKlass(ik).getJSJavaClass();
} else {
return UNDEFINED;
}
} else {
return UNDEFINED;
}
}
/**
* dumpClass function creates a .class file for a given Class object.
* On success, returns true. Else, returns false. Second optional argument
* specifies the directory in which .class content is dumped. This defaults
* to '.'
*/
public Object dumpClass(Object[] args) {
if (args.length == 0) {
return Boolean.FALSE;
}
Object clazz = args[0];
if (clazz == null) {
return Boolean.FALSE;
}
InstanceKlass ik = null;
if (clazz instanceof String) {
String name = (String) clazz;
if (name.startsWith("0x")) {
// treat it as address
VM vm = VM.getVM();
Address addr = vm.getDebugger().parseAddress(name);
Metadata metadata = Metadata.instantiateWrapperFor(addr.addOffsetTo(0));
if (metadata instanceof InstanceKlass) {
ik = (InstanceKlass) metadata;
} else {
return Boolean.FALSE;
}
} else {
ik = SystemDictionaryHelper.findInstanceKlass((String) clazz);
}
} else if (clazz instanceof JSJavaClass) {
JSJavaKlass jk = ((JSJavaClass)clazz).getJSJavaKlass();
if (jk != null && jk instanceof JSJavaInstanceKlass) {
ik = ((JSJavaInstanceKlass)jk).getInstanceKlass();
}
} else {
return Boolean.FALSE;
}
if (ik == null) return Boolean.FALSE;
StringBuffer buf = new StringBuffer();
if (args.length > 1) {
buf.append(args[1].toString());
} else {
buf.append('.');
}
buf.append(File.separatorChar);
buf.append(ik.getName().asString().replace('/', File.separatorChar));
buf.append(".class");
String fileName = buf.toString();
File file = new File(fileName);
try {
int index = fileName.lastIndexOf(File.separatorChar);
File dir = new File(fileName.substring(0, index));
dir.mkdirs();
FileOutputStream fos = new FileOutputStream(file);
ClassWriter cw = new ClassWriter(ik, fos);
cw.write();
fos.close();
} catch (IOException exp) {
printError(exp.toString(), exp);
return Boolean.FALSE;
}
return Boolean.TRUE;
}
/**
* dumpHeap function creates a heap dump file.
* On success, returns true. Else, returns false.
*/
public Object dumpHeap(Object[] args) {
String fileName = "heap.bin";
if (args.length > 0) {
fileName = args[0].toString();
}
return new JMap().writeHeapHprofBin(fileName)? Boolean.TRUE: Boolean.FALSE;
}
/**
help function prints help message for global functions and variables.
*/
public void help(Object[] args) {
println("Function/Variable Description");
println("================= ===========");
println("address(jobject) returns the address of the Java object");
println("classof(jobject) returns the class object of the Java object");
println("dumpClass(jclass,[dir]) writes .class for the given Java Class");
println("dumpHeap([file]) writes heap in hprof binary format");
println("help() prints this help message");
println("identityHash(jobject) returns the hashCode of the Java object");
println("mirror(jobject) returns a local mirror of the Java object");
println("load([file1, file2,...]) loads JavaScript file(s). With no files, reads <stdin>");
println("object(string) converts a string address into Java object");
println("owner(jobject) returns the owner thread of this monitor or null");
println("sizeof(jobject) returns the size of Java object in bytes");
println("staticof(jclass, field) returns a static field of the given Java class");
println("read([prompt]) reads a single line from standard input");
println("quit() quits the interactive load call");
println("jvm the target jvm that is being debugged");
}
/**
identityHash function gets identity hash code value of given
JSJavaObject. For other type of objects, the result is undefined.
*/
public Object identityHash(Object[] args) {
if (args.length != 1) return UNDEFINED;
Object o = args[0];
if (o != null && o instanceof JSJavaObject) {
return ((JSJavaObject) o).getOop().identityHash();
} else {
return UNDEFINED;
}
}
/**
* Load and execute a set of JavaScript source files.
* This method is defined as a JavaScript function.
*/
public void load(Object[] args) {
for (int i = 0; i < args.length; i++) {
processSource(args[i].toString());
}
}
/**
mirror function creats local copy of the Oop wrapper supplied.
if mirror can not be created, return undefined. For other types,
mirror is undefined.
*/
public Object mirror(Object[] args) {
Object o = args[0];
Object res = UNDEFINED;
if (o != null) {
if (o instanceof JSJavaObject) {
Oop oop = ((JSJavaObject)o).getOop();
try {
res = getObjectReader().readObject(oop);
} catch (Exception e) {
if (debug) e.printStackTrace(getErrorStream());
}
} else if (o instanceof JSMetadata) {
Metadata metadata = ((JSMetadata)o).getMetadata();
try {
if (metadata instanceof InstanceKlass) {
res = getObjectReader().readClass((InstanceKlass) metadata);
}
} catch (Exception e) {
if (debug) e.printStackTrace(getErrorStream());
}
}
}
return res;
}
/**
owner function gets owning thread of given JSJavaObjec, if any, else
returns null. For other type of objects, the result is undefined.
*/
public Object owner(Object[] args) {
Object o = args[0];
if (o != null && o instanceof JSJavaObject) {
return getOwningThread((JSJavaObject)o);
} else {
return UNDEFINED;
}
}
/**
object function takes a string address and returns a JSJavaObject.
For other type of objects, the result is undefined.
*/
public Object object(Object[] args) {
Object o = args[0];
if (o != null && o instanceof String) {
VM vm = VM.getVM();
Address addr = vm.getDebugger().parseAddress((String)o);
Oop oop = vm.getObjectHeap().newOop(addr.addOffsetToAsOopHandle(0));
return getJSJavaFactory().newJSJavaObject(oop);
} else {
return UNDEFINED;
}
}
/**
sizeof function returns size of a Java object in bytes. For other type
of objects, the result is undefined.
*/
public Object sizeof(Object[] args) {
if (args.length != 1) return UNDEFINED;
Object o = args[0];
if (o != null && o instanceof JSJavaObject) {
return ((JSJavaObject) o).getOop().getObjectSize();
} else {
return UNDEFINED;
}
}
/**
staticof function gets static field of given class. Both class and
field name are specified as strings. undefined is returned if there is
no such named field.
*/
public Object staticof(Object[] args) {
Object classname = args[0];
Object fieldname = args[1];
if (fieldname == null || classname == null ||
!(fieldname instanceof String)) {
return UNDEFINED;
}
InstanceKlass ik = null;
if (classname instanceof JSJavaClass) {
JSJavaClass jclass = (JSJavaClass) classname;
JSJavaKlass jk = jclass.getJSJavaKlass();
if (jk != null && jk instanceof JSJavaInstanceKlass) {
ik = ((JSJavaInstanceKlass)jk).getInstanceKlass();
}
} else if (classname instanceof String) {
ik = SystemDictionaryHelper.findInstanceKlass((String)classname);
} else {
return UNDEFINED;
}
if (ik == null) {
return UNDEFINED;
}
JSJavaFactory factory = getJSJavaFactory();
try {
return ((JSJavaInstanceKlass) factory.newJSJavaKlass(ik)).getStaticFieldValue((String)fieldname);
} catch (NoSuchFieldException e) {
return UNDEFINED;
}
}
/**
* read function reads a single line of input from standard input
*/
public Object read(Object[] args) {
BufferedReader in = getInputReader();
if (in == null) {
return null;
}
if (args.length > 0) {
print(args[0].toString());
print(":");
}
try {
return in.readLine();
} catch (IOException exp) {
exp.printStackTrace();
throw new RuntimeException(exp);
}
}
/**
* Quit the shell.
* This only affects the interactive mode.
*/
public void quit(Object[] args) {
quit();
}
public void writeln(Object[] args) {
for (int i = 0; i < args.length; i++) {
print(args[i].toString());
print(" ");
}
println("");
}
public void write(Object[] args) {
for (int i = 0; i < args.length; i++) {
print(args[i].toString());
print(" ");
}
}
//-- Internals only below this point
protected void start(boolean console) {
ScriptContext context = engine.getContext();
OutputStream out = getOutputStream();
if (out != null) {
context.setWriter(new PrintWriter(out));
}
OutputStream err = getErrorStream();
if (err != null) {
context.setErrorWriter(new PrintWriter(err));
}
// load "sa.js" initialization file
loadInitFile();
// load "~/jsdb.js" (if found) to perform user specific
// initialization steps, if any.
loadUserInitFile();
JSJavaFactory fac = getJSJavaFactory();
JSJavaVM jvm = (fac != null)? fac.newJSJavaVM() : null;
// call "main" function from "sa.js" -- main expects
// 'this' object and jvm object
call("main", new Object[] { this, jvm });
// if asked, start read-eval-print console
if (console) {
processSource(null);
}
}
protected JSJavaScriptEngine(boolean debug) {
this.debug = debug;
ScriptEngineManager manager = new ScriptEngineManager();
engine = manager.getEngineByName("javascript");
if (engine == null) {
throw new RuntimeException("can't load JavaScript engine");
}
Method[] methods = getClass().getMethods();
for (int i = 0; i < methods.length; i++) {
Method m = methods[i];
if (! Modifier.isPublic(m.getModifiers())) {
continue;
}
Class[] argTypes = m.getParameterTypes();
if (argTypes.length == 1 &&
argTypes[0] == Object[].class) {
putFunction(this, m);
}
}
}
protected JSJavaScriptEngine() {
this(false);
}
protected abstract ObjectReader getObjectReader();
protected abstract JSJavaFactory getJSJavaFactory();
protected void printPrompt(String str) {
System.err.print(str);
System.err.flush();
}
protected void loadInitFile() {
InputStream is = JSJavaScriptEngine.class.getResourceAsStream("sa.js");
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
evalReader(reader, "sa.js");
}
protected void loadUserInitFile() {
File initFile = new File(getUserInitFileDir(), getUserInitFileName());
if (initFile.exists() && initFile.isFile()) {
// load the init script
processSource(initFile.getAbsolutePath());
}
}
protected String getUserInitFileDir() {
return System.getProperty("user.home");
}
protected String getUserInitFileName() {
return "jsdb.js";
}
protected BufferedReader getInputReader() {
if (inReader == null) {
inReader = new BufferedReader(new InputStreamReader(System.in));
}
return inReader;
}
protected PrintStream getOutputStream() {
return System.out;
}
protected PrintStream getErrorStream() {
return System.err;
}
protected void print(String name) {
getOutputStream().print(name);
}
protected void println(String name) {
getOutputStream().println(name);
}
protected void printError(String message) {
printError(message, null);
}
protected void printError(String message, Exception exp) {
getErrorStream().println(message);
if (exp != null && debug) {
exp.printStackTrace(getErrorStream());
}
}
protected boolean isQuitting() {
return quitting;
}
protected void quit() {
quitting = true;
}
protected ScriptEngine getScriptEngine() {
return engine;
}
private JSJavaThread getOwningThread(JSJavaObject jo) {
Oop oop = jo.getOop();
Mark mark = oop.getMark();
ObjectMonitor mon = null;
Address owner = null;
JSJavaThread owningThread = null;
// check for heavyweight monitor
if (! mark.hasMonitor()) {
// check for lightweight monitor
if (mark.hasLocker()) {
owner = mark.locker().getAddress(); // save the address of the Lock word
}
// implied else: no owner
} else {
// this object has a heavyweight monitor
mon = mark.monitor();
// The owner field of a heavyweight monitor may be NULL for no
// owner, a JavaThread * or it may still be the address of the
// Lock word in a JavaThread's stack. A monitor can be inflated
// by a non-owning JavaThread, but only the owning JavaThread
// can change the owner field from the Lock word to the
// JavaThread * and it may not have done that yet.
owner = mon.owner();
}
// find the owning thread
if (owner != null) {
JSJavaFactory factory = getJSJavaFactory();
owningThread = (JSJavaThread) factory.newJSJavaThread(VM.getVM().getThreads().owningThreadFromMonitor(owner));
}
return owningThread;
}
/**
* Evaluate JavaScript source.
* @param filename the name of the file to compile, or null
* for interactive mode.
*/
private void processSource(String filename) {
if (filename == null) {
BufferedReader in = getInputReader();
String sourceName = "<stdin>";
int lineno = 0;
boolean hitEOF = false;
do {
int startline = lineno;
printPrompt("jsdb> ");
Object source = read(EMPTY_ARRAY);
if (source == null) {
hitEOF = true;
break;
}
lineno++;
Object result = evalString(source.toString(), sourceName, startline);
if (result != null) {
printError(result.toString());
}
if (isQuitting()) {
// The user executed the quit() function.
break;
}
} while (!hitEOF);
} else {
Reader in = null;
try {
in = new BufferedReader(new FileReader(filename));
evalReader(in, filename);
} catch (FileNotFoundException ex) {
println("File '" + filename + "' not found");
throw new RuntimeException(ex);
}
}
}
protected Object evalString(String source, String filename, int lineNum) {
try {
engine.put(ScriptEngine.FILENAME, filename);
return engine.eval(source);
} catch (ScriptException sexp) {
printError(sexp.toString(), sexp);
} catch (Exception exp) {
printError(exp.toString(), exp);
}
return null;
}
private Object evalReader(Reader in, String filename) {
try {
engine.put(ScriptEngine.FILENAME, filename);
return engine.eval(in);
} catch (ScriptException sexp) {
System.err.println(sexp);
printError(sexp.toString(), sexp);
} finally {
try {
in.close();
} catch (IOException ioe) {
printError(ioe.toString(), ioe);
}
}
return null;
}
// lazily initialized input reader
private BufferedReader inReader;
// debug mode or not
protected final boolean debug;
private boolean quitting;
// underlying jsr-223 script engine
private ScriptEngine engine;
}

@ -1,77 +0,0 @@
/*
* Copyright (c) 2004, 2007, 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 sun.jvm.hotspot.utilities.soql;
import sun.jvm.hotspot.oops.*;
/**
* Wraps a java.lang.String instance of the target VM.
*/
public class JSJavaString extends JSJavaInstance {
public JSJavaString(Instance instance, JSJavaFactory fac) {
super(instance, fac);
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("String (address=");
buf.append(getOop().getHandle());
buf.append(", value=");
buf.append("'");
buf.append(getString());
buf.append('\'');
buf.append(')');
return buf.toString();
}
protected Object getFieldValue(String name) {
if (name.equals("stringValue")) {
return getString();
} else {
return super.getFieldValue(name);
}
}
protected String[] getFieldNames() {
String[] fields = super.getFieldNames();
String[] res = new String[fields.length + 1];
System.arraycopy(fields, 0, res, 0, fields.length);
res[fields.length] = "stringValue";
return res;
}
protected boolean hasField(String name) {
if (name.equals("stringValue")) {
return true;
} else {
return super.hasField(name);
}
}
//-- Internals only below this point
private String getString() {
return OopUtilities.stringOopToString(getOop());
}
}

@ -1,190 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
/**
* Wraps a JavaThread instance in the target VM.
*/
public class JSJavaThread extends JSJavaInstance {
public JSJavaThread(Instance threadOop, JSJavaFactory fac) {
super(threadOop, fac);
// JavaThread retrieved from java.lang.Thread instance may be null.
// This is the case for threads not-started and for zombies. Wherever
// appropriate, check for null instead of resulting in NullPointerException.
this.jthread = OopUtilities.threadOopGetJavaThread(threadOop);
}
public JSJavaThread(JavaThread jt, JSJavaFactory fac) {
super((Instance) jt.getThreadObj(), fac);
this.jthread = jt;
}
public String toString() {
String name = getName();
StringBuffer buf = new StringBuffer();
buf.append("Thread (address=");
buf.append(getOop().getHandle());
buf.append(", name=");
if (name != null) {
buf.append(name);
} else {
buf.append("<unnamed>");
}
buf.append(')');
return buf.toString();
}
protected Object getFieldValue(String name) {
if (name.equals("name")) {
return getName();
} else if (name.equals("frames")) {
return getFrames();
} else if (name.equals("monitors")) {
return getOwnedMonitors();
} else {
return super.getFieldValue(name);
}
}
protected String[] getFieldNames() {
String[] flds = super.getFieldNames();
String[] res = new String[flds.length + 2];
System.arraycopy(flds, 0, res, 0, flds.length);
res[flds.length] = "frames";
res[flds.length + 1] = "monitors";
return res;
}
protected boolean hasField(String name) {
if (name.equals("frames") || name.equals("monitors")) {
return true;
} else {
return super.hasField(name);
}
}
//-- Internals only below this point
private String getName() {
return OopUtilities.threadOopGetName(getOop());
}
private synchronized JSList getFrames() {
if (framesCache == null) {
final List<JavaVFrame> list = new ArrayList<>(0);
if (jthread != null) {
JavaVFrame jvf = jthread.getLastJavaVFrameDbg();
while (jvf != null) {
list.add(jvf);
jvf = jvf.javaSender();
}
}
framesCache = factory.newJSList(list);
}
return framesCache;
}
private synchronized JSList getOwnedMonitors() {
if (monitorsCache == null) {
final List<Oop> ownedMonitors = new ArrayList<>(0);
if (jthread != null) {
List<OopHandle> lockedObjects = new ArrayList<>();
ObjectMonitor waitingMonitor = jthread.getCurrentWaitingMonitor();
OopHandle waitingObj = null;
if (waitingMonitor != null) {
// save object of current wait() call (if any) for later comparison
waitingObj = waitingMonitor.object();
}
ObjectMonitor pendingMonitor = jthread.getCurrentPendingMonitor();
OopHandle pendingObj = null;
if (pendingMonitor != null) {
// save object of current enter() call (if any) for later comparison
pendingObj = pendingMonitor.object();
}
JavaVFrame frame = jthread.getLastJavaVFrameDbg();
while (frame != null) {
List<MonitorInfo> frameMonitors = frame.getMonitors();
for (Iterator<MonitorInfo> miItr = frameMonitors.iterator(); miItr.hasNext(); ) {
MonitorInfo mi = miItr.next();
if (mi.eliminated() && frame.isCompiledFrame()) {
continue; // skip eliminated monitor
}
OopHandle obj = mi.owner();
if (obj == null) {
// this monitor doesn't have an owning object so skip it
continue;
}
if (obj.equals(waitingObj)) {
// the thread is waiting on this monitor so it isn't really owned
continue;
}
if (obj.equals(pendingObj)) {
// the thread is pending on this monitor so it isn't really owned
continue;
}
boolean found = false;
for (Iterator loItr = lockedObjects.iterator(); loItr.hasNext(); ) {
// check for recursive locks
if (obj.equals(loItr.next())) {
found = true;
break;
}
}
if (found) {
// already have this object so don't include it
continue;
}
// add the owning object to our list
lockedObjects.add(obj);
}
frame = (JavaVFrame) frame.javaSender();
}
// now convert List<OopHandle> to List<Oop>
ObjectHeap heap = VM.getVM().getObjectHeap();
for (Iterator loItr = lockedObjects.iterator(); loItr.hasNext(); ) {
ownedMonitors.add(heap.newOop((OopHandle)loItr.next()));
}
}
monitorsCache = factory.newJSList(ownedMonitors);
}
return monitorsCache;
}
private JavaThread jthread;
private JSList framesCache;
private JSList monitorsCache;
}

@ -1,41 +0,0 @@
/*
* Copyright (c) 2004, 2007, 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 sun.jvm.hotspot.utilities.soql;
import sun.jvm.hotspot.oops.TypeArray;
/**
This is JavaScript wrapper for Java Primitive Array.
*/
public class JSJavaTypeArray extends JSJavaArray {
public JSJavaTypeArray(TypeArray array, JSJavaFactory fac) {
super(array, fac);
}
public final TypeArray getTypeArray() {
return (TypeArray) getArray();
}
}

@ -1,98 +0,0 @@
/*
* Copyright (c) 2003, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.utilities.*;
/**
This is JavaScript wrapper for TypeArrayKlass.
*/
public class JSJavaTypeArrayKlass extends JSJavaArrayKlass {
public JSJavaTypeArrayKlass(TypeArrayKlass kls, JSJavaFactory fac) {
super(kls, fac);
}
public final TypeArrayKlass getTypeArrayKlass() {
return (TypeArrayKlass) getArrayKlass();
}
public String getName() {
int type = (int) getTypeArrayKlass().getElementType();
switch (type) {
case TypeArrayKlass.T_BOOLEAN:
return "boolean[]";
case TypeArrayKlass.T_CHAR:
return "char[]";
case TypeArrayKlass.T_FLOAT:
return "float[]";
case TypeArrayKlass.T_DOUBLE:
return "double[]";
case TypeArrayKlass.T_BYTE:
return "byte[]";
case TypeArrayKlass.T_SHORT:
return "short[]";
case TypeArrayKlass.T_INT:
return "int[]";
case TypeArrayKlass.T_LONG:
return "long[]";
default:
if (Assert.ASSERTS_ENABLED) {
Assert.that(false, "Unknown primitive array type");
}
return null;
}
}
public Object getFieldValue(int index, Array array) {
TypeArray typeArr = (TypeArray) array;
int type = (int) getTypeArrayKlass().getElementType();
switch (type) {
case TypeArrayKlass.T_BOOLEAN:
return typeArr.getBooleanAt(index);
case TypeArrayKlass.T_CHAR:
return new String(new char[] { typeArr.getCharAt(index) });
case TypeArrayKlass.T_FLOAT:
return typeArr.getFloatAt(index);
case TypeArrayKlass.T_DOUBLE:
return typeArr.getDoubleAt(index);
case TypeArrayKlass.T_BYTE:
return typeArr.getByteAt(index);
case TypeArrayKlass.T_SHORT:
return typeArr.getShortAt(index);
case TypeArrayKlass.T_INT:
return typeArr.getIntAt(index);
case TypeArrayKlass.T_LONG:
return typeArr.getLongAt(index);
default:
if (Assert.ASSERTS_ENABLED) {
Assert.that(false, "Unknown primitive array type");
}
return null;
}
}
}

@ -1,227 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.debugger.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.runtime.*;
public class JSJavaVM extends DefaultScriptObject {
private static final int FIELD_ADDRESS_SIZE = 0;
private static final int FIELD_BUILD_INFO = 1;
private static final int FIELD_CPU = 2;
private static final int FIELD_FLAGS = 3;
private static final int FIELD_HEAP = 4;
private static final int FIELD_OS = 5;
private static final int FIELD_SYS_PROPS = 6;
private static final int FIELD_THREADS = 7;
private static final int FIELD_TYPE = 8;
private static final int FIELD_VERSION = 9;
private static final int FIELD_CLASS_PATH = 10;
private static final int FIELD_BOOT_CLASS_PATH = 11;
private static final int FIELD_USER_DIR = 12;
private static final int FIELD_UNDEFINED = -1;
public JSJavaVM(JSJavaFactory factory) {
this.factory = factory;
this.vm = VM.getVM();
}
public Object get(String name) {
int fieldID = getFieldID(name);
switch (fieldID) {
case FIELD_ADDRESS_SIZE:
return getVMBit();
case FIELD_BUILD_INFO:
return vm.getVMInternalInfo();
case FIELD_CPU:
return vm.getCPU();
case FIELD_FLAGS:
return getFlags();
case FIELD_HEAP:
return getHeap();
case FIELD_OS:
return vm.getOS();
case FIELD_SYS_PROPS:
return getSysProps();
case FIELD_THREADS:
return getThreads();
case FIELD_TYPE:
return getType();
case FIELD_VERSION:
return vm.getVMRelease();
case FIELD_CLASS_PATH:
return getClassPath();
case FIELD_USER_DIR:
return getUserDir();
case FIELD_UNDEFINED:
default:
return super.get(name);
}
}
public Object[] getIds() {
Object[] superIds = super.getIds();
Object[] tmp = fields.keySet().toArray();
Object[] res = new Object[superIds.length + tmp.length];
System.arraycopy(tmp, 0, res, 0, tmp.length);
System.arraycopy(superIds, 0, res, tmp.length, superIds.length);
return res;
}
public boolean has(String name) {
if (getFieldID(name) != FIELD_UNDEFINED) {
return true;
} else {
return super.has(name);
}
}
public void put(String name, Object value) {
if (getFieldID(name) == FIELD_UNDEFINED) {
super.put(name, value);
}
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append("Java Hotspot ");
buf.append(getType());
buf.append(' ');
buf.append(getVMBit());
buf.append(" bit VM (build ");
buf.append(vm.getVMRelease());
buf.append(")");
return buf.toString();
}
//-- Internals only below this point
private static Map<String, Integer> fields = new HashMap<>();
private static void addField(String name, int fieldId) {
fields.put(name, fieldId);
}
private static int getFieldID(String name) {
Integer res = (Integer) fields.get(name);
return (res != null)? res.intValue() : FIELD_UNDEFINED;
}
static {
addField("addressSize", FIELD_ADDRESS_SIZE);
addField("buildInfo", FIELD_BUILD_INFO);
addField("cpu", FIELD_CPU);
addField("flags", FIELD_FLAGS);
addField("heap", FIELD_HEAP);
addField("os", FIELD_OS);
addField("sysProps", FIELD_SYS_PROPS);
addField("threads", FIELD_THREADS);
addField("type", FIELD_TYPE);
addField("version", FIELD_VERSION);
addField("classPath", FIELD_CLASS_PATH);
addField("userDir", FIELD_USER_DIR);
}
private long getVMBit() {
// address size in bits
return vm.getAddressSize() * 8;
}
private synchronized JSMap getFlags() {
if (flagsCache == null) {
VM.Flag[] flags = vm.getCommandLineFlags();
Map<String, String> map = new HashMap<>();
if (flags != null) {
for (int f = 0; f < flags.length; f++) {
VM.Flag flag = flags[f];
map.put(flag.getName(), flag.getValue());
}
}
flagsCache = factory.newJSMap(map);
}
return flagsCache;
}
private synchronized JSJavaHeap getHeap() {
if (heapCache == null) {
heapCache = factory.newJSJavaHeap();
}
return heapCache;
}
private synchronized JSMap getSysProps() {
if (sysPropsCache == null) {
Properties props = vm.getSystemProperties();
Map<String, String> map = new HashMap<>();
if (props != null) {
Enumeration e = props.propertyNames();
while (e.hasMoreElements()) {
String key = (String) e.nextElement();
map.put(key, props.getProperty(key));
}
}
sysPropsCache = factory.newJSMap(map);
}
return sysPropsCache;
}
private synchronized JSList getThreads() {
if (threadsCache == null) {
List<JavaThread> threadsList = new ArrayList<>(0);
threadsCache = factory.newJSList(threadsList);
Threads threads = VM.getVM().getThreads();
for (int i = 0; i < threads.getNumberOfThreads(); i++) {
JavaThread thread = threads.getJavaThreadAt(i);
threadsList.add(thread);
}
}
return threadsCache;
}
private String getType() {
if (vm.isClientCompiler()) {
return "Client";
} else if (vm.isServerCompiler()) {
return "Server";
} else {
return "Core";
}
}
private String getClassPath() {
return vm.getSystemProperty("java.class.path");
}
private String getUserDir() {
return vm.getSystemProperty("user.dir");
}
private JSMap flagsCache;
private JSJavaHeap heapCache;
private JSMap sysPropsCache;
private JSList threadsCache;
private final JSJavaFactory factory;
private final VM vm;
}

@ -1,120 +0,0 @@
/*
* Copyright (c) 2004, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
/**
This is JavaScript wrapper for Java List.
*/
public class JSList extends DefaultScriptObject {
public JSList(List list, JSJavaFactory fac) {
this.list = list;
this.factory = fac;
}
public Object get(String name) {
if (name.equals("length")) {
return list.size();
} else {
return super.get(name);
}
}
public Object get(int index) {
if (isInRange(index)) {
Object item = list.get(index);
return wrapObject(item);
} else {
return super.get(index);
}
}
public Object[] getIds() {
Object[] superIds = super.getIds();
final int size = list.size();
Object[] res = new Object[superIds.length + size];
for (int i = 0; i < size; i++) {
res[i] = i;
}
System.arraycopy(superIds, 0, res, size, superIds.length);
return res;
}
public boolean has(String name) {
if (name.equals("length")) {
return true;
} else {
return super.has(name);
}
}
public boolean has(int index) {
if (isInRange(index)) {
return true;
} else {
return super.has(index);
}
}
public void put(String name, Object value) {
if (! name.equals("length")) {
super.put(name, value);
}
}
public void put(int index, Object value) {
if (! isInRange(index)) {
super.put(index, value);
}
}
public String toString() {
StringBuffer buf = new StringBuffer();
buf.append('[');
for (Iterator itr = list.iterator(); itr.hasNext();) {
buf.append(wrapObject(itr.next()));
if (itr.hasNext()) {
buf.append(", ");
}
}
buf.append(']');
return buf.toString();
}
//-- Internals only below this point
private boolean isInRange(int index) {
return index >= 0 && index < list.size();
}
private Object wrapObject(Object obj) {
return factory.newJSJavaWrapper(obj);
}
private final List list;
private final JSJavaFactory factory;
}

@ -1,94 +0,0 @@
/*
* Copyright (c) 2004, 2007, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
/**
This is JavaScript wrapper for a Map.
*/
public class JSMap extends DefaultScriptObject {
public JSMap(Map map, JSJavaFactory fac) {
this.map = map;
this.factory = fac;
}
public Object get(String name) {
if (map.containsKey(name)) {
return wrapObject(map.get(name));
} else {
return super.get(name);
}
}
public Object[] getIds() {
Object[] superIds = super.getIds();
Object[] tmp = map.keySet().toArray();
Object[] res = new Object[superIds.length + tmp.length];
System.arraycopy(tmp, 0, res, 0, tmp.length);
System.arraycopy(superIds, 0, res, tmp.length, superIds.length);
return res;
}
public boolean has(String name) {
if (map.containsKey(name)) {
return true;
} else {
return super.has(name);
}
}
public void put(String name, Object value) {
if (! map.containsKey(name)) {
super.put(name, value);
}
}
public String toString() {
StringBuffer buf = new StringBuffer();
Set keys = map.keySet();
buf.append('{');
for (Iterator itr = keys.iterator(); itr.hasNext();) {
Object key = itr.next();
buf.append(key);
buf.append('=');
buf.append(wrapObject(map.get(key)));
if (itr.hasNext()) {
buf.append(", ");
}
}
buf.append('}');
return buf.toString();
}
private Object wrapObject(Object obj) {
return factory.newJSJavaWrapper(obj);
}
private final Map map;
private final JSJavaFactory factory;
}

@ -1,60 +0,0 @@
/*
* Copyright (c) 2012, 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 sun.jvm.hotspot.utilities.soql;
import sun.jvm.hotspot.oops.Metadata;
/** This is JavaScript wrapper for a metadata object in debuggee.*/
public abstract class JSMetadata extends DefaultScriptObject {
public JSMetadata(Metadata metadata, JSJavaFactory factory) {
this.metadata = metadata;
this.factory = factory;
}
public final Metadata getMetadata() {
return metadata;
}
public boolean equals(Object o) {
if (o == null || !(o instanceof JSMetadata)) {
return false;
}
JSMetadata other = (JSMetadata) o;
return metadata.equals(other.metadata);
}
public int hashCode() {
return metadata.hashCode();
}
public String toString() {
return "Metadata " + metadata.getAddress().toString();
}
private final Metadata metadata;
protected final JSJavaFactory factory;
}

@ -1,122 +0,0 @@
/*
* Copyright (c) 2007, 2020, 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 sun.jvm.hotspot.utilities.soql;
import java.util.Map;
import java.util.HashMap;
import java.util.Collections;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import javax.script.Invocable;
/**
* Simple implementation of ScriptObject interface
* with property storage backed by a Map. This class
* can be extended to override any of the methods, in
* particular to add "function" valued properties.
*/
public class MapScriptObject implements ScriptObject {
// map to store the properties
private Map<Object, Object> map;
public MapScriptObject() {
this(new HashMap<>());
}
public MapScriptObject(Map<Object, Object> map) {
// make it synchronized
this.map = Collections.synchronizedMap(map);
}
public Object[] getIds() {
return map.keySet().toArray();
}
public Object get(String name) {
if (has(name)) {
return map.get(name);
} else {
return UNDEFINED;
}
}
public Object get(int index) {
if (has(index)) {
Object key = Integer.valueOf(index);
return map.get(key);
} else {
return UNDEFINED;
}
}
public void put(String name, Object value) {
map.put(name, value);
}
public void put(int index, Object value) {
map.put(Integer.valueOf(index), value);
}
public boolean has(String name) {
return map.containsKey(name);
}
public boolean has(int index) {
return map.containsKey(Integer.valueOf(index));
}
public boolean delete(String name) {
if (map.containsKey(name)) {
map.remove(name);
return true;
} else {
return false;
}
}
public boolean delete(int index) {
Object key = Integer.valueOf(index);
if (map.containsKey(key)) {
map.remove(key);
return true;
} else {
return false;
}
}
// add a function valued property that invokes given Method
protected void putFunction(Object target, Method method) {
putFunction(target, method, true);
}
// add a function valued property that invokes given Method
protected void putFunction(Object target, Method method, boolean wrapArgs) {
map.put(method.getName(), new MethodCallable(target, method, wrapArgs));
}
// add a function valued property that invokes given script function
protected void putFunction(Object target, String name, Invocable invocable) {
map.put(name, new InvocableCallable(target, name, invocable));
}
}

@ -1,66 +0,0 @@
/*
* Copyright (c) 2007, 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 sun.jvm.hotspot.utilities.soql;
import java.lang.reflect.Method;
import javax.script.ScriptException;
/**
* An implementation of Callable interface that
* invokes an instance or static Java method when
* called.
*/
public class MethodCallable implements Callable {
private Object target;
private Method method;
private boolean wrapArgs;
// "wrapArgs" tells whether the underlying java Method
// accepts one Object[] argument or it wants usual way of
// passing arguments. The former method is used when you
// want to implement a Callable that is variadic.
public MethodCallable(Object target, Method method, boolean wrapArgs) {
this.method = method;
this.target = target;
this.wrapArgs = wrapArgs;
}
public MethodCallable(Object target, Method method) {
this(target, method, true);
}
public Object call(Object[] args) throws ScriptException {
try {
if (wrapArgs) {
return method.invoke(target, new Object[] { args });
} else {
return method.invoke(target, args);
}
} catch (RuntimeException re) {
throw re;
} catch (Exception exp) {
throw new ScriptException(exp);
}
}
}

@ -1,265 +0,0 @@
/*
* Copyright (c) 2003, 2007, 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 sun.jvm.hotspot.utilities.soql;
import java.util.*;
import sun.jvm.hotspot.oops.*;
import sun.jvm.hotspot.memory.*;
import sun.jvm.hotspot.runtime.*;
import sun.jvm.hotspot.utilities.*;
/**
* This is SOQL (Simple Object Query Language) engine. This
* uses JavaScript engine for the "select" and "where" expression
* parts.
*/
public class SOQLEngine extends JSJavaScriptEngine {
public static synchronized SOQLEngine getEngine() {
if (soleInstance == null) {
soleInstance = new SOQLEngine();
}
return soleInstance;
}
/**
Query is of the form
select &lt;java script code to select&gt;
[ from [instanceof] &lt;class name&gt; [&lt;identifier&gt;]
[ where &lt;java script boolean expression&gt; ]
]
*/
public synchronized void executeQuery(String query, ObjectVisitor visitor)
throws SOQLException {
debugPrint("query : " + query);
StringTokenizer st = new StringTokenizer(query);
if (st.hasMoreTokens()) {
String first = st.nextToken();
if (! first.equals("select") ) {
throw new SOQLException("query syntax error: no 'select' clause");
}
} else {
throw new SOQLException("query syntax error: no 'select' clause");
}
int selectStart = query.indexOf("select");
int fromStart = query.indexOf("from");
String selectExpr = null;
String className = null;
boolean isInstanceOf = false;
String whereExpr = null;
String identifier = null;
if (fromStart != -1) {
selectExpr = query.substring(selectStart + "select".length(), fromStart);
st = new StringTokenizer(query.substring(fromStart + "from".length()));
if (st.hasMoreTokens()) {
String tmp = st.nextToken();
if (tmp.equals("instanceof")) {
isInstanceOf = true;
if (! st.hasMoreTokens()) {
throw new SOQLException("no class name after 'instanceof'");
}
className = st.nextToken();
} else {
className = tmp;
}
} else {
throw new SOQLException("query syntax error: class name must follow 'from'");
}
if (st.hasMoreTokens()) {
identifier = st.nextToken();
if (identifier.equals("where")) {
throw new SOQLException("query syntax error: identifier should follow class name");
}
if (st.hasMoreTokens()) {
String tmp = st.nextToken();
if (! tmp.equals("where")) {
throw new SOQLException("query syntax error: 'where' clause expected after 'from' clause");
}
int whereEnd = query.lastIndexOf("where") + 5; // "where".length
whereExpr = query.substring(whereEnd);
}
} else {
throw new SOQLException("query syntax error: identifier should follow class name");
}
} else { // no from clause
selectExpr = query.substring(selectStart + "select".length(), query.length());
}
executeQuery(new SOQLQuery(selectExpr, isInstanceOf, className, identifier, whereExpr), visitor);
}
private void executeQuery(SOQLQuery q, ObjectVisitor visitor) throws SOQLException {
InstanceKlass kls = null;
if (q.className != null) {
kls = SystemDictionaryHelper.findInstanceKlass(q.className);
if (kls == null) {
throw new SOQLException(q.className + " is not found!");
}
}
StringBuffer buf = new StringBuffer();
buf.append("function result(");
if (q.identifier != null) {
buf.append(q.identifier);
}
buf.append(") { return ");
buf.append(q.selectExpr.replace('\n', ' '));
buf.append("; }");
String selectCode = buf.toString();
debugPrint(selectCode);
String whereCode = null;
if (q.whereExpr != null) {
buf = new StringBuffer();
buf.append("function filter(");
buf.append(q.identifier);
buf.append(") { return ");
buf.append(q.whereExpr.replace('\n', ' '));
buf.append("; }");
whereCode = buf.toString();
debugPrint(whereCode);
} else {
whereCode = "filter = null;";
}
beginQuery();
// compile select expression and where condition
evalString(selectCode, "", 1);
evalString(whereCode, "", 1);
// iterate thru heap, if needed
if (q.className != null) {
try {
iterateOops(kls, visitor, q.isInstanceOf);
} finally {
endQuery();
}
} else {
// simple "select <expr>" query
try {
Object select = call("result", new Object[] {});
visitor.visit(select);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void dispatchObject(Oop oop, ObjectVisitor visitor, boolean filterExists) {
JSJavaObject jsObj = factory.newJSJavaObject(oop);
Object[] args = new Object[] { jsObj };
boolean b = true;
try {
if (filterExists) {
Object res = call("filter", args);
if (res instanceof Boolean) {
b = ((Boolean)res).booleanValue();
} else if (res instanceof Number) {
b = ((Number)res).intValue() != 0;
} else {
b = (res != null);
}
}
if (b) {
Object select = call("result", args);
visitor.visit(select);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private void iterateOops(final InstanceKlass ik, final ObjectVisitor visitor,
boolean includeSubtypes) {
ObjectHeap oh = VM.getVM().getObjectHeap();
oh.iterateObjectsOfKlass(new HeapVisitor() {
boolean filterExists;
public void prologue(long usedSize) {
filterExists = getScriptEngine().get("filter") != null;
}
public boolean doObj(Oop obj) {
dispatchObject(obj, visitor, filterExists);
return false;
}
public void epilogue() {}
}, ik, includeSubtypes);
}
// we create fresh ObjectReader and factory to avoid
// excessive cache across queries.
private void beginQuery() {
objReader = new ObjectReader();
factory = new JSJavaFactoryImpl();
}
// at the end of query we clear object reader cache
// and factory cache
private void endQuery() {
objReader = null;
factory = null;
}
protected ObjectReader getObjectReader() {
return objReader;
}
protected JSJavaFactory getJSJavaFactory() {
return factory;
}
protected boolean isQuitting() {
return false;
}
protected void quit() {
// do nothing
}
private static void debugPrint(String msg) {
if (debug) System.out.println(msg);
}
private static final boolean debug;
static {
debug = System.getProperty("sun.jvm.hotspot.utilities.soql.SOQLEngine.debug") != null;
}
protected SOQLEngine() {
super(debug);
start();
}
private ObjectReader objReader;
private JSJavaFactory factory;
private static SOQLEngine soleInstance;
}

@ -1,42 +0,0 @@
/*
* Copyright (c) 2003, 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 sun.jvm.hotspot.utilities.soql;
class SOQLQuery {
SOQLQuery(String selectExpr, boolean isInstanceOf,
String className, String identifier, String whereExpr) {
this.selectExpr = selectExpr;
this.isInstanceOf = isInstanceOf;
this.className = className;
this.identifier = identifier;
this.whereExpr = whereExpr;
}
String selectExpr;
boolean isInstanceOf;
String className;
String identifier;
String whereExpr;
}

@ -1,89 +0,0 @@
/*
* Copyright (c) 2007, 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 sun.jvm.hotspot.utilities.soql;
/**
* Any Java object supporting this interface can be
* accessed from scripts with "simpler" access pattern.
* For example, a script engine may support natural
* property/field access syntax for the properties exposed
* via this interface. We use this interface so that we
* can dynamically add/delete/modify fields exposed to
* scripts. If we stick to JavaBean pattern, then property
* set is fixed.
*/
public interface ScriptObject {
// special sentinel to denote no-result -- so that
// null could be used as proper value
public static final Object UNDEFINED = new Object();
// empty object array
public static final Object[] EMPTY_ARRAY = new Object[0];
/*
* Returns all property names supported by this object.
* Property "name" is either a String or an Integer".
*/
public Object[] getIds();
/**
* Get the value of the named property.
*/
public Object get(String name);
/**
* Get the value of the "indexed" property.
* Returns UNDEFINED if the property does not exist.
*/
public Object get(int index);
/**
* Set the value of the named property.
*/
public void put(String name, Object value);
/**
* Set the value of the indexed property.
*/
public void put(int index, Object value);
/**
* Returns whether the named property exists or not.
*/
public boolean has(String name);
/**
* Returns whether the indexed property exists or not.
*/
public boolean has(int index);
/**
* Deletes the named property. Returns true on success.
*/
public boolean delete(String name);
/**
* Deletes the indexed property. Returns true on success.
*/
public boolean delete(int index);
}

@ -1,910 +0,0 @@
/*
* Copyright (c) 2004, 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.
*
*/
// shorter names for SA packages
// SA package name abbreviations are kept in 'sapkg' object
// to avoid global namespace pollution
var sapkg = new Object();
sapkg.hotspot = Packages.sun.jvm.hotspot;
sapkg.asm = sapkg.hotspot.asm;
sapkg.c1 = sapkg.hotspot.c1;
sapkg.code = sapkg.hotspot.code;
sapkg.compiler = sapkg.hotspot.compiler;
// 'debugger' is a JavaScript keyword, but ES5 relaxes the
// restriction of using keywords as property name
sapkg.debugger = sapkg.hotspot.debugger;
sapkg.interpreter = sapkg.hotspot.interpreter;
sapkg.jdi = sapkg.hotspot.jdi;
sapkg.memory = sapkg.hotspot.memory;
sapkg.oops = sapkg.hotspot.oops;
sapkg.runtime = sapkg.hotspot.runtime;
sapkg.tools = sapkg.hotspot.tools;
sapkg.types = sapkg.hotspot.types;
sapkg.ui = sapkg.hotspot.ui;
sapkg.utilities = sapkg.hotspot.utilities;
// SA singletons are kept in 'sa' object
var sa = new Object();
sa.vm = sapkg.runtime.VM.getVM();
sa.dbg = sa.vm.getDebugger();
sa.cdbg = sa.dbg.CDebugger;
sa.heap = sa.vm.universe.heap();
sa.systemDictionary = sa.vm.systemDictionary;
sa.sysDict = sa.systemDictionary;
sa.symbolTable = sa.vm.symbolTable;
sa.symTbl = sa.symbolTable;
sa.threads = sa.vm.threads;
sa.interpreter = sa.vm.interpreter;
sa.typedb = sa.vm.typeDataBase;
sa.codeCache = sa.vm.codeCache;
// 'objHeap' is different from 'heap'!.
// This is SA's Oop factory and heap-walker
sa.objHeap = sa.vm.objectHeap;
// few useful global variables
var OS = sa.vm.OS;
var CPU = sa.vm.CPU;
var LP64 = sa.vm.LP64;
var isClient = sa.vm.clientCompiler;
var isServer = sa.vm.serverCompiler;
var isCore = sa.vm.isCore();
var addressSize = sa.vm.addressSize;
var oopSize = sa.vm.oopSize;
// this "main" function is called immediately
// after loading this script file
function main(globals, jvmarg) {
// wrap a sun.jvm.hotspot.utilities.soql.ScriptObject
// object so that the properties of it can be accessed
// in natural object.field syntax.
function wrapScriptObject(so) {
function unwrapScriptObject(wso) {
var objType = typeof(wso);
if ((objType == 'object' ||
objType == 'function')
&& "__wrapped__" in wso) {
return wso.__wrapped__;
} else {
return wso;
}
}
function prepareArgsArray(array) {
var args = new Array(array.length);
for (var a = 0; a < array.length; a++) {
var elem = array[a];
elem = unwrapScriptObject(elem);
if (typeof(elem) == 'function') {
args[a] = new sapkg.utilities.soql.Callable() {
call: function(myargs) {
var tmp = new Array(myargs.length);
for (var i = 0; i < myargs.length; i++) {
tmp[i] = wrapScriptObject(myargs[i]);
}
return elem.apply(this, tmp);
}
}
} else {
args[a] = elem;
}
}
return args;
}
// Handle __has__ specially to avoid metacircularity problems
// when called from __get__.
// Calling
// this.__has__(name)
// will in turn call
// this.__call__('__has__', name)
// which is not handled below
function __has__(name) {
if (typeof(name) == 'number') {
return so["has(int)"](name);
} else {
if (name == '__wrapped__') {
return true;
} else if (so["has(java.lang.String)"](name)) {
return true;
} else if (name.equals('toString')) {
return true;
} else {
return false;
}
}
}
if (so instanceof sapkg.utilities.soql.ScriptObject) {
return new JSAdapter() {
__getIds__: function() {
return so.getIds();
},
__has__ : __has__,
__delete__ : function(name) {
if (typeof(name) == 'number') {
return so["delete(int)"](name);
} else {
return so["delete(java.lang.String)"](name);
}
},
__get__ : function(name) {
// don't call this.__has__(name); see comments above function __has__
if (! __has__.call(this, name)) {
return undefined;
}
if (typeof(name) == 'number') {
return wrapScriptObject(so["get(int)"](name));
} else {
if (name == '__wrapped__') {
return so;
} else {
var value = so["get(java.lang.String)"](name);
if (value instanceof sapkg.utilities.soql.Callable) {
return function() {
var args = prepareArgsArray(arguments);
var r;
try {
r = value.call(Java.to(args, 'java.lang.Object[]'));
} catch (e) {
println("call to " + name + " failed!");
throw e;
}
return wrapScriptObject(r);
}
} else if (name == 'toString') {
return function() {
return so.toString();
}
} else {
return wrapScriptObject(value);
}
}
}
}
};
} else {
return so;
}
}
// set "jvm" global variable that wraps a
// sun.jvm.hotspot.utilities.soql.JSJavaVM instance
if (jvmarg != null) {
jvm = wrapScriptObject(jvmarg);
// expose "heap" global variable
heap = jvm.heap;
}
// expose all "function" type properties of
// sun.jvm.hotspot.utilitites.soql.JSJavaScriptEngine
// as global functions here.
globals = wrapScriptObject(globals);
for (var prop in globals) {
if (typeof(globals[prop]) == 'function') {
this[prop] = globals[prop];
}
}
// define "writeln" and "write" if not defined
if (typeof(println) == 'undefined') {
println = function (str) {
java.lang.System.out.println(String(str));
}
}
if (typeof(print) == 'undefined') {
print = function (str) {
java.lang.System.out.print(String(str));
}
}
if (typeof(writeln) == 'undefined') {
writeln = println;
}
if (typeof(write) == 'undefined') {
write = print;
}
// "registerCommand" function is defined if we
// are running as part of "CLHSDB" tool. CLHSDB
// tool exposes Unix-style commands.
// if "registerCommand" function is defined
// then register few global functions as "commands".
if (typeof(registerCommand) == 'function') {
this.jclass = function(name) {
if (typeof(name) == "string") {
var clazz = sapkg.utilities.SystemDictionaryHelper.findInstanceKlass(name);
if (clazz) {
writeln(clazz.getName().asString() + " @" + clazz.getAddress().toString());
} else {
writeln("class not found: " + name);
}
} else {
writeln("Usage: class name");
}
}
registerCommand("class", "class name", "jclass");
this.jclasses = function() {
forEachKlass(function (clazz) {
writeln(clazz.getName().asString() + " @" + clazz.getAddress().toString());
});
}
registerCommand("classes", "classes", "jclasses");
this.dclass = function(clazz, dir) {
if (!clazz) {
writeln("Usage: dumpclass { address | name } [ directory ]");
} else {
if (!dir) { dir = "."; }
dumpClass(clazz, dir);
}
}
registerCommand("dumpclass", "dumpclass { address | name } [ directory ]", "dclass");
registerCommand("dumpheap", "dumpheap [ file ]", "dumpHeap");
this.jseval = function(str) {
if (!str) {
writeln("Usage: jseval script");
} else {
var res = eval(str);
if (res) { writeln(res); }
}
}
registerCommand("jseval", "jseval script", "jseval");
this.jsload = function(file) {
if (!file) {
writeln("Usage: jsload file");
} else {
load(file);
}
}
registerCommand("jsload", "jsload file", "jsload");
this.printMem = function(addr, len) {
if (!addr) {
writeln("Usage: mem [ length ]");
} else {
mem(addr, len);
}
}
registerCommand("mem", "mem address [ length ]", "printMem");
this.sysProps = function() {
for (var i in jvm.sysProps) {
writeln(i + ' = ' + jvm.sysProps[i]);
}
}
registerCommand("sysprops", "sysprops", "sysProps");
this.printWhatis = function(addr) {
if (!addr) {
writeln("Usage: whatis address");
} else {
writeln(whatis(addr));
}
}
registerCommand("whatis", "whatis address", "printWhatis");
}
}
// debugger functionality
// string-to-Address
function str2addr(str) {
return sa.dbg.parseAddress(str);
}
// number-to-Address
if (addressSize == 4) {
eval("function num2addr(num) { \
return str2addr('0x' + java.lang.Integer.toHexString(0xffffffff & num)); \
}");
} else {
eval("function num2addr(num) { \
return str2addr('0x' + java.lang.Long.toHexString(num)); \
}");
}
// generic any-type-to-Address
// use this convenience function to accept address in any
// format -- number, string or an Address instance.
function any2addr(addr) {
var type = typeof(addr);
if (type == 'number') {
return num2addr(addr);
} else if (type == 'string') {
return str2addr(addr);
} else {
return addr;
}
}
// Address-to-string
function addr2str(addr) {
if (addr == null) {
return (addressSize == 4)? '0x00000000' : '0x0000000000000000';
} else {
return addr + '';
}
}
// Address-to-number
function addr2num(addr) {
return sa.dbg.getAddressValue(addr);
}
// symbol-to-Address
function sym2addr(dso, sym) {
return sa.dbg.lookup(dso, sym);
}
function loadObjectContainingPC(addr) {
if (sa.cdbg == null) {
// no CDebugger support, return null
return null;
}
return sa.cdbg.loadObjectContainingPC(addr);
}
// returns the ClosestSymbol or null
function closestSymbolFor(addr) {
var dso = loadObjectContainingPC(addr);
if (dso != null) {
return dso.closestSymbolToPC(addr);
}
return null;
}
// Address-to-symbol
// returns nearest symbol as string if found
// else returns address as string
function addr2sym(addr) {
var sym = closestSymbolFor(addr);
if (sym != null) {
return sym.name + '+' + sym.offset;
} else {
return addr2str(addr);
}
}
// read 'num' words at 'addr' and return an array as result.
// returns Java long[] type result and not a JavaScript array.
function readWordsAt(addr, num) {
addr = any2addr(addr);
var res = java.lang.reflect.Array.newInstance(java.lang.Long.TYPE, num);
var i;
for (i = 0; i < num; i++) {
res[i] = addr2num(addr.getAddressAt(i * addressSize));
}
return res;
}
// read the 'C' string at 'addr'
function readCStrAt(addr) {
addr = any2addr(addr);
return sapkg.utilities.CStringUtilities.getString(addr);
}
// read the length of the 'C' string at 'addr'
function readCStrLen(addr) {
addr = any2addr(addr);
return sapkg.utilities.CStringUtilities.getStringLength(addr);
}
// iterate through ThreadList of CDebugger
function forEachThread(callback) {
if (sa.cdbg == null) {
// no CDebugger support
return;
} else {
var itr = sa.cdbg.threadList.iterator();
while (itr.hasNext()) {
if (callback(itr.next()) == false) return;
}
}
}
// read register set of a ThreadProxy as name-value pairs
function readRegs(threadProxy) {
var ctx = threadProxy.context;
var num = ctx.numRegisters;
var res = new Object();
var i;
for (i = 0; i < num; i++) {
res[ctx.getRegisterName(i)]= addr2str(ctx.getRegisterAsAddress(i));
}
return res;
}
// print register set for a given ThreaProxy
function regs(threadProxy) {
var res = readRegs(threadProxy);
for (i in res) {
writeln(i, '=', res[i]);
}
}
// iterate through each CFrame of a given ThreadProxy
function forEachCFrame(threadProxy, callback) {
if (sa.cdbg == null) {
// no CDebugger support
return;
} else {
var cframe = sa.cdbg.topFrameForThread(threadProxy);
while (cframe != null) {
if (callback(cframe) == false) return;
cframe = cframe.sender();
}
}
}
// iterate through list of load objects (DLLs, DSOs)
function forEachLoadObject(callback) {
if (sa.cdbg == null) {
// no CDebugger support
return;
} else {
var itr = sa.cdbg.loadObjectList.iterator();
while (itr.hasNext()) {
if (callback(itr.next()) == false) return;
}
}
}
// print 'num' words at 'addr'
function mem(addr, num) {
if (num == undefined) {
num = 1;
}
addr = any2addr(addr);
var i;
for (i = 0; i < num; i++) {
var value = addr.getAddressAt(0);
writeln(addr2sym(addr) + ':', addr2str(value));
addr = addr.addOffsetTo(addressSize);
}
writeln();
}
// System dictionary functions
// find InstanceKlass by name
function findInstanceKlass(name) {
return sapkg.utilities.SystemDictionaryHelper.findInstanceKlass(name);
}
// get Java system loader (i.e., application launcher loader)
function systemLoader() {
return sa.sysDict.javaSystemLoader();
}
// iterate class loader data for each 'Klass'
function forEachKlass(callback) {
var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassVisitor;
var visitor = new VisitorClass() { visit: callback };
sa.sysDict["classesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassVisitor)"](visitor);
}
// iterate system dictionary for each 'Klass' and initiating loader
function forEachKlassAndLoader(callback) {
var VisitorClass = sapkg.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor;
var visitor = new VisitorClass() { visit: callback };
sa.sysDict["allEntriesDo(sun.jvm.hotspot.classfile.ClassLoaderDataGraph.ClassAndLoaderVisitor)"](visitor);
}
// 'oop' to higher-level java object wrapper in which for(i in o)
// works by iterating java level fields and javaobject.javafield
// syntax works.
function oop2obj(oop) {
return object(addr2str(oop.handle));
}
// higher level java object wrapper to oop
function obj2oop(obj) {
return addr2oop(str2addr(address(obj)));
}
// Java heap iteration
// iterates Java heap for each Oop
function forEachOop(callback) {
function empty() { }
sa.objHeap.iterate(new sapkg.oops.HeapVisitor() {
prologue: empty,
doObj: callback,
epilogue: empty
});
}
// iterates Java heap for each Oop of given 'klass'.
// 'includeSubtypes' tells whether to include objects
// of subtypes of 'klass' or not
function forEachOopOfKlass(callback, klass, includeSubtypes) {
if (klass == undefined) {
klass = findInstanceKlass("java.lang.Object");
}
if (includeSubtypes == undefined) {
includeSubtypes = true;
}
function empty() { }
sa.objHeap.iterateObjectsOfKlass(
new sapkg.oops.HeapVisitor() {
prologue: empty,
doObj: callback,
epilogue: empty
},
klass, includeSubtypes);
}
// Java thread
// iterates each Thread
function forEachJavaThread(callback) {
var threads = sa.threads;
var thread = threads.first();
while (thread != null) {
if (callback(thread) == false) return;
thread = thread.next();
}
}
// iterate Frames of a given thread
function forEachFrame(javaThread, callback) {
var fr = javaThread.getLastFrameDbg();
while (fr != null) {
if (callback(fr) == false) return;
fr = fr.sender();
}
}
// iterate JavaVFrames of a given JavaThread
function forEachVFrame(javaThread, callback) {
var vfr = javaThread.getLastJavaVFrameDbg();
while (vfr != null) {
if (callback(vfr) == false) return;
vfr = vfr.javaSender();
}
}
function printStackTrace(javaThread) {
write("Thread ");
javaThread.printThreadIDOn(java.lang.System.out);
writeln();
forEachVFrame(javaThread, function (vf) {
var method = vf.method;
write(' - ', method.externalNameAndSignature(), '@bci =', vf.getBCI());
var line = method.getLineNumberFromBCI(vf.getBCI());
if (line != -1) { write(', line=', line); }
if (vf.isCompiledFrame()) { write(" (Compiled Frame)"); }
if (vf.isInterpretedFrame()) { write(" (Interpreted Frame)"); }
writeln();
});
writeln();
writeln();
}
// print Java stack trace for all threads
function where(javaThread) {
if (javaThread == undefined) {
forEachJavaThread(function (jt) { printStackTrace(jt); });
} else {
printStackTrace(javaThread);
}
}
// vmStructs access -- type database functions
// find a VM type
function findVMType(typeName) {
return sa.typedb.lookupType(typeName);
}
// iterate VM types
function forEachVMType(callback) {
var itr = sa.typedb.types;
while (itr.hasNext()) {
if (callback(itr.next()) == false) return;
}
}
// find VM int constant
function findVMIntConst(name) {
return sa.typedb.lookupIntConstant(name);
}
// find VM long constant
function findVMLongConst(name) {
return sa.typedb.lookupLongConstant(name);
}
// iterate VM int constants
function forEachVMIntConst(callback) {
var itr = sa.typedb.intConstants;
while (itr.hasNext()) {
if (callback(itr.next()) == false) return;
}
}
// iterate VM long constants
function forEachVMLongConst(callback) {
var itr = sa.typedb.longConstants;
while (itr.hasNext()) {
if (callback(itr.next()) == false) return;
}
}
// returns VM Type at address
function vmTypeof(addr) {
addr = any2addr(addr);
return sa.typedb.guessTypeForAddress(addr);
}
// does the given 'addr' points to an object of given 'type'?
// OR any valid Type at all (if type is undefined)
function isOfVMType(addr, type) {
addr = any2addr(addr);
if (type == undefined) {
return vmTypeof(addr) != null;
} else {
if (typeof(type) == 'string') {
type = findVMType(type);
}
return sa.typedb.addressTypeIsEqualToType(addr, type);
}
}
// reads static field value
function readVMStaticField(field) {
var type = field.type;
if (type.isCIntegerType() || type.isJavaPrimitiveType()) {
return field.value;
} else if (type.isPointerType()) {
return field.address;
} else if (type.isOopType()) {
return field.oopHandle;
} else {
return field.staticFieldAddress;
}
}
// reads given instance field of VM object at 'addr'
function readVMInstanceField(field, addr) {
var type = field.type;
if (type.isCIntegerType() || type.isJavaPrimitiveType()) {
return field.getValue(addr);
} else if (type.isPointerType()) {
return field.getAddress(addr);
} else if (type.isOopType()) {
return field.getOopHandle(addr);
} else {
return addr.addOffsetTo(field.offset);
}
}
// returns name-value of pairs of VM type at given address.
// If address is unspecified, reads static fields as name-value pairs.
function readVMType(type, addr) {
if (typeof(type) == 'string') {
type = findVMType(type);
}
if (addr != undefined) {
addr = any2addr(addr);
}
var result = new Object();
var staticOnly = (addr == undefined);
while (type != null) {
var itr = type.fields;
while (itr.hasNext()) {
var field = itr.next();
var isStatic = field.isStatic();
if (staticOnly && isStatic) {
result[field.name] = readVMStaticField(field);
} else if (!staticOnly && !isStatic) {
result[field.name] = readVMInstanceField(field, addr);
}
}
type = type.superclass;
}
return result;
}
function printVMType(type, addr) {
if (typeof(type) == 'string') {
type = findVMType(type);
}
var obj = readVMType(type, addr);
while (type != null) {
var itr = type.fields;
while (itr.hasNext()) {
var field = itr.next();
var name = field.name;
var value = obj[name];
if (value != undefined) {
writeln(field.type.name, type.name + '::' + name, '=', value);
}
}
type = type.superclass;
}
}
// define readXXX and printXXX functions for each VM struct/class Type
tmp = new Object();
tmp.itr = sa.typedb.types;
while (tmp.itr.hasNext()) {
tmp.type = tmp.itr.next();
tmp.name = tmp.type.name;
if (tmp.type.isPointerType() || tmp.type.isOopType() ||
tmp.type.isCIntegerType() || tmp.type.isJavaPrimitiveType() ||
tmp.name.equals('address') ||
tmp.name.equals("<opaque>")) {
// ignore;
continue;
} else {
// some type names have ':', '<', '>', '*', ' '. replace to make it as a
// JavaScript identifier
tmp.name = ("" + tmp.name).replace(/[:<>* ]/g, '_');
eval("function read" + tmp.name + "(addr) {" +
" return readVMType('" + tmp.name + "', addr);}");
eval("function print" + tmp.name + "(addr) {" +
" printVMType('" + tmp.name + "', addr); }");
/* FIXME: do we need this?
if (typeof(registerCommand) != 'undefined') {
var name = "print" + tmp.name;
registerCommand(name, name + " [address]", name);
}
*/
}
}
//clean-up the temporary
delete tmp;
// VMObject factory
// VM type to SA class map
var vmType2Class = new Object();
// C2 only classes
try{
vmType2Class["ExceptionBlob"] = sapkg.code.ExceptionBlob;
vmType2Class["UncommonTrapBlob"] = sapkg.code.UncommonTrapBlob;
} catch(e) {
// Ignore exception. C2 specific objects might be not
// available in client VM
}
// This is *not* exhaustive. Add more if needed.
// code blobs
vmType2Class["BufferBlob"] = sapkg.code.BufferBlob;
vmType2Class["nmethod"] = sapkg.code.NMethod;
vmType2Class["RuntimeStub"] = sapkg.code.RuntimeStub;
vmType2Class["SafepointBlob"] = sapkg.code.SafepointBlob;
vmType2Class["C2IAdapter"] = sapkg.code.C2IAdapter;
vmType2Class["DeoptimizationBlob"] = sapkg.code.DeoptimizationBlob;
vmType2Class["I2CAdapter"] = sapkg.code.I2CAdapter;
vmType2Class["OSRAdapter"] = sapkg.code.OSRAdapter;
vmType2Class["PCDesc"] = sapkg.code.PCDesc;
// interpreter
vmType2Class["InterpreterCodelet"] = sapkg.interpreter.InterpreterCodelet;
// Java Threads
vmType2Class["JavaThread"] = sapkg.runtime.JavaThread;
vmType2Class["CompilerThread"] = sapkg.runtime.CompilerThread;
vmType2Class["CodeCacheSweeperThread"] = sapkg.runtime.CodeCacheSweeperThread;
vmType2Class["DebuggerThread"] = sapkg.runtime.DebuggerThread;
// gc
vmType2Class["GenCollectedHeap"] = sapkg.memory.GenCollectedHeap;
vmType2Class["DefNewGeneration"] = sapkg.memory.DefNewGeneration;
vmType2Class["TenuredGeneration"] = sapkg.memory.TenuredGeneration;
// generic VMObject factory for a given address
// This is equivalent to VirtualConstructor.
function newVMObject(addr) {
addr = any2addr(addr);
var result = null;
forEachVMType(function (type) {
if (isOfVMType(addr, type)) {
var clazz = vmType2Class[type.name];
if (clazz != undefined) {
result = new clazz(addr);
}
return false;
} else {
return true;
}
});
return result;
}
function vmobj2addr(vmobj) {
return vmobj.address;
}
function addr2vmobj(addr) {
return newVMObject(addr);
}
// Miscellaneous utilities
// returns PointerLocation that describes the given pointer
function findPtr(addr) {
addr = any2addr(addr);
return sapkg.utilities.PointerFinder.find(addr);
}
// is given address a valid Oop?
function isOop(addr) {
addr = any2addr(addr);
var oopHandle = addr.addOffsetToAsOopHandle(0);
return sapkg.utilities.RobustOopDeterminator.oopLooksValid(oopHandle);
}
// returns description of given pointer as a String
function whatis(addr) {
addr = any2addr(addr);
var ptrLoc = findPtr(addr);
if (!ptrLoc.isUnknown()) {
return ptrLoc.toString();
}
var vmType = vmTypeof(addr);
if (vmType != null) {
return "pointer to " + vmType.name;
}
var dso = loadObjectContainingPC(addr);
if (dso == null) {
return ptrLoc.toString();
}
var sym = dso.closestSymbolToPC(addr);
if (sym != null) {
return sym.name + '+' + sym.offset;
}
var s = dso.getName();
var p = s.lastIndexOf("/");
var base = dso.getBase();
return s.substring(p+1, s.length) + '+' + addr.minus(base);
}

@ -26,6 +26,8 @@
package jdk.internal.foreign;
import jdk.incubator.foreign.MemoryAddress;
import jdk.incubator.foreign.MemoryLayout;
import jdk.incubator.foreign.MemoryLayouts;
import jdk.incubator.foreign.MemorySegment;
import jdk.incubator.foreign.SequenceLayout;
import jdk.internal.access.JavaNioAccess;
@ -68,14 +70,12 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
final long length;
final int mask;
final Thread owner;
final MemoryScope scope;
@ForceInline
AbstractMemorySegmentImpl(long length, int mask, Thread owner, MemoryScope scope) {
AbstractMemorySegmentImpl(long length, int mask, MemoryScope scope) {
this.length = length;
this.mask = mask;
this.owner = owner;
this.scope = scope;
}
@ -83,7 +83,7 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
abstract Object base();
abstract AbstractMemorySegmentImpl dup(long offset, long size, int mask, Thread owner, MemoryScope scope);
abstract AbstractMemorySegmentImpl dup(long offset, long size, int mask, MemoryScope scope);
abstract ByteBuffer makeByteBuffer();
@ -100,7 +100,7 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
}
private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) {
return dup(offset, newSize, mask, owner, scope);
return dup(offset, newSize, mask, scope);
}
@SuppressWarnings("unchecked")
@ -145,12 +145,12 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
@Override
public final boolean isAlive() {
return scope.isAliveThreadSafe();
return scope.isAlive();
}
@Override
public Thread ownerThread() {
return owner;
return scope.ownerThread();
}
@Override
@ -159,7 +159,7 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
if ((~accessModes() & accessModes) != 0) {
throw new IllegalArgumentException("Cannot acquire more access modes");
}
return dup(0, length, (mask & ~ACCESS_MASK) | accessModes, owner, scope);
return dup(0, length, (mask & ~ACCESS_MASK) | accessModes, scope);
}
@Override
@ -177,17 +177,16 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
@Override
public MemorySegment withOwnerThread(Thread newOwner) {
Objects.requireNonNull(newOwner);
checkValidState();
if (!isSet(HANDOFF)) {
throw unsupportedAccessMode(HANDOFF);
}
if (owner == newOwner) {
if (scope.ownerThread() == newOwner) {
throw new IllegalArgumentException("Segment already owned by thread: " + newOwner);
} else {
try {
return dup(0L, length, mask, newOwner, scope.dup());
return dup(0L, length, mask, scope.dup(newOwner));
} finally {
//flush read/writes to memory before returning the new segment
//flush read/writes to segment memory before returning the new segment
VarHandle.fullFence();
}
}
@ -198,19 +197,18 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
if (!isSet(CLOSE)) {
throw unsupportedAccessMode(CLOSE);
}
checkValidState();
closeNoCheck();
}
private final void closeNoCheck() {
scope.close(true);
scope.close();
}
final AbstractMemorySegmentImpl acquire() {
if (Thread.currentThread() != ownerThread() && !isSet(ACQUIRE)) {
throw unsupportedAccessMode(ACQUIRE);
}
return dup(0, length, mask, Thread.currentThread(), scope.acquire());
return dup(0, length, mask, scope.acquire());
}
@Override
@ -227,7 +225,7 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
}
void checkRange(long offset, long length, boolean writeAccess) {
checkValidState();
scope.checkValidState();
if (writeAccess && !isSet(WRITE)) {
throw unsupportedAccessMode(WRITE);
} else if (!writeAccess && !isSet(READ)) {
@ -238,10 +236,7 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
@Override
public final void checkValidState() {
if (owner != null && owner != Thread.currentThread()) {
throw new IllegalStateException("Attempt to access segment outside owning thread");
}
scope.checkAliveConfined();
scope.checkValidState();
}
// Helper methods
@ -415,29 +410,28 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
AbstractMemorySegmentImpl bufferSegment = (AbstractMemorySegmentImpl)nioAccess.bufferSegment(bb);
final MemoryScope bufferScope;
int modes;
final Thread owner;
if (bufferSegment != null) {
bufferScope = bufferSegment.scope;
modes = bufferSegment.mask;
owner = bufferSegment.owner;
} else {
bufferScope = new MemoryScope(bb, null);
bufferScope = MemoryScope.create(bb, null);
modes = defaultAccessModes(size);
owner = Thread.currentThread();
}
if (bb.isReadOnly()) {
modes &= ~WRITE;
}
if (base != null) {
return new HeapMemorySegmentImpl<>(bbAddress + pos, () -> (byte[])base, size, modes, owner, bufferScope);
return new HeapMemorySegmentImpl<>(bbAddress + pos, () -> (byte[])base, size, modes, bufferScope);
} else if (unmapper == null) {
return new NativeMemorySegmentImpl(bbAddress + pos, size, modes, owner, bufferScope);
return new NativeMemorySegmentImpl(bbAddress + pos, size, modes, bufferScope);
} else {
return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, modes, owner, bufferScope);
return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, modes, bufferScope);
}
}
public static AbstractMemorySegmentImpl NOTHING = new AbstractMemorySegmentImpl(0, 0, null, MemoryScope.GLOBAL) {
public static final AbstractMemorySegmentImpl NOTHING = new AbstractMemorySegmentImpl(
0, 0, MemoryScope.createUnchecked(null, null, null)
) {
@Override
ByteBuffer makeByteBuffer() {
throw new UnsupportedOperationException();
@ -454,7 +448,7 @@ public abstract class AbstractMemorySegmentImpl implements MemorySegment, Memory
}
@Override
AbstractMemorySegmentImpl dup(long offset, long size, int mask, Thread owner, MemoryScope scope) {
AbstractMemorySegmentImpl dup(long offset, long size, int mask, MemoryScope scope) {
throw new UnsupportedOperationException();
}
};

@ -52,8 +52,8 @@ public class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl {
final Supplier<H> baseProvider;
@ForceInline
HeapMemorySegmentImpl(long offset, Supplier<H> baseProvider, long length, int mask, Thread owner, MemoryScope scope) {
super(length, mask, owner, scope);
HeapMemorySegmentImpl(long offset, Supplier<H> baseProvider, long length, int mask, MemoryScope scope) {
super(length, mask, scope);
this.offset = offset;
this.baseProvider = baseProvider;
}
@ -69,8 +69,8 @@ public class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl {
}
@Override
HeapMemorySegmentImpl<H> dup(long offset, long size, int mask, Thread owner, MemoryScope scope) {
return new HeapMemorySegmentImpl<H>(this.offset + offset, baseProvider, size, mask, owner, scope);
HeapMemorySegmentImpl<H> dup(long offset, long size, int mask, MemoryScope scope) {
return new HeapMemorySegmentImpl<>(this.offset + offset, baseProvider, size, mask, scope);
}
@Override
@ -121,7 +121,7 @@ public class HeapMemorySegmentImpl<H> extends AbstractMemorySegmentImpl {
static <Z> HeapMemorySegmentImpl<Z> makeHeapSegment(Supplier<Z> obj, int length, int base, int scale) {
int byteSize = length * scale;
MemoryScope scope = new MemoryScope(null, null);
return new HeapMemorySegmentImpl<>(base, obj, byteSize, defaultAccessModes(byteSize), Thread.currentThread(), scope);
MemoryScope scope = MemoryScope.create(null, null);
return new HeapMemorySegmentImpl<>(base, obj, byteSize, defaultAccessModes(byteSize), scope);
}
}

@ -48,8 +48,8 @@ public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl implements
private final UnmapperProxy unmapper;
MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, int mask, Thread owner, MemoryScope scope) {
super(min, length, mask, owner, scope);
MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, int mask, MemoryScope scope) {
super(min, length, mask, scope);
this.unmapper = unmapper;
}
@ -60,8 +60,8 @@ public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl implements
}
@Override
MappedMemorySegmentImpl dup(long offset, long size, int mask, Thread owner, MemoryScope scope) {
return new MappedMemorySegmentImpl(min + offset, unmapper, size, mask, owner, scope);
MappedMemorySegmentImpl dup(long offset, long size, int mask, MemoryScope scope) {
return new MappedMemorySegmentImpl(min + offset, unmapper, size, mask, scope);
}
// mapped segment methods
@ -103,13 +103,13 @@ public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl implements
if (bytesSize <= 0) throw new IllegalArgumentException("Requested bytes size must be > 0.");
try (FileChannelImpl channelImpl = (FileChannelImpl)FileChannel.open(path, openOptions(mapMode))) {
UnmapperProxy unmapperProxy = channelImpl.mapInternal(mapMode, 0L, bytesSize);
MemoryScope scope = new MemoryScope(null, unmapperProxy::unmap);
MemoryScope scope = MemoryScope.create(null, unmapperProxy::unmap);
int modes = defaultAccessModes(bytesSize);
if (mapMode == FileChannel.MapMode.READ_ONLY) {
modes &= ~WRITE;
}
return new MappedMemorySegmentImpl(unmapperProxy.address(), unmapperProxy, bytesSize,
modes, Thread.currentThread(), scope);
modes, scope);
}
}

@ -26,101 +26,287 @@
package jdk.internal.foreign;
import jdk.internal.vm.annotation.ForceInline;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.util.Objects;
import java.util.concurrent.atomic.LongAdder;
import java.util.concurrent.locks.StampedLock;
/**
* This class manages the temporal bounds associated with a memory segment. A scope has a liveness bit, which is updated
* when the scope is closed (this operation is triggered by {@link AbstractMemorySegmentImpl#close()}). Furthermore, a scope is
* associated with an <em>atomic</em> counter which can be incremented (upon calling the {@link #acquire()} method),
* and is decremented (when a previously acquired segment is later closed).
* This class manages the temporal bounds associated with a memory segment as well
* as thread confinement.
* A scope has a liveness bit, which is updated when the scope is closed
* (this operation is triggered by {@link AbstractMemorySegmentImpl#close()}).
* A scope may also have an associated "owner" thread that confines some operations to
* associated owner thread such as {@link #close()} or {@link #dup(Thread)}.
* Furthermore, a scope is either root scope ({@link #create(Object, Runnable) created}
* when memory segment is allocated) or child scope ({@link #acquire() acquired} from root scope).
* When a child scope is acquired from another child scope, it is actually acquired from
* the root scope. There is only a single level of children. All child scopes are peers.
* A child scope can be {@link #close() closed} at any time, but root scope can only
* be closed after all its children have been closed, at which time any associated
* cleanup action is executed (the associated memory segment is freed).
* Besides thread-confined checked scopes, {@linkplain #createUnchecked(Thread, Object, Runnable)}
* method may be used passing {@code null} as the "owner" thread to create a
* scope that doesn't check for thread-confinement while its temporal bounds are
* enforced reliably only under condition that thread that closes the scope is also
* the single thread performing the checked access or there is an external synchronization
* in place that prevents concurrent access and closing of the scope.
*/
public final class MemoryScope {
abstract class MemoryScope {
//reference to keep hold onto
final Object ref;
/**
* Creates a root MemoryScope with given ref, cleanupAction and current
* thread as the "owner" thread.
* This method may be called in any thread.
* The returned instance may be published unsafely to and used in any thread,
* but methods that explicitly state that they may only be called in "owner" thread,
* must strictly be called in the thread that created the scope
* or else IllegalStateException is thrown.
*
* @param ref an optional reference to an instance that needs to be kept reachable
* @param cleanupAction an optional cleanup action to be executed when returned scope is closed
* @return a root MemoryScope
*/
static MemoryScope create(Object ref, Runnable cleanupAction) {
return new Root(Thread.currentThread(), ref, cleanupAction);
}
int activeCount = UNACQUIRED;
/**
* Creates a root MemoryScope with given ref, cleanupAction and "owner" thread.
* This method may be called in any thread.
* The returned instance may be published unsafely to and used in any thread,
* but methods that explicitly state that they may only be called in "owner" thread,
* must strictly be called in given owner thread or else IllegalStateException is thrown.
* If given owner thread is null, the returned MemoryScope is unchecked, meaning
* that all methods may be called in any thread and that {@link #checkValidState()}
* does not check for temporal bounds.
*
* @param owner the desired owner thread. If {@code owner == null},
* the returned scope is <em>not</em> thread-confined and not checked.
* @param ref an optional reference to an instance that needs to be kept reachable
* @param cleanupAction an optional cleanup action to be executed when returned scope is closed
* @return a root MemoryScope
*/
static MemoryScope createUnchecked(Thread owner, Object ref, Runnable cleanupAction) {
return new Root(owner, ref, cleanupAction);
}
final static VarHandle COUNT_HANDLE;
private final Thread owner;
private boolean closed; // = false
private static final VarHandle CLOSED;
static {
try {
COUNT_HANDLE = MethodHandles.lookup().findVarHandle(MemoryScope.class, "activeCount", int.class);
CLOSED = MethodHandles.lookup().findVarHandle(MemoryScope.class, "closed", boolean.class);
} catch (Throwable ex) {
throw new ExceptionInInitializerError(ex);
}
}
final static int UNACQUIRED = 0;
final static int CLOSED = -1;
final static int MAX_ACQUIRE = Integer.MAX_VALUE;
final Runnable cleanupAction;
final static MemoryScope GLOBAL = new MemoryScope(null, null);
public MemoryScope(Object ref, Runnable cleanupAction) {
this.ref = ref;
this.cleanupAction = cleanupAction;
private MemoryScope(Thread owner) {
this.owner = owner;
}
/**
* This method performs a full, thread-safe liveness check; can be used outside confinement thread.
* Acquires a child scope (or peer scope if this is a child) with current
* thread as the "owner" thread.
* This method may be called in any thread.
* The returned instance may be published unsafely to and used in any thread,
* but methods that explicitly state that they may only be called in "owner" thread,
* must strictly be called in the thread that acquired the scope
* or else IllegalStateException is thrown.
*
* @return a child (or peer) scope
* @throws IllegalStateException if root scope is already closed
*/
final boolean isAliveThreadSafe() {
return ((int)COUNT_HANDLE.getVolatile(this)) != CLOSED;
abstract MemoryScope acquire();
/**
* Closes this scope, executing any cleanup action if this is the root scope.
* This method may only be called in the "owner" thread of this scope unless the
* scope is a root scope with no owner thread - i.e. is not checked.
*
* @throws IllegalStateException if this scope is already closed or if this is
* a root scope and there is/are still active child
* scope(s) or if this method is called outside of
* owner thread in checked scope
*/
abstract void close();
/**
* Duplicates this scope with given new "owner" thread and {@link #close() closes} it.
* If this is a root scope, a new root scope is returned; this root scope is closed, but
* without executing the cleanup action, which is instead transferred to the duped scope.
* If this is a child scope, a new child scope is returned.
* This method may only be called in the "owner" thread of this scope unless the
* scope is a root scope with no owner thread - i.e. is not checked.
* The returned instance may be published unsafely to and used in any thread,
* but methods that explicitly state that they may only be called in "owner" thread,
* must strictly be called in given new "owner" thread
* or else IllegalStateException is thrown.
*
* @param newOwner new owner thread of the returned MemoryScope
* @return a duplicate of this scope
* @throws NullPointerException if given owner thread is null
* @throws IllegalStateException if this scope is already closed or if this is
* a root scope and there is/are still active child
* scope(s) or if this method is called outside of
* owner thread in checked scope
*/
abstract MemoryScope dup(Thread newOwner);
/**
* Returns "owner" thread of this scope.
*
* @return owner thread (or null for unchecked scope)
*/
final Thread ownerThread() {
return owner;
}
/**
* This method performs a quick liveness check; must be called from the confinement thread.
* This method may be called in any thread.
*
* @return {@code true} if this scope is not closed yet.
*/
final void checkAliveConfined() {
if (activeCount == CLOSED) {
throw new IllegalStateException("Segment is not alive");
final boolean isAlive() {
return !((boolean)CLOSED.getVolatile(this));
}
/**
* Checks that this scope is still alive and that this method is executed
* in the "owner" thread of this scope or this scope is unchecked (not associated
* with owner thread).
*
* @throws IllegalStateException if this scope is already closed or this
* method is executed outside owning thread
* in checked scope
*/
@ForceInline
final void checkValidState() {
if (owner != null && owner != Thread.currentThread()) {
throw new IllegalStateException("Attempted access outside owning thread");
}
checkAliveConfined(this);
}
/**
* Checks that this scope is still alive.
*
* @throws IllegalStateException if this scope is already closed
*/
@ForceInline
private static void checkAliveConfined(MemoryScope scope) {
if (scope.closed) {
throw new IllegalStateException("This segment is already closed");
}
}
MemoryScope acquire() {
int value;
do {
value = (int)COUNT_HANDLE.getVolatile(this);
if (value == CLOSED) {
//segment is not alive!
throw new IllegalStateException("Segment is not alive");
} else if (value == MAX_ACQUIRE) {
//overflow
throw new IllegalStateException("Segment acquire limit exceeded");
private static final class Root extends MemoryScope {
private final StampedLock lock = new StampedLock();
private final LongAdder acquired = new LongAdder();
private final Object ref;
private final Runnable cleanupAction;
private Root(Thread owner, Object ref, Runnable cleanupAction) {
super(owner);
this.ref = ref;
this.cleanupAction = cleanupAction;
}
@Override
MemoryScope acquire() {
// try to optimistically acquire the lock
long stamp = lock.tryOptimisticRead();
try {
for (; ; stamp = lock.readLock()) {
if (stamp == 0L)
continue;
checkAliveConfined(this); // plain read is enough here (either successful optimistic read, or full read lock)
// increment acquires
acquired.increment();
// did a call to close() occur since we acquired the lock?
if (lock.validate(stamp)) {
// no, just return the acquired scope
return new Child(Thread.currentThread());
} else {
// yes, just back off and retry (close might have failed, after all)
acquired.decrement();
}
}
} finally {
if (StampedLock.isReadLockStamp(stamp))
lock.unlockRead(stamp);
}
} while (!COUNT_HANDLE.compareAndSet(this, value, value + 1));
return new MemoryScope(ref, this::release);
}
}
private void release() {
int value;
do {
value = (int)COUNT_HANDLE.getVolatile(this);
if (value <= UNACQUIRED) {
//cannot get here - we can't close segment twice
throw new IllegalStateException();
@Override
MemoryScope dup(Thread newOwner) {
Objects.requireNonNull(newOwner, "newOwner");
// pre-allocate duped scope so we don't get OOME later and be left with this scope closed
var duped = new Root(newOwner, ref, cleanupAction);
justClose();
return duped;
}
@Override
void close() {
justClose();
if (cleanupAction != null) {
cleanupAction.run();
}
} while (!COUNT_HANDLE.compareAndSet(this, value, value - 1));
}
void close(boolean doCleanup) {
if (!COUNT_HANDLE.compareAndSet(this, UNACQUIRED, CLOSED)) {
//first check if already closed...
checkAliveConfined();
//...if not, then we have acquired views that are still active
throw new IllegalStateException("Cannot close a segment that has active acquired views");
}
if (doCleanup && cleanupAction != null) {
cleanupAction.run();
}
}
MemoryScope dup() {
close(false);
return new MemoryScope(ref, cleanupAction);
@ForceInline
private void justClose() {
// enter critical section - no acquires are possible past this point
long stamp = lock.writeLock();
try {
checkValidState(); // plain read is enough here (full write lock)
// check for absence of active acquired children
if (acquired.sum() > 0) {
throw new IllegalStateException("Cannot close this scope as it has active acquired children");
}
// now that we made sure there's no active acquired children, we can mark scope as closed
CLOSED.set(this, true); // plain write is enough here (full write lock)
} finally {
// leave critical section
lock.unlockWrite(stamp);
}
}
private final class Child extends MemoryScope {
private Child(Thread owner) {
super(owner);
}
@Override
MemoryScope acquire() {
return Root.this.acquire();
}
@Override
MemoryScope dup(Thread newOwner) {
checkValidState(); // child scope is always checked
// pre-allocate duped scope so we don't get OOME later and be left with this scope closed
var duped = new Child(newOwner);
CLOSED.setVolatile(this, true);
return duped;
}
@Override
void close() {
checkValidState(); // child scope is always checked
CLOSED.set(this, true);
// following acts as a volatile write after plain write above so
// plain write gets flushed too (which is important for isAliveThreadSafe())
Root.this.acquired.decrement();
}
}
}
}

@ -53,14 +53,14 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
final long min;
@ForceInline
NativeMemorySegmentImpl(long min, long length, int mask, Thread owner, MemoryScope scope) {
super(length, mask, owner, scope);
NativeMemorySegmentImpl(long min, long length, int mask, MemoryScope scope) {
super(length, mask, scope);
this.min = min;
}
@Override
NativeMemorySegmentImpl dup(long offset, long size, int mask, Thread owner, MemoryScope scope) {
return new NativeMemorySegmentImpl(min + offset, size, mask, owner, scope);
NativeMemorySegmentImpl dup(long offset, long size, int mask, MemoryScope scope) {
return new NativeMemorySegmentImpl(min + offset, size, mask, scope);
}
@Override
@ -93,9 +93,9 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
unsafe.setMemory(buf, alignedSize, (byte)0);
}
long alignedBuf = Utils.alignUp(buf, alignmentBytes);
MemoryScope scope = new MemoryScope(null, () -> unsafe.freeMemory(buf));
MemorySegment segment = new NativeMemorySegmentImpl(buf, alignedSize, defaultAccessModes(alignedSize),
Thread.currentThread(), scope);
MemoryScope scope = MemoryScope.create(null, () -> unsafe.freeMemory(buf));
MemorySegment segment = new NativeMemorySegmentImpl(buf, alignedSize,
defaultAccessModes(alignedSize), scope);
if (alignedSize != bytesSize) {
long delta = alignedBuf - buf;
segment = segment.asSlice(delta, bytesSize);
@ -104,7 +104,7 @@ public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl {
}
public static MemorySegment makeNativeSegmentUnchecked(MemoryAddress min, long bytesSize, Thread owner, Runnable cleanup, Object attachment) {
MemoryScope scope = new MemoryScope(attachment, cleanup);
return new NativeMemorySegmentImpl(min.toRawLongValue(), bytesSize, defaultAccessModes(bytesSize), owner, scope);
MemoryScope scope = MemoryScope.createUnchecked(owner, attachment, cleanup);
return new NativeMemorySegmentImpl(min.toRawLongValue(), bytesSize, defaultAccessModes(bytesSize), scope);
}
}

@ -121,7 +121,7 @@ public class ReplaceConstantNodesPhaseTest extends HotSpotGraalCompilerTest {
new EliminateRedundantInitializationPhase().apply(graph, highTierContext);
new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext);
new LoadJavaMirrorWithKlassPhase(config).apply(graph, highTierContext);
new ReplaceConstantNodesPhase(false).apply(graph, highTierContext);
new ReplaceConstantNodesPhase(true, false).apply(graph, highTierContext);
Assert.assertEquals(expectedInits, graph.getNodes().filter(InitializeKlassNode.class).count());
Assert.assertEquals(expectedResolves, graph.getNodes().filter(ResolveConstantNode.class).count());
Assert.assertEquals(expectedLoads, graph.getNodes().filter(LoadConstantIndirectlyNode.class).count());

@ -59,6 +59,7 @@ import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.LoweringPhase;
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.phases.tiers.LowTierContext;
import org.graalvm.compiler.phases.tiers.MidTierContext;
import org.graalvm.compiler.phases.tiers.Suites;
import org.graalvm.compiler.phases.tiers.SuitesCreator;
@ -100,7 +101,11 @@ public class HotSpotSuitesProvider extends SuitesProviderBase {
highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options)));
}
ListIterator<BasePhase<? super MidTierContext>> midTierLowering = ret.getMidTier().findPhase(LoweringPhase.class);
midTierLowering.add(new ReplaceConstantNodesPhase());
midTierLowering.add(new ReplaceConstantNodesPhase(true));
// Replace possible constants after GC barrier expansion.
ListIterator<BasePhase<? super LowTierContext>> lowTierLowering = ret.getLowTier().findPhase(LoweringPhase.class);
lowTierLowering.add(new ReplaceConstantNodesPhase(false));
// Replace inlining policy
if (Inline.getValue(options)) {

@ -28,6 +28,7 @@ import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.stri
import static org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode.getLoadMethodCountersNodes;
import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
import java.lang.ref.Reference;
import java.util.HashSet;
import java.util.List;
@ -82,6 +83,7 @@ import jdk.vm.ci.meta.ResolvedJavaType;
public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
private final boolean verifyFingerprints;
private final boolean allowResolution;
static Class<?> characterCacheClass = Character.class.getDeclaredClasses()[0];
static Class<?> byteCacheClass = Byte.class.getDeclaredClasses()[0];
@ -92,6 +94,7 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
static class ClassInfo {
private ResolvedJavaType stringType;
private ResolvedJavaType referenceType;
private final HashSet<ResolvedJavaType> builtIns = new HashSet<>();
ClassInfo(MetaAccessProvider metaAccessProvider) {
@ -113,6 +116,7 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
builtIns.add(metaAccessProvider.lookupJavaType(longCacheClass));
stringType = metaAccessProvider.lookupJavaType(String.class);
referenceType = metaAccessProvider.lookupJavaType(Reference.class);
}
}
@ -313,8 +317,10 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
* @param graph
* @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
* resolution.
* @return return true if all usages of the node have been replaced
*/
private static void tryToReplaceWithExisting(StructuredGraph graph, ConstantNode node) {
private static boolean tryToReplaceWithExisting(StructuredGraph graph, ConstantNode node) {
boolean allUsagesReplaced = true;
ScheduleResult schedule = graph.getLastSchedule();
NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
BlockMap<List<Node>> blockToNodes = schedule.getBlockToNodesMap();
@ -347,16 +353,20 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
for (Block d : blockToExisting.getKeys()) {
if (strictlyDominates(d, b)) {
use.replaceFirstInput(node, blockToExisting.get(d));
replaced = true;
break;
}
}
}
if (!replaced && allUsagesReplaced) {
allUsagesReplaced = false;
}
}
return allUsagesReplaced;
}
/**
* Replace the uses of a constant with either {@link LoadConstantIndirectlyNode} or
* {@link ResolveConstantNode}.
* Replace the uses of a constant with {@link ResolveConstantNode}.
*
* @param graph
* @param stateMapper
@ -366,30 +376,63 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
private static void replaceWithResolution(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node, ClassInfo classInfo) {
HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass();
ValueNode replacement;
if (type.isArray() && type.getComponentType().isPrimitive()) {
// Special case for primitive arrays. The AOT runtime pre-resolves them, so we may
// omit the resolution call.
FixedWithNextNode fixedReplacement;
if (classInfo.builtIns.contains(type)) {
// Special case of klass constants that come from {@link BoxingSnippets}.
fixedReplacement = graph.add(new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE));
} else {
fixedReplacement = graph.add(new ResolveConstantNode(node));
}
insertReplacement(graph, stateMapper, node, fixedReplacement);
node.replaceAtUsages(fixedReplacement, n -> !isReplacementNode(n));
}
/**
* Replace the uses of a constant with either {@link LoadConstantIndirectlyNode} if possible.
*
* @param graph
* @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
* resolution.
* @return return true if all usages of the node have been replaced
*/
private static boolean replaceWithLoad(StructuredGraph graph, ConstantNode node, ClassInfo classInfo) {
HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass();
ValueNode replacement = null;
if ((type.isArray() && type.getComponentType().isPrimitive()) || type.equals(classInfo.referenceType)) {
// Special case for primitive arrays and j.l.ref.Reference.
// The AOT runtime pre-resolves them, so we may omit the resolution call.
replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node));
} else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) {
// If it's a supertype of or the same class that declares the top method, we are
// guaranteed to have it resolved already. If it's an interface, we just test for
// equality.
replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node));
} else {
FixedWithNextNode fixedReplacement;
if (classInfo.builtIns.contains(type)) {
// Special case of klass constants that come from {@link BoxingSnippets}.
fixedReplacement = graph.add(new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE));
} else {
fixedReplacement = graph.add(new ResolveConstantNode(node));
}
insertReplacement(graph, stateMapper, node, fixedReplacement);
replacement = fixedReplacement;
}
node.replaceAtUsages(replacement, n -> !isReplacementNode(n));
if (replacement != null) {
node.replaceAtUsages(replacement, n -> !isReplacementNode(n));
return true;
}
return false;
}
/**
* Verify that {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} has a valid
* fingerprint.
*
* @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType}.
*/
private void verifyFingerprint(ConstantNode node) {
HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
if (type != null) {
assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants";
if (verifyFingerprints && checkForBadFingerprint(type)) {
throw new GraalError("Type with bad fingerprint: " + type);
}
}
}
/**
@ -400,17 +443,11 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
* @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
* resolution.
*/
private void handleHotSpotMetaspaceConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node, ClassInfo classInfo) {
private static void handleHotSpotMetaspaceConstant(StructuredGraph graph, FrameStateMapperClosure stateMapper, ConstantNode node, ClassInfo classInfo) {
HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
if (type != null) {
if (verifyFingerprints && checkForBadFingerprint(type)) {
throw new GraalError("Type with bad fingerprint: " + type);
}
assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants";
tryToReplaceWithExisting(graph, node);
if (anyUsagesNeedReplacement(node)) {
if (!tryToReplaceWithExisting(graph, node) && !replaceWithLoad(graph, node, classInfo)) {
replaceWithResolution(graph, stateMapper, node, classInfo);
}
} else {
@ -418,6 +455,24 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
}
}
/**
* Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with a load. This
* variant handles only constants that don't require resolution.
*
* @param graph
* @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
* resolution.
*/
private static void handleHotSpotMetaspaceConstantWithoutResolution(StructuredGraph graph, ConstantNode node, ClassInfo classInfo) {
HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
if (type != null) {
replaceWithLoad(graph, node, classInfo);
} else {
throw new GraalError("Unsupported metaspace constant type: " + type);
}
}
/**
* Replace an object constant with an indirect load {@link ResolveConstantNode}. Currently we
* support only strings.
@ -482,6 +537,7 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
*
* @param graph
* @param stateMapper
* @param classInfo
*/
private void replaceKlassesAndObjects(StructuredGraph graph, FrameStateMapperClosure stateMapper, ClassInfo classInfo) {
new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false);
@ -489,6 +545,7 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
for (ConstantNode node : getConstantNodes(graph)) {
Constant constant = node.asConstant();
if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) {
verifyFingerprint(node);
handleHotSpotMetaspaceConstant(graph, stateMapper, node, classInfo);
} else if (constant instanceof HotSpotObjectConstant && anyUsagesNeedReplacement(node)) {
handleHotSpotObjectConstant(graph, stateMapper, node, classInfo);
@ -496,18 +553,37 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
}
}
/**
* Replace well-known klass constants with indirect loads.
*
* @param graph
* @param classInfo
*/
private static void replaceKlassesWithoutResolution(StructuredGraph graph, ClassInfo classInfo) {
for (ConstantNode node : getConstantNodes(graph)) {
Constant constant = node.asConstant();
if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) {
handleHotSpotMetaspaceConstantWithoutResolution(graph, node, classInfo);
}
}
}
@Override
protected void run(StructuredGraph graph, CoreProviders context) {
FrameStateMapperClosure stateMapper = new FrameStateMapperClosure(graph);
ReentrantNodeIterator.apply(stateMapper, graph.start(), null);
if (allowResolution) {
FrameStateMapperClosure stateMapper = new FrameStateMapperClosure(graph);
ReentrantNodeIterator.apply(stateMapper, graph.start(), null);
// Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass
// constants.
replaceLoadMethodCounters(graph, stateMapper, context);
// Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass
// constants.
replaceLoadMethodCounters(graph, stateMapper, context);
// Replace object and klass constants (including the ones added in the previous pass) with
// resolution nodes.
replaceKlassesAndObjects(graph, stateMapper, new ClassInfo(context.getMetaAccess()));
// Replace object and klass constants (including the ones added in the previous pass)
// with resolution nodes.
replaceKlassesAndObjects(graph, stateMapper, new ClassInfo(context.getMetaAccess()));
} else {
replaceKlassesWithoutResolution(graph, new ClassInfo(context.getMetaAccess()));
}
}
@Override
@ -515,11 +591,12 @@ public class ReplaceConstantNodesPhase extends BasePhase<CoreProviders> {
return false;
}
public ReplaceConstantNodesPhase() {
this(true);
public ReplaceConstantNodesPhase(boolean allowResolution) {
this(allowResolution, true);
}
public ReplaceConstantNodesPhase(boolean verifyFingerprints) {
public ReplaceConstantNodesPhase(boolean allowResolution, boolean verifyFingerprints) {
this.allowResolution = allowResolution;
this.verifyFingerprints = verifyFingerprints;
}
}

@ -1047,19 +1047,15 @@ public class HtmlDocletWriter {
} else if (refMemName == null) {
// Must be a class reference since refClass is not null and refMemName is null.
if (label.isEmpty()) {
/*
* it seems to me this is the right thing to do, but it causes comparator failures.
*/
if (!configuration.backwardCompatibility) {
StringContent content = utils.isEnclosingPackageIncluded(refClass)
? new StringContent(utils.getSimpleName(refClass))
: new StringContent(utils.getFullyQualifiedName(refClass));
label = plainOrCode(isLinkPlain, content);
} else {
label = plainOrCode(isLinkPlain,
new StringContent(utils.getSimpleName(refClass)));
if (!refClass.getTypeParameters().isEmpty() && seetext.contains("<")) {
// If this is a generic type link try to use the TypeMirror representation.
TypeMirror refType = ch.getReferencedType(see);
if (refType != null) {
return plainOrCode(isLinkPlain, getLink(
new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, refType)));
}
}
label = plainOrCode(isLinkPlain, new StringContent(utils.getSimpleName(refClass)));
}
return getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.DEFAULT, refClass)
.label(label));

@ -136,7 +136,7 @@ public class LinkFactoryImpl extends LinkFactory {
vars.addAll(((DeclaredType) linkInfo.type).getTypeArguments());
} else if (ctype != null && utils.isDeclaredType(ctype)) {
vars.addAll(((DeclaredType) ctype).getTypeArguments());
} else if (linkInfo.typeElement != null) {
} else if (ctype == null && linkInfo.typeElement != null) {
linkInfo.typeElement.getTypeParameters().forEach(t -> vars.add(t.asType()));
} else {
// Nothing to document.

@ -47,11 +47,6 @@ public class LinkInfoImpl extends LinkInfo {
public enum Kind {
DEFAULT,
/**
* Indicate that the link appears in a class list.
*/
ALL_CLASSES_FRAME,
/**
* Indicate that the link appears in a class documentation.
*/
@ -187,11 +182,6 @@ public class LinkInfoImpl extends LinkInfo {
*/
ANNOTATION,
/**
* The header for field documentation copied from parent.
*/
VARIABLE_ELEMENT_COPY,
/**
* The parent nodes in the class tree.
*/
@ -350,12 +340,10 @@ public class LinkInfoImpl extends LinkInfo {
public final void setContext(Kind c) {
//NOTE: Put context specific link code here.
switch (c) {
case ALL_CLASSES_FRAME:
case PACKAGE_FRAME:
case IMPLEMENTED_CLASSES:
case SUBCLASSES:
case EXECUTABLE_ELEMENT_COPY:
case VARIABLE_ELEMENT_COPY:
case PROPERTY_COPY:
case CLASS_USE_HEADER:
includeTypeInClassLinkLabel = false;

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