Merge
This commit is contained in:
commit
d101efc16b
.hgtags
make
src
hotspot
cpu
aarch64
arm
ppc
s390
x86
os
share
aot
c1
gc
epsilon
shared
shenandoah
jfr
opto
prims
runtime
java.base/share/classes/java/net
java.net.http/share/classes
java/net/http
jdk/internal/net/http
jdk.compiler/share/classes/com/sun
jdk.hotspot.agent
doc
share/classes/sun/jvm/hotspot
CommandProcessor.javaHSDB.java
memory
oops
tools/soql
ui
utilities/soql
Callable.javaDefaultScriptObject.javaInvocableCallable.javaJSJavaArray.javaJSJavaArrayKlass.javaJSJavaClass.javaJSJavaFactory.javaJSJavaFactoryImpl.javaJSJavaField.javaJSJavaFrame.javaJSJavaHeap.javaJSJavaInstance.javaJSJavaInstanceKlass.javaJSJavaKlass.javaJSJavaMethod.javaJSJavaObjArray.javaJSJavaObjArrayKlass.javaJSJavaObject.javaJSJavaScriptEngine.javaJSJavaString.javaJSJavaThread.javaJSJavaTypeArray.javaJSJavaTypeArrayKlass.javaJSJavaVM.javaJSList.javaJSMap.javaJSMetadata.javaMapScriptObject.javaMethodCallable.javaSOQLEngine.javaSOQLQuery.javaScriptObject.javasa.js
jdk.incubator.foreign/share/classes/jdk/internal/foreign
AbstractMemorySegmentImpl.javaHeapMemorySegmentImpl.javaMappedMemorySegmentImpl.javaMemoryScope.javaNativeMemorySegmentImpl.java
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
2
.hgtags
2
.hgtags
@ -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;
|
||||
}
|
||||
|
63
src/hotspot/share/gc/epsilon/epsilonInitLogger.cpp
Normal file
63
src/hotspot/share/gc/epsilon/epsilonInitLogger.cpp
Normal file
@ -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&" fieldType="Tickspan"/>
|
||||
<XmlType name="Ticks" contentType="tickstamp" javaType="long" parameterType="const Ticks&" fieldType="Ticks"/>
|
||||
<XmlType name="Tickspan" contentType="tickspan" unsigned="true" javaType="long" parameterType="const Tickspan&" fieldType="Tickspan"/>
|
||||
<XmlType name="Ticks" contentType="tickstamp" unsigned="true" javaType="long" parameterType="const Ticks&" 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 <java script code to select>
|
||||
[ from [instanceof] <class name> [<identifier>]
|
||||
[ where <java script boolean expression> ]
|
||||
]
|
||||
*/
|
||||
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
Loading…
x
Reference in New Issue
Block a user