Merge
This commit is contained in:
commit
5f44b6ca1b
1
.hgtags
1
.hgtags
@ -618,3 +618,4 @@ a96bc204e3b31ddbf909b20088964112f052927e jdk-14+34
|
||||
c7d4f2849dbfb755fc5860b362a4044ea0c9e082 jdk-15+8
|
||||
4a87bb7ebfd7f6a25ec59a5982fe3607242777f8 jdk-14+35
|
||||
62b5bfef8d618e08e6f3a56cf1fb0e67e89e9cc2 jdk-15+9
|
||||
bc54620a3848c26cff9766e5e2a6e5ddab98ed18 jdk-14+36
|
||||
|
@ -75,6 +75,7 @@ $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR)
|
||||
$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@.raw \
|
||||
-Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
|
||||
-Duser.language=en -Duser.country=US \
|
||||
--module-path $(SUPPORT_OUTPUTDIR)/classlist.jar \
|
||||
-cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
|
||||
build.tools.classlist.HelloClasslist \
|
||||
2> $(LINK_OPT_DIR)/stderr > $(JLI_TRACE_FILE) \
|
||||
|
@ -31,6 +31,9 @@
|
||||
*/
|
||||
package build.tools.classlist;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.time.LocalDateTime;
|
||||
@ -55,19 +58,20 @@ public class HelloClasslist {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger("Hello");
|
||||
|
||||
public static void main(String ... args) {
|
||||
public static void main(String ... args) throws Throwable {
|
||||
|
||||
FileSystems.getDefault();
|
||||
|
||||
List<String> strings = Arrays.asList("Hello", "World!", "From: ",
|
||||
InetAddress.getLoopbackAddress().toString());
|
||||
InetAddress.getLoopbackAddress().toString());
|
||||
|
||||
String helloWorld = strings.parallelStream()
|
||||
.map(s -> s.toLowerCase(Locale.ROOT))
|
||||
.collect(joining(","));
|
||||
.map(s -> s.toLowerCase(Locale.ROOT))
|
||||
.collect(joining(","));
|
||||
|
||||
Stream.of(helloWorld.split(","))
|
||||
.forEach(System.out::println);
|
||||
Stream.of(helloWorld.split("([,x-z]{1,3})([\\s]*)"))
|
||||
.map(String::toString)
|
||||
.forEach(System.out::println);
|
||||
|
||||
// Common concatenation patterns
|
||||
String SS = String.valueOf(args.length) + String.valueOf(args.length);
|
||||
@ -83,6 +87,10 @@ public class HelloClasslist {
|
||||
String SCSCS = String.valueOf(args.length) + "string" + String.valueOf(args.length) + "string" + String.valueOf(args.length);
|
||||
String CI = "string" + args.length;
|
||||
String IC = args.length + "string";
|
||||
String SI = String.valueOf(args.length) + args.length;
|
||||
String IS = args.length + String.valueOf(args.length);
|
||||
String CIS = "string" + args.length + String.valueOf(args.length);
|
||||
String CSCI = "string" + String.valueOf(args.length) + "string" + args.length;
|
||||
String CIC = "string" + args.length + "string";
|
||||
String CICI = "string" + args.length + "string" + args.length;
|
||||
String CJ = "string" + System.currentTimeMillis();
|
||||
@ -99,7 +107,31 @@ public class HelloClasslist {
|
||||
DateFormat.getDateInstance(DateFormat.DEFAULT, Locale.ROOT)
|
||||
.format(new Date()));
|
||||
|
||||
// A selection of trivial and relatively common MH operations
|
||||
invoke(MethodHandles.identity(double.class), 1.0);
|
||||
invoke(MethodHandles.identity(int.class), 1);
|
||||
invoke(MethodHandles.identity(String.class), "x");
|
||||
|
||||
invoke(handle("staticMethod_V", MethodType.methodType(void.class)));
|
||||
|
||||
LOGGER.log(Level.FINE, "New Date: " + newDate + " - old: " + oldDate);
|
||||
}
|
||||
|
||||
public static void staticMethod_V() {}
|
||||
|
||||
private static MethodHandle handle(String name, MethodType type) throws Throwable {
|
||||
return MethodHandles.lookup().findStatic(HelloClasslist.class, name, type);
|
||||
}
|
||||
|
||||
private static Object invoke(MethodHandle mh, Object ... args) throws Throwable {
|
||||
try {
|
||||
for (Object o : args) {
|
||||
mh = MethodHandles.insertArguments(mh, 0, o);
|
||||
}
|
||||
return mh.invoke();
|
||||
} catch (Throwable t) {
|
||||
LOGGER.warning("Failed to find, link and/or invoke " + mh.toString() + ": " + t.getMessage());
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -672,11 +672,14 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
}
|
||||
if (FLAG_IS_DEFAULT(UseAVX)) {
|
||||
FLAG_SET_DEFAULT(UseAVX, use_avx_limit);
|
||||
if (is_intel_family_core() && _model == CPU_MODEL_SKYLAKE && _stepping < 5) {
|
||||
FLAG_SET_DEFAULT(UseAVX, 2); //Set UseAVX=2 for Skylake
|
||||
// Don't use AVX-512 on older Skylakes unless explicitly requested.
|
||||
if (use_avx_limit > 2 && is_intel_skylake() && _stepping < 5) {
|
||||
FLAG_SET_DEFAULT(UseAVX, 2);
|
||||
} else {
|
||||
FLAG_SET_DEFAULT(UseAVX, use_avx_limit);
|
||||
}
|
||||
} else if (UseAVX > use_avx_limit) {
|
||||
}
|
||||
if (UseAVX > use_avx_limit) {
|
||||
warning("UseAVX=%d is not supported on this CPU, setting it to UseAVX=%d", (int) UseAVX, use_avx_limit);
|
||||
FLAG_SET_DEFAULT(UseAVX, use_avx_limit);
|
||||
} else if (UseAVX < 0) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -868,6 +868,9 @@ public:
|
||||
static bool is_intel_family_core() { return is_intel() &&
|
||||
extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
|
||||
|
||||
static bool is_intel_skylake() { return is_intel_family_core() &&
|
||||
extended_cpu_model() == CPU_MODEL_SKYLAKE; }
|
||||
|
||||
static bool is_intel_tsc_synched_at_init() {
|
||||
if (is_intel_family_core()) {
|
||||
uint32_t ext_model = extended_cpu_model();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -36,11 +36,12 @@ void OSThread::pd_initialize() {
|
||||
#else
|
||||
_thread_id = NULL;
|
||||
#endif
|
||||
_unique_thread_id = 0;
|
||||
_pthread_id = NULL;
|
||||
_siginfo = NULL;
|
||||
_ucontext = NULL;
|
||||
_expanding_stack = 0;
|
||||
_alt_sig_stack = NULL;
|
||||
_siginfo = NULL;
|
||||
_ucontext = NULL;
|
||||
_expanding_stack = 0;
|
||||
_alt_sig_stack = NULL;
|
||||
|
||||
sigemptyset(&_caller_sigmask);
|
||||
|
||||
@ -49,6 +50,22 @@ void OSThread::pd_initialize() {
|
||||
assert(_startThread_lock !=NULL, "check");
|
||||
}
|
||||
|
||||
// Additional thread_id used to correlate threads in SA
|
||||
void OSThread::set_unique_thread_id() {
|
||||
#ifdef __APPLE__
|
||||
thread_identifier_info_data_t m_ident_info;
|
||||
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
|
||||
|
||||
mach_port_t mach_thread_port = mach_thread_self();
|
||||
guarantee(mach_thread_port != 0, "just checking");
|
||||
thread_info(mach_thread_port, THREAD_IDENTIFIER_INFO,
|
||||
(thread_info_t) &m_ident_info, &count);
|
||||
mach_port_deallocate(mach_task_self(), mach_thread_port);
|
||||
|
||||
_unique_thread_id = m_ident_info.thread_id;
|
||||
#endif
|
||||
}
|
||||
|
||||
void OSThread::pd_destroy() {
|
||||
delete _startThread_lock;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -82,9 +82,7 @@
|
||||
_pthread_id = tid;
|
||||
}
|
||||
|
||||
void set_unique_thread_id(uint64_t id) {
|
||||
_unique_thread_id = id;
|
||||
}
|
||||
void set_unique_thread_id();
|
||||
|
||||
// ***************************************************************
|
||||
// suspension support.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -634,19 +634,6 @@ extern "C" objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFu
|
||||
objc_registerThreadWithCollector_t objc_registerThreadWithCollectorFunction = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
static uint64_t locate_unique_thread_id(mach_port_t mach_thread_port) {
|
||||
// Additional thread_id used to correlate threads in SA
|
||||
thread_identifier_info_data_t m_ident_info;
|
||||
mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT;
|
||||
|
||||
thread_info(mach_thread_port, THREAD_IDENTIFIER_INFO,
|
||||
(thread_info_t) &m_ident_info, &count);
|
||||
|
||||
return m_ident_info.thread_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Thread start routine for all newly created threads
|
||||
static void *thread_native_entry(Thread *thread) {
|
||||
|
||||
@ -672,10 +659,10 @@ static void *thread_native_entry(Thread *thread) {
|
||||
os::current_thread_id(), (uintx) pthread_self());
|
||||
|
||||
#ifdef __APPLE__
|
||||
uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id());
|
||||
guarantee(unique_thread_id != 0, "unique thread id was not found");
|
||||
osthread->set_unique_thread_id(unique_thread_id);
|
||||
// Store unique OS X thread id used by SA
|
||||
osthread->set_unique_thread_id();
|
||||
#endif
|
||||
|
||||
// initialize signal mask for this thread
|
||||
os::Bsd::hotspot_sigmask(thread);
|
||||
|
||||
@ -823,12 +810,12 @@ bool os::create_attached_thread(JavaThread* thread) {
|
||||
|
||||
osthread->set_thread_id(os::Bsd::gettid());
|
||||
|
||||
// Store pthread info into the OSThread
|
||||
#ifdef __APPLE__
|
||||
uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id());
|
||||
guarantee(unique_thread_id != 0, "just checking");
|
||||
osthread->set_unique_thread_id(unique_thread_id);
|
||||
// Store unique OS X thread id used by SA
|
||||
osthread->set_unique_thread_id();
|
||||
#endif
|
||||
|
||||
// Store pthread info into the OSThread
|
||||
osthread->set_pthread_id(::pthread_self());
|
||||
|
||||
// initialize floating point control register
|
||||
@ -1100,12 +1087,11 @@ void os::die() {
|
||||
pid_t os::Bsd::gettid() {
|
||||
int retval = -1;
|
||||
|
||||
#ifdef __APPLE__ //XNU kernel
|
||||
// despite the fact mach port is actually not a thread id use it
|
||||
// instead of syscall(SYS_thread_selfid) as it certainly fits to u4
|
||||
retval = ::pthread_mach_thread_np(::pthread_self());
|
||||
guarantee(retval != 0, "just checking");
|
||||
return retval;
|
||||
#ifdef __APPLE__ // XNU kernel
|
||||
mach_port_t port = mach_thread_self();
|
||||
guarantee(MACH_PORT_VALID(port), "just checking");
|
||||
mach_port_deallocate(mach_task_self(), port);
|
||||
return (pid_t)port;
|
||||
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
@ -1128,7 +1114,7 @@ pid_t os::Bsd::gettid() {
|
||||
|
||||
intx os::current_thread_id() {
|
||||
#ifdef __APPLE__
|
||||
return (intx)::pthread_mach_thread_np(::pthread_self());
|
||||
return (intx)os::Bsd::gettid();
|
||||
#else
|
||||
return (intx)::pthread_self();
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -213,14 +213,19 @@ ciInstanceKlass* ciInstanceKlass::get_canonical_holder(int offset) {
|
||||
}
|
||||
|
||||
ciInstanceKlass* self = this;
|
||||
for (;;) {
|
||||
assert(self->is_loaded(), "must be loaded to have size");
|
||||
ciInstanceKlass* super = self->super();
|
||||
if (super == NULL || super->nof_nonstatic_fields() == 0 ||
|
||||
!super->contains_field_offset(offset)) {
|
||||
return self;
|
||||
} else {
|
||||
self = super; // return super->get_canonical_holder(offset)
|
||||
assert(self->is_loaded(), "must be loaded to access field info");
|
||||
ciField* field = self->get_field_by_offset(offset, false);
|
||||
if (field != NULL) {
|
||||
return field->holder();
|
||||
} else {
|
||||
for (;;) {
|
||||
assert(self->is_loaded(), "must be loaded to have size");
|
||||
ciInstanceKlass* super = self->super();
|
||||
if (super == NULL || super->nof_nonstatic_fields() == 0) {
|
||||
return self;
|
||||
} else {
|
||||
self = super; // return super->get_canonical_holder(offset)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -391,6 +396,13 @@ bool ciInstanceKlass::has_finalizable_subclass() {
|
||||
return Dependencies::find_finalizable_subclass(get_instanceKlass()) != NULL;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciInstanceKlass::contains_field_offset
|
||||
bool ciInstanceKlass::contains_field_offset(int offset) {
|
||||
VM_ENTRY_MARK;
|
||||
return get_instanceKlass()->contains_field_offset(offset);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciInstanceKlass::get_field_by_offset
|
||||
ciField* ciInstanceKlass::get_field_by_offset(int field_offset, bool is_static) {
|
||||
@ -457,15 +469,9 @@ int ciInstanceKlass::compute_nonstatic_fields() {
|
||||
ciInstanceKlass* super = this->super();
|
||||
GrowableArray<ciField*>* super_fields = NULL;
|
||||
if (super != NULL && super->has_nonstatic_fields()) {
|
||||
int super_fsize = super->nonstatic_field_size() * heapOopSize;
|
||||
int super_flen = super->nof_nonstatic_fields();
|
||||
super_fields = super->_nonstatic_fields;
|
||||
assert(super_flen == 0 || super_fields != NULL, "first get nof_fields");
|
||||
// See if I am no larger than my super; if so, I can use his fields.
|
||||
if (fsize == super_fsize) {
|
||||
_nonstatic_fields = super_fields;
|
||||
return super_fields->length();
|
||||
}
|
||||
}
|
||||
|
||||
GrowableArray<ciField*>* fields = NULL;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -225,9 +225,7 @@ public:
|
||||
ciInstanceKlass* unique_concrete_subklass();
|
||||
bool has_finalizable_subclass();
|
||||
|
||||
bool contains_field_offset(int offset) {
|
||||
return instanceOopDesc::contains_field_offset(offset, nonstatic_field_size());
|
||||
}
|
||||
bool contains_field_offset(int offset);
|
||||
|
||||
// Get the instance of java.lang.Class corresponding to
|
||||
// this klass. This instance is used for locking of
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/defaultMethods.hpp"
|
||||
#include "classfile/dictionary.hpp"
|
||||
#include "classfile/fieldLayoutBuilder.hpp"
|
||||
#include "classfile/javaClasses.inline.hpp"
|
||||
#include "classfile/moduleEntry.hpp"
|
||||
#include "classfile/packageEntry.hpp"
|
||||
@ -60,6 +61,7 @@
|
||||
#include "prims/jvmtiExport.hpp"
|
||||
#include "prims/jvmtiThreadState.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
#include "runtime/javaCalls.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
@ -1686,8 +1688,12 @@ void ClassFileParser::parse_fields(const ClassFileStream* const cfs,
|
||||
field->set_allocation_type(atype);
|
||||
|
||||
// After field is initialized with type, we can augment it with aux info
|
||||
if (parsed_annotations.has_any_annotations())
|
||||
if (parsed_annotations.has_any_annotations()) {
|
||||
parsed_annotations.apply_to(field);
|
||||
if (field->is_contended()) {
|
||||
_has_contended_fields = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int index = length;
|
||||
@ -3932,39 +3938,6 @@ const InstanceKlass* ClassFileParser::parse_super_class(ConstantPool* const cp,
|
||||
return super_klass;
|
||||
}
|
||||
|
||||
static unsigned int compute_oop_map_count(const InstanceKlass* super,
|
||||
unsigned int nonstatic_oop_map_count,
|
||||
int first_nonstatic_oop_offset) {
|
||||
|
||||
unsigned int map_count =
|
||||
NULL == super ? 0 : super->nonstatic_oop_map_count();
|
||||
if (nonstatic_oop_map_count > 0) {
|
||||
// We have oops to add to map
|
||||
if (map_count == 0) {
|
||||
map_count = nonstatic_oop_map_count;
|
||||
}
|
||||
else {
|
||||
// Check whether we should add a new map block or whether the last one can
|
||||
// be extended
|
||||
const OopMapBlock* const first_map = super->start_of_nonstatic_oop_maps();
|
||||
const OopMapBlock* const last_map = first_map + map_count - 1;
|
||||
|
||||
const int next_offset = last_map->offset() + last_map->count() * heapOopSize;
|
||||
if (next_offset == first_nonstatic_oop_offset) {
|
||||
// There is no gap bettwen superklass's last oop field and first
|
||||
// local oop field, merge maps.
|
||||
nonstatic_oop_map_count -= 1;
|
||||
}
|
||||
else {
|
||||
// Superklass didn't end with a oop field, add extra maps
|
||||
assert(next_offset < first_nonstatic_oop_offset, "just checking");
|
||||
}
|
||||
map_count += nonstatic_oop_map_count;
|
||||
}
|
||||
}
|
||||
return map_count;
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
static void print_field_layout(const Symbol* name,
|
||||
Array<u2>* fields,
|
||||
@ -4002,18 +3975,121 @@ static void print_field_layout(const Symbol* name,
|
||||
}
|
||||
#endif
|
||||
|
||||
// Values needed for oopmap and InstanceKlass creation
|
||||
class ClassFileParser::FieldLayoutInfo : public ResourceObj {
|
||||
public:
|
||||
int* nonstatic_oop_offsets;
|
||||
unsigned int* nonstatic_oop_counts;
|
||||
unsigned int nonstatic_oop_map_count;
|
||||
unsigned int total_oop_map_count;
|
||||
int instance_size;
|
||||
int nonstatic_field_size;
|
||||
int static_field_size;
|
||||
bool has_nonstatic_fields;
|
||||
};
|
||||
OopMapBlocksBuilder::OopMapBlocksBuilder(unsigned int max_blocks) {
|
||||
_max_nonstatic_oop_maps = max_blocks;
|
||||
_nonstatic_oop_map_count = 0;
|
||||
if (max_blocks == 0) {
|
||||
_nonstatic_oop_maps = NULL;
|
||||
} else {
|
||||
_nonstatic_oop_maps =
|
||||
NEW_RESOURCE_ARRAY(OopMapBlock, _max_nonstatic_oop_maps);
|
||||
memset(_nonstatic_oop_maps, 0, sizeof(OopMapBlock) * max_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
OopMapBlock* OopMapBlocksBuilder::last_oop_map() const {
|
||||
assert(_nonstatic_oop_map_count > 0, "Has no oop maps");
|
||||
return _nonstatic_oop_maps + (_nonstatic_oop_map_count - 1);
|
||||
}
|
||||
|
||||
// addition of super oop maps
|
||||
void OopMapBlocksBuilder::initialize_inherited_blocks(OopMapBlock* blocks, unsigned int nof_blocks) {
|
||||
assert(nof_blocks && _nonstatic_oop_map_count == 0 &&
|
||||
nof_blocks <= _max_nonstatic_oop_maps, "invariant");
|
||||
|
||||
memcpy(_nonstatic_oop_maps, blocks, sizeof(OopMapBlock) * nof_blocks);
|
||||
_nonstatic_oop_map_count += nof_blocks;
|
||||
}
|
||||
|
||||
// collection of oops
|
||||
void OopMapBlocksBuilder::add(int offset, int count) {
|
||||
if (_nonstatic_oop_map_count == 0) {
|
||||
_nonstatic_oop_map_count++;
|
||||
}
|
||||
OopMapBlock* nonstatic_oop_map = last_oop_map();
|
||||
if (nonstatic_oop_map->count() == 0) { // Unused map, set it up
|
||||
nonstatic_oop_map->set_offset(offset);
|
||||
nonstatic_oop_map->set_count(count);
|
||||
} else if (nonstatic_oop_map->is_contiguous(offset)) { // contiguous, add
|
||||
nonstatic_oop_map->increment_count(count);
|
||||
} else { // Need a new one...
|
||||
_nonstatic_oop_map_count++;
|
||||
assert(_nonstatic_oop_map_count <= _max_nonstatic_oop_maps, "range check");
|
||||
nonstatic_oop_map = last_oop_map();
|
||||
nonstatic_oop_map->set_offset(offset);
|
||||
nonstatic_oop_map->set_count(count);
|
||||
}
|
||||
}
|
||||
|
||||
// general purpose copy, e.g. into allocated instanceKlass
|
||||
void OopMapBlocksBuilder::copy(OopMapBlock* dst) {
|
||||
if (_nonstatic_oop_map_count != 0) {
|
||||
memcpy(dst, _nonstatic_oop_maps, sizeof(OopMapBlock) * _nonstatic_oop_map_count);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort and compact adjacent blocks
|
||||
void OopMapBlocksBuilder::compact() {
|
||||
if (_nonstatic_oop_map_count <= 1) {
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Since field layout sneeks in oops before values, we will be able to condense
|
||||
* blocks. There is potential to compact between super, own refs and values
|
||||
* containing refs.
|
||||
*
|
||||
* Currently compaction is slightly limited due to values being 8 byte aligned.
|
||||
* This may well change: FixMe if it doesn't, the code below is fairly general purpose
|
||||
* and maybe it doesn't need to be.
|
||||
*/
|
||||
qsort(_nonstatic_oop_maps, _nonstatic_oop_map_count, sizeof(OopMapBlock),
|
||||
(_sort_Fn)OopMapBlock::compare_offset);
|
||||
if (_nonstatic_oop_map_count < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make a temp copy, and iterate through and copy back into the original
|
||||
ResourceMark rm;
|
||||
OopMapBlock* oop_maps_copy =
|
||||
NEW_RESOURCE_ARRAY(OopMapBlock, _nonstatic_oop_map_count);
|
||||
OopMapBlock* oop_maps_copy_end = oop_maps_copy + _nonstatic_oop_map_count;
|
||||
copy(oop_maps_copy);
|
||||
OopMapBlock* nonstatic_oop_map = _nonstatic_oop_maps;
|
||||
unsigned int new_count = 1;
|
||||
oop_maps_copy++;
|
||||
while(oop_maps_copy < oop_maps_copy_end) {
|
||||
assert(nonstatic_oop_map->offset() < oop_maps_copy->offset(), "invariant");
|
||||
if (nonstatic_oop_map->is_contiguous(oop_maps_copy->offset())) {
|
||||
nonstatic_oop_map->increment_count(oop_maps_copy->count());
|
||||
} else {
|
||||
nonstatic_oop_map++;
|
||||
new_count++;
|
||||
nonstatic_oop_map->set_offset(oop_maps_copy->offset());
|
||||
nonstatic_oop_map->set_count(oop_maps_copy->count());
|
||||
}
|
||||
oop_maps_copy++;
|
||||
}
|
||||
assert(new_count <= _nonstatic_oop_map_count, "end up with more maps after compact() ?");
|
||||
_nonstatic_oop_map_count = new_count;
|
||||
}
|
||||
|
||||
void OopMapBlocksBuilder::print_on(outputStream* st) const {
|
||||
st->print_cr(" OopMapBlocks: %3d /%3d", _nonstatic_oop_map_count, _max_nonstatic_oop_maps);
|
||||
if (_nonstatic_oop_map_count > 0) {
|
||||
OopMapBlock* map = _nonstatic_oop_maps;
|
||||
OopMapBlock* last_map = last_oop_map();
|
||||
assert(map <= last_map, "Last less than first");
|
||||
while (map <= last_map) {
|
||||
st->print_cr(" Offset: %3d -%3d Count: %3d", map->offset(),
|
||||
map->offset() + map->offset_span() - heapOopSize, map->count());
|
||||
map++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OopMapBlocksBuilder::print_value_on(outputStream* st) const {
|
||||
print_on(st);
|
||||
}
|
||||
|
||||
// Layout fields and fill in FieldLayoutInfo. Could use more refactoring!
|
||||
void ClassFileParser::layout_fields(ConstantPool* cp,
|
||||
@ -4100,16 +4176,15 @@ void ClassFileParser::layout_fields(ConstantPool* cp,
|
||||
// count[i] oops following. Before we know how many regions are required,
|
||||
// we pessimistically allocate the maps to fit all the oops into the
|
||||
// distinct regions.
|
||||
//
|
||||
// TODO: We add +1 to always allocate non-zero resource arrays; we need
|
||||
// to figure out if we still need to do this.
|
||||
unsigned int nonstatic_oop_map_count = 0;
|
||||
unsigned int max_nonstatic_oop_maps = fac->count[NONSTATIC_OOP] + 1;
|
||||
|
||||
int* nonstatic_oop_offsets = NEW_RESOURCE_ARRAY_IN_THREAD(
|
||||
THREAD, int, max_nonstatic_oop_maps);
|
||||
unsigned int* const nonstatic_oop_counts = NEW_RESOURCE_ARRAY_IN_THREAD(
|
||||
THREAD, unsigned int, max_nonstatic_oop_maps);
|
||||
int super_oop_map_count = (_super_klass == NULL) ? 0 :_super_klass->nonstatic_oop_map_count();
|
||||
int max_oop_map_count = super_oop_map_count + fac->count[NONSTATIC_OOP];
|
||||
|
||||
OopMapBlocksBuilder* nonstatic_oop_maps = new OopMapBlocksBuilder(max_oop_map_count);
|
||||
if (super_oop_map_count > 0) {
|
||||
nonstatic_oop_maps->initialize_inherited_blocks(_super_klass->start_of_nonstatic_oop_maps(),
|
||||
_super_klass->nonstatic_oop_map_count());
|
||||
}
|
||||
|
||||
int first_nonstatic_oop_offset = 0; // will be set for first oop field
|
||||
|
||||
@ -4260,26 +4335,7 @@ void ClassFileParser::layout_fields(ConstantPool* cp,
|
||||
real_offset = next_nonstatic_oop_offset;
|
||||
next_nonstatic_oop_offset += heapOopSize;
|
||||
}
|
||||
|
||||
// Record this oop in the oop maps
|
||||
if( nonstatic_oop_map_count > 0 &&
|
||||
nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
|
||||
real_offset -
|
||||
int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
|
||||
heapOopSize ) {
|
||||
// This oop is adjacent to the previous one, add to current oop map
|
||||
assert(nonstatic_oop_map_count - 1 < max_nonstatic_oop_maps, "range check");
|
||||
nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
|
||||
} else {
|
||||
// This oop is not adjacent to the previous one, create new oop map
|
||||
assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
|
||||
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
|
||||
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
|
||||
nonstatic_oop_map_count += 1;
|
||||
if( first_nonstatic_oop_offset == 0 ) { // Undefined
|
||||
first_nonstatic_oop_offset = real_offset;
|
||||
}
|
||||
}
|
||||
nonstatic_oop_maps->add(real_offset, 1);
|
||||
break;
|
||||
case NONSTATIC_BYTE:
|
||||
if( nonstatic_byte_space_count > 0 ) {
|
||||
@ -4392,26 +4448,7 @@ void ClassFileParser::layout_fields(ConstantPool* cp,
|
||||
next_nonstatic_padded_offset = align_up(next_nonstatic_padded_offset, heapOopSize);
|
||||
real_offset = next_nonstatic_padded_offset;
|
||||
next_nonstatic_padded_offset += heapOopSize;
|
||||
|
||||
// Record this oop in the oop maps
|
||||
if( nonstatic_oop_map_count > 0 &&
|
||||
nonstatic_oop_offsets[nonstatic_oop_map_count - 1] ==
|
||||
real_offset -
|
||||
int(nonstatic_oop_counts[nonstatic_oop_map_count - 1]) *
|
||||
heapOopSize ) {
|
||||
// This oop is adjacent to the previous one, add to current oop map
|
||||
assert(nonstatic_oop_map_count - 1 < max_nonstatic_oop_maps, "range check");
|
||||
nonstatic_oop_counts[nonstatic_oop_map_count - 1] += 1;
|
||||
} else {
|
||||
// This oop is not adjacent to the previous one, create new oop map
|
||||
assert(nonstatic_oop_map_count < max_nonstatic_oop_maps, "range check");
|
||||
nonstatic_oop_offsets[nonstatic_oop_map_count] = real_offset;
|
||||
nonstatic_oop_counts [nonstatic_oop_map_count] = 1;
|
||||
nonstatic_oop_map_count += 1;
|
||||
if( first_nonstatic_oop_offset == 0 ) { // Undefined
|
||||
first_nonstatic_oop_offset = real_offset;
|
||||
}
|
||||
}
|
||||
nonstatic_oop_maps->add(real_offset, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -4475,9 +4512,7 @@ void ClassFileParser::layout_fields(ConstantPool* cp,
|
||||
(nonstatic_fields_count > 0), "double-check nonstatic start/end");
|
||||
|
||||
// Number of non-static oop map blocks allocated at end of klass.
|
||||
const unsigned int total_oop_map_count =
|
||||
compute_oop_map_count(_super_klass, nonstatic_oop_map_count,
|
||||
first_nonstatic_oop_offset);
|
||||
nonstatic_oop_maps->compact();
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (PrintFieldLayout) {
|
||||
@ -4492,58 +4527,13 @@ void ClassFileParser::layout_fields(ConstantPool* cp,
|
||||
|
||||
#endif
|
||||
// Pass back information needed for InstanceKlass creation
|
||||
info->nonstatic_oop_offsets = nonstatic_oop_offsets;
|
||||
info->nonstatic_oop_counts = nonstatic_oop_counts;
|
||||
info->nonstatic_oop_map_count = nonstatic_oop_map_count;
|
||||
info->total_oop_map_count = total_oop_map_count;
|
||||
info->instance_size = instance_size;
|
||||
info->static_field_size = static_field_size;
|
||||
info->nonstatic_field_size = nonstatic_field_size;
|
||||
info->has_nonstatic_fields = has_nonstatic_fields;
|
||||
info->oop_map_blocks = nonstatic_oop_maps;
|
||||
info->_instance_size = instance_size;
|
||||
info->_static_field_size = static_field_size;
|
||||
info->_nonstatic_field_size = nonstatic_field_size;
|
||||
info->_has_nonstatic_fields = has_nonstatic_fields;
|
||||
}
|
||||
|
||||
static void fill_oop_maps(const InstanceKlass* k,
|
||||
unsigned int nonstatic_oop_map_count,
|
||||
const int* nonstatic_oop_offsets,
|
||||
const unsigned int* nonstatic_oop_counts) {
|
||||
|
||||
assert(k != NULL, "invariant");
|
||||
|
||||
OopMapBlock* this_oop_map = k->start_of_nonstatic_oop_maps();
|
||||
const InstanceKlass* const super = k->superklass();
|
||||
const unsigned int super_count = super ? super->nonstatic_oop_map_count() : 0;
|
||||
if (super_count > 0) {
|
||||
// Copy maps from superklass
|
||||
OopMapBlock* super_oop_map = super->start_of_nonstatic_oop_maps();
|
||||
for (unsigned int i = 0; i < super_count; ++i) {
|
||||
*this_oop_map++ = *super_oop_map++;
|
||||
}
|
||||
}
|
||||
|
||||
if (nonstatic_oop_map_count > 0) {
|
||||
if (super_count + nonstatic_oop_map_count > k->nonstatic_oop_map_count()) {
|
||||
// The counts differ because there is no gap between superklass's last oop
|
||||
// field and the first local oop field. Extend the last oop map copied
|
||||
// from the superklass instead of creating new one.
|
||||
nonstatic_oop_map_count--;
|
||||
nonstatic_oop_offsets++;
|
||||
this_oop_map--;
|
||||
this_oop_map->set_count(this_oop_map->count() + *nonstatic_oop_counts++);
|
||||
this_oop_map++;
|
||||
}
|
||||
|
||||
// Add new map blocks, fill them
|
||||
while (nonstatic_oop_map_count-- > 0) {
|
||||
this_oop_map->set_offset(*nonstatic_oop_offsets++);
|
||||
this_oop_map->set_count(*nonstatic_oop_counts++);
|
||||
this_oop_map++;
|
||||
}
|
||||
assert(k->start_of_nonstatic_oop_maps() + k->nonstatic_oop_map_count() ==
|
||||
this_oop_map, "sanity");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ClassFileParser::set_precomputed_flags(InstanceKlass* ik) {
|
||||
assert(ik != NULL, "invariant");
|
||||
|
||||
@ -5498,17 +5488,17 @@ int ClassFileParser::verify_legal_method_signature(const Symbol* name,
|
||||
|
||||
int ClassFileParser::static_field_size() const {
|
||||
assert(_field_info != NULL, "invariant");
|
||||
return _field_info->static_field_size;
|
||||
return _field_info->_static_field_size;
|
||||
}
|
||||
|
||||
int ClassFileParser::total_oop_map_count() const {
|
||||
assert(_field_info != NULL, "invariant");
|
||||
return _field_info->total_oop_map_count;
|
||||
return _field_info->oop_map_blocks->_nonstatic_oop_map_count;
|
||||
}
|
||||
|
||||
jint ClassFileParser::layout_size() const {
|
||||
assert(_field_info != NULL, "invariant");
|
||||
return _field_info->instance_size;
|
||||
return _field_info->_instance_size;
|
||||
}
|
||||
|
||||
static void check_methods_for_intrinsics(const InstanceKlass* ik,
|
||||
@ -5652,19 +5642,19 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
|
||||
set_klass_to_deallocate(ik);
|
||||
|
||||
assert(_field_info != NULL, "invariant");
|
||||
assert(ik->static_field_size() == _field_info->static_field_size, "sanity");
|
||||
assert(ik->nonstatic_oop_map_count() == _field_info->total_oop_map_count,
|
||||
"sanity");
|
||||
assert(ik->static_field_size() == _field_info->_static_field_size, "sanity");
|
||||
assert(ik->nonstatic_oop_map_count() == _field_info->oop_map_blocks->_nonstatic_oop_map_count,
|
||||
"sanity");
|
||||
|
||||
assert(ik->is_instance_klass(), "sanity");
|
||||
assert(ik->size_helper() == _field_info->instance_size, "sanity");
|
||||
assert(ik->size_helper() == _field_info->_instance_size, "sanity");
|
||||
|
||||
// Fill in information already parsed
|
||||
ik->set_should_verify_class(_need_verify);
|
||||
|
||||
// Not yet: supers are done below to support the new subtype-checking fields
|
||||
ik->set_nonstatic_field_size(_field_info->nonstatic_field_size);
|
||||
ik->set_has_nonstatic_fields(_field_info->has_nonstatic_fields);
|
||||
ik->set_nonstatic_field_size(_field_info->_nonstatic_field_size);
|
||||
ik->set_has_nonstatic_fields(_field_info->_has_nonstatic_fields);
|
||||
assert(_fac != NULL, "invariant");
|
||||
ik->set_static_oop_field_count(_fac->count[STATIC_OOP]);
|
||||
|
||||
@ -5755,10 +5745,15 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loa
|
||||
|
||||
// Compute transitive closure of interfaces this class implements
|
||||
// Do final class setup
|
||||
fill_oop_maps(ik,
|
||||
_field_info->nonstatic_oop_map_count,
|
||||
_field_info->nonstatic_oop_offsets,
|
||||
_field_info->nonstatic_oop_counts);
|
||||
OopMapBlocksBuilder* oop_map_blocks = _field_info->oop_map_blocks;
|
||||
if (oop_map_blocks->_nonstatic_oop_map_count > 0) {
|
||||
oop_map_blocks->copy(ik->start_of_nonstatic_oop_maps());
|
||||
}
|
||||
|
||||
if (_has_contended_fields || _parsed_annotations->is_contended() ||
|
||||
( _super_klass != NULL && _super_klass->has_contended_annotations())) {
|
||||
ik->set_has_contended_annotations(true);
|
||||
}
|
||||
|
||||
// Fill in has_finalizer, has_vanilla_constructor, and layout_helper
|
||||
set_precomputed_flags(ik);
|
||||
@ -6001,6 +5996,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream,
|
||||
_has_nonstatic_concrete_methods(false),
|
||||
_declares_nonstatic_concrete_methods(false),
|
||||
_has_final_method(false),
|
||||
_has_contended_fields(false),
|
||||
_has_finalizer(false),
|
||||
_has_empty_finalizer(false),
|
||||
_has_vanilla_constructor(false),
|
||||
@ -6478,7 +6474,13 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st
|
||||
assert(_parsed_annotations != NULL, "invariant");
|
||||
|
||||
_field_info = new FieldLayoutInfo();
|
||||
layout_fields(cp, _fac, _parsed_annotations, _field_info, CHECK);
|
||||
if (UseNewFieldLayout) {
|
||||
FieldLayoutBuilder lb(class_name(), super_klass(), _cp, _fields,
|
||||
_parsed_annotations->is_contended(), _field_info);
|
||||
lb.build_layout();
|
||||
} else {
|
||||
layout_fields(cp, _fac, _parsed_annotations, _field_info, CHECK);
|
||||
}
|
||||
|
||||
// Compute reference typ
|
||||
_rt = (NULL ==_super_klass) ? REF_NONE : _super_klass->reference_type();
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -28,6 +28,7 @@
|
||||
#include "memory/referenceType.hpp"
|
||||
#include "oops/annotations.hpp"
|
||||
#include "oops/constantPool.hpp"
|
||||
#include "oops/instanceKlass.hpp"
|
||||
#include "oops/typeArrayOop.hpp"
|
||||
#include "utilities/accessFlags.hpp"
|
||||
|
||||
@ -45,17 +46,46 @@ class InstanceKlass;
|
||||
class RecordComponent;
|
||||
class Symbol;
|
||||
class TempNewSymbol;
|
||||
class FieldLayoutBuilder;
|
||||
|
||||
// Utility to collect and compact oop maps during layout
|
||||
class OopMapBlocksBuilder : public ResourceObj {
|
||||
public:
|
||||
OopMapBlock* _nonstatic_oop_maps;
|
||||
unsigned int _nonstatic_oop_map_count;
|
||||
unsigned int _max_nonstatic_oop_maps;
|
||||
|
||||
OopMapBlocksBuilder(unsigned int max_blocks);
|
||||
OopMapBlock* last_oop_map() const;
|
||||
void initialize_inherited_blocks(OopMapBlock* blocks, unsigned int nof_blocks);
|
||||
void add(int offset, int count);
|
||||
void copy(OopMapBlock* dst);
|
||||
void compact();
|
||||
void print_on(outputStream* st) const;
|
||||
void print_value_on(outputStream* st) const;
|
||||
};
|
||||
|
||||
// Values needed for oopmap and InstanceKlass creation
|
||||
class FieldLayoutInfo : public ResourceObj {
|
||||
public:
|
||||
OopMapBlocksBuilder* oop_map_blocks;
|
||||
int _instance_size;
|
||||
int _nonstatic_field_size;
|
||||
int _static_field_size;
|
||||
bool _has_nonstatic_fields;
|
||||
};
|
||||
|
||||
// Parser for for .class files
|
||||
//
|
||||
// The bytes describing the class file structure is read from a Stream object
|
||||
|
||||
class ClassFileParser {
|
||||
friend class FieldLayoutBuilder;
|
||||
friend class FieldLayout;
|
||||
|
||||
class ClassAnnotationCollector;
|
||||
class FieldAllocationCount;
|
||||
class FieldAnnotationCollector;
|
||||
class FieldLayoutInfo;
|
||||
class ClassAnnotationCollector;
|
||||
class FieldAllocationCount;
|
||||
class FieldAnnotationCollector;
|
||||
|
||||
public:
|
||||
// The ClassFileParser has an associated "publicity" level
|
||||
@ -161,6 +191,7 @@ class ClassFileParser {
|
||||
bool _has_nonstatic_concrete_methods;
|
||||
bool _declares_nonstatic_concrete_methods;
|
||||
bool _has_final_method;
|
||||
bool _has_contended_fields;
|
||||
|
||||
// precomputed flags
|
||||
bool _has_finalizer;
|
||||
|
780
src/hotspot/share/classfile/fieldLayoutBuilder.cpp
Normal file
780
src/hotspot/share/classfile/fieldLayoutBuilder.cpp
Normal file
@ -0,0 +1,780 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "jvm.h"
|
||||
#include "classfile/classFileParser.hpp"
|
||||
#include "classfile/fieldLayoutBuilder.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/array.hpp"
|
||||
#include "oops/fieldStreams.inline.hpp"
|
||||
#include "oops/instanceMirrorKlass.hpp"
|
||||
#include "oops/klass.inline.hpp"
|
||||
#include "runtime/fieldDescriptor.inline.hpp"
|
||||
|
||||
|
||||
LayoutRawBlock::LayoutRawBlock(Kind kind, int size) :
|
||||
_next_block(NULL),
|
||||
_prev_block(NULL),
|
||||
_kind(kind),
|
||||
_offset(-1),
|
||||
_alignment(1),
|
||||
_size(size),
|
||||
_field_index(-1),
|
||||
_is_reference(false) {
|
||||
assert(kind == EMPTY || kind == RESERVED || kind == PADDING || kind == INHERITED,
|
||||
"Otherwise, should use the constructor with a field index argument");
|
||||
assert(size > 0, "Sanity check");
|
||||
}
|
||||
|
||||
|
||||
LayoutRawBlock::LayoutRawBlock(int index, Kind kind, int size, int alignment, bool is_reference) :
|
||||
_next_block(NULL),
|
||||
_prev_block(NULL),
|
||||
_kind(kind),
|
||||
_offset(-1),
|
||||
_alignment(alignment),
|
||||
_size(size),
|
||||
_field_index(index),
|
||||
_is_reference(is_reference) {
|
||||
assert(kind == REGULAR || kind == FLATTENED || kind == INHERITED,
|
||||
"Other kind do not have a field index");
|
||||
assert(size > 0, "Sanity check");
|
||||
assert(alignment > 0, "Sanity check");
|
||||
}
|
||||
|
||||
bool LayoutRawBlock::fit(int size, int alignment) {
|
||||
int adjustment = 0;
|
||||
if ((_offset % alignment) != 0) {
|
||||
adjustment = alignment - (_offset % alignment);
|
||||
}
|
||||
return _size >= size + adjustment;
|
||||
}
|
||||
|
||||
FieldGroup::FieldGroup(int contended_group) :
|
||||
_next(NULL),
|
||||
_primitive_fields(NULL),
|
||||
_oop_fields(NULL),
|
||||
_contended_group(contended_group), // -1 means no contended group, 0 means default contended group
|
||||
_oop_count(0) {}
|
||||
|
||||
void FieldGroup::add_primitive_field(AllFieldStream fs, BasicType type) {
|
||||
int size = type2aelembytes(type);
|
||||
LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::REGULAR, size, size /* alignment == size for primitive types */, false);
|
||||
if (_primitive_fields == NULL) {
|
||||
_primitive_fields = new(ResourceObj::RESOURCE_AREA, mtInternal) GrowableArray<LayoutRawBlock*>(INITIAL_LIST_SIZE);
|
||||
}
|
||||
_primitive_fields->append(block);
|
||||
}
|
||||
|
||||
void FieldGroup::add_oop_field(AllFieldStream fs) {
|
||||
int size = type2aelembytes(T_OBJECT);
|
||||
LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::REGULAR, size, size /* alignment == size for oops */, true);
|
||||
if (_oop_fields == NULL) {
|
||||
_oop_fields = new(ResourceObj::RESOURCE_AREA, mtInternal) GrowableArray<LayoutRawBlock*>(INITIAL_LIST_SIZE);
|
||||
}
|
||||
_oop_fields->append(block);
|
||||
_oop_count++;
|
||||
}
|
||||
|
||||
void FieldGroup::sort_by_size() {
|
||||
if (_primitive_fields != NULL) {
|
||||
_primitive_fields->sort(LayoutRawBlock::compare_size_inverted);
|
||||
}
|
||||
}
|
||||
|
||||
FieldLayout::FieldLayout(Array<u2>* fields, ConstantPool* cp) :
|
||||
_fields(fields),
|
||||
_cp(cp),
|
||||
_blocks(NULL),
|
||||
_start(_blocks),
|
||||
_last(_blocks) {}
|
||||
|
||||
void FieldLayout::initialize_static_layout() {
|
||||
_blocks = new LayoutRawBlock(LayoutRawBlock::EMPTY, INT_MAX);
|
||||
_blocks->set_offset(0);
|
||||
_last = _blocks;
|
||||
_start = _blocks;
|
||||
// Note: at this stage, InstanceMirrorKlass::offset_of_static_fields() could be zero, because
|
||||
// during bootstrapping, the size of the java.lang.Class is still not known when layout
|
||||
// of static field is computed. Field offsets are fixed later when the size is known
|
||||
// (see java_lang_Class::fixup_mirror())
|
||||
if (InstanceMirrorKlass::offset_of_static_fields() > 0) {
|
||||
insert(first_empty_block(), new LayoutRawBlock(LayoutRawBlock::RESERVED, InstanceMirrorKlass::offset_of_static_fields()));
|
||||
_blocks->set_offset(0);
|
||||
}
|
||||
}
|
||||
|
||||
void FieldLayout::initialize_instance_layout(const InstanceKlass* super_klass) {
|
||||
if (super_klass == NULL) {
|
||||
_blocks = new LayoutRawBlock(LayoutRawBlock::EMPTY, INT_MAX);
|
||||
_blocks->set_offset(0);
|
||||
_last = _blocks;
|
||||
_start = _blocks;
|
||||
insert(first_empty_block(), new LayoutRawBlock(LayoutRawBlock::RESERVED, instanceOopDesc::base_offset_in_bytes()));
|
||||
} else {
|
||||
reconstruct_layout(super_klass);
|
||||
fill_holes(super_klass);
|
||||
if (UseEmptySlotsInSupers && !super_klass->has_contended_annotations()) {
|
||||
_start = _blocks; // Setting _start to _blocks instead of _last would allow subclasses
|
||||
// to allocate fields in empty slots of their super classes
|
||||
} else {
|
||||
_start = _last;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LayoutRawBlock* FieldLayout::first_field_block() {
|
||||
LayoutRawBlock* block = _start;
|
||||
while (block->kind() != LayoutRawBlock::INHERITED && block->kind() != LayoutRawBlock::REGULAR
|
||||
&& block->kind() != LayoutRawBlock::FLATTENED && block->kind() != LayoutRawBlock::PADDING) {
|
||||
block = block->next_block();
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
// Insert a set of fields into a layout using a best-fit strategy.
|
||||
// For each field, search for the smallest empty slot able to fit the field
|
||||
// (satisfying both size and alignment requirements), if none is found,
|
||||
// add the field at the end of the layout.
|
||||
// Fields cannot be inserted before the block specified in the "start" argument
|
||||
void FieldLayout::add(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start) {
|
||||
if (list == NULL) return;
|
||||
if (start == NULL) start = this->_start;
|
||||
bool last_search_success = false;
|
||||
int last_size = 0;
|
||||
int last_alignment = 0;
|
||||
for (int i = 0; i < list->length(); i ++) {
|
||||
LayoutRawBlock* b = list->at(i);
|
||||
LayoutRawBlock* cursor = NULL;
|
||||
LayoutRawBlock* candidate = NULL;
|
||||
|
||||
// if start is the last block, just append the field
|
||||
if (start == last_block()) {
|
||||
candidate = last_block();
|
||||
}
|
||||
// Before iterating over the layout to find an empty slot fitting the field's requirements,
|
||||
// check if the previous field had the same requirements and if the search for a fitting slot
|
||||
// was successful. If the requirements were the same but the search failed, a new search will
|
||||
// fail the same way, so just append the field at the of the layout.
|
||||
else if (b->size() == last_size && b->alignment() == last_alignment && !last_search_success) {
|
||||
candidate = last_block();
|
||||
} else {
|
||||
// Iterate over the layout to find an empty slot fitting the field's requirements
|
||||
last_size = b->size();
|
||||
last_alignment = b->alignment();
|
||||
cursor = last_block()->prev_block();
|
||||
assert(cursor != NULL, "Sanity check");
|
||||
last_search_success = true;
|
||||
while (cursor != start) {
|
||||
if (cursor->kind() == LayoutRawBlock::EMPTY && cursor->fit(b->size(), b->alignment())) {
|
||||
if (candidate == NULL || cursor->size() < candidate->size()) {
|
||||
candidate = cursor;
|
||||
}
|
||||
}
|
||||
cursor = cursor->prev_block();
|
||||
}
|
||||
if (candidate == NULL) {
|
||||
candidate = last_block();
|
||||
last_search_success = false;
|
||||
}
|
||||
assert(candidate != NULL, "Candidate must not be null");
|
||||
assert(candidate->kind() == LayoutRawBlock::EMPTY, "Candidate must be an empty block");
|
||||
assert(candidate->fit(b->size(), b->alignment()), "Candidate must be able to store the block");
|
||||
}
|
||||
|
||||
insert_field_block(candidate, b);
|
||||
}
|
||||
}
|
||||
|
||||
// Used for classes with hard coded field offsets, insert a field at the specified offset */
|
||||
void FieldLayout::add_field_at_offset(LayoutRawBlock* block, int offset, LayoutRawBlock* start) {
|
||||
assert(block != NULL, "Sanity check");
|
||||
block->set_offset(offset);
|
||||
if (start == NULL) {
|
||||
start = this->_start;
|
||||
}
|
||||
LayoutRawBlock* slot = start;
|
||||
while (slot != NULL) {
|
||||
if ((slot->offset() <= block->offset() && (slot->offset() + slot->size()) > block->offset()) ||
|
||||
slot == _last){
|
||||
assert(slot->kind() == LayoutRawBlock::EMPTY, "Matching slot must be an empty slot");
|
||||
assert(slot->size() >= block->offset() + block->size() ,"Matching slot must be big enough");
|
||||
if (slot->offset() < block->offset()) {
|
||||
int adjustment = block->offset() - slot->offset();
|
||||
LayoutRawBlock* adj = new LayoutRawBlock(LayoutRawBlock::EMPTY, adjustment);
|
||||
insert(slot, adj);
|
||||
}
|
||||
insert(slot, block);
|
||||
if (slot->size() == 0) {
|
||||
remove(slot);
|
||||
}
|
||||
FieldInfo::from_field_array(_fields, block->field_index())->set_offset(block->offset());
|
||||
return;
|
||||
}
|
||||
slot = slot->next_block();
|
||||
}
|
||||
fatal("Should have found a matching slot above, corrupted layout or invalid offset");
|
||||
}
|
||||
|
||||
// The allocation logic uses a best fit strategy: the set of fields is allocated
|
||||
// in the first empty slot big enough to contain the whole set ((including padding
|
||||
// to fit alignment constraints).
|
||||
void FieldLayout::add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start) {
|
||||
if (list == NULL) return;
|
||||
if (start == NULL) {
|
||||
start = _start;
|
||||
}
|
||||
// This code assumes that if the first block is well aligned, the following
|
||||
// blocks would naturally be well aligned (no need for adjustment)
|
||||
int size = 0;
|
||||
for (int i = 0; i < list->length(); i++) {
|
||||
size += list->at(i)->size();
|
||||
}
|
||||
|
||||
LayoutRawBlock* candidate = NULL;
|
||||
if (start == last_block()) {
|
||||
candidate = last_block();
|
||||
} else {
|
||||
LayoutRawBlock* first = list->at(0);
|
||||
candidate = last_block()->prev_block();
|
||||
while (candidate->kind() != LayoutRawBlock::EMPTY || !candidate->fit(size, first->alignment())) {
|
||||
if (candidate == start) {
|
||||
candidate = last_block();
|
||||
break;
|
||||
}
|
||||
candidate = candidate->prev_block();
|
||||
}
|
||||
assert(candidate != NULL, "Candidate must not be null");
|
||||
assert(candidate->kind() == LayoutRawBlock::EMPTY, "Candidate must be an empty block");
|
||||
assert(candidate->fit(size, first->alignment()), "Candidate must be able to store the whole contiguous block");
|
||||
}
|
||||
|
||||
for (int i = 0; i < list->length(); i++) {
|
||||
LayoutRawBlock* b = list->at(i);
|
||||
insert_field_block(candidate, b);
|
||||
assert((candidate->offset() % b->alignment() == 0), "Contiguous blocks must be naturally well aligned");
|
||||
}
|
||||
}
|
||||
|
||||
LayoutRawBlock* FieldLayout::insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block) {
|
||||
assert(slot->kind() == LayoutRawBlock::EMPTY, "Blocks can only be inserted in empty blocks");
|
||||
if (slot->offset() % block->alignment() != 0) {
|
||||
int adjustment = block->alignment() - (slot->offset() % block->alignment());
|
||||
LayoutRawBlock* adj = new LayoutRawBlock(LayoutRawBlock::EMPTY, adjustment);
|
||||
insert(slot, adj);
|
||||
}
|
||||
insert(slot, block);
|
||||
if (slot->size() == 0) {
|
||||
remove(slot);
|
||||
}
|
||||
FieldInfo::from_field_array(_fields, block->field_index())->set_offset(block->offset());
|
||||
return block;
|
||||
}
|
||||
|
||||
void FieldLayout::reconstruct_layout(const InstanceKlass* ik) {
|
||||
GrowableArray<LayoutRawBlock*>* all_fields = new GrowableArray<LayoutRawBlock*>(32);
|
||||
while (ik != NULL) {
|
||||
for (AllFieldStream fs(ik->fields(), ik->constants()); !fs.done(); fs.next()) {
|
||||
BasicType type = Signature::basic_type(fs.signature());
|
||||
// distinction between static and non-static fields is missing
|
||||
if (fs.access_flags().is_static()) continue;
|
||||
int size = type2aelembytes(type);
|
||||
// INHERITED blocks are marked as non-reference because oop_maps are handled by their holder class
|
||||
LayoutRawBlock* block = new LayoutRawBlock(fs.index(), LayoutRawBlock::INHERITED, size, size, false);
|
||||
block->set_offset(fs.offset());
|
||||
all_fields->append(block);
|
||||
}
|
||||
ik = ik->super() == NULL ? NULL : InstanceKlass::cast(ik->super());
|
||||
}
|
||||
|
||||
all_fields->sort(LayoutRawBlock::compare_offset);
|
||||
_blocks = new LayoutRawBlock(LayoutRawBlock::RESERVED, instanceOopDesc::base_offset_in_bytes());
|
||||
_blocks->set_offset(0);
|
||||
_last = _blocks;
|
||||
|
||||
for(int i = 0; i < all_fields->length(); i++) {
|
||||
LayoutRawBlock* b = all_fields->at(i);
|
||||
_last->set_next_block(b);
|
||||
b->set_prev_block(_last);
|
||||
_last = b;
|
||||
}
|
||||
_start = _blocks;
|
||||
}
|
||||
|
||||
// Called during the reconstruction of a layout, after fields from super
|
||||
// classes have been inserted. It fills unused slots between inserted fields
|
||||
// with EMPTY blocks, so the regular field insertion methods would work.
|
||||
// This method handles classes with @Contended annotations differently
|
||||
// by inserting PADDING blocks instead of EMPTY block to prevent subclasses'
|
||||
// fields to interfere with contended fields/classes.
|
||||
void FieldLayout::fill_holes(const InstanceKlass* super_klass) {
|
||||
assert(_blocks != NULL, "Sanity check");
|
||||
assert(_blocks->offset() == 0, "first block must be at offset zero");
|
||||
LayoutRawBlock::Kind filling_type = super_klass->has_contended_annotations() ? LayoutRawBlock::PADDING: LayoutRawBlock::EMPTY;
|
||||
LayoutRawBlock* b = _blocks;
|
||||
while (b->next_block() != NULL) {
|
||||
if (b->next_block()->offset() > (b->offset() + b->size())) {
|
||||
int size = b->next_block()->offset() - (b->offset() + b->size());
|
||||
LayoutRawBlock* empty = new LayoutRawBlock(filling_type, size);
|
||||
empty->set_offset(b->offset() + b->size());
|
||||
empty->set_next_block(b->next_block());
|
||||
b->next_block()->set_prev_block(empty);
|
||||
b->set_next_block(empty);
|
||||
empty->set_prev_block(b);
|
||||
}
|
||||
b = b->next_block();
|
||||
}
|
||||
assert(b->next_block() == NULL, "Invariant at this point");
|
||||
assert(b->kind() != LayoutRawBlock::EMPTY, "Sanity check");
|
||||
|
||||
// If the super class has @Contended annotation, a padding block is
|
||||
// inserted at the end to ensure that fields from the subclasses won't share
|
||||
// the cache line of the last field of the contended class
|
||||
if (super_klass->has_contended_annotations()) {
|
||||
LayoutRawBlock* p = new LayoutRawBlock(LayoutRawBlock::PADDING, ContendedPaddingWidth);
|
||||
p->set_offset(b->offset() + b->size());
|
||||
b->set_next_block(p);
|
||||
p->set_prev_block(b);
|
||||
b = p;
|
||||
}
|
||||
|
||||
if (!UseEmptySlotsInSupers) {
|
||||
// Add an empty slots to align fields of the subclass on a heapOopSize boundary
|
||||
// in order to emulate the behavior of the previous algorithm
|
||||
int align = (b->offset() + b->size()) % heapOopSize;
|
||||
if (align != 0) {
|
||||
int sz = heapOopSize - align;
|
||||
LayoutRawBlock* p = new LayoutRawBlock(LayoutRawBlock::EMPTY, sz);
|
||||
p->set_offset(b->offset() + b->size());
|
||||
b->set_next_block(p);
|
||||
p->set_prev_block(b);
|
||||
b = p;
|
||||
}
|
||||
}
|
||||
|
||||
LayoutRawBlock* last = new LayoutRawBlock(LayoutRawBlock::EMPTY, INT_MAX);
|
||||
last->set_offset(b->offset() + b->size());
|
||||
assert(last->offset() > 0, "Sanity check");
|
||||
b->set_next_block(last);
|
||||
last->set_prev_block(b);
|
||||
_last = last;
|
||||
}
|
||||
|
||||
LayoutRawBlock* FieldLayout::insert(LayoutRawBlock* slot, LayoutRawBlock* block) {
|
||||
assert(slot->kind() == LayoutRawBlock::EMPTY, "Blocks can only be inserted in empty blocks");
|
||||
assert(slot->offset() % block->alignment() == 0, "Incompatible alignment");
|
||||
block->set_offset(slot->offset());
|
||||
slot->set_offset(slot->offset() + block->size());
|
||||
assert((slot->size() - block->size()) < slot->size(), "underflow checking");
|
||||
assert(slot->size() - block->size() >= 0, "no negative size allowed");
|
||||
slot->set_size(slot->size() - block->size());
|
||||
block->set_prev_block(slot->prev_block());
|
||||
block->set_next_block(slot);
|
||||
slot->set_prev_block(block);
|
||||
if (block->prev_block() != NULL) {
|
||||
block->prev_block()->set_next_block(block);
|
||||
}
|
||||
if (_blocks == slot) {
|
||||
_blocks = block;
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
void FieldLayout::remove(LayoutRawBlock* block) {
|
||||
assert(block != NULL, "Sanity check");
|
||||
assert(block != _last, "Sanity check");
|
||||
if (_blocks == block) {
|
||||
_blocks = block->next_block();
|
||||
if (_blocks != NULL) {
|
||||
_blocks->set_prev_block(NULL);
|
||||
}
|
||||
} else {
|
||||
assert(block->prev_block() != NULL, "_prev should be set for non-head blocks");
|
||||
block->prev_block()->set_next_block(block->next_block());
|
||||
block->next_block()->set_prev_block(block->prev_block());
|
||||
}
|
||||
if (block == _start) {
|
||||
_start = block->prev_block();
|
||||
}
|
||||
}
|
||||
|
||||
void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlass* super) {
|
||||
ResourceMark rm;
|
||||
LayoutRawBlock* b = _blocks;
|
||||
while(b != _last) {
|
||||
switch(b->kind()) {
|
||||
case LayoutRawBlock::REGULAR: {
|
||||
FieldInfo* fi = FieldInfo::from_field_array(_fields, b->field_index());
|
||||
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
||||
b->offset(),
|
||||
fi->name(_cp)->as_C_string(),
|
||||
fi->signature(_cp)->as_C_string(),
|
||||
b->size(),
|
||||
b->alignment(),
|
||||
"REGULAR");
|
||||
break;
|
||||
}
|
||||
case LayoutRawBlock::FLATTENED: {
|
||||
FieldInfo* fi = FieldInfo::from_field_array(_fields, b->field_index());
|
||||
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
||||
b->offset(),
|
||||
fi->name(_cp)->as_C_string(),
|
||||
fi->signature(_cp)->as_C_string(),
|
||||
b->size(),
|
||||
b->alignment(),
|
||||
"FLATTENED");
|
||||
break;
|
||||
}
|
||||
case LayoutRawBlock::RESERVED: {
|
||||
output->print_cr(" @%d %d/- %s",
|
||||
b->offset(),
|
||||
b->size(),
|
||||
"RESERVED");
|
||||
break;
|
||||
}
|
||||
case LayoutRawBlock::INHERITED: {
|
||||
assert(!is_static, "Static fields are not inherited in layouts");
|
||||
assert(super != NULL, "super klass must be provided to retrieve inherited fields info");
|
||||
bool found = false;
|
||||
const InstanceKlass* ik = super;
|
||||
while (!found && ik != NULL) {
|
||||
for (AllFieldStream fs(ik->fields(), ik->constants()); !fs.done(); fs.next()) {
|
||||
if (fs.offset() == b->offset()) {
|
||||
output->print_cr(" @%d \"%s\" %s %d/%d %s",
|
||||
b->offset(),
|
||||
fs.name()->as_C_string(),
|
||||
fs.signature()->as_C_string(),
|
||||
b->size(),
|
||||
b->size(), // so far, alignment constraint == size, will change with Valhalla
|
||||
"INHERITED");
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ik = ik->java_super();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LayoutRawBlock::EMPTY:
|
||||
output->print_cr(" @%d %d/1 %s",
|
||||
b->offset(),
|
||||
b->size(),
|
||||
"EMPTY");
|
||||
break;
|
||||
case LayoutRawBlock::PADDING:
|
||||
output->print_cr(" @%d %d/1 %s",
|
||||
b->offset(),
|
||||
b->size(),
|
||||
"PADDING");
|
||||
break;
|
||||
}
|
||||
b = b->next_block();
|
||||
}
|
||||
}
|
||||
|
||||
FieldLayoutBuilder::FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
|
||||
Array<u2>* fields, bool is_contended, FieldLayoutInfo* info) :
|
||||
_classname(classname),
|
||||
_super_klass(super_klass),
|
||||
_constant_pool(constant_pool),
|
||||
_fields(fields),
|
||||
_info(info),
|
||||
_root_group(NULL),
|
||||
_contended_groups(GrowableArray<FieldGroup*>(8)),
|
||||
_static_fields(NULL),
|
||||
_layout(NULL),
|
||||
_static_layout(NULL),
|
||||
_nonstatic_oopmap_count(0),
|
||||
_alignment(-1),
|
||||
_has_nonstatic_fields(false),
|
||||
_is_contended(is_contended) {}
|
||||
|
||||
|
||||
FieldGroup* FieldLayoutBuilder::get_or_create_contended_group(int g) {
|
||||
assert(g > 0, "must only be called for named contended groups");
|
||||
FieldGroup* fg = NULL;
|
||||
for (int i = 0; i < _contended_groups.length(); i++) {
|
||||
fg = _contended_groups.at(i);
|
||||
if (fg->contended_group() == g) return fg;
|
||||
}
|
||||
fg = new FieldGroup(g);
|
||||
_contended_groups.append(fg);
|
||||
return fg;
|
||||
}
|
||||
|
||||
void FieldLayoutBuilder::prologue() {
|
||||
_layout = new FieldLayout(_fields, _constant_pool);
|
||||
const InstanceKlass* super_klass = _super_klass;
|
||||
_layout->initialize_instance_layout(super_klass);
|
||||
if (super_klass != NULL) {
|
||||
_has_nonstatic_fields = super_klass->has_nonstatic_fields();
|
||||
}
|
||||
_static_layout = new FieldLayout(_fields, _constant_pool);
|
||||
_static_layout->initialize_static_layout();
|
||||
_static_fields = new FieldGroup();
|
||||
_root_group = new FieldGroup();
|
||||
}
|
||||
|
||||
// Field sorting for regular classes:
|
||||
// - fields are sorted in static and non-static fields
|
||||
// - non-static fields are also sorted according to their contention group
|
||||
// (support of the @Contended annotation)
|
||||
// - @Contended annotation is ignored for static fields
|
||||
void FieldLayoutBuilder::regular_field_sorting() {
|
||||
for (AllFieldStream fs(_fields, _constant_pool); !fs.done(); fs.next()) {
|
||||
FieldGroup* group = NULL;
|
||||
if (fs.access_flags().is_static()) {
|
||||
group = _static_fields;
|
||||
} else {
|
||||
_has_nonstatic_fields = true;
|
||||
if (fs.is_contended()) {
|
||||
int g = fs.contended_group();
|
||||
if (g == 0) {
|
||||
group = new FieldGroup(true);
|
||||
_contended_groups.append(group);
|
||||
} else {
|
||||
group = get_or_create_contended_group(g);
|
||||
}
|
||||
} else {
|
||||
group = _root_group;
|
||||
}
|
||||
}
|
||||
assert(group != NULL, "invariant");
|
||||
BasicType type = Signature::basic_type(fs.signature());
|
||||
switch(type) {
|
||||
case T_BYTE:
|
||||
case T_CHAR:
|
||||
case T_DOUBLE:
|
||||
case T_FLOAT:
|
||||
case T_INT:
|
||||
case T_LONG:
|
||||
case T_SHORT:
|
||||
case T_BOOLEAN:
|
||||
group->add_primitive_field(fs, type);
|
||||
break;
|
||||
case T_OBJECT:
|
||||
case T_ARRAY:
|
||||
if (group != _static_fields) _nonstatic_oopmap_count++;
|
||||
group->add_oop_field(fs);
|
||||
break;
|
||||
default:
|
||||
fatal("Something wrong?");
|
||||
}
|
||||
}
|
||||
_root_group->sort_by_size();
|
||||
_static_fields->sort_by_size();
|
||||
if (!_contended_groups.is_empty()) {
|
||||
for (int i = 0; i < _contended_groups.length(); i++) {
|
||||
_contended_groups.at(i)->sort_by_size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FieldLayoutBuilder::insert_contended_padding(LayoutRawBlock* slot) {
|
||||
if (ContendedPaddingWidth > 0) {
|
||||
LayoutRawBlock* padding = new LayoutRawBlock(LayoutRawBlock::PADDING, ContendedPaddingWidth);
|
||||
_layout->insert(slot, padding);
|
||||
}
|
||||
}
|
||||
|
||||
// Computation of regular classes layout is an evolution of the previous default layout
|
||||
// (FieldAllocationStyle 1):
|
||||
// - primitive fields are allocated first (from the biggest to the smallest)
|
||||
// - then oop fields are allocated, either in existing gaps or at the end of
|
||||
// the layout
|
||||
void FieldLayoutBuilder::compute_regular_layout() {
|
||||
bool need_tail_padding = false;
|
||||
prologue();
|
||||
regular_field_sorting();
|
||||
|
||||
if (_is_contended) {
|
||||
_layout->set_start(_layout->last_block());
|
||||
// insertion is currently easy because the current strategy doesn't try to fill holes
|
||||
// in super classes layouts => the _start block is by consequence the _last_block
|
||||
insert_contended_padding(_layout->start());
|
||||
need_tail_padding = true;
|
||||
}
|
||||
_layout->add(_root_group->primitive_fields());
|
||||
_layout->add(_root_group->oop_fields());
|
||||
|
||||
if (!_contended_groups.is_empty()) {
|
||||
for (int i = 0; i < _contended_groups.length(); i++) {
|
||||
FieldGroup* cg = _contended_groups.at(i);
|
||||
LayoutRawBlock* start = _layout->last_block();
|
||||
insert_contended_padding(start);
|
||||
_layout->add(cg->primitive_fields(), start);
|
||||
_layout->add(cg->oop_fields(), start);
|
||||
need_tail_padding = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (need_tail_padding) {
|
||||
insert_contended_padding(_layout->last_block());
|
||||
}
|
||||
|
||||
_static_layout->add_contiguously(this->_static_fields->oop_fields());
|
||||
_static_layout->add(this->_static_fields->primitive_fields());
|
||||
|
||||
epilogue();
|
||||
}
|
||||
|
||||
// Compute layout of the java/lang/ref/Reference class according
|
||||
// to the hard coded offsets of its fields
|
||||
void FieldLayoutBuilder::compute_java_lang_ref_Reference_layout() {
|
||||
prologue();
|
||||
regular_field_sorting();
|
||||
|
||||
assert(_contended_groups.is_empty(), "java.lang.Reference has no @Contended annotations");
|
||||
assert(_root_group->primitive_fields() == NULL, "java.lang.Reference has no nonstatic primitive fields");
|
||||
int field_count = 0;
|
||||
int offset = -1;
|
||||
for (int i = 0; i < _root_group->oop_fields()->length(); i++) {
|
||||
LayoutRawBlock* b = _root_group->oop_fields()->at(i);
|
||||
FieldInfo* fi = FieldInfo::from_field_array(_fields, b->field_index());
|
||||
if (fi->name(_constant_pool)->equals("referent")) {
|
||||
offset = java_lang_ref_Reference::referent_offset;
|
||||
} else if (fi->name(_constant_pool)->equals("queue")) {
|
||||
offset = java_lang_ref_Reference::queue_offset;
|
||||
} else if (fi->name(_constant_pool)->equals("next")) {
|
||||
offset = java_lang_ref_Reference::next_offset;
|
||||
} else if (fi->name(_constant_pool)->equals("discovered")) {
|
||||
offset = java_lang_ref_Reference::discovered_offset;
|
||||
}
|
||||
assert(offset != -1, "Unknown field");
|
||||
_layout->add_field_at_offset(b, offset);
|
||||
field_count++;
|
||||
}
|
||||
assert(field_count == 4, "Wrong number of fields in java.lang.ref.Reference");
|
||||
|
||||
_static_layout->add_contiguously(this->_static_fields->oop_fields());
|
||||
_static_layout->add(this->_static_fields->primitive_fields());
|
||||
|
||||
epilogue();
|
||||
}
|
||||
|
||||
// Compute layout of the boxing class according
|
||||
// to the hard coded offsets of their fields
|
||||
void FieldLayoutBuilder::compute_boxing_class_layout() {
|
||||
prologue();
|
||||
regular_field_sorting();
|
||||
|
||||
assert(_contended_groups.is_empty(), "Boxing classes have no @Contended annotations");
|
||||
assert(_root_group->oop_fields() == NULL, "Boxing classes have no nonstatic oops fields");
|
||||
int field_count = 0;
|
||||
int offset = -1;
|
||||
|
||||
for (int i = 0; i < _root_group->primitive_fields()->length(); i++) {
|
||||
LayoutRawBlock* b = _root_group->primitive_fields()->at(i);
|
||||
FieldInfo* fi = FieldInfo::from_field_array(_fields, b->field_index());
|
||||
assert(fi->name(_constant_pool)->equals("value"), "Boxing classes have a single nonstatic field named 'value'");
|
||||
BasicType type = Signature::basic_type(fi->signature(_constant_pool));
|
||||
offset = java_lang_boxing_object::value_offset_in_bytes(type);
|
||||
assert(offset != -1, "Unknown field");
|
||||
_layout->add_field_at_offset(b, offset);
|
||||
field_count++;
|
||||
}
|
||||
assert(field_count == 1, "Wrong number of fields for a boxing class");
|
||||
|
||||
_static_layout->add_contiguously(this->_static_fields->oop_fields());
|
||||
_static_layout->add(this->_static_fields->primitive_fields());
|
||||
|
||||
epilogue();
|
||||
}
|
||||
|
||||
void FieldLayoutBuilder::epilogue() {
|
||||
// Computing oopmaps
|
||||
int super_oop_map_count = (_super_klass == NULL) ? 0 :_super_klass->nonstatic_oop_map_count();
|
||||
int max_oop_map_count = super_oop_map_count + _nonstatic_oopmap_count;
|
||||
|
||||
OopMapBlocksBuilder* nonstatic_oop_maps =
|
||||
new OopMapBlocksBuilder(max_oop_map_count);
|
||||
if (super_oop_map_count > 0) {
|
||||
nonstatic_oop_maps->initialize_inherited_blocks(_super_klass->start_of_nonstatic_oop_maps(),
|
||||
_super_klass->nonstatic_oop_map_count());
|
||||
}
|
||||
|
||||
if (_root_group->oop_fields() != NULL) {
|
||||
for (int i = 0; i < _root_group->oop_fields()->length(); i++) {
|
||||
LayoutRawBlock* b = _root_group->oop_fields()->at(i);
|
||||
nonstatic_oop_maps->add(b->offset(), 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_contended_groups.is_empty()) {
|
||||
for (int i = 0; i < _contended_groups.length(); i++) {
|
||||
FieldGroup* cg = _contended_groups.at(i);
|
||||
if (cg->oop_count() > 0) {
|
||||
assert(cg->oop_fields() != NULL && cg->oop_fields()->at(0) != NULL, "oop_count > 0 but no oop fields found");
|
||||
nonstatic_oop_maps->add(cg->oop_fields()->at(0)->offset(), cg->oop_count());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nonstatic_oop_maps->compact();
|
||||
|
||||
int instance_end = align_up(_layout->last_block()->offset(), wordSize);
|
||||
int static_fields_end = align_up(_static_layout->last_block()->offset(), wordSize);
|
||||
int static_fields_size = (static_fields_end -
|
||||
InstanceMirrorKlass::offset_of_static_fields()) / wordSize;
|
||||
int nonstatic_field_end = align_up(_layout->last_block()->offset(), heapOopSize);
|
||||
|
||||
// Pass back information needed for InstanceKlass creation
|
||||
|
||||
_info->oop_map_blocks = nonstatic_oop_maps;
|
||||
_info->_instance_size = align_object_size(instance_end / wordSize);
|
||||
_info->_static_field_size = static_fields_size;
|
||||
_info->_nonstatic_field_size = (nonstatic_field_end - instanceOopDesc::base_offset_in_bytes()) / heapOopSize;
|
||||
_info->_has_nonstatic_fields = _has_nonstatic_fields;
|
||||
|
||||
if (PrintFieldLayout) {
|
||||
ResourceMark rm;
|
||||
tty->print_cr("Layout of class %s", _classname->as_C_string());
|
||||
tty->print_cr("Instance fields:");
|
||||
_layout->print(tty, false, _super_klass);
|
||||
tty->print_cr("Static fields:");
|
||||
_static_layout->print(tty, true, NULL);
|
||||
tty->print_cr("Instance size = %d bytes", _info->_instance_size * wordSize);
|
||||
tty->print_cr("---");
|
||||
}
|
||||
}
|
||||
|
||||
void FieldLayoutBuilder::build_layout() {
|
||||
if (_classname == vmSymbols::java_lang_ref_Reference()) {
|
||||
compute_java_lang_ref_Reference_layout();
|
||||
} else if (_classname == vmSymbols::java_lang_Boolean() ||
|
||||
_classname == vmSymbols::java_lang_Character() ||
|
||||
_classname == vmSymbols::java_lang_Float() ||
|
||||
_classname == vmSymbols::java_lang_Double() ||
|
||||
_classname == vmSymbols::java_lang_Byte() ||
|
||||
_classname == vmSymbols::java_lang_Short() ||
|
||||
_classname == vmSymbols::java_lang_Integer() ||
|
||||
_classname == vmSymbols::java_lang_Long()) {
|
||||
compute_boxing_class_layout();
|
||||
} else {
|
||||
compute_regular_layout();
|
||||
}
|
||||
}
|
||||
|
267
src/hotspot/share/classfile/fieldLayoutBuilder.hpp
Normal file
267
src/hotspot/share/classfile/fieldLayoutBuilder.hpp
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
|
||||
#define SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
|
||||
|
||||
#include "classfile/classFileParser.hpp"
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "oops/fieldStreams.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
|
||||
// Classes below are used to compute the field layout of classes.
|
||||
|
||||
|
||||
// A LayoutRawBlock describes an element of a layout.
|
||||
// Each field is represented by a LayoutRawBlock.
|
||||
// LayoutRawBlocks can also represent elements injected by the JVM:
|
||||
// padding, empty blocks, inherited fields, etc.
|
||||
// All LayoutRawBlocks must have a size and an alignment. The size is the
|
||||
// exact size of the field expressed in bytes. The alignment is
|
||||
// the alignment constraint of the field (1 for byte, 2 for short,
|
||||
// 4 for int, 8 for long, etc.)
|
||||
//
|
||||
// LayoutRawBlock are designed to be used in two data structures:
|
||||
// - a linked list in a layout (using _next_block, _prev_block)
|
||||
// - a GrowableArray in field group (the growable array contains pointers to LayoutRawBlocks)
|
||||
//
|
||||
// next/prev pointers are included in the LayoutRawBlock class to narrow
|
||||
// the number of allocation required during the computation of a layout.
|
||||
//
|
||||
class LayoutRawBlock : public ResourceObj {
|
||||
public:
|
||||
// Some code relies on the order of values below.
|
||||
enum Kind {
|
||||
EMPTY, // empty slot, space is taken from this to allocate fields
|
||||
RESERVED, // reserved for JVM usage (for instance object header)
|
||||
PADDING, // padding (because of alignment constraints or @Contended)
|
||||
REGULAR, // primitive or oop field (including non-flattened inline fields)
|
||||
FLATTENED, // flattened field
|
||||
INHERITED // field(s) inherited from super classes
|
||||
};
|
||||
|
||||
private:
|
||||
LayoutRawBlock* _next_block;
|
||||
LayoutRawBlock* _prev_block;
|
||||
Kind _kind;
|
||||
int _offset;
|
||||
int _alignment;
|
||||
int _size;
|
||||
int _field_index;
|
||||
bool _is_reference;
|
||||
|
||||
public:
|
||||
LayoutRawBlock(Kind kind, int size);
|
||||
LayoutRawBlock(int index, Kind kind, int size, int alignment, bool is_reference = false);
|
||||
LayoutRawBlock* next_block() const { return _next_block; }
|
||||
void set_next_block(LayoutRawBlock* next) { _next_block = next; }
|
||||
LayoutRawBlock* prev_block() const { return _prev_block; }
|
||||
void set_prev_block(LayoutRawBlock* prev) { _prev_block = prev; }
|
||||
Kind kind() const { return _kind; }
|
||||
int offset() const {
|
||||
assert(_offset >= 0, "Must be initialized");
|
||||
return _offset;
|
||||
}
|
||||
void set_offset(int offset) { _offset = offset; }
|
||||
int alignment() const { return _alignment; }
|
||||
int size() const { return _size; }
|
||||
void set_size(int size) { _size = size; }
|
||||
int field_index() const {
|
||||
assert(_field_index != -1, "Must be initialized");
|
||||
return _field_index;
|
||||
}
|
||||
bool is_reference() const { return _is_reference; }
|
||||
|
||||
bool fit(int size, int alignment);
|
||||
|
||||
static int compare_offset(LayoutRawBlock** x, LayoutRawBlock** y) { return (*x)->offset() - (*y)->offset(); }
|
||||
// compare_size_inverted() returns the opposite of a regular compare method in order to
|
||||
// sort fields in decreasing order.
|
||||
// Note: with line types, the comparison should include alignment constraint if sizes are equals
|
||||
static int compare_size_inverted(LayoutRawBlock** x, LayoutRawBlock** y) {
|
||||
#ifdef _WINDOWS
|
||||
// qsort() on Windows reverse the order of fields with the same size
|
||||
// the extension of the comparison function below preserves this order
|
||||
int diff = (*y)->size() - (*x)->size();
|
||||
if (diff == 0) {
|
||||
diff = (*x)->field_index() - (*y)->field_index();
|
||||
}
|
||||
return diff;
|
||||
#else
|
||||
return (*y)->size() - (*x)->size();
|
||||
#endif // _WINDOWS
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// A Field group represents a set of fields that have to be allocated together,
|
||||
// this is the way the @Contended annotation is supported.
|
||||
// Inside a FieldGroup, fields are sorted based on their kind: primitive,
|
||||
// oop, or flattened.
|
||||
//
|
||||
class FieldGroup : public ResourceObj {
|
||||
|
||||
private:
|
||||
FieldGroup* _next;
|
||||
GrowableArray<LayoutRawBlock*>* _primitive_fields;
|
||||
GrowableArray<LayoutRawBlock*>* _oop_fields;
|
||||
int _contended_group;
|
||||
int _oop_count;
|
||||
static const int INITIAL_LIST_SIZE = 16;
|
||||
|
||||
public:
|
||||
FieldGroup(int contended_group = -1);
|
||||
|
||||
FieldGroup* next() const { return _next; }
|
||||
void set_next(FieldGroup* next) { _next = next; }
|
||||
GrowableArray<LayoutRawBlock*>* primitive_fields() const { return _primitive_fields; }
|
||||
GrowableArray<LayoutRawBlock*>* oop_fields() const { return _oop_fields; }
|
||||
int contended_group() const { return _contended_group; }
|
||||
int oop_count() const { return _oop_count; }
|
||||
|
||||
void add_primitive_field(AllFieldStream fs, BasicType type);
|
||||
void add_oop_field(AllFieldStream fs);
|
||||
void sort_by_size();
|
||||
};
|
||||
|
||||
// The FieldLayout class represents a set of fields organized
|
||||
// in a layout.
|
||||
// An instance of FieldLayout can either represent the layout
|
||||
// of non-static fields (used in an instance object) or the
|
||||
// layout of static fields (to be included in the class mirror).
|
||||
//
|
||||
// _block is a pointer to a list of LayoutRawBlock ordered by increasing
|
||||
// offsets.
|
||||
// _start points to the LayoutRawBlock with the first offset that can
|
||||
// be used to allocate fields of the current class
|
||||
// _last points to the last LayoutRawBlock of the list. In order to
|
||||
// simplify the code, the LayoutRawBlock list always ends with an
|
||||
// EMPTY block (the kind of LayoutRawBlock from which space is taken
|
||||
// to allocate fields) with a size big enough to satisfy all
|
||||
// field allocations.
|
||||
//
|
||||
class FieldLayout : public ResourceObj {
|
||||
private:
|
||||
Array<u2>* _fields;
|
||||
ConstantPool* _cp;
|
||||
LayoutRawBlock* _blocks; // the layout being computed
|
||||
LayoutRawBlock* _start; // points to the first block where a field can be inserted
|
||||
LayoutRawBlock* _last; // points to the last block of the layout (big empty block)
|
||||
|
||||
public:
|
||||
FieldLayout(Array<u2>* fields, ConstantPool* cp);
|
||||
void initialize_static_layout();
|
||||
void initialize_instance_layout(const InstanceKlass* ik);
|
||||
|
||||
LayoutRawBlock* first_empty_block() {
|
||||
LayoutRawBlock* block = _start;
|
||||
while (block->kind() != LayoutRawBlock::EMPTY) {
|
||||
block = block->next_block();
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
LayoutRawBlock* start() { return _start; }
|
||||
void set_start(LayoutRawBlock* start) { _start = start; }
|
||||
LayoutRawBlock* last_block() { return _last; }
|
||||
|
||||
LayoutRawBlock* first_field_block();
|
||||
void add(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = NULL);
|
||||
void add_field_at_offset(LayoutRawBlock* blocks, int offset, LayoutRawBlock* start = NULL);
|
||||
void add_contiguously(GrowableArray<LayoutRawBlock*>* list, LayoutRawBlock* start = NULL);
|
||||
LayoutRawBlock* insert_field_block(LayoutRawBlock* slot, LayoutRawBlock* block);
|
||||
void reconstruct_layout(const InstanceKlass* ik);
|
||||
void fill_holes(const InstanceKlass* ik);
|
||||
LayoutRawBlock* insert(LayoutRawBlock* slot, LayoutRawBlock* block);
|
||||
void remove(LayoutRawBlock* block);
|
||||
void print(outputStream* output, bool is_static, const InstanceKlass* super);
|
||||
};
|
||||
|
||||
|
||||
// FieldLayoutBuilder is the main entry point for layout computation.
|
||||
// This class has three methods to generate layout: one for regular classes
|
||||
// and two for classes with hard coded offsets (java,lang.ref.Reference
|
||||
// and the boxing classes). The rationale for having multiple methods
|
||||
// is that each kind of class has a different set goals regarding
|
||||
// its layout, so instead of mixing several layout strategies into a
|
||||
// single method, each kind has its own method (see comments below
|
||||
// for more details about the allocation strategies).
|
||||
//
|
||||
// Computing the layout of a class always goes through 4 steps:
|
||||
// 1 - Prologue: preparation of data structure and gathering of
|
||||
// layout information inherited from super classes
|
||||
// 2 - Field sorting: fields are sorted according to their
|
||||
// kind (oop, primitive, inline class) and their contention
|
||||
// annotation (if any)
|
||||
// 3 - Layout is computed from the set of lists generated during
|
||||
// step 2
|
||||
// 4 - Epilogue: oopmaps are generated, layout information is
|
||||
// prepared so other VM components can use it (instance size,
|
||||
// static field size, non-static field size, etc.)
|
||||
//
|
||||
// Steps 1 and 4 are common to all layout computations. Step 2 and 3
|
||||
// can vary with the allocation strategy.
|
||||
//
|
||||
class FieldLayoutBuilder : public ResourceObj {
|
||||
private:
|
||||
|
||||
const Symbol* _classname;
|
||||
const InstanceKlass* _super_klass;
|
||||
ConstantPool* _constant_pool;
|
||||
Array<u2>* _fields;
|
||||
FieldLayoutInfo* _info;
|
||||
FieldGroup* _root_group;
|
||||
GrowableArray<FieldGroup*> _contended_groups;
|
||||
FieldGroup* _static_fields;
|
||||
FieldLayout* _layout;
|
||||
FieldLayout* _static_layout;
|
||||
int _nonstatic_oopmap_count;
|
||||
int _alignment;
|
||||
bool _has_nonstatic_fields;
|
||||
bool _is_contended; // is a contended class?
|
||||
|
||||
public:
|
||||
FieldLayoutBuilder(const Symbol* classname, const InstanceKlass* super_klass, ConstantPool* constant_pool,
|
||||
Array<u2>* fields, bool is_contended, FieldLayoutInfo* info);
|
||||
|
||||
int get_alignment() {
|
||||
assert(_alignment != -1, "Uninitialized");
|
||||
return _alignment;
|
||||
}
|
||||
|
||||
void build_layout();
|
||||
void compute_regular_layout();
|
||||
void compute_java_lang_ref_Reference_layout();
|
||||
void compute_boxing_class_layout();
|
||||
void insert_contended_padding(LayoutRawBlock* slot);
|
||||
|
||||
private:
|
||||
void prologue();
|
||||
void epilogue();
|
||||
void regular_field_sorting();
|
||||
FieldGroup* get_or_create_contended_group(int g);
|
||||
};
|
||||
|
||||
#endif // SHARE_CLASSFILE_FIELDLAYOUTBUILDER_HPP
|
@ -740,6 +740,9 @@ bool ShenandoahBarrierSetC2::is_gc_barrier_node(Node* node) const {
|
||||
}
|
||||
|
||||
Node* ShenandoahBarrierSetC2::step_over_gc_barrier(Node* c) const {
|
||||
if (c == NULL) {
|
||||
return c;
|
||||
}
|
||||
if (c->Opcode() == Op_ShenandoahLoadReferenceBarrier) {
|
||||
return c->in(ShenandoahLoadReferenceBarrierNode::ValueIn);
|
||||
}
|
||||
|
@ -58,6 +58,11 @@ bool ShenandoahBarrierC2Support::expand(Compile* C, PhaseIterGVN& igvn) {
|
||||
return false;
|
||||
}
|
||||
C->clear_major_progress();
|
||||
if (C->range_check_cast_count() > 0) {
|
||||
// No more loop optimizations. Remove all range check dependent CastIINodes.
|
||||
C->remove_range_check_casts(igvn);
|
||||
igvn.optimize();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
@ -2009,21 +2014,22 @@ void ShenandoahBarrierC2Support::optimize_after_expansion(VectorSet &visited, No
|
||||
if (loop != phase->ltree_root() &&
|
||||
loop->_child == NULL &&
|
||||
!loop->_irreducible) {
|
||||
LoopNode* head = loop->_head->as_Loop();
|
||||
if ((!head->is_CountedLoop() || head->as_CountedLoop()->is_main_loop() || head->as_CountedLoop()->is_normal_loop()) &&
|
||||
Node* head = loop->_head;
|
||||
if (head->is_Loop() &&
|
||||
(!head->is_CountedLoop() || head->as_CountedLoop()->is_main_loop() || head->as_CountedLoop()->is_normal_loop()) &&
|
||||
!seen.test_set(head->_idx)) {
|
||||
IfNode* iff = find_unswitching_candidate(loop, phase);
|
||||
if (iff != NULL) {
|
||||
Node* bol = iff->in(1);
|
||||
if (head->is_strip_mined()) {
|
||||
head->verify_strip_mined(0);
|
||||
if (head->as_Loop()->is_strip_mined()) {
|
||||
head->as_Loop()->verify_strip_mined(0);
|
||||
}
|
||||
move_heap_stable_test_out_of_loop(iff, phase);
|
||||
|
||||
AutoNodeBudget node_budget(phase);
|
||||
|
||||
if (loop->policy_unswitching(phase)) {
|
||||
if (head->is_strip_mined()) {
|
||||
if (head->as_Loop()->is_strip_mined()) {
|
||||
OuterStripMinedLoopNode* outer = head->as_CountedLoop()->outer_loop();
|
||||
hide_strip_mined_loop(outer, head->as_CountedLoop(), phase);
|
||||
}
|
||||
@ -2291,7 +2297,12 @@ void MemoryGraphFixer::collect_memory_nodes() {
|
||||
if (in_opc == Op_Return || in_opc == Op_Rethrow) {
|
||||
mem = in->in(TypeFunc::Memory);
|
||||
} else if (in_opc == Op_Halt) {
|
||||
if (!in->in(0)->is_Region()) {
|
||||
if (in->in(0)->is_Region()) {
|
||||
Node* r = in->in(0);
|
||||
for (uint j = 1; j < r->req(); j++) {
|
||||
assert(r->in(j)->Opcode() != Op_NeverBranch, "");
|
||||
}
|
||||
} else {
|
||||
Node* proj = in->in(0);
|
||||
assert(proj->is_Proj(), "");
|
||||
Node* in = proj->in(0);
|
||||
@ -2303,25 +2314,37 @@ void MemoryGraphFixer::collect_memory_nodes() {
|
||||
assert(call->is_Call(), "");
|
||||
mem = call->in(TypeFunc::Memory);
|
||||
} else if (in->Opcode() == Op_NeverBranch) {
|
||||
ResourceMark rm;
|
||||
Unique_Node_List wq;
|
||||
wq.push(in);
|
||||
wq.push(in->as_Multi()->proj_out(0));
|
||||
for (uint j = 1; j < wq.size(); j++) {
|
||||
Node* c = wq.at(j);
|
||||
assert(!c->is_Root(), "shouldn't leave loop");
|
||||
if (c->is_SafePoint()) {
|
||||
assert(mem == NULL, "only one safepoint");
|
||||
Node* head = in->in(0);
|
||||
assert(head->is_Region() && head->req() == 3, "unexpected infinite loop graph shape");
|
||||
assert(_phase->is_dominator(head, head->in(1)) || _phase->is_dominator(head, head->in(2)), "no back branch?");
|
||||
Node* tail = _phase->is_dominator(head, head->in(1)) ? head->in(1) : head->in(2);
|
||||
Node* c = tail;
|
||||
while (c != head) {
|
||||
if (c->is_SafePoint() && !c->is_CallLeaf()) {
|
||||
mem = c->in(TypeFunc::Memory);
|
||||
}
|
||||
for (DUIterator_Fast kmax, k = c->fast_outs(kmax); k < kmax; k++) {
|
||||
Node* u = c->fast_out(k);
|
||||
if (u->is_CFG()) {
|
||||
wq.push(u);
|
||||
c = _phase->idom(c);
|
||||
}
|
||||
assert(mem != NULL, "should have found safepoint");
|
||||
|
||||
Node* phi_mem = NULL;
|
||||
for (DUIterator_Fast jmax, j = head->fast_outs(jmax); j < jmax; j++) {
|
||||
Node* u = head->fast_out(j);
|
||||
if (u->is_Phi() && u->bottom_type() == Type::MEMORY) {
|
||||
if (_phase->C->get_alias_index(u->adr_type()) == _alias) {
|
||||
assert(phi_mem == NULL || phi_mem->adr_type() == TypePtr::BOTTOM, "");
|
||||
phi_mem = u;
|
||||
} else if (u->adr_type() == TypePtr::BOTTOM) {
|
||||
assert(phi_mem == NULL || _phase->C->get_alias_index(phi_mem->adr_type()) == _alias, "");
|
||||
if (phi_mem == NULL) {
|
||||
phi_mem = u;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(mem != NULL, "should have found safepoint");
|
||||
if (phi_mem != NULL) {
|
||||
mem = phi_mem;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2019, 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
|
||||
@ -435,7 +435,7 @@ void JfrThreadSampler::start_thread() {
|
||||
|
||||
void JfrThreadSampler::enroll() {
|
||||
if (_disenrolled) {
|
||||
log_info(jfr)("Enrolling thread sampler");
|
||||
log_trace(jfr)("Enrolling thread sampler");
|
||||
_sample.signal();
|
||||
_disenrolled = false;
|
||||
}
|
||||
@ -445,7 +445,7 @@ void JfrThreadSampler::disenroll() {
|
||||
if (!_disenrolled) {
|
||||
_sample.wait();
|
||||
_disenrolled = true;
|
||||
log_info(jfr)("Disenrolling thread sampler");
|
||||
log_trace(jfr)("Disenrolling thread sampler");
|
||||
}
|
||||
}
|
||||
|
||||
@ -583,12 +583,12 @@ JfrThreadSampling::~JfrThreadSampling() {
|
||||
}
|
||||
|
||||
static void log(size_t interval_java, size_t interval_native) {
|
||||
log_info(jfr)("Updated thread sampler for java: " SIZE_FORMAT " ms, native " SIZE_FORMAT " ms", interval_java, interval_native);
|
||||
log_trace(jfr)("Updated thread sampler for java: " SIZE_FORMAT " ms, native " SIZE_FORMAT " ms", interval_java, interval_native);
|
||||
}
|
||||
|
||||
void JfrThreadSampling::start_sampler(size_t interval_java, size_t interval_native) {
|
||||
assert(_sampler == NULL, "invariant");
|
||||
log_info(jfr)("Enrolling thread sampler");
|
||||
log_trace(jfr)("Enrolling thread sampler");
|
||||
_sampler = new JfrThreadSampler(interval_java, interval_native, JfrOptionSet::stackdepth());
|
||||
_sampler->start_thread();
|
||||
_sampler->enroll();
|
||||
@ -608,7 +608,7 @@ void JfrThreadSampling::set_sampling_interval(bool java_interval, size_t period)
|
||||
}
|
||||
if (interval_java > 0 || interval_native > 0) {
|
||||
if (_sampler == NULL) {
|
||||
log_info(jfr)("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native);
|
||||
log_trace(jfr)("Creating thread sampler for java:%zu ms, native %zu ms", interval_java, interval_native);
|
||||
start_sampler(interval_java, interval_native);
|
||||
} else {
|
||||
_sampler->set_java_interval(interval_java);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -157,7 +157,7 @@
|
||||
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
|
||||
nonstatic_field(InstanceKlass, _source_file_name_index, u2) \
|
||||
nonstatic_field(InstanceKlass, _init_state, u1) \
|
||||
nonstatic_field(InstanceKlass, _misc_flags, u2) \
|
||||
nonstatic_field(InstanceKlass, _misc_flags, u4) \
|
||||
nonstatic_field(InstanceKlass, _annotations, Annotations*) \
|
||||
\
|
||||
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_sp, intptr_t*) \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, 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
|
||||
@ -47,7 +47,6 @@ class FieldStreamBase : public StackObj {
|
||||
fieldDescriptor _fd_buf;
|
||||
|
||||
FieldInfo* field() const { return FieldInfo::from_field_array(_fields, _index); }
|
||||
InstanceKlass* field_holder() const { return _constants->pool_holder(); }
|
||||
|
||||
int init_generic_signature_start_slot() {
|
||||
int length = _fields->length();
|
||||
@ -87,6 +86,7 @@ class FieldStreamBase : public StackObj {
|
||||
|
||||
// accessors
|
||||
int index() const { return _index; }
|
||||
InstanceKlass* field_holder() const { return _constants->pool_holder(); }
|
||||
|
||||
void next() {
|
||||
if (access_flags().field_has_generic_signature()) {
|
||||
|
@ -1399,6 +1399,10 @@ void InstanceKlass::mask_for(const methodHandle& method, int bci,
|
||||
oop_map_cache->lookup(method, bci, entry_for);
|
||||
}
|
||||
|
||||
bool InstanceKlass::contains_field_offset(int offset) {
|
||||
fieldDescriptor fd;
|
||||
return find_field_from_offset(offset, false, &fd);
|
||||
}
|
||||
|
||||
bool InstanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const {
|
||||
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
|
||||
|
@ -103,12 +103,28 @@ class OopMapBlock {
|
||||
uint count() const { return _count; }
|
||||
void set_count(uint count) { _count = count; }
|
||||
|
||||
void increment_count(int diff) { _count += diff; }
|
||||
|
||||
int offset_span() const { return _count * heapOopSize; }
|
||||
|
||||
int end_offset() const {
|
||||
return offset() + offset_span();
|
||||
}
|
||||
|
||||
bool is_contiguous(int another_offset) const {
|
||||
return another_offset == end_offset();
|
||||
}
|
||||
|
||||
// sizeof(OopMapBlock) in words.
|
||||
static const int size_in_words() {
|
||||
return align_up((int)sizeof(OopMapBlock), wordSize) >>
|
||||
LogBytesPerWord;
|
||||
}
|
||||
|
||||
static int compare_offset(const OopMapBlock* a, const OopMapBlock* b) {
|
||||
return a->offset() - b->offset();
|
||||
}
|
||||
|
||||
private:
|
||||
int _offset;
|
||||
uint _count;
|
||||
@ -212,7 +228,6 @@ class InstanceKlass: public Klass {
|
||||
// _is_marked_dependent can be set concurrently, thus cannot be part of the
|
||||
// _misc_flags.
|
||||
bool _is_marked_dependent; // used for marking during flushing and deoptimization
|
||||
bool _is_being_redefined; // used for locking redefinition
|
||||
|
||||
// The low two bits of _misc_flags contains the kind field.
|
||||
// This can be used to quickly discriminate among the four kinds of
|
||||
@ -243,12 +258,14 @@ class InstanceKlass: public Klass {
|
||||
_misc_is_shared_boot_class = 1 << 12, // defining class loader is boot class loader
|
||||
_misc_is_shared_platform_class = 1 << 13, // defining class loader is platform class loader
|
||||
_misc_is_shared_app_class = 1 << 14, // defining class loader is app class loader
|
||||
_misc_has_resolved_methods = 1 << 15 // resolved methods table entries added for this class
|
||||
_misc_has_resolved_methods = 1 << 15, // resolved methods table entries added for this class
|
||||
_misc_is_being_redefined = 1 << 16, // used for locking redefinition
|
||||
_misc_has_contended_annotations = 1 << 17 // has @Contended annotation
|
||||
};
|
||||
u2 loader_type_bits() {
|
||||
return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class;
|
||||
}
|
||||
u2 _misc_flags;
|
||||
u4 _misc_flags;
|
||||
u2 _minor_version; // minor version number of class file
|
||||
u2 _major_version; // major version number of class file
|
||||
Thread* _init_thread; // Pointer to current thread doing initialization (to handle recursive initialization)
|
||||
@ -571,9 +588,7 @@ public:
|
||||
Klass* find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const;
|
||||
|
||||
// find a non-static or static field given its offset within the class.
|
||||
bool contains_field_offset(int offset) {
|
||||
return instanceOopDesc::contains_field_offset(offset, nonstatic_field_size());
|
||||
}
|
||||
bool contains_field_offset(int offset);
|
||||
|
||||
bool find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
|
||||
bool find_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const;
|
||||
@ -735,10 +750,29 @@ public:
|
||||
_nonstatic_oop_map_size = words;
|
||||
}
|
||||
|
||||
bool has_contended_annotations() const {
|
||||
return ((_misc_flags & _misc_has_contended_annotations) != 0);
|
||||
}
|
||||
void set_has_contended_annotations(bool value) {
|
||||
if (value) {
|
||||
_misc_flags |= _misc_has_contended_annotations;
|
||||
} else {
|
||||
_misc_flags &= ~_misc_has_contended_annotations;
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
// Redefinition locking. Class can only be redefined by one thread at a time.
|
||||
bool is_being_redefined() const { return _is_being_redefined; }
|
||||
void set_is_being_redefined(bool value) { _is_being_redefined = value; }
|
||||
bool is_being_redefined() const {
|
||||
return ((_misc_flags & _misc_is_being_redefined) != 0);
|
||||
}
|
||||
void set_is_being_redefined(bool value) {
|
||||
if (value) {
|
||||
_misc_flags |= _misc_is_being_redefined;
|
||||
} else {
|
||||
_misc_flags &= ~_misc_is_being_redefined;
|
||||
}
|
||||
}
|
||||
|
||||
// RedefineClasses() support for previous versions:
|
||||
void add_previous_version(InstanceKlass* ik, int emcp_method_count);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1997, 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
|
||||
@ -43,12 +43,6 @@ class instanceOopDesc : public oopDesc {
|
||||
klass_gap_offset_in_bytes() :
|
||||
sizeof(instanceOopDesc);
|
||||
}
|
||||
|
||||
static bool contains_field_offset(int offset, int nonstatic_field_size) {
|
||||
int base_in_bytes = base_offset_in_bytes();
|
||||
return (offset >= base_in_bytes &&
|
||||
(offset-base_in_bytes) < nonstatic_field_size * heapOopSize);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_OOPS_INSTANCEOOP_HPP
|
||||
|
@ -522,6 +522,8 @@ static SpecialFlag const special_jvm_flags[] = {
|
||||
{ "AllowRedefinitionToAddDeleteMethods", JDK_Version::jdk(13), JDK_Version::undefined(), JDK_Version::undefined() },
|
||||
{ "FlightRecorder", JDK_Version::jdk(13), JDK_Version::undefined(), JDK_Version::undefined() },
|
||||
{ "MonitorBound", JDK_Version::jdk(14), JDK_Version::jdk(15), JDK_Version::jdk(16) },
|
||||
{ "PrintVMQWaitTime", JDK_Version::jdk(15), JDK_Version::jdk(16), JDK_Version::jdk(17) },
|
||||
{ "UseNewFieldLayout", JDK_Version::jdk(15), JDK_Version::jdk(16), JDK_Version::jdk(17) },
|
||||
|
||||
// --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in:
|
||||
{ "DefaultMaxRAMFraction", JDK_Version::jdk(8), JDK_Version::undefined(), JDK_Version::undefined() },
|
||||
|
@ -1156,18 +1156,18 @@ int compare(ReassignedField* left, ReassignedField* right) {
|
||||
// Restore fields of an eliminated instance object using the same field order
|
||||
// returned by HotSpotResolvedObjectTypeImpl.getInstanceFields(true)
|
||||
static int reassign_fields_by_klass(InstanceKlass* klass, frame* fr, RegisterMap* reg_map, ObjectValue* sv, int svIndex, oop obj, bool skip_internal) {
|
||||
if (klass->superklass() != NULL) {
|
||||
svIndex = reassign_fields_by_klass(klass->superklass(), fr, reg_map, sv, svIndex, obj, skip_internal);
|
||||
}
|
||||
|
||||
GrowableArray<ReassignedField>* fields = new GrowableArray<ReassignedField>();
|
||||
for (AllFieldStream fs(klass); !fs.done(); fs.next()) {
|
||||
if (!fs.access_flags().is_static() && (!skip_internal || !fs.access_flags().is_internal())) {
|
||||
ReassignedField field;
|
||||
field._offset = fs.offset();
|
||||
field._type = Signature::basic_type(fs.signature());
|
||||
fields->append(field);
|
||||
InstanceKlass* ik = klass;
|
||||
while (ik != NULL) {
|
||||
for (AllFieldStream fs(ik); !fs.done(); fs.next()) {
|
||||
if (!fs.access_flags().is_static() && (!skip_internal || !fs.access_flags().is_internal())) {
|
||||
ReassignedField field;
|
||||
field._offset = fs.offset();
|
||||
field._type = Signature::basic_type(fs.signature());
|
||||
fields->append(field);
|
||||
}
|
||||
}
|
||||
ik = ik->superklass();
|
||||
}
|
||||
fields->sort(compare);
|
||||
for (int i = 0; i < fields->length(); i++) {
|
||||
|
@ -267,7 +267,7 @@ const size_t minimumSymbolTableSize = 1024;
|
||||
"compilation") \
|
||||
\
|
||||
product(bool, PrintVMQWaitTime, false, \
|
||||
"Print out the waiting time in VM operation queue") \
|
||||
"(Deprecated) Print out the waiting time in VM operation queue") \
|
||||
\
|
||||
product(bool, MethodFlushing, true, \
|
||||
"Reclamation of zombie and not-entrant methods") \
|
||||
@ -2488,7 +2488,15 @@ const size_t minimumSymbolTableSize = 1024;
|
||||
"Start flight recording with options")) \
|
||||
\
|
||||
experimental(bool, UseFastUnorderedTimeStamps, false, \
|
||||
"Use platform unstable time where supported for timestamps only")
|
||||
"Use platform unstable time where supported for timestamps only") \
|
||||
\
|
||||
product(bool, UseNewFieldLayout, true, \
|
||||
"(Deprecated) Use new algorithm to compute field layouts") \
|
||||
\
|
||||
product(bool, UseEmptySlotsInSupers, true, \
|
||||
"Allow allocating fields in empty slots of super-classes") \
|
||||
\
|
||||
|
||||
|
||||
// Interface macros
|
||||
#define DECLARE_PRODUCT_FLAG(type, name, value, doc) extern "C" type name;
|
||||
|
@ -235,7 +235,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
|
||||
nonstatic_field(InstanceKlass, _static_oop_field_count, u2) \
|
||||
nonstatic_field(InstanceKlass, _nonstatic_oop_map_size, int) \
|
||||
nonstatic_field(InstanceKlass, _is_marked_dependent, bool) \
|
||||
nonstatic_field(InstanceKlass, _misc_flags, u2) \
|
||||
nonstatic_field(InstanceKlass, _misc_flags, u4) \
|
||||
nonstatic_field(InstanceKlass, _minor_version, u2) \
|
||||
nonstatic_field(InstanceKlass, _major_version, u2) \
|
||||
nonstatic_field(InstanceKlass, _init_state, u1) \
|
||||
|
@ -1094,13 +1094,14 @@ public final class Module implements AnnotatedElement {
|
||||
|
||||
// map each module to a class loader
|
||||
ClassLoader pcl = ClassLoaders.platformClassLoader();
|
||||
boolean isModuleLoaderMapper = ModuleLoaderMap.isBuiltinMapper(clf);
|
||||
|
||||
for (int index = 0; index < numModules; index++) {
|
||||
String name = resolvedModules[index].name();
|
||||
ClassLoader loader = clf.apply(name);
|
||||
|
||||
if (loader == null || loader == pcl) {
|
||||
if (!(clf instanceof ModuleLoaderMap.Mapper)) {
|
||||
if (!isModuleLoaderMapper) {
|
||||
throw new IllegalArgumentException("loader can't be 'null'"
|
||||
+ " or the platform class loader");
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ public abstract class Record {
|
||||
* @implSpec
|
||||
* The implicitly provided implementation returns {@code true} if
|
||||
* and only if the argument is an instance of the same record type
|
||||
* as this object, and each component of this record is equal to
|
||||
* as this record, and each component of this record is equal to
|
||||
* the corresponding component of the argument; otherwise, {@code
|
||||
* false} is returned. Equality of a component {@code c} is
|
||||
* determined as follows:
|
||||
@ -130,46 +130,70 @@ public abstract class Record {
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* The implicitly provided implementation conforms to the
|
||||
* semantics described above; the implementation may or may not
|
||||
* accomplish this by using calls to the particular methods
|
||||
* listed.
|
||||
* Apart from the semantics described above, the precise algorithm
|
||||
* used in the implicitly provided implementation is unspecified
|
||||
* and is subject to change. The implementation may or may not use
|
||||
* calls to the particular methods listed, and may or may not
|
||||
* perform comparisons in the order of component declaration.
|
||||
*
|
||||
* @see java.util.Objects#equals(Object,Object)
|
||||
*
|
||||
* @param obj the reference object with which to compare.
|
||||
* @return {@code true} if this object is equal to the
|
||||
* @return {@code true} if this record is equal to the
|
||||
* argument; {@code false} otherwise.
|
||||
*/
|
||||
@Override
|
||||
public abstract boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* Returns a hash code value for the record.
|
||||
* Obeys the general contract of {@link Object#hashCode Object.hashCode}.
|
||||
* For records, hashing behavior is constrained by the refined contract
|
||||
* of {@link Record#equals Record.equals}, so that any two records
|
||||
* created from the same components must have the same hash code.
|
||||
*
|
||||
* @implSpec
|
||||
* The implicitly provided implementation returns a hash code value derived
|
||||
* by combining the hash code value for all the components, according to
|
||||
* {@link Object#hashCode()} for components whose types are reference types,
|
||||
* or the primitive wrapper hash code for components whose types are primitive
|
||||
* types.
|
||||
* by combining appropriate hashes from each component.
|
||||
* The precise algorithm used in the implicitly provided implementation
|
||||
* is unspecified and is subject to change within the above limits.
|
||||
* The resulting integer need not remain consistent from one
|
||||
* execution of an application to another execution of the same
|
||||
* application, even if the hashes of the component values were to
|
||||
* remain consistent in this way. Also, a component of primitive
|
||||
* type may contribute its bits to the hash code differently than
|
||||
* the {@code hashCode} of its primitive wrapper class.
|
||||
*
|
||||
* @see Object#hashCode()
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
* @return a hash code value for this record.
|
||||
*/
|
||||
@Override
|
||||
public abstract int hashCode();
|
||||
|
||||
/**
|
||||
* Obeys the general contract of {@link Object#toString Object.toString}.
|
||||
* Returns a string representation of the record.
|
||||
* In accordance with the general contract of {@link Object#toString()},
|
||||
* the {@code toString} method returns a string that
|
||||
* "textually represents" this record. The result should
|
||||
* be a concise but informative representation that is easy for a
|
||||
* person to read.
|
||||
* <p>
|
||||
* In addition to this general contract, record classes must further
|
||||
* participate in the invariant that any two records which are
|
||||
* {@linkplain Record#equals(Object) equal} must produce equal
|
||||
* strings. This invariant is necessarily relaxed in the rare
|
||||
* case where corresponding equal component values might fail
|
||||
* to produce equal strings for themselves.
|
||||
*
|
||||
* @implSpec
|
||||
* The implicitly provided implementation returns a string that is derived
|
||||
* from the name of the record class and the names and string representations
|
||||
* of all the components, according to {@link Object#toString()} for components
|
||||
* whose types are reference types, and the primitive wrapper {@code toString}
|
||||
* method for components whose types are primitive types.
|
||||
* The implicitly provided implementation returns a string which
|
||||
* contains the name of the record class, the names of components
|
||||
* of the record, and string representations of component values,
|
||||
* so as to fulfill the contract of this method.
|
||||
* The precise format produced by this implicitly provided implementation
|
||||
* is subject to change, so the present syntax should not be parsed
|
||||
* by applications to recover record component values.
|
||||
*
|
||||
* @see Object#toString()
|
||||
*
|
||||
|
@ -79,7 +79,7 @@ public final class ResolvedModule {
|
||||
* @return The module descriptor
|
||||
*/
|
||||
ModuleDescriptor descriptor() {
|
||||
return reference().descriptor();
|
||||
return mref.descriptor();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,7 +93,7 @@ public final class ResolvedModule {
|
||||
* @return The module name
|
||||
*/
|
||||
public String name() {
|
||||
return reference().descriptor().name();
|
||||
return mref.descriptor().name();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -904,6 +904,20 @@ class ImmutableCollections {
|
||||
@Override public V replace(K key, V value) { throw uoe(); }
|
||||
@Override public boolean replace(K key, V oldValue, V newValue) { throw uoe(); }
|
||||
@Override public void replaceAll(BiFunction<? super K,? super V,? extends V> f) { throw uoe(); }
|
||||
|
||||
/**
|
||||
* @implNote {@code null} values are disallowed in these immutable maps,
|
||||
* so we can improve upon the default implementation since a
|
||||
* {@code null} return from {@code get(key)} always means the default
|
||||
* value should be returned.
|
||||
*/
|
||||
@Override
|
||||
public V getOrDefault(Object key, V defaultValue) {
|
||||
V v;
|
||||
return ((v = get(key)) != null)
|
||||
? v
|
||||
: defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
static final class Map1<K,V> extends AbstractImmutableMap<K,V> {
|
||||
|
@ -2064,7 +2064,7 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
Node prev = null;
|
||||
Node firstTail = null;
|
||||
Branch branch = null;
|
||||
Node branchConn = null;
|
||||
BranchConn branchConn = null;
|
||||
|
||||
for (;;) {
|
||||
Node node = sequence(end);
|
||||
@ -2212,7 +2212,24 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
break;
|
||||
}
|
||||
|
||||
node = closure(node);
|
||||
if (node instanceof LineEnding) {
|
||||
LineEnding le = (LineEnding)node;
|
||||
node = closureOfLineEnding(le);
|
||||
|
||||
if (node != le) {
|
||||
// LineEnding was replaced with an anonymous group
|
||||
if (head == null)
|
||||
head = node;
|
||||
else
|
||||
tail.next = node;
|
||||
// Double return: Tail was returned in root
|
||||
tail = root;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
node = closure(node);
|
||||
}
|
||||
|
||||
/* save the top dot-greedy nodes (.*, .+) as well
|
||||
if (node instanceof GreedyCharProperty &&
|
||||
((GreedyCharProperty)node).cp instanceof Dot) {
|
||||
@ -3079,18 +3096,31 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
if (saveTCNCount < topClosureNodes.size())
|
||||
topClosureNodes.subList(saveTCNCount, topClosureNodes.size()).clear();
|
||||
|
||||
return groupWithClosure(node, head, tail, capturingGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a Group with quantifiers into some special constructs
|
||||
* (such as Branch or Loop/GroupCurly), if necessary.
|
||||
*
|
||||
* This method is applied either to actual groups or to the Unicode
|
||||
* linebreak (aka \\R) represented as an anonymous group.
|
||||
*/
|
||||
private Node groupWithClosure(Node node, Node head, Node tail,
|
||||
boolean capturingGroup)
|
||||
{
|
||||
if (node instanceof Ques) {
|
||||
Ques ques = (Ques) node;
|
||||
if (ques.type == Qtype.POSSESSIVE) {
|
||||
root = node;
|
||||
return node;
|
||||
}
|
||||
tail.next = new BranchConn();
|
||||
tail = tail.next;
|
||||
BranchConn branchConn = new BranchConn();
|
||||
tail = tail.next = branchConn;
|
||||
if (ques.type == Qtype.GREEDY) {
|
||||
head = new Branch(head, null, tail);
|
||||
head = new Branch(head, null, branchConn);
|
||||
} else { // Reluctant quantifier
|
||||
head = new Branch(null, head, tail);
|
||||
head = new Branch(null, head, branchConn);
|
||||
}
|
||||
root = tail;
|
||||
return head;
|
||||
@ -3267,6 +3297,31 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
return new Curly(prev, cmin, MAX_REPS, qtype);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processing repetition of a Unicode linebreak \\R.
|
||||
*/
|
||||
private Node closureOfLineEnding(LineEnding le) {
|
||||
int ch = peek();
|
||||
if (ch != '?' && ch != '*' && ch != '+' && ch != '{') {
|
||||
return le;
|
||||
}
|
||||
|
||||
// Replace the LineEnding with an anonymous group
|
||||
// (?:\\u000D\\u000A|[\\u000A\\u000B\\u000C\\u000D\\u0085\\u2028\\u2029])
|
||||
Node grHead = createGroup(true);
|
||||
Node grTail = root;
|
||||
BranchConn branchConn = new BranchConn();
|
||||
branchConn.next = grTail;
|
||||
Node slice = new Slice(new int[] {0x0D, 0x0A});
|
||||
slice.next = branchConn;
|
||||
Node chClass = newCharProperty(x -> x == 0x0A || x == 0x0B ||
|
||||
x == 0x0C || x == 0x0D || x == 0x85 || x == 0x2028 ||
|
||||
x == 0x2029);
|
||||
chClass.next = branchConn;
|
||||
grHead.next = new Branch(slice, chClass, branchConn);
|
||||
return groupWithClosure(closure(grHead), grHead, grTail, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes repetition. If the next character peeked is a quantifier
|
||||
* then new nodes must be appended to handle the repetition.
|
||||
@ -4723,8 +4778,8 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
static final class Branch extends Node {
|
||||
Node[] atoms = new Node[2];
|
||||
int size = 2;
|
||||
Node conn;
|
||||
Branch(Node first, Node second, Node branchConn) {
|
||||
BranchConn conn;
|
||||
Branch(Node first, Node second, BranchConn branchConn) {
|
||||
conn = branchConn;
|
||||
atoms[0] = first;
|
||||
atoms[1] = second;
|
||||
@ -4732,9 +4787,10 @@ loop: for(int x=0, offset=0; x<nCodePoints; x++, offset+=len) {
|
||||
|
||||
void add(Node node) {
|
||||
if (size >= atoms.length) {
|
||||
Node[] tmp = new Node[atoms.length*2];
|
||||
System.arraycopy(atoms, 0, tmp, 0, atoms.length);
|
||||
atoms = tmp;
|
||||
int len = ArraysSupport.newLength(size,
|
||||
1, /* minimum growth */
|
||||
size /* preferred growth */);
|
||||
atoms = Arrays.copyOf(atoms, len);
|
||||
}
|
||||
atoms[size++] = node;
|
||||
}
|
||||
|
@ -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
|
||||
@ -28,8 +28,8 @@ package jdk.internal.module;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jdk.internal.misc.VM;
|
||||
|
||||
@ -39,26 +39,26 @@ import jdk.internal.misc.VM;
|
||||
final class ArchivedModuleGraph {
|
||||
private static ArchivedModuleGraph archivedModuleGraph;
|
||||
|
||||
private final String mainModule;
|
||||
private final boolean hasSplitPackages;
|
||||
private final boolean hasIncubatorModules;
|
||||
private final ModuleFinder finder;
|
||||
private final Configuration configuration;
|
||||
private final Function<String, ClassLoader> classLoaderFunction;
|
||||
private final Map<String, Set<String>> concealedPackagesToOpen;
|
||||
private final Map<String, Set<String>> exportedPackagesToOpen;
|
||||
|
||||
private ArchivedModuleGraph(String mainModule,
|
||||
boolean hasSplitPackages,
|
||||
boolean hasIncubatorModules,
|
||||
ModuleFinder finder,
|
||||
Configuration configuration,
|
||||
Map<String, Set<String>> concealedPackagesToOpen,
|
||||
Map<String, Set<String>> exportedPackagesToOpen) {
|
||||
this.mainModule = mainModule;
|
||||
public ArchivedModuleGraph(boolean hasSplitPackages,
|
||||
boolean hasIncubatorModules,
|
||||
ModuleFinder finder,
|
||||
Configuration configuration,
|
||||
Function<String, ClassLoader> classLoaderFunction,
|
||||
Map<String, Set<String>> concealedPackagesToOpen,
|
||||
Map<String, Set<String>> exportedPackagesToOpen) {
|
||||
this.hasSplitPackages = hasSplitPackages;
|
||||
this.hasIncubatorModules = hasIncubatorModules;
|
||||
this.finder = finder;
|
||||
this.configuration = configuration;
|
||||
this.classLoaderFunction = classLoaderFunction;
|
||||
this.concealedPackagesToOpen = concealedPackagesToOpen;
|
||||
this.exportedPackagesToOpen = exportedPackagesToOpen;
|
||||
}
|
||||
@ -71,6 +71,10 @@ final class ArchivedModuleGraph {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
Function<String, ClassLoader> classLoaderFunction() {
|
||||
return classLoaderFunction;
|
||||
}
|
||||
|
||||
Map<String, Set<String>> concealedPackagesToOpen() {
|
||||
return concealedPackagesToOpen;
|
||||
}
|
||||
@ -92,7 +96,8 @@ final class ArchivedModuleGraph {
|
||||
*/
|
||||
static ArchivedModuleGraph get(String mainModule) {
|
||||
ArchivedModuleGraph graph = archivedModuleGraph;
|
||||
if (graph != null && Objects.equals(mainModule, graph.mainModule)) {
|
||||
// We only allow the unnamed module (default) case for now
|
||||
if (mainModule == null) {
|
||||
return graph;
|
||||
} else {
|
||||
return null;
|
||||
@ -102,23 +107,8 @@ final class ArchivedModuleGraph {
|
||||
/**
|
||||
* Archive the module graph for the given initial module.
|
||||
*/
|
||||
static void archive(String mainModule,
|
||||
boolean hasSplitPackages,
|
||||
boolean hasIncubatorModules,
|
||||
ModuleFinder finder,
|
||||
Configuration configuration,
|
||||
Map<String, Set<String>> concealedPackagesToOpen,
|
||||
Map<String, Set<String>> exportedPackagesToOpen) {
|
||||
if (mainModule != null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
archivedModuleGraph = new ArchivedModuleGraph(mainModule,
|
||||
hasSplitPackages,
|
||||
hasIncubatorModules,
|
||||
finder,
|
||||
configuration,
|
||||
concealedPackagesToOpen,
|
||||
exportedPackagesToOpen);
|
||||
static void archive(ArchivedModuleGraph graph) {
|
||||
archivedModuleGraph = graph;
|
||||
}
|
||||
|
||||
static {
|
||||
|
@ -370,7 +370,12 @@ public final class ModuleBootstrap {
|
||||
// loader.
|
||||
|
||||
// mapping of modules to class loaders
|
||||
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
|
||||
Function<String, ClassLoader> clf;
|
||||
if (archivedModuleGraph != null) {
|
||||
clf = archivedModuleGraph.classLoaderFunction();
|
||||
} else {
|
||||
clf = ModuleLoaderMap.mappingFunction(cf);
|
||||
}
|
||||
|
||||
// check that all modules to be mapped to the boot loader will be
|
||||
// loaded from the runtime image
|
||||
@ -440,13 +445,14 @@ public final class ModuleBootstrap {
|
||||
// Module graph can be archived at CDS dump time. Only allow the
|
||||
// unnamed module case for now.
|
||||
if (canArchive && (mainModule == null)) {
|
||||
ArchivedModuleGraph.archive(mainModule,
|
||||
hasSplitPackages,
|
||||
hasIncubatorModules,
|
||||
systemModuleFinder,
|
||||
cf,
|
||||
concealedPackagesToOpen,
|
||||
exportedPackagesToOpen);
|
||||
ArchivedModuleGraph.archive(
|
||||
new ArchivedModuleGraph(hasSplitPackages,
|
||||
hasIncubatorModules,
|
||||
systemModuleFinder,
|
||||
cf,
|
||||
clf,
|
||||
concealedPackagesToOpen,
|
||||
exportedPackagesToOpen));
|
||||
}
|
||||
|
||||
// total time to initialize
|
||||
@ -737,7 +743,6 @@ public final class ModuleBootstrap {
|
||||
Modules.addExports(m, pn, other);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -28,14 +28,12 @@ package jdk.internal.module;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ResolvedModule;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
import jdk.internal.loader.ClassLoaders;
|
||||
|
||||
|
||||
/**
|
||||
* Supports the mapping of modules to class loaders. The set of modules mapped
|
||||
* to the boot and platform class loaders is generated at build time from
|
||||
@ -46,16 +44,55 @@ public final class ModuleLoaderMap {
|
||||
/**
|
||||
* Maps the system modules to the built-in class loaders.
|
||||
*/
|
||||
public static final class Mapper implements Function<String, ClassLoader> {
|
||||
private final Map<String, ClassLoader> map;
|
||||
private static final class Mapper implements Function<String, ClassLoader> {
|
||||
|
||||
Mapper(Map<String, ClassLoader> map) {
|
||||
this.map = map; // defensive copy not needed
|
||||
private static final ClassLoader PLATFORM_CLASSLOADER =
|
||||
ClassLoaders.platformClassLoader();
|
||||
private static final ClassLoader APP_CLASSLOADER =
|
||||
ClassLoaders.appClassLoader();
|
||||
|
||||
private static final Integer PLATFORM_LOADER_INDEX = 1;
|
||||
private static final Integer APP_LOADER_INDEX = 2;
|
||||
|
||||
/**
|
||||
* Map from module to a class loader index. The index is resolved to the
|
||||
* actual class loader in {@code apply}.
|
||||
*/
|
||||
private final Map<String, Integer> map;
|
||||
|
||||
/**
|
||||
* Creates a Mapper to map module names in the given Configuration to
|
||||
* built-in classloaders.
|
||||
*
|
||||
* As a proxy for the actual classloader, we store an easily archiveable
|
||||
* index value in the internal map. The index is stored as a boxed value
|
||||
* so that we can cheaply do identity comparisons during bootstrap.
|
||||
*/
|
||||
Mapper(Configuration cf) {
|
||||
var map = new HashMap<String, Integer>();
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
String mn = resolvedModule.name();
|
||||
if (!Modules.bootModules.contains(mn)) {
|
||||
if (Modules.platformModules.contains(mn)) {
|
||||
map.put(mn, PLATFORM_LOADER_INDEX);
|
||||
} else {
|
||||
map.put(mn, APP_LOADER_INDEX);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassLoader apply(String name) {
|
||||
return map.get(name);
|
||||
Integer loader = map.get(name);
|
||||
if (loader == APP_LOADER_INDEX) {
|
||||
return APP_CLASSLOADER;
|
||||
} else if (loader == PLATFORM_LOADER_INDEX) {
|
||||
return PLATFORM_CLASSLOADER;
|
||||
} else { // BOOT_LOADER_INDEX
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,50 +100,40 @@ public final class ModuleLoaderMap {
|
||||
* Returns the names of the modules defined to the boot loader.
|
||||
*/
|
||||
public static Set<String> bootModules() {
|
||||
// The list of boot modules generated at build time.
|
||||
String[] BOOT_MODULES = new String[] { "@@BOOT_MODULE_NAMES@@" };
|
||||
Set<String> bootModules = new HashSet<>(BOOT_MODULES.length);
|
||||
for (String mn : BOOT_MODULES) {
|
||||
bootModules.add(mn);
|
||||
}
|
||||
return bootModules;
|
||||
return Modules.bootModules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of the modules defined to the platform loader.
|
||||
*/
|
||||
public static Set<String> platformModules() {
|
||||
// The list of platform modules generated at build time.
|
||||
String[] PLATFORM_MODULES = new String[] { "@@PLATFORM_MODULE_NAMES@@" };
|
||||
Set<String> platformModules = new HashSet<>(PLATFORM_MODULES.length);
|
||||
for (String mn : PLATFORM_MODULES) {
|
||||
platformModules.add(mn);
|
||||
}
|
||||
return platformModules;
|
||||
return Modules.platformModules;
|
||||
}
|
||||
|
||||
private static class Modules {
|
||||
// list of boot modules is generated at build time.
|
||||
private static final Set<String> bootModules =
|
||||
Set.of(new String[] { "@@BOOT_MODULE_NAMES@@" });
|
||||
|
||||
// list of platform modules is generated at build time.
|
||||
private static final Set<String> platformModules =
|
||||
Set.of(new String[] { "@@PLATFORM_MODULE_NAMES@@" });
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the function to map modules in the given configuration to the
|
||||
* Returns a function to map modules in the given configuration to the
|
||||
* built-in class loaders.
|
||||
*/
|
||||
static Function<String, ClassLoader> mappingFunction(Configuration cf) {
|
||||
Set<String> bootModules = bootModules();
|
||||
Set<String> platformModules = platformModules();
|
||||
return new Mapper(cf);
|
||||
}
|
||||
|
||||
ClassLoader platformClassLoader = ClassLoaders.platformClassLoader();
|
||||
ClassLoader appClassLoader = ClassLoaders.appClassLoader();
|
||||
|
||||
Map<String, ClassLoader> map = new HashMap<>();
|
||||
for (ResolvedModule resolvedModule : cf.modules()) {
|
||||
String mn = resolvedModule.name();
|
||||
if (!bootModules.contains(mn)) {
|
||||
if (platformModules.contains(mn)) {
|
||||
map.put(mn, platformClassLoader);
|
||||
} else {
|
||||
map.put(mn, appClassLoader);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Mapper(map);
|
||||
/**
|
||||
* When defining modules for a configuration, we only allow defining modules
|
||||
* to the boot or platform classloader if the ClassLoader mapping function
|
||||
* originate from here.
|
||||
*/
|
||||
public static boolean isBuiltinMapper(Function<String, ClassLoader> clf) {
|
||||
return clf instanceof Mapper;
|
||||
}
|
||||
}
|
||||
|
@ -162,7 +162,8 @@ module java.base {
|
||||
jdk.jlink;
|
||||
exports jdk.internal.loader to
|
||||
java.instrument,
|
||||
java.logging;
|
||||
java.logging,
|
||||
java.naming;
|
||||
exports jdk.internal.jmod to
|
||||
jdk.compiler,
|
||||
jdk.jlink;
|
||||
|
@ -1,4 +1,4 @@
|
||||
## Unicode Common Local Data Repository (CLDR) v35.1
|
||||
## Unicode Common Local Data Repository (CLDR) v36
|
||||
|
||||
### CLDR License
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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,6 +34,7 @@
|
||||
|
||||
#include "childproc.h"
|
||||
|
||||
const char * const *parentPathv;
|
||||
|
||||
ssize_t
|
||||
restartableWrite(int fd, const void *buf, size_t count)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 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
|
||||
@ -126,7 +126,7 @@ typedef struct _SpawnInfo {
|
||||
* The cached and split version of the JDK's effective PATH.
|
||||
* (We don't support putenv("PATH=...") in native code)
|
||||
*/
|
||||
const char * const *parentPathv;
|
||||
extern const char * const *parentPathv;
|
||||
|
||||
ssize_t restartableWrite(int fd, const void *buf, size_t count);
|
||||
int restartableDup2(int fd_from, int fd_to);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -26,13 +26,15 @@
|
||||
package javax.naming.spi;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
import javax.naming.*;
|
||||
import com.sun.naming.internal.VersionHelper;
|
||||
import com.sun.naming.internal.ResourceManager;
|
||||
import com.sun.naming.internal.FactoryEnumeration;
|
||||
import jdk.internal.loader.ClassLoaderValue;
|
||||
|
||||
/**
|
||||
* This class contains methods for creating context objects
|
||||
@ -79,6 +81,9 @@ public class NamingManager {
|
||||
*/
|
||||
private static ObjectFactoryBuilder object_factory_builder = null;
|
||||
|
||||
private static final ClassLoaderValue<InitialContextFactory> FACTORIES_CACHE =
|
||||
new ClassLoaderValue<>();
|
||||
|
||||
/**
|
||||
* The ObjectFactoryBuilder determines the policy used when
|
||||
* trying to load object factories.
|
||||
@ -672,6 +677,7 @@ public class NamingManager {
|
||||
*/
|
||||
public static Context getInitialContext(Hashtable<?,?> env)
|
||||
throws NamingException {
|
||||
ClassLoader loader;
|
||||
InitialContextFactory factory = null;
|
||||
|
||||
InitialContextFactoryBuilder builder = getInitialContextFactoryBuilder();
|
||||
@ -689,39 +695,22 @@ public class NamingManager {
|
||||
throw ne;
|
||||
}
|
||||
|
||||
ServiceLoader<InitialContextFactory> loader =
|
||||
ServiceLoader.load(InitialContextFactory.class);
|
||||
|
||||
Iterator<InitialContextFactory> iterator = loader.iterator();
|
||||
try {
|
||||
while (iterator.hasNext()) {
|
||||
InitialContextFactory f = iterator.next();
|
||||
if (f.getClass().getName().equals(className)) {
|
||||
factory = f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (ServiceConfigurationError e) {
|
||||
NoInitialContextException ne =
|
||||
new NoInitialContextException(
|
||||
"Cannot load initial context factory "
|
||||
+ "'" + className + "'");
|
||||
ne.setRootCause(e);
|
||||
throw ne;
|
||||
if (System.getSecurityManager() == null) {
|
||||
loader = Thread.currentThread().getContextClassLoader();
|
||||
if (loader == null) loader = ClassLoader.getSystemClassLoader();
|
||||
} else {
|
||||
PrivilegedAction<ClassLoader> pa = () -> {
|
||||
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
||||
return (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
|
||||
};
|
||||
loader = AccessController.doPrivileged(pa);
|
||||
}
|
||||
|
||||
if (factory == null) {
|
||||
try {
|
||||
@SuppressWarnings("deprecation")
|
||||
Object o = helper.loadClass(className).newInstance();
|
||||
factory = (InitialContextFactory) o;
|
||||
} catch (Exception e) {
|
||||
NoInitialContextException ne =
|
||||
new NoInitialContextException(
|
||||
"Cannot instantiate class: " + className);
|
||||
ne.setRootCause(e);
|
||||
throw ne;
|
||||
}
|
||||
var key = FACTORIES_CACHE.sub(className);
|
||||
try {
|
||||
factory = key.computeIfAbsent(loader, (ld, ky) -> getFactory(ky.key()));
|
||||
} catch (FactoryInitializationError e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
} else {
|
||||
factory = builder.createInitialContextFactory(env);
|
||||
@ -730,6 +719,43 @@ public class NamingManager {
|
||||
return factory.getInitialContext(env);
|
||||
}
|
||||
|
||||
private static InitialContextFactory getFactory(String className) {
|
||||
InitialContextFactory factory;
|
||||
try {
|
||||
ServiceLoader<InitialContextFactory> loader =
|
||||
ServiceLoader.load(InitialContextFactory.class);
|
||||
|
||||
factory = loader
|
||||
.stream()
|
||||
.filter(p -> p.type().getName().equals(className))
|
||||
.findFirst()
|
||||
.map(ServiceLoader.Provider::get)
|
||||
.orElse(null);
|
||||
} catch (ServiceConfigurationError e) {
|
||||
NoInitialContextException ne =
|
||||
new NoInitialContextException(
|
||||
"Cannot load initial context factory "
|
||||
+ "'" + className + "'");
|
||||
ne.setRootCause(e);
|
||||
throw new FactoryInitializationError(ne);
|
||||
}
|
||||
|
||||
if (factory == null) {
|
||||
try {
|
||||
@SuppressWarnings("deprecation")
|
||||
Object o = helper.loadClass(className).newInstance();
|
||||
factory = (InitialContextFactory) o;
|
||||
} catch (Exception e) {
|
||||
NoInitialContextException ne =
|
||||
new NoInitialContextException(
|
||||
"Cannot instantiate class: " + className);
|
||||
ne.setRootCause(e);
|
||||
throw new FactoryInitializationError(ne);
|
||||
}
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the InitialContextFactory builder to be builder.
|
||||
@ -921,4 +947,18 @@ public class NamingManager {
|
||||
|
||||
return (answer != null) ? answer : obj;
|
||||
}
|
||||
|
||||
private static class FactoryInitializationError extends Error {
|
||||
@java.io.Serial
|
||||
static final long serialVersionUID = -5805552256848841560L;
|
||||
|
||||
private FactoryInitializationError(NoInitialContextException cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NoInitialContextException getCause() {
|
||||
return (NoInitialContextException) super.getCause();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -305,9 +305,7 @@ public final class KeyTab {
|
||||
* Checks if the keytab file exists. Implementation of this method
|
||||
* should make sure that the result matches the latest status of the
|
||||
* keytab file.
|
||||
* <p>
|
||||
* The caller can use the result to determine if it should fallback to
|
||||
* another mechanism to read the keys.
|
||||
*
|
||||
* @return true if the keytab file exists; false otherwise.
|
||||
* @throws SecurityException if a security manager exists and the read
|
||||
* access to the keytab file is not permitted
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, 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
|
||||
@ -34,6 +34,8 @@ import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
||||
import jdk.vm.ci.common.JVMCIError;
|
||||
@ -61,6 +63,7 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
|
||||
private static final HotSpotResolvedJavaField[] NO_FIELDS = new HotSpotResolvedJavaField[0];
|
||||
private static final int METHOD_CACHE_ARRAY_CAPACITY = 8;
|
||||
private static final SortByOffset fieldSortingMethod = new SortByOffset();
|
||||
|
||||
/**
|
||||
* The Java class this type represents.
|
||||
@ -708,6 +711,12 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
}
|
||||
}
|
||||
|
||||
static class SortByOffset implements Comparator<ResolvedJavaField> {
|
||||
public int compare(ResolvedJavaField a, ResolvedJavaField b) {
|
||||
return a.getOffset() - b.getOffset();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
|
||||
if (instanceFields == null) {
|
||||
@ -727,8 +736,17 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
// This class does not have any instance fields of its own.
|
||||
return NO_FIELDS;
|
||||
} else if (superClassFieldCount != 0) {
|
||||
// Fields of the current class can be interleaved with fields of its super-classes
|
||||
// but the array of fields to be returned must be sorted by increasing offset
|
||||
// This code populates the array, then applies the sorting function
|
||||
HotSpotResolvedJavaField[] result = new HotSpotResolvedJavaField[instanceFields.length - superClassFieldCount];
|
||||
System.arraycopy(instanceFields, superClassFieldCount, result, 0, result.length);
|
||||
int i = 0;
|
||||
for (HotSpotResolvedJavaField f : instanceFields) {
|
||||
if (f.getDeclaringClass() == this) {
|
||||
result[i++] = f;
|
||||
}
|
||||
}
|
||||
Arrays.sort(result, fieldSortingMethod);
|
||||
return result;
|
||||
} else {
|
||||
// The super classes of this class do not have any instance fields.
|
||||
@ -781,23 +799,19 @@ final class HotSpotResolvedObjectTypeImpl extends HotSpotResolvedJavaType implem
|
||||
System.arraycopy(prepend, 0, result, 0, prependLength);
|
||||
}
|
||||
|
||||
// Fields of the current class can be interleaved with fields of its super-classes
|
||||
// but the array of fields to be returned must be sorted by increasing offset
|
||||
// This code populates the array, then applies the sorting function
|
||||
int resultIndex = prependLength;
|
||||
for (int i = 0; i < index; ++i) {
|
||||
FieldInfo field = new FieldInfo(i);
|
||||
if (field.isStatic() == retrieveStaticFields) {
|
||||
int offset = field.getOffset();
|
||||
HotSpotResolvedJavaField resolvedJavaField = createField(field.getType(), offset, field.getAccessFlags(), i);
|
||||
|
||||
// Make sure the result is sorted by offset.
|
||||
int j;
|
||||
for (j = resultIndex - 1; j >= prependLength && result[j].getOffset() > offset; j--) {
|
||||
result[j + 1] = result[j];
|
||||
}
|
||||
result[j + 1] = resolvedJavaField;
|
||||
resultIndex++;
|
||||
result[resultIndex++] = resolvedJavaField;
|
||||
}
|
||||
}
|
||||
|
||||
Arrays.sort(result, fieldSortingMethod);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, 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
|
||||
@ -101,7 +101,7 @@ class HotSpotVMConfig extends HotSpotVMConfigAccess {
|
||||
final int instanceKlassConstantsOffset = getFieldOffset("InstanceKlass::_constants", Integer.class, "ConstantPool*");
|
||||
final int instanceKlassFieldsOffset = getFieldOffset("InstanceKlass::_fields", Integer.class, "Array<u2>*");
|
||||
final int instanceKlassAnnotationsOffset = getFieldOffset("InstanceKlass::_annotations", Integer.class, "Annotations*");
|
||||
final int instanceKlassMiscFlagsOffset = getFieldOffset("InstanceKlass::_misc_flags", Integer.class, "u2");
|
||||
final int instanceKlassMiscFlagsOffset = getFieldOffset("InstanceKlass::_misc_flags", Integer.class, "u4");
|
||||
final int klassVtableStartOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_start_offset", Integer.class, "int");
|
||||
final int klassVtableLengthOffset = getFieldValue("CompilerToVM::Data::Klass_vtable_length_offset", Integer.class, "int");
|
||||
|
||||
|
@ -89,7 +89,7 @@ public abstract class AbstractMemberWriter implements MemberSummaryWriter {
|
||||
this.typeElement = typeElement;
|
||||
this.utils = configuration.utils;
|
||||
this.contents = configuration.contents;
|
||||
this.resources = configuration.resources;
|
||||
this.resources = configuration.docResources;
|
||||
this.links = writer.links;
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter
|
||||
Content div = HtmlTree.DIV(HtmlStyle.deprecationBlock, deprLabel);
|
||||
if (!deprs.isEmpty()) {
|
||||
|
||||
List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
|
||||
List<? extends DocTree> commentTags = ch.getDescription(deprs.get(0));
|
||||
if (!commentTags.isEmpty()) {
|
||||
addInlineDeprecatedComment(annotationType, deprs.get(0), div);
|
||||
}
|
||||
|
@ -495,7 +495,7 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite
|
||||
if (!deprs.isEmpty()) {
|
||||
CommentHelper ch = utils.getCommentHelper(typeElement);
|
||||
DocTree dt = deprs.get(0);
|
||||
List<? extends DocTree> commentTags = ch.getBody(configuration, dt);
|
||||
List<? extends DocTree> commentTags = ch.getBody(dt);
|
||||
if (!commentTags.isEmpty()) {
|
||||
addInlineDeprecatedComment(typeElement, deprs.get(0), div);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -182,7 +182,7 @@ public class Contents {
|
||||
* resources used to look up resource keys, and other details.
|
||||
*/
|
||||
Contents(HtmlConfiguration configuration) {
|
||||
this.resources = configuration.getResources();
|
||||
this.resources = configuration.getDocResources();
|
||||
|
||||
allClassesLabel = getNonBreakContent("doclet.All_Classes");
|
||||
allImplementedInterfacesLabel = getContent("doclet.All_Implemented_Interfaces");
|
||||
|
@ -78,7 +78,7 @@ public class HtmlConfiguration extends BaseConfiguration {
|
||||
*/
|
||||
public static final String HTML_DEFAULT_CHARSET = "utf-8";
|
||||
|
||||
public final Resources resources;
|
||||
public final Resources docResources;
|
||||
|
||||
/**
|
||||
* First file to appear in the right-hand frame in the generated
|
||||
@ -133,17 +133,31 @@ public class HtmlConfiguration extends BaseConfiguration {
|
||||
*/
|
||||
public HtmlConfiguration(Doclet doclet, Locale locale, Reporter reporter) {
|
||||
super(doclet, locale, reporter);
|
||||
resources = new Resources(locale,
|
||||
|
||||
// Use the default locale for console messages.
|
||||
Resources msgResources = new Resources(Locale.getDefault(),
|
||||
BaseConfiguration.sharedResourceBundleName,
|
||||
"jdk.javadoc.internal.doclets.formats.html.resources.standard");
|
||||
|
||||
messages = new Messages(this);
|
||||
// Use the provided locale for generated docs
|
||||
// Ideally, the doc resources would be in different resource files than the
|
||||
// message resources, so that we do not have different copies of the same resources.
|
||||
if (locale.equals(Locale.getDefault())) {
|
||||
docResources = msgResources;
|
||||
} else {
|
||||
docResources = new Resources(locale,
|
||||
BaseConfiguration.sharedResourceBundleName,
|
||||
"jdk.javadoc.internal.doclets.formats.html.resources.standard");
|
||||
}
|
||||
|
||||
messages = new Messages(this, msgResources);
|
||||
contents = new Contents(this);
|
||||
options = new HtmlOptions(this);
|
||||
|
||||
String v;
|
||||
try {
|
||||
ResourceBundle rb = ResourceBundle.getBundle(versionBundleName, getLocale());
|
||||
// the version bundle is not localized
|
||||
ResourceBundle rb = ResourceBundle.getBundle(versionBundleName, Locale.getDefault());
|
||||
try {
|
||||
v = rb.getString("release");
|
||||
} catch (MissingResourceException e) {
|
||||
@ -166,10 +180,15 @@ public class HtmlConfiguration extends BaseConfiguration {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Resources getResources() {
|
||||
return resources;
|
||||
public Resources getDocResources() {
|
||||
return docResources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a utility object providing commonly used fragments of content.
|
||||
*
|
||||
* @return a utility object providing commonly used fragments of content
|
||||
*/
|
||||
public Contents getContents() {
|
||||
return contents;
|
||||
}
|
||||
@ -335,12 +354,7 @@ public class HtmlConfiguration extends BaseConfiguration {
|
||||
Character unicode = (tagLabel.length() == 0)
|
||||
? '*'
|
||||
: Character.toUpperCase(tagLabel.charAt(0));
|
||||
List<SearchIndexItem> list = tagSearchIndexMap.get(unicode);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
tagSearchIndexMap.put(unicode, list);
|
||||
}
|
||||
list.add(sii);
|
||||
tagSearchIndexMap.computeIfAbsent(unicode, k -> new ArrayList<>()).add(sii);
|
||||
}
|
||||
tagSearchIndexKeys = tagSearchIndexMap.keySet();
|
||||
}
|
||||
@ -359,7 +373,7 @@ public class HtmlConfiguration extends BaseConfiguration {
|
||||
if (options.charset() == null) {
|
||||
options.setCharset(options.docEncoding());
|
||||
} else if (!options.charset().equals(options.docEncoding())) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_conflict", "-charset", "-docencoding"));
|
||||
messages.error("doclet.Option_conflict", "-charset", "-docencoding");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ public class HtmlDocletWriter {
|
||||
this.options = configuration.getOptions();
|
||||
this.contents = configuration.contents;
|
||||
this.messages = configuration.messages;
|
||||
this.resources = configuration.resources;
|
||||
this.resources = configuration.docResources;
|
||||
this.links = new Links(path);
|
||||
this.utils = configuration.utils;
|
||||
this.path = path;
|
||||
@ -1038,14 +1038,14 @@ public class HtmlDocletWriter {
|
||||
return new RawHtml(seetext);
|
||||
}
|
||||
boolean isLinkPlain = kind == LINK_PLAIN;
|
||||
Content label = plainOrCode(isLinkPlain, new RawHtml(ch.getLabel(configuration, see)));
|
||||
Content label = plainOrCode(isLinkPlain, new RawHtml(ch.getLabel(see)));
|
||||
|
||||
//The text from the @see tag. We will output this text when a label is not specified.
|
||||
Content text = plainOrCode(kind == LINK_PLAIN, new RawHtml(seetext));
|
||||
|
||||
TypeElement refClass = ch.getReferencedClass(configuration, see);
|
||||
String refClassName = ch.getReferencedClassName(configuration, see);
|
||||
Element refMem = ch.getReferencedMember(configuration, see);
|
||||
TypeElement refClass = ch.getReferencedClass(see);
|
||||
String refClassName = ch.getReferencedClassName(see);
|
||||
Element refMem = ch.getReferencedMember(see);
|
||||
String refMemName = ch.getReferencedMemberName(see);
|
||||
|
||||
if (refMemName == null && refMem != null) {
|
||||
@ -1053,7 +1053,7 @@ public class HtmlDocletWriter {
|
||||
}
|
||||
if (refClass == null) {
|
||||
//@see is not referencing an included class
|
||||
PackageElement refPackage = ch.getReferencedPackage(configuration, see);
|
||||
PackageElement refPackage = ch.getReferencedPackage(see);
|
||||
if (refPackage != null && utils.isIncluded(refPackage)) {
|
||||
//@see is referencing an included package
|
||||
if (label.isEmpty())
|
||||
@ -1169,7 +1169,7 @@ public class HtmlDocletWriter {
|
||||
*/
|
||||
public void addInlineComment(Element element, DocTree tag, Content htmltree) {
|
||||
CommentHelper ch = utils.getCommentHelper(element);
|
||||
List<? extends DocTree> description = ch.getDescription(configuration, tag);
|
||||
List<? extends DocTree> description = ch.getDescription(tag);
|
||||
addCommentTags(element, tag, description, false, false, false, htmltree);
|
||||
}
|
||||
|
||||
@ -1194,7 +1194,7 @@ public class HtmlDocletWriter {
|
||||
*/
|
||||
public void addInlineDeprecatedComment(Element e, DocTree tag, Content htmltree) {
|
||||
CommentHelper ch = utils.getCommentHelper(e);
|
||||
addCommentTags(e, ch.getBody(configuration, tag), true, false, false, htmltree);
|
||||
addCommentTags(e, ch.getBody(tag), true, false, false, htmltree);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1220,8 +1220,8 @@ public class HtmlDocletWriter {
|
||||
|
||||
public void addSummaryDeprecatedComment(Element element, DocTree tag, Content htmltree) {
|
||||
CommentHelper ch = utils.getCommentHelper(element);
|
||||
List<? extends DocTree> body = ch.getBody(configuration, tag);
|
||||
addCommentTags(element, ch.getFirstSentenceTrees(configuration, body), true, true, true, htmltree);
|
||||
List<? extends DocTree> body = ch.getBody(tag);
|
||||
addCommentTags(element, ch.getFirstSentenceTrees(body), true, true, true, htmltree);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,15 +33,12 @@ import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.sun.tools.doclint.DocLint;
|
||||
import jdk.javadoc.doclet.Reporter;
|
||||
import jdk.javadoc.internal.doclets.toolkit.BaseOptions;
|
||||
import jdk.javadoc.internal.doclets.toolkit.Messages;
|
||||
import jdk.javadoc.internal.doclets.toolkit.Resources;
|
||||
import jdk.javadoc.internal.doclets.toolkit.util.DocFile;
|
||||
import jdk.javadoc.internal.doclets.toolkit.util.Utils;
|
||||
|
||||
import static javax.tools.Diagnostic.Kind.ERROR;
|
||||
import static javax.tools.Diagnostic.Kind.WARNING;
|
||||
|
||||
/**
|
||||
* Storage for all options supported by the
|
||||
* {@link jdk.javadoc.doclet.StandardDoclet standard doclet},
|
||||
@ -199,8 +196,8 @@ public class HtmlOptions extends BaseOptions {
|
||||
|
||||
@Override
|
||||
public Set<? extends Option> getSupportedOptions() {
|
||||
Resources resources = config.getResources();
|
||||
Reporter reporter = config.getReporter();
|
||||
Messages messages = config.getMessages();
|
||||
Resources resources = messages.getResources();
|
||||
|
||||
List<Option> options = List.of(
|
||||
new Option(resources, "--add-stylesheet", 1) {
|
||||
@ -255,13 +252,11 @@ public class HtmlOptions extends BaseOptions {
|
||||
@Override
|
||||
public boolean process(String opt, List<String> args) {
|
||||
if (noHelp) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_conflict",
|
||||
"-helpfile", "-nohelp"));
|
||||
messages.error("doclet.Option_conflict", "-helpfile", "-nohelp");
|
||||
return false;
|
||||
}
|
||||
if (!helpFile.isEmpty()) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_reuse",
|
||||
"-helpfile"));
|
||||
messages.error("doclet.Option_reuse", "-helpfile");
|
||||
return false;
|
||||
}
|
||||
helpFile = args.get(0);
|
||||
@ -281,8 +276,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
public boolean process(String opt, List<String> args) {
|
||||
noHelp = true;
|
||||
if (!helpFile.isEmpty()) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_conflict",
|
||||
"-nohelp", "-helpfile"));
|
||||
messages.error("doclet.Option_conflict", "-nohelp", "-helpfile");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -302,8 +296,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
public boolean process(String opt, List<String> args) {
|
||||
createIndex = false;
|
||||
if (splitIndex) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_conflict",
|
||||
"-noindex", "-splitindex"));
|
||||
messages.error("doclet.Option_conflict", "-noindex", "-splitindex");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -323,8 +316,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
public boolean process(String opt, List<String> args) {
|
||||
noOverview = true;
|
||||
if (overviewPath != null) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_conflict",
|
||||
"-nooverview", "-overview"));
|
||||
messages.error("doclet.Option_conflict", "-nooverview", "-overview");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -344,8 +336,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
public boolean process(String opt, List<String> args) {
|
||||
overviewPath = args.get(0);
|
||||
if (noOverview) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_conflict",
|
||||
"-overview", "-nooverview"));
|
||||
messages.error("doclet.Option_conflict", "-overview", "-nooverview");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -365,8 +356,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
public boolean process(String opt, List<String> args) {
|
||||
splitIndex = true;
|
||||
if (!createIndex) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_conflict",
|
||||
"-splitindex", "-noindex"));
|
||||
messages.error("doclet.Option_conflict", "-splitindex", "-noindex");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -418,11 +408,11 @@ public class HtmlOptions extends BaseOptions {
|
||||
public boolean process(String opt, List<String> args) {
|
||||
String dopt = opt.replace("-Xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX);
|
||||
if (dopt.contains("/")) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_doclint_no_qualifiers"));
|
||||
messages.error("doclet.Option_doclint_no_qualifiers");
|
||||
return false;
|
||||
}
|
||||
if (!DocLint.isValidOption(dopt)) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_doclint_invalid_arg"));
|
||||
messages.error("doclet.Option_doclint_invalid_arg");
|
||||
return false;
|
||||
}
|
||||
doclintOpts.add(dopt);
|
||||
@ -435,7 +425,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
public boolean process(String opt, List<String> args) {
|
||||
String dopt = opt.replace("-Xdoclint/package:", DocLint.XCHECK_PACKAGE);
|
||||
if (!DocLint.isValidOption(dopt)) {
|
||||
reporter.print(ERROR, resources.getText("doclet.Option_doclint_package_invalid_arg"));
|
||||
messages.error("doclet.Option_doclint_package_invalid_arg");
|
||||
return false;
|
||||
}
|
||||
doclintOpts.add(dopt);
|
||||
@ -450,7 +440,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
try {
|
||||
new URL(docrootParent);
|
||||
} catch (MalformedURLException e) {
|
||||
reporter.print(ERROR, resources.getText("doclet.MalformedURL", docrootParent));
|
||||
messages.error("doclet.MalformedURL", docrootParent);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -460,7 +450,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
new XOption(resources, "--no-frames") {
|
||||
@Override
|
||||
public boolean process(String opt, List<String> args) {
|
||||
reporter.print(WARNING, resources.getText("doclet.NoFrames_specified"));
|
||||
messages.warning("doclet.NoFrames_specified");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -477,14 +467,13 @@ public class HtmlOptions extends BaseOptions {
|
||||
return false;
|
||||
}
|
||||
|
||||
Resources resources = config.getResources();
|
||||
Reporter reporter = config.getReporter();
|
||||
Messages messages = config.getMessages();
|
||||
|
||||
// check if helpfile exists
|
||||
if (!helpFile.isEmpty()) {
|
||||
DocFile help = DocFile.createFileForInput(config, helpFile);
|
||||
if (!help.exists()) {
|
||||
reporter.print(ERROR, resources.getText("doclet.File_not_found", helpFile));
|
||||
messages.error("doclet.File_not_found", helpFile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -492,7 +481,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
if (!stylesheetFile.isEmpty()) {
|
||||
DocFile stylesheet = DocFile.createFileForInput(config, stylesheetFile);
|
||||
if (!stylesheet.exists()) {
|
||||
reporter.print(ERROR, resources.getText("doclet.File_not_found", stylesheetFile));
|
||||
messages.error("doclet.File_not_found", stylesheetFile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -500,7 +489,7 @@ public class HtmlOptions extends BaseOptions {
|
||||
for (String ssheet : additionalStylesheets) {
|
||||
DocFile ssfile = DocFile.createFileForInput(config, ssheet);
|
||||
if (!ssfile.exists()) {
|
||||
reporter.print(ERROR, resources.getText("doclet.File_not_found", ssheet));
|
||||
messages.error("doclet.File_not_found", ssheet);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ public class HtmlSerialFieldWriter extends FieldWriterImpl
|
||||
@Override
|
||||
public void addMemberDescription(VariableElement field, DocTree serialFieldTag, Content contentTree) {
|
||||
CommentHelper ch = utils.getCommentHelper(field);
|
||||
List<? extends DocTree> description = ch.getDescription(configuration, serialFieldTag);
|
||||
List<? extends DocTree> description = ch.getDescription(serialFieldTag);
|
||||
if (!description.isEmpty()) {
|
||||
Content serialFieldContent = new RawHtml(ch.getText(description));
|
||||
Content div = HtmlTree.DIV(HtmlStyle.block, serialFieldContent);
|
||||
|
@ -234,7 +234,7 @@ public class LinkFactoryImpl extends LinkFactory {
|
||||
* @return the tool tip for the appropriate class.
|
||||
*/
|
||||
private String getClassToolTip(TypeElement typeElement, boolean isTypeLink) {
|
||||
Resources resources = m_writer.configuration.getResources();
|
||||
Resources resources = m_writer.configuration.getDocResources();
|
||||
if (isTypeLink) {
|
||||
return resources.getText("doclet.Href_Type_Param_Title",
|
||||
utils.getSimpleName(typeElement));
|
||||
|
@ -375,16 +375,16 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
|
||||
});
|
||||
// Generate the map of all services listed using @provides, and the description.
|
||||
(utils.getBlockTags(mdle, DocTree.Kind.PROVIDES)).forEach((tree) -> {
|
||||
TypeElement t = ch.getServiceType(configuration, tree);
|
||||
TypeElement t = ch.getServiceType(tree);
|
||||
if (t != null) {
|
||||
providesTrees.put(t, commentTagsToContent(tree, mdle, ch.getDescription(configuration, tree), false, true));
|
||||
providesTrees.put(t, commentTagsToContent(tree, mdle, ch.getDescription(tree), false, true));
|
||||
}
|
||||
});
|
||||
// Generate the map of all services listed using @uses, and the description.
|
||||
(utils.getBlockTags(mdle, DocTree.Kind.USES)).forEach((tree) -> {
|
||||
TypeElement t = ch.getServiceType(configuration, tree);
|
||||
TypeElement t = ch.getServiceType(tree);
|
||||
if (t != null) {
|
||||
usesTrees.put(t, commentTagsToContent(tree, mdle, ch.getDescription(configuration, tree), false, true));
|
||||
usesTrees.put(t, commentTagsToContent(tree, mdle, ch.getDescription(tree), false, true));
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -827,7 +827,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
|
||||
Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(mdle));
|
||||
deprDiv.add(deprPhrase);
|
||||
if (!deprs.isEmpty()) {
|
||||
List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
|
||||
List<? extends DocTree> commentTags = ch.getDescription(deprs.get(0));
|
||||
if (!commentTags.isEmpty()) {
|
||||
addInlineDeprecatedComment(mdle, deprs.get(0), deprDiv);
|
||||
}
|
||||
@ -892,7 +892,7 @@ public class ModuleWriterImpl extends HtmlDocletWriter implements ModuleSummaryW
|
||||
deprDiv.add(deprPhrase);
|
||||
if (!deprs.isEmpty()) {
|
||||
CommentHelper ch = utils.getCommentHelper(pkg);
|
||||
List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
|
||||
List<? extends DocTree> commentTags = ch.getDescription(deprs.get(0));
|
||||
if (!commentTags.isEmpty()) {
|
||||
addInlineDeprecatedComment(pkg, deprs.get(0), deprDiv);
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ public class PackageWriterImpl extends HtmlDocletWriter
|
||||
Content deprPhrase = HtmlTree.SPAN(HtmlStyle.deprecatedLabel, getDeprecatedPhrase(packageElement));
|
||||
deprDiv.add(deprPhrase);
|
||||
if (!deprs.isEmpty()) {
|
||||
List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
|
||||
List<? extends DocTree> commentTags = ch.getDescription(deprs.get(0));
|
||||
if (!commentTags.isEmpty()) {
|
||||
addInlineDeprecatedComment(packageElement, deprs.get(0), deprDiv);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ public class SourceToHTMLConverter {
|
||||
this.configuration = configuration;
|
||||
this.options = configuration.getOptions();
|
||||
this.messages = configuration.getMessages();
|
||||
this.resources = configuration.resources;
|
||||
this.resources = configuration.docResources;
|
||||
this.utils = configuration.utils;
|
||||
this.docEnv = rd;
|
||||
this.outputdir = outputdir;
|
||||
|
@ -88,7 +88,7 @@ public class TagletWriterImpl extends TagletWriter {
|
||||
configuration = htmlWriter.configuration;
|
||||
options = configuration.getOptions();
|
||||
utils = configuration.utils;
|
||||
resources = configuration.getResources();
|
||||
resources = configuration.getDocResources();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -139,7 +139,7 @@ public class TagletWriterImpl extends TagletWriter {
|
||||
result.add(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
|
||||
htmlWriter.getDeprecatedPhrase(element)));
|
||||
if (!deprs.isEmpty()) {
|
||||
List<? extends DocTree> commentTags = ch.getDescription(configuration, deprs.get(0));
|
||||
List<? extends DocTree> commentTags = ch.getDescription(deprs.get(0));
|
||||
if (!commentTags.isEmpty()) {
|
||||
result.add(commentTagsToOutput(null, element, commentTags, false));
|
||||
}
|
||||
@ -150,7 +150,7 @@ public class TagletWriterImpl extends TagletWriter {
|
||||
result.add(HtmlTree.SPAN(HtmlStyle.deprecatedLabel,
|
||||
htmlWriter.getDeprecatedPhrase(element)));
|
||||
if (!deprs.isEmpty()) {
|
||||
List<? extends DocTree> bodyTags = ch.getBody(configuration, deprs.get(0));
|
||||
List<? extends DocTree> bodyTags = ch.getBody(deprs.get(0));
|
||||
Content body = commentTagsToOutput(null, element, bodyTags, false);
|
||||
if (!body.isEmpty())
|
||||
result.add(HtmlTree.DIV(HtmlStyle.deprecationComment, body));
|
||||
@ -191,7 +191,7 @@ public class TagletWriterImpl extends TagletWriter {
|
||||
Content nameTree = new StringContent(paramName);
|
||||
body.add(HtmlTree.CODE(defineID ? HtmlTree.SPAN_ID("param-" + paramName, nameTree) : nameTree));
|
||||
body.add(" - ");
|
||||
List<? extends DocTree> description = ch.getDescription(configuration, paramTag);
|
||||
List<? extends DocTree> description = ch.getDescription(paramTag);
|
||||
body.add(htmlWriter.commentTagsToContent(paramTag, element, description, false, inSummary));
|
||||
return HtmlTree.DD(body);
|
||||
}
|
||||
@ -215,7 +215,7 @@ public class TagletWriterImpl extends TagletWriter {
|
||||
result.add(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.returnLabel,
|
||||
new StringContent(resources.getText("doclet.Returns")))));
|
||||
result.add(HtmlTree.DD(htmlWriter.commentTagsToContent(
|
||||
returnTag, element, ch.getDescription(configuration, returnTag), false, inSummary)));
|
||||
returnTag, element, ch.getDescription(returnTag), false, inSummary)));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -279,7 +279,7 @@ public class TagletWriterImpl extends TagletWriter {
|
||||
if (many) {
|
||||
body.add(", ");
|
||||
}
|
||||
List<? extends DocTree> bodyTags = ch.getBody(configuration, simpleTag);
|
||||
List<? extends DocTree> bodyTags = ch.getBody(simpleTag);
|
||||
body.add(htmlWriter.commentTagsToContent(simpleTag, element, bodyTags, false, inSummary));
|
||||
many = true;
|
||||
}
|
||||
@ -292,7 +292,7 @@ public class TagletWriterImpl extends TagletWriter {
|
||||
ContentBuilder result = new ContentBuilder();
|
||||
result.add(HtmlTree.DT(HtmlTree.SPAN(HtmlStyle.simpleTagLabel, new RawHtml(header))));
|
||||
CommentHelper ch = utils.getCommentHelper(element);
|
||||
List<? extends DocTree> description = ch.getDescription(configuration, simpleTag);
|
||||
List<? extends DocTree> description = ch.getDescription(simpleTag);
|
||||
Content body = htmlWriter.commentTagsToContent(simpleTag, element, description, false, inSummary);
|
||||
result.add(HtmlTree.DD(body));
|
||||
return result;
|
||||
@ -317,7 +317,7 @@ public class TagletWriterImpl extends TagletWriter {
|
||||
public Content throwsTagOutput(Element element, DocTree throwsTag, TypeMirror substituteType) {
|
||||
ContentBuilder body = new ContentBuilder();
|
||||
CommentHelper ch = utils.getCommentHelper(element);
|
||||
Element exception = ch.getException(configuration, throwsTag);
|
||||
Element exception = ch.getException(throwsTag);
|
||||
Content excName;
|
||||
if (substituteType != null) {
|
||||
excName = htmlWriter.getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.MEMBER,
|
||||
@ -333,7 +333,7 @@ public class TagletWriterImpl extends TagletWriter {
|
||||
excName = htmlWriter.getLink(link);
|
||||
}
|
||||
body.add(HtmlTree.CODE(excName));
|
||||
List<? extends DocTree> description = ch.getDescription(configuration, throwsTag);
|
||||
List<? extends DocTree> description = ch.getDescription(throwsTag);
|
||||
Content desc = htmlWriter.commentTagsToContent(throwsTag, element, description, false, inSummary);
|
||||
if (desc != null && !desc.isEmpty()) {
|
||||
body.add(" - ");
|
||||
|
@ -141,7 +141,7 @@ public class Navigation {
|
||||
this.path = path;
|
||||
this.pathToRoot = path.parent().invert();
|
||||
this.links = new Links(path);
|
||||
this.rowListTitle = configuration.getResources().getText("doclet.Navigation");
|
||||
this.rowListTitle = configuration.getDocResources().getText("doclet.Navigation");
|
||||
this.searchLabel = contents.getContent("doclet.search");
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ public abstract class AbstractDoclet implements Doclet {
|
||||
|
||||
private void reportInternalError(Throwable t) {
|
||||
if (getClass().equals(StandardDoclet.class) || getClass().equals(HtmlDoclet.class)) {
|
||||
System.err.println(configuration.getResources().getText("doclet.internal.report.bug"));
|
||||
System.err.println(configuration.getDocResources().getText("doclet.internal.report.bug"));
|
||||
}
|
||||
dumpStack(true, t);
|
||||
}
|
||||
|
@ -60,8 +60,6 @@ import jdk.javadoc.internal.doclets.toolkit.util.Utils.Pair;
|
||||
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberCache;
|
||||
import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
|
||||
|
||||
import static javax.tools.Diagnostic.Kind.*;
|
||||
|
||||
/**
|
||||
* Configure the output based on the options. Doclets should sub-class
|
||||
* BaseConfiguration, to configure and add their own options. This class contains
|
||||
@ -154,7 +152,7 @@ public abstract class BaseConfiguration {
|
||||
|
||||
public abstract Messages getMessages();
|
||||
|
||||
public abstract Resources getResources();
|
||||
public abstract Resources getDocResources();
|
||||
|
||||
/**
|
||||
* Returns a string identifying the version of the doclet.
|
||||
@ -334,9 +332,7 @@ public abstract class BaseConfiguration {
|
||||
}
|
||||
|
||||
// add entries for modules which may not have exported packages
|
||||
modules.forEach((ModuleElement mdle) -> {
|
||||
modulePackages.computeIfAbsent(mdle, m -> Collections.emptySet());
|
||||
});
|
||||
modules.forEach(mdle -> modulePackages.computeIfAbsent(mdle, m -> Collections.emptySet()));
|
||||
|
||||
modules.addAll(modulePackages.keySet());
|
||||
showModules = !modules.isEmpty();
|
||||
@ -396,18 +392,18 @@ public abstract class BaseConfiguration {
|
||||
private void initDestDirectory() throws DocletException {
|
||||
String destDirName = getOptions().destDirName();
|
||||
if (!destDirName.isEmpty()) {
|
||||
Resources resources = getResources();
|
||||
Messages messages = getMessages();
|
||||
DocFile destDir = DocFile.createFileForDirectory(this, destDirName);
|
||||
if (!destDir.exists()) {
|
||||
//Create the output directory (in case it doesn't exist yet)
|
||||
reporter.print(NOTE, resources.getText("doclet.dest_dir_create", destDirName));
|
||||
messages.notice("doclet.dest_dir_create", destDirName);
|
||||
destDir.mkdirs();
|
||||
} else if (!destDir.isDirectory()) {
|
||||
throw new SimpleDocletException(resources.getText(
|
||||
throw new SimpleDocletException(messages.getResources().getText(
|
||||
"doclet.destination_directory_not_directory_0",
|
||||
destDir.getPath()));
|
||||
} else if (!destDir.canWrite()) {
|
||||
throw new SimpleDocletException(resources.getText(
|
||||
throw new SimpleDocletException(messages.getResources().getText(
|
||||
"doclet.destination_directory_not_writable_0",
|
||||
destDir.getPath()));
|
||||
}
|
||||
@ -689,12 +685,12 @@ public abstract class BaseConfiguration {
|
||||
*/
|
||||
public boolean isJavaFXMode() {
|
||||
TypeElement observable = utils.elementUtils.getTypeElement("javafx.beans.Observable");
|
||||
if (observable != null) {
|
||||
ModuleElement javafxModule = utils.elementUtils.getModuleOf(observable);
|
||||
if (javafxModule == null || javafxModule.isUnnamed() || javafxModule.getQualifiedName().contentEquals("javafx.base")) {
|
||||
return true;
|
||||
}
|
||||
if (observable == null) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
ModuleElement javafxModule = utils.elementUtils.getModuleOf(observable);
|
||||
return javafxModule == null
|
||||
|| javafxModule.isUnnamed()
|
||||
|| javafxModule.getQualifiedName().contentEquals("javafx.base");
|
||||
}
|
||||
}
|
||||
|
@ -271,7 +271,7 @@ public abstract class BaseOptions {
|
||||
}
|
||||
|
||||
public Set<? extends Option> getSupportedOptions() {
|
||||
Resources resources = config.getResources();
|
||||
Resources resources = config.getDocResources();
|
||||
Messages messages = config.getMessages();
|
||||
Reporter reporter = config.getReporter();
|
||||
|
||||
@ -572,7 +572,7 @@ public abstract class BaseOptions {
|
||||
osw = new OutputStreamWriter(ost, docencoding);
|
||||
} catch (UnsupportedEncodingException exc) {
|
||||
config.reporter.print(ERROR,
|
||||
config.getResources().getText("doclet.Encoding_not_supported", docencoding));
|
||||
config.getDocResources().getText("doclet.Encoding_not_supported", docencoding));
|
||||
return false;
|
||||
} finally {
|
||||
try {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -81,7 +81,7 @@ public class CommentUtils {
|
||||
protected CommentUtils(BaseConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
utils = configuration.utils;
|
||||
resources = configuration.getResources();
|
||||
resources = configuration.getDocResources();
|
||||
trees = configuration.docEnv.getDocTrees();
|
||||
treeFactory = trees.getDocTreeFactory();
|
||||
elementUtils = configuration.docEnv.getElementUtils();
|
||||
|
@ -51,16 +51,26 @@ public class Messages {
|
||||
* Creates a {@code Messages} object to provide standardized access to
|
||||
* the doclet's diagnostic reporting mechanisms.
|
||||
*
|
||||
* @param configuration the doclet's configuration, used to access
|
||||
* the doclet's resources, reporter, and additional methods and state
|
||||
* used to filter out messages, if any, which should be suppressed.
|
||||
* @param configuration the doclet's configuration, used to access the doclet's
|
||||
* reporter, and additional methods and state used to
|
||||
* filter out messages, if any, which should be suppressed.
|
||||
* @param resources resources for console messages and exceptions
|
||||
*/
|
||||
public Messages(BaseConfiguration configuration) {
|
||||
public Messages(BaseConfiguration configuration, Resources resources) {
|
||||
this.configuration = configuration;
|
||||
resources = configuration.getResources();
|
||||
this.resources = resources;
|
||||
reporter = configuration.getReporter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resources being used when generating messages.
|
||||
*
|
||||
* @return the resources
|
||||
*/
|
||||
public Resources getResources() {
|
||||
return resources;
|
||||
}
|
||||
|
||||
// ***** Errors *****
|
||||
|
||||
/**
|
||||
|
@ -63,7 +63,6 @@ public class Resources {
|
||||
* specific to a particular format
|
||||
*/
|
||||
public Resources(Locale locale, String commonBundleName, String docletBundleName) {
|
||||
|
||||
this.commonBundle = ResourceBundle.getBundle(commonBundleName, locale);
|
||||
this.docletBundle = ResourceBundle.getBundle(docletBundleName, locale);
|
||||
|
||||
|
@ -100,7 +100,7 @@ public abstract class AbstractBuilder {
|
||||
this.options = configuration.getOptions();
|
||||
this.builderFactory = configuration.getBuilderFactory();
|
||||
this.messages = configuration.getMessages();
|
||||
this.resources = configuration.getResources();
|
||||
this.resources = configuration.getDocResources();
|
||||
this.utils = configuration.utils;
|
||||
this.containingPackagesSeen = c.containingPackagesSeen;
|
||||
}
|
||||
|
@ -482,7 +482,7 @@ public class SerializedFormBuilder extends AbstractBuilder {
|
||||
if (tag.getName() == null || tag.getType() == null) // ignore malformed @serialField tags
|
||||
continue;
|
||||
Content fieldsContentTree = fieldWriter.getFieldsContentHeader(tag.equals(tags.last()));
|
||||
TypeElement te = ch.getReferencedClass(configuration, tag);
|
||||
TypeElement te = ch.getReferencedClass(tag);
|
||||
String fieldType = ch.getReferencedMemberName(tag);
|
||||
if (te != null && utils.isPrimitive(te.asType())) {
|
||||
fieldType = utils.getTypeName(te.asType(), false);
|
||||
|
@ -49,23 +49,13 @@ public abstract class BasePropertyTaglet extends BaseTaglet {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the text to be put in the resulting javadoc before
|
||||
* the property name.
|
||||
* Returns the text to be included in the documentation before the property name.
|
||||
*
|
||||
* @param tagletWriter the taglet writer for output
|
||||
* @return the string to be put in the resulting javadoc.
|
||||
* @param tagletWriter the taglet-writer used by the doclet
|
||||
* @return the text to be included in the documentation before the property name
|
||||
*/
|
||||
abstract String getText(TagletWriter tagletWriter);
|
||||
|
||||
/**
|
||||
* Given the <code>Tag</code> representation of this custom
|
||||
* tag, return its string representation, which is output
|
||||
* to the generated page.
|
||||
* @param element
|
||||
* @param tag the <code>Tag</code> representation of this custom tag.
|
||||
* @param tagletWriter the taglet writer for output.
|
||||
* @return the TagletOutput representation of this <code>Tag</code>.
|
||||
*/
|
||||
@Override
|
||||
public Content getTagletOutput(Element element, DocTree tag, TagletWriter tagletWriter) {
|
||||
return tagletWriter.propertyTagOutput(element, tag, getText(tagletWriter));
|
||||
|
@ -188,11 +188,21 @@ public class BaseTaglet implements Taglet {
|
||||
: tree.getKind() == tagKind;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec This implementation throws {@link UnsupportedTagletOperationException}.
|
||||
*/
|
||||
@Override
|
||||
public Content getTagletOutput(Element element, DocTree tag, TagletWriter writer) {
|
||||
throw new UnsupportedTagletOperationException("Method not supported in taglet " + getName() + ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @implSpec This implementation throws {@link UnsupportedTagletOperationException}
|
||||
*/
|
||||
@Override
|
||||
public Content getTagletOutput(Element holder, TagletWriter writer) {
|
||||
throw new UnsupportedTagletOperationException("Method not supported in taglet " + getName() + ".");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
@ -126,7 +126,7 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
|
||||
if (rankMap.containsKey(paramName) && rankMap.get(paramName).equals((input.tagId))) {
|
||||
output.holder = input.element;
|
||||
output.holderTag = tag;
|
||||
output.inlineTags = ch.getBody(utils.configuration, tag);
|
||||
output.inlineTags = ch.getBody(tag);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -305,7 +305,7 @@ public class ParamTaglet extends BaseTaglet implements InheritableTaglet {
|
||||
case RECORD_COMPONENT: key = "doclet.RecordComponents" ; break;
|
||||
default: throw new IllegalArgumentException(kind.toString());
|
||||
}
|
||||
String header = writer.configuration().getResources().getText(key);
|
||||
String header = writer.configuration().getDocResources().getText(key);
|
||||
result.add(writer.getParamHeader(header));
|
||||
}
|
||||
result.add(writer.paramTagOutput(e, paramTag, name));
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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,13 +25,6 @@
|
||||
|
||||
package jdk.javadoc.internal.doclets.toolkit.taglets;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
|
||||
import com.sun.source.doctree.DocTree;
|
||||
import jdk.javadoc.internal.doclets.toolkit.Content;
|
||||
|
||||
/**
|
||||
* A taglet that adds the initial line of documentation to the JavaFX
|
||||
* property getters.
|
||||
@ -52,6 +45,6 @@ public class PropertyGetterTaglet extends BasePropertyTaglet {
|
||||
|
||||
@Override
|
||||
String getText(TagletWriter tagletWriter) {
|
||||
return tagletWriter.configuration().getResources().getText("doclet.PropertyGetter");
|
||||
return tagletWriter.configuration().getDocResources().getText("doclet.PropertyGetter");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 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
|
||||
@ -45,6 +45,6 @@ public class PropertySetterTaglet extends BasePropertyTaglet {
|
||||
|
||||
@Override
|
||||
String getText(TagletWriter tagletWriter) {
|
||||
return tagletWriter.configuration().getResources().getText("doclet.PropertySetter");
|
||||
return tagletWriter.configuration().getDocResources().getText("doclet.PropertySetter");
|
||||
}
|
||||
}
|
||||
|
@ -64,8 +64,8 @@ public class ReturnTaglet extends BaseTaglet implements InheritableTaglet {
|
||||
output.holder = input.element;
|
||||
output.holderTag = tags.get(0);
|
||||
output.inlineTags = input.isFirstSentence
|
||||
? ch.getFirstSentenceTrees(input.utils.configuration, output.holderTag)
|
||||
: ch.getDescription(input.utils.configuration, output.holderTag);
|
||||
? ch.getFirstSentenceTrees(output.holderTag)
|
||||
: ch.getDescription(output.holderTag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ public class SeeTaglet extends BaseTaglet implements InheritableTaglet {
|
||||
output.holder = input.element;
|
||||
output.holderTag = tags.get(0);
|
||||
output.inlineTags = input.isFirstSentence
|
||||
? ch.getFirstSentenceTrees(input.utils.configuration, output.holderTag)
|
||||
? ch.getFirstSentenceTrees(output.holderTag)
|
||||
: ch.getReference(output.holderTag);
|
||||
}
|
||||
}
|
||||
|
@ -173,8 +173,8 @@ public class SimpleTaglet extends BaseTaglet implements InheritableTaglet {
|
||||
output.holderTag = tags.get(0);
|
||||
CommentHelper ch = input.utils.getCommentHelper(output.holder);
|
||||
output.inlineTags = input.isFirstSentence
|
||||
? ch.getFirstSentenceTrees(input.utils.configuration, output.holderTag)
|
||||
: ch.getTags(input.utils.configuration, output.holderTag);
|
||||
? ch.getFirstSentenceTrees(output.holderTag)
|
||||
: ch.getTags(output.holderTag);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -135,29 +135,28 @@ public interface Taglet {
|
||||
String getName();
|
||||
|
||||
/**
|
||||
* Given the <code>Tag</code> representation of this custom
|
||||
* tag, return its Content representation, which is output
|
||||
* to the generated page.
|
||||
* @param holder the element holding the tag
|
||||
* @param tag the <code>Tag</code> representation of this custom tag.
|
||||
* @param writer a {@link TagletWriter} Taglet writer.
|
||||
* @throws UnsupportedOperationException thrown when the method is not supported by the taglet.
|
||||
* @return the Content representation of this <code>Tag</code>.
|
||||
* Returns the content to be included in the generated output for an
|
||||
* instance of a tag handled by this taglet.
|
||||
*
|
||||
* @param element the element for the enclosing doc comment
|
||||
* @param tag the tag
|
||||
* @param writer the taglet-writer used in this doclet
|
||||
* @return the output for this tag
|
||||
* @throws UnsupportedTagletOperationException thrown when the method is not supported by the taglet
|
||||
*/
|
||||
Content getTagletOutput(Element holder, DocTree tag, TagletWriter writer) throws
|
||||
UnsupportedOperationException;
|
||||
Content getTagletOutput(Element element, DocTree tag, TagletWriter writer) throws
|
||||
UnsupportedTagletOperationException;
|
||||
|
||||
/**
|
||||
* Given an element object, check if it holds any tags of
|
||||
* this type. If it does, return the content representing the output.
|
||||
* If it does not, return null.
|
||||
* @param holder an element holding the custom tag.
|
||||
* @param writer a {@link TagletWriter} Taglet writer.
|
||||
* @throws UnsupportedTagletOperationException thrown when the method is not
|
||||
* supported by the taglet.
|
||||
* @return the content representation of this <code>Tag</code>.
|
||||
* Returns the content to be included in the generated output for all
|
||||
* instances of tags handled by this taglet.
|
||||
*
|
||||
* @param element the element for the enclosing doc comment
|
||||
* @param writer the taglet-writer used in this doclet
|
||||
* @return the output for this tag
|
||||
* @throws UnsupportedTagletOperationException thrown when the method is not supported by the taglet
|
||||
*/
|
||||
Content getTagletOutput(Element holder, TagletWriter writer) throws
|
||||
Content getTagletOutput(Element element, TagletWriter writer) throws
|
||||
UnsupportedTagletOperationException;
|
||||
|
||||
class UnsupportedTagletOperationException extends UnsupportedOperationException {
|
||||
|
@ -199,7 +199,7 @@ public class TagletManager {
|
||||
this.docEnv = configuration.docEnv;
|
||||
this.doclet = configuration.doclet;
|
||||
this.messages = configuration.getMessages();
|
||||
this.resources = configuration.getResources();
|
||||
this.resources = configuration.getDocResources();
|
||||
this.showTaglets = options.showTaglets();
|
||||
this.utils = configuration.utils;
|
||||
this.tagletPath = options.tagletPath();
|
||||
|
@ -72,26 +72,25 @@ public class ThrowsTaglet extends BaseTaglet
|
||||
Element exception;
|
||||
CommentHelper ch = utils.getCommentHelper(input.element);
|
||||
if (input.tagId == null) {
|
||||
exception = ch.getException(utils.configuration, input.docTreeInfo.docTree);
|
||||
exception = ch.getException(input.docTreeInfo.docTree);
|
||||
input.tagId = exception == null
|
||||
? ch.getExceptionName(input.docTreeInfo.docTree).getSignature()
|
||||
: utils.getFullyQualifiedName(exception);
|
||||
} else {
|
||||
TypeElement element = input.utils.findClass(input.element, input.tagId);
|
||||
exception = (element == null) ? null : element;
|
||||
exception = input.utils.findClass(input.element, input.tagId);
|
||||
}
|
||||
|
||||
for (DocTree dt : input.utils.getThrowsTrees(input.element)) {
|
||||
Element texception = ch.getException(utils.configuration, dt);
|
||||
if (texception != null && (input.tagId.equals(utils.getSimpleName(texception)) ||
|
||||
(input.tagId.equals(utils.getFullyQualifiedName(texception))))) {
|
||||
Element exc = ch.getException(dt);
|
||||
if (exc != null && (input.tagId.equals(utils.getSimpleName(exc)) ||
|
||||
(input.tagId.equals(utils.getFullyQualifiedName(exc))))) {
|
||||
output.holder = input.element;
|
||||
output.holderTag = dt;
|
||||
output.inlineTags = ch.getBody(input.utils.configuration, output.holderTag);
|
||||
output.inlineTags = ch.getBody(output.holderTag);
|
||||
output.tagList.add(dt);
|
||||
} else if (exception != null && texception != null &&
|
||||
utils.isTypeElement(texception) && utils.isTypeElement(exception) &&
|
||||
utils.isSubclassOf((TypeElement)texception, (TypeElement)exception)) {
|
||||
} else if (exception != null && exc != null &&
|
||||
utils.isTypeElement(exc) && utils.isTypeElement(exception) &&
|
||||
utils.isSubclassOf((TypeElement)exc, (TypeElement)exception)) {
|
||||
output.tagList.add(dt);
|
||||
}
|
||||
}
|
||||
@ -106,15 +105,15 @@ public class ThrowsTaglet extends BaseTaglet
|
||||
Content result = writer.getOutputInstance();
|
||||
//Add links to the exceptions declared but not documented.
|
||||
for (TypeMirror declaredExceptionType : declaredExceptionTypes) {
|
||||
TypeElement klass = utils.asTypeElement(declaredExceptionType);
|
||||
if (klass != null &&
|
||||
TypeElement te = utils.asTypeElement(declaredExceptionType);
|
||||
if (te != null &&
|
||||
!alreadyDocumented.contains(declaredExceptionType.toString()) &&
|
||||
!alreadyDocumented.contains(utils.getFullyQualifiedName(klass, false))) {
|
||||
!alreadyDocumented.contains(utils.getFullyQualifiedName(te, false))) {
|
||||
if (alreadyDocumented.isEmpty()) {
|
||||
result.add(writer.getThrowsHeader());
|
||||
}
|
||||
result.add(writer.throwsTagOutput(declaredExceptionType));
|
||||
alreadyDocumented.add(utils.getSimpleName(klass));
|
||||
alreadyDocumented.add(utils.getSimpleName(te));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -176,18 +175,17 @@ public class ThrowsTaglet extends BaseTaglet
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of <code>Tag</code>s representing this custom
|
||||
* tag, return its string representation.
|
||||
* @param throwTags the array of <code>ThrowsTag</code>s to convert.
|
||||
* @param writer the TagletWriter that will write this tag.
|
||||
* @param alreadyDocumented the set of exceptions that have already
|
||||
* been documented.
|
||||
* @param allowDups True if we allow duplicate throws tags to be documented.
|
||||
* @return the Content representation of this <code>Tag</code>.
|
||||
* Returns the generated content for a collection of {@code @throws} tags.
|
||||
*
|
||||
* @param throwTags the collection of tags to be converted
|
||||
* @param writer the taglet-writer used by the doclet
|
||||
* @param alreadyDocumented the set of exceptions that have already been documented
|
||||
* @param allowDuplicates {@code true} if we allow duplicate tags to be documented
|
||||
* @return the generated content for the tags
|
||||
*/
|
||||
protected Content throwsTagsOutput(Map<List<? extends DocTree>, ExecutableElement> throwTags,
|
||||
TagletWriter writer, Set<String> alreadyDocumented,
|
||||
Map<String,TypeMirror> typeSubstitutions, boolean allowDups) {
|
||||
Map<String,TypeMirror> typeSubstitutions, boolean allowDuplicates) {
|
||||
Utils utils = writer.configuration().utils;
|
||||
Content result = writer.getOutputInstance();
|
||||
if (!throwTags.isEmpty()) {
|
||||
@ -195,10 +193,10 @@ public class ThrowsTaglet extends BaseTaglet
|
||||
CommentHelper ch = utils.getCommentHelper(entry.getValue());
|
||||
Element e = entry.getValue();
|
||||
for (DocTree dt : entry.getKey()) {
|
||||
Element te = ch.getException(utils.configuration, dt);
|
||||
Element te = ch.getException(dt);
|
||||
String excName = ch.getExceptionName(dt).toString();
|
||||
TypeMirror substituteType = typeSubstitutions.get(excName);
|
||||
if ((!allowDups) &&
|
||||
if ((!allowDuplicates) &&
|
||||
(alreadyDocumented.contains(excName) ||
|
||||
(te != null && alreadyDocumented.contains(utils.getFullyQualifiedName(te, false)))) ||
|
||||
(substituteType != null && alreadyDocumented.contains(substituteType.toString()))) {
|
||||
|
@ -77,7 +77,7 @@ public class ValueTaglet extends BaseTaglet {
|
||||
|
||||
Element e = signature == null
|
||||
? holder
|
||||
: ch.getReferencedMember(config, tag);
|
||||
: ch.getReferencedMember(tag);
|
||||
|
||||
return (e != null && config.utils.isVariableElement(e))
|
||||
? (VariableElement) e
|
||||
|
@ -28,11 +28,10 @@ package jdk.javadoc.internal.doclets.toolkit.util;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.lang.model.element.Element;
|
||||
import javax.lang.model.element.ExecutableElement;
|
||||
import javax.lang.model.element.ModuleElement;
|
||||
import javax.lang.model.element.Name;
|
||||
import javax.lang.model.element.PackageElement;
|
||||
import javax.lang.model.element.TypeElement;
|
||||
import javax.lang.model.type.TypeMirror;
|
||||
@ -84,18 +83,27 @@ import static com.sun.source.doctree.DocTree.Kind.*;
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class CommentHelper {
|
||||
private final BaseConfiguration configuration;
|
||||
public final TreePath path;
|
||||
public final DocCommentTree dctree;
|
||||
public final DocCommentTree dcTree;
|
||||
public final Element element;
|
||||
private Element overriddenElement;
|
||||
|
||||
public static final String SPACER = " ";
|
||||
|
||||
public CommentHelper(BaseConfiguration configuration, Element element, TreePath path, DocCommentTree dctree) {
|
||||
//this.configuration = configuration;
|
||||
/**
|
||||
* Creates a utility class to encapsulate the contextual information for a doc comment tree.
|
||||
*
|
||||
* @param configuration the configuration
|
||||
* @param element the element for which this is a doc comment
|
||||
* @param path the path for the element
|
||||
* @param dcTree the doc comment
|
||||
*/
|
||||
public CommentHelper(BaseConfiguration configuration, Element element, TreePath path, DocCommentTree dcTree) {
|
||||
this.configuration = configuration;
|
||||
this.element = element;
|
||||
this.path = path;
|
||||
this.dctree = dctree;
|
||||
this.dcTree = dcTree;
|
||||
}
|
||||
|
||||
public void setOverrideElement(Element ove) {
|
||||
@ -144,17 +152,18 @@ public class CommentHelper {
|
||||
}
|
||||
}
|
||||
|
||||
Element getElement(BaseConfiguration c, ReferenceTree rtree) {
|
||||
Element getElement(ReferenceTree rtree) {
|
||||
Utils utils = configuration.utils;
|
||||
// likely a synthesized tree
|
||||
if (path == null) {
|
||||
// NOTE: this code path only supports module/package/type signatures
|
||||
// and not member signatures. For more complete support,
|
||||
// set a suitable path and avoid this branch.
|
||||
TypeMirror symbol = c.utils.getSymbol(rtree.getSignature());
|
||||
TypeMirror symbol = utils.getSymbol(rtree.getSignature());
|
||||
if (symbol == null) {
|
||||
return null;
|
||||
}
|
||||
return c.docEnv.getTypeUtils().asElement(symbol);
|
||||
return configuration.docEnv.getTypeUtils().asElement(symbol);
|
||||
}
|
||||
// case A: the element contains no comments associated and
|
||||
// the comments need to be copied from ancestor
|
||||
@ -162,37 +171,37 @@ public class CommentHelper {
|
||||
// as appropriate has to be copied over.
|
||||
|
||||
// Case A.
|
||||
if (dctree == null && overriddenElement != null) {
|
||||
CommentHelper ovch = c.utils.getCommentHelper(overriddenElement);
|
||||
return ovch.getElement(c, rtree);
|
||||
if (dcTree == null && overriddenElement != null) {
|
||||
CommentHelper ovch = utils.getCommentHelper(overriddenElement);
|
||||
return ovch.getElement(rtree);
|
||||
}
|
||||
if (dctree == null) {
|
||||
if (dcTree == null) {
|
||||
return null;
|
||||
}
|
||||
DocTreePath docTreePath = DocTreePath.getPath(path, dctree, rtree);
|
||||
DocTreePath docTreePath = DocTreePath.getPath(path, dcTree, rtree);
|
||||
if (docTreePath == null) {
|
||||
// Case B.
|
||||
if (overriddenElement != null) {
|
||||
CommentHelper ovch = c.utils.getCommentHelper(overriddenElement);
|
||||
return ovch.getElement(c, rtree);
|
||||
CommentHelper ovch = utils.getCommentHelper(overriddenElement);
|
||||
return ovch.getElement(rtree);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
DocTrees doctrees = c.docEnv.getDocTrees();
|
||||
DocTrees doctrees = configuration.docEnv.getDocTrees();
|
||||
return doctrees.getElement(docTreePath);
|
||||
}
|
||||
|
||||
public Element getException(BaseConfiguration c, DocTree dtree) {
|
||||
public Element getException(DocTree dtree) {
|
||||
if (dtree.getKind() == THROWS || dtree.getKind() == EXCEPTION) {
|
||||
ThrowsTree tt = (ThrowsTree)dtree;
|
||||
ReferenceTree exceptionName = tt.getExceptionName();
|
||||
return getElement(c, exceptionName);
|
||||
return getElement(exceptionName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<? extends DocTree> getDescription(BaseConfiguration c, DocTree dtree) {
|
||||
return getTags(c, dtree);
|
||||
public List<? extends DocTree> getDescription(DocTree dtree) {
|
||||
return getTags(dtree);
|
||||
}
|
||||
|
||||
public String getText(List<? extends DocTree> list) {
|
||||
@ -224,16 +233,14 @@ public class CommentHelper {
|
||||
quote = "\"";
|
||||
break;
|
||||
case SINGLE:
|
||||
quote = "\'";
|
||||
quote = "'";
|
||||
break;
|
||||
default:
|
||||
quote = "";
|
||||
break;
|
||||
}
|
||||
sb.append(quote);
|
||||
node.getValue().stream().forEach((dt) -> {
|
||||
dt.accept(this, null);
|
||||
});
|
||||
node.getValue().forEach(dt -> dt.accept(this, null));
|
||||
sb.append(quote);
|
||||
return null;
|
||||
}
|
||||
@ -259,9 +266,7 @@ public class CommentHelper {
|
||||
}
|
||||
|
||||
node.getReference().accept(this, null);
|
||||
node.getLabel().stream().forEach((dt) -> {
|
||||
dt.accept(this, null);
|
||||
});
|
||||
node.getLabel().forEach(dt -> dt.accept(this, null) );
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -285,17 +290,13 @@ public class CommentHelper {
|
||||
|
||||
@Override
|
||||
public Void visitSee(SeeTree node, Void p) {
|
||||
node.getReference().stream().forEach((dt) -> {
|
||||
dt.accept(this, null);
|
||||
});
|
||||
node.getReference().forEach(dt -> dt.accept(this, null));
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitSerial(SerialTree node, Void p) {
|
||||
node.getDescription().stream().forEach((dt) -> {
|
||||
dt.accept(this, null);
|
||||
});
|
||||
node.getDescription().forEach(dt -> dt.accept(this, null));
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -303,9 +304,7 @@ public class CommentHelper {
|
||||
public Void visitStartElement(StartElementTree node, Void p) {
|
||||
sb.append("<");
|
||||
sb.append(node.getName());
|
||||
node.getAttributes().stream().forEach((dt) -> {
|
||||
dt.accept(this, null);
|
||||
});
|
||||
node.getAttributes().forEach(dt -> dt.accept(this, null));
|
||||
sb.append((node.isSelfClosing() ? "/>" : ">"));
|
||||
return null;
|
||||
}
|
||||
@ -318,9 +317,7 @@ public class CommentHelper {
|
||||
|
||||
@Override
|
||||
public Void visitUnknownBlockTag(UnknownBlockTagTree node, Void p) {
|
||||
node.getContent().stream().forEach((dt) -> {
|
||||
dt.accept(this, null);
|
||||
});
|
||||
node.getContent().forEach(dt -> dt.accept(this, null));
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -338,24 +335,22 @@ public class CommentHelper {
|
||||
return sb;
|
||||
}
|
||||
|
||||
public String getLabel(BaseConfiguration c, DocTree dtree) {
|
||||
public String getLabel(DocTree dtree) {
|
||||
return new SimpleDocTreeVisitor<String, Void>() {
|
||||
@Override
|
||||
public String visitLink(LinkTree node, Void p) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
node.getLabel().stream().forEach((dt) -> {
|
||||
sb.append(getText(dt));
|
||||
});
|
||||
return sb.toString();
|
||||
return node.getLabel().stream()
|
||||
.map(dt -> getText(dt))
|
||||
.collect(Collectors.joining());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visitSee(SeeTree node, Void p) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
node.getReference().stream().filter((dt) -> (c.utils.isText(dt))).forEach((dt) -> {
|
||||
sb.append(((TextTree)dt).getBody());
|
||||
});
|
||||
return sb.toString();
|
||||
Utils utils = configuration.utils;
|
||||
return node.getReference().stream()
|
||||
.filter(utils::isText)
|
||||
.map(dt -> ((TextTree) dt).getBody())
|
||||
.collect(Collectors.joining());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -365,22 +360,24 @@ public class CommentHelper {
|
||||
}.visit(dtree, null);
|
||||
}
|
||||
|
||||
public TypeElement getReferencedClass(BaseConfiguration c, DocTree dtree) {
|
||||
Element e = getReferencedElement(c, dtree);
|
||||
public TypeElement getReferencedClass(DocTree dtree) {
|
||||
Utils utils = configuration.utils;
|
||||
Element e = getReferencedElement(dtree);
|
||||
if (e == null) {
|
||||
return null;
|
||||
} else if (c.utils.isTypeElement(e)) {
|
||||
} else if (utils.isTypeElement(e)) {
|
||||
return (TypeElement) e;
|
||||
} else if (!c.utils.isPackage(e)) {
|
||||
return c.utils.getEnclosingTypeElement(e);
|
||||
} else if (!utils.isPackage(e)) {
|
||||
return utils.getEnclosingTypeElement(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getReferencedClassName(BaseConfiguration c, DocTree dtree) {
|
||||
Element e = getReferencedClass(c, dtree);
|
||||
public String getReferencedClassName(DocTree dtree) {
|
||||
Utils utils = configuration.utils;
|
||||
Element e = getReferencedClass(dtree);
|
||||
if (e != null) {
|
||||
return c.utils.isTypeElement(e) ? c.utils.getSimpleName(e) : null;
|
||||
return utils.isTypeElement(e) ? utils.getSimpleName(e) : null;
|
||||
}
|
||||
String s = getReferencedSignature(dtree);
|
||||
if (s == null) {
|
||||
@ -390,12 +387,13 @@ public class CommentHelper {
|
||||
return (n == -1) ? s : s.substring(0, n);
|
||||
}
|
||||
|
||||
public Element getReferencedMember(BaseConfiguration c, DocTree dtree) {
|
||||
Element e = getReferencedElement(c, dtree);
|
||||
public Element getReferencedMember(DocTree dtree) {
|
||||
Utils utils = configuration.utils;
|
||||
Element e = getReferencedElement(dtree);
|
||||
if (e == null) {
|
||||
return null;
|
||||
}
|
||||
return (c.utils.isExecutableElement(e) || c.utils.isVariableElement(e)) ? e : null;
|
||||
return (utils.isExecutableElement(e) || utils.isVariableElement(e)) ? e : null;
|
||||
}
|
||||
|
||||
public String getReferencedMemberName(DocTree dtree) {
|
||||
@ -407,33 +405,34 @@ public class CommentHelper {
|
||||
return (n == -1) ? null : s.substring(n + 1);
|
||||
}
|
||||
|
||||
public String getReferencedMemberName(BaseConfiguration c, Element e) {
|
||||
public String getReferencedMemberName(Element e) {
|
||||
if (e == null) {
|
||||
return null;
|
||||
}
|
||||
return c.utils.isExecutableElement(e)
|
||||
? c.utils.getSimpleName(e) + c.utils.makeSignature((ExecutableElement) e, true, true)
|
||||
: c.utils.getSimpleName(e);
|
||||
Utils utils = configuration.utils;
|
||||
return utils.isExecutableElement(e)
|
||||
? utils.getSimpleName(e) + utils.makeSignature((ExecutableElement) e, true, true)
|
||||
: utils.getSimpleName(e);
|
||||
}
|
||||
|
||||
public PackageElement getReferencedPackage(BaseConfiguration c, DocTree dtree) {
|
||||
Element e = getReferencedElement(c, dtree);
|
||||
public PackageElement getReferencedPackage(DocTree dtree) {
|
||||
Element e = getReferencedElement(dtree);
|
||||
if (e != null) {
|
||||
return c.utils.containingPackage(e);
|
||||
Utils utils = configuration.utils;
|
||||
return utils.containingPackage(e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<? extends DocTree> getFirstSentenceTrees(BaseConfiguration c, List<? extends DocTree> body) {
|
||||
List<DocTree> firstSentence = c.docEnv.getDocTrees().getFirstSentence(body);
|
||||
return firstSentence;
|
||||
public List<? extends DocTree> getFirstSentenceTrees(List<? extends DocTree> body) {
|
||||
return configuration.docEnv.getDocTrees().getFirstSentence(body);
|
||||
}
|
||||
|
||||
public List<? extends DocTree> getFirstSentenceTrees(BaseConfiguration c, DocTree dtree) {
|
||||
return getFirstSentenceTrees(c, getBody(c, dtree));
|
||||
public List<? extends DocTree> getFirstSentenceTrees(DocTree dtree) {
|
||||
return getFirstSentenceTrees(getBody(dtree));
|
||||
}
|
||||
|
||||
private Element getReferencedElement(BaseConfiguration c, DocTree dtree) {
|
||||
private Element getReferencedElement(DocTree dtree) {
|
||||
return new SimpleDocTreeVisitor<Element, Void>() {
|
||||
@Override
|
||||
public Element visitSee(SeeTree node, Void p) {
|
||||
@ -460,7 +459,7 @@ public class CommentHelper {
|
||||
|
||||
@Override
|
||||
public Element visitReference(ReferenceTree node, Void p) {
|
||||
return getElement(c, node);
|
||||
return getElement(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -480,10 +479,11 @@ public class CommentHelper {
|
||||
}.visit(dtree, null);
|
||||
}
|
||||
|
||||
public TypeElement getServiceType(BaseConfiguration c, DocTree dtree) {
|
||||
Element e = getReferencedElement(c, dtree);
|
||||
public TypeElement getServiceType(DocTree dtree) {
|
||||
Element e = getReferencedElement(dtree);
|
||||
if (e != null) {
|
||||
return c.utils.isTypeElement(e) ? (TypeElement) e : null;
|
||||
Utils utils = configuration.utils;
|
||||
return utils.isTypeElement(e) ? (TypeElement) e : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -546,11 +546,11 @@ public class CommentHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public List<? extends DocTree> getTags(BaseConfiguration c, DocTree dtree) {
|
||||
public List<? extends DocTree> getTags(DocTree dtree) {
|
||||
return new SimpleDocTreeVisitor<List<? extends DocTree>, Void>() {
|
||||
List<? extends DocTree> asList(String content) {
|
||||
List<DocTree> out = new ArrayList<>();
|
||||
out.add(c.cmtUtils.makeTextTree(content));
|
||||
out.add(configuration.cmtUtils.makeTextTree(content));
|
||||
return out;
|
||||
}
|
||||
|
||||
@ -651,22 +651,22 @@ public class CommentHelper {
|
||||
}.visit(dtree, null);
|
||||
}
|
||||
|
||||
public List<? extends DocTree> getBody(BaseConfiguration c, DocTree dtree) {
|
||||
return getTags(c, dtree);
|
||||
public List<? extends DocTree> getBody(DocTree dtree) {
|
||||
return getTags(dtree);
|
||||
}
|
||||
|
||||
public ReferenceTree getType(DocTree dtree) {
|
||||
if (dtree.getKind() == SERIAL_FIELD) {
|
||||
return ((SerialFieldTree)dtree).getType();
|
||||
return ((SerialFieldTree) dtree).getType();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public DocTreePath getDocTreePath(DocTree dtree) {
|
||||
if (path == null || dctree == null || dtree == null)
|
||||
if (path == null || dcTree == null || dtree == null)
|
||||
return null;
|
||||
return DocTreePath.getPath(path, dctree, dtree);
|
||||
return DocTreePath.getPath(path, dcTree, dtree);
|
||||
}
|
||||
|
||||
public Element getOverriddenElement() {
|
||||
@ -680,7 +680,7 @@ public class CommentHelper {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder("CommentHelper{" + "path=" + path + ", dctree=" + dctree);
|
||||
StringBuilder sb = new StringBuilder("CommentHelper{" + "path=" + path + ", dcTree=" + dcTree);
|
||||
sb.append(", element=");
|
||||
sb.append(element.getEnclosingElement());
|
||||
sb.append("::");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1998, 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
|
||||
@ -134,7 +134,7 @@ public class Extern {
|
||||
|
||||
public Extern(BaseConfiguration configuration) {
|
||||
this.configuration = configuration;
|
||||
this.resources = configuration.getResources();
|
||||
this.resources = configuration.getDocResources();
|
||||
this.utils = configuration.utils;
|
||||
}
|
||||
|
||||
|
@ -240,8 +240,8 @@ public class Group {
|
||||
Map<String, SortedSet<ModuleElement>> groupModuleMap = new HashMap<>();
|
||||
String defaultGroupName =
|
||||
(elementNameGroupMap.isEmpty() && regExpGroupMap.isEmpty())?
|
||||
configuration.getResources().getText("doclet.Modules") :
|
||||
configuration.getResources().getText("doclet.Other_Modules");
|
||||
configuration.getDocResources().getText("doclet.Modules") :
|
||||
configuration.getDocResources().getText("doclet.Other_Modules");
|
||||
// if the user has not used the default group name, add it
|
||||
if (!groupList.contains(defaultGroupName)) {
|
||||
groupList.add(defaultGroupName);
|
||||
@ -282,8 +282,8 @@ public class Group {
|
||||
Map<String, SortedSet<PackageElement>> groupPackageMap = new HashMap<>();
|
||||
String defaultGroupName =
|
||||
(elementNameGroupMap.isEmpty() && regExpGroupMap.isEmpty())?
|
||||
configuration.getResources().getText("doclet.Packages") :
|
||||
configuration.getResources().getText("doclet.Other_Packages");
|
||||
configuration.getDocResources().getText("doclet.Packages") :
|
||||
configuration.getDocResources().getText("doclet.Other_Packages");
|
||||
// if the user has not used the default group name, add it
|
||||
if (!groupList.contains(defaultGroupName)) {
|
||||
groupList.add(defaultGroupName);
|
||||
|
@ -58,7 +58,7 @@ public class MetaKeywords {
|
||||
*/
|
||||
public MetaKeywords(BaseConfiguration configuration) {
|
||||
options = configuration.getOptions();
|
||||
resources = configuration.getResources();
|
||||
resources = configuration.getDocResources();
|
||||
utils = configuration.utils;
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ class StandardDocFileFactory extends DocFileFactory {
|
||||
fileManager.setLocationFromPaths(DocumentationTool.Location.DOCUMENTATION_OUTPUT, Arrays.asList(dir));
|
||||
} catch (IOException e) {
|
||||
// generic IOException from file manager, setting location, e.g. file not a directory
|
||||
String message = configuration.getResources().getText("doclet.error.initializing.dest.dir", e);
|
||||
String message = configuration.getDocResources().getText("doclet.error.initializing.dest.dir", e);
|
||||
throw new SimpleDocletException(message, e);
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,28 @@ import java.text.CollationKey;
|
||||
import java.text.Collator;
|
||||
import java.text.ParseException;
|
||||
import java.text.RuleBasedCollator;
|
||||
import java.util.*;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Deque;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeMap;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -125,7 +144,7 @@ public class Utils {
|
||||
configuration = c;
|
||||
options = configuration.getOptions();
|
||||
messages = configuration.getMessages();
|
||||
resources = configuration.getResources();
|
||||
resources = configuration.getDocResources();
|
||||
elementUtils = c.docEnv.getElementUtils();
|
||||
typeUtils = c.docEnv.getTypeUtils();
|
||||
docTrees = c.docEnv.getDocTrees();
|
||||
@ -937,7 +956,7 @@ public class Utils {
|
||||
* @return
|
||||
*/
|
||||
public TypeMirror getDeclaredType(Collection<TypeMirror> values,
|
||||
TypeElement enclosing, TypeMirror target) {
|
||||
TypeElement enclosing, TypeMirror target) {
|
||||
TypeElement targetElement = asTypeElement(target);
|
||||
List<? extends TypeParameterElement> targetTypeArgs = targetElement.getTypeParameters();
|
||||
if (targetTypeArgs.isEmpty()) {
|
||||
@ -2546,7 +2565,7 @@ public class Utils {
|
||||
}.visit(e);
|
||||
}
|
||||
|
||||
EnumSet<ElementKind> nestedKinds = EnumSet.of(ANNOTATION_TYPE, CLASS, ENUM, INTERFACE);
|
||||
Set<ElementKind> nestedKinds = EnumSet.of(ANNOTATION_TYPE, CLASS, ENUM, INTERFACE);
|
||||
void recursiveGetItems(Collection<Element> list, Element e, boolean filter, ElementKind... select) {
|
||||
list.addAll(getItems0(e, filter, select));
|
||||
List<Element> classes = getItems0(e, filter, nestedKinds);
|
||||
@ -2559,7 +2578,7 @@ public class Utils {
|
||||
}
|
||||
|
||||
private List<Element> getItems0(Element te, boolean filter, ElementKind... select) {
|
||||
EnumSet<ElementKind> kinds = EnumSet.copyOf(Arrays.asList(select));
|
||||
Set<ElementKind> kinds = EnumSet.copyOf(Arrays.asList(select));
|
||||
return getItems0(te, filter, kinds);
|
||||
}
|
||||
|
||||
@ -3002,14 +3021,14 @@ public class Utils {
|
||||
return doctree.getKind() == match;
|
||||
}
|
||||
|
||||
private final WeakSoftHashMap wksMap = new WeakSoftHashMap(this);
|
||||
private final CommentHelperCache commentHelperCache = new CommentHelperCache(this);
|
||||
|
||||
public CommentHelper getCommentHelper(Element element) {
|
||||
return wksMap.computeIfAbsent(element);
|
||||
return commentHelperCache.computeIfAbsent(element);
|
||||
}
|
||||
|
||||
public void removeCommentHelper(Element element) {
|
||||
wksMap.remove(element);
|
||||
commentHelperCache.remove(element);
|
||||
}
|
||||
|
||||
public List<? extends DocTree> getBlockTags(Element element) {
|
||||
@ -3177,13 +3196,13 @@ public class Utils {
|
||||
}
|
||||
|
||||
public DocCommentTree getDocCommentTree(Element element) {
|
||||
CommentHelper ch = wksMap.get(element);
|
||||
CommentHelper ch = commentHelperCache.get(element);
|
||||
if (ch != null) {
|
||||
return ch.dctree;
|
||||
return ch.dcTree;
|
||||
}
|
||||
DocCommentTree dcTree = getDocCommentTree0(element);
|
||||
if (dcTree != null) {
|
||||
wksMap.put(element, new CommentHelper(configuration, element, getTreePath(element), dcTree));
|
||||
commentHelperCache.put(element, new CommentHelper(configuration, element, getTreePath(element), dcTree));
|
||||
}
|
||||
return dcTree;
|
||||
}
|
||||
@ -3297,106 +3316,48 @@ public class Utils {
|
||||
return outer;
|
||||
}
|
||||
|
||||
static class WeakSoftHashMap implements Map<Element, CommentHelper> {
|
||||
/**
|
||||
* A memory-sensitive cache for {@link CommentHelper} objects,
|
||||
* which are expensive to compute.
|
||||
*/
|
||||
private static class CommentHelperCache {
|
||||
|
||||
private final WeakHashMap<Element, SoftReference<CommentHelper>> wkMap;
|
||||
private final Map<Element, SoftReference<CommentHelper>> map;
|
||||
private final Utils utils;
|
||||
public WeakSoftHashMap(Utils utils) {
|
||||
wkMap = new WeakHashMap<>();
|
||||
|
||||
public CommentHelperCache(Utils utils) {
|
||||
map = new HashMap<>();
|
||||
this.utils = utils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return wkMap.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CommentHelper> values() {
|
||||
Set<CommentHelper> out = new LinkedHashSet<>();
|
||||
for (SoftReference<CommentHelper> v : wkMap.values()) {
|
||||
out.add(v.get());
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
return wkMap.containsValue(new SoftReference<>((CommentHelper)value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommentHelper remove(Object key) {
|
||||
SoftReference<CommentHelper> value = wkMap.remove(key);
|
||||
public CommentHelper remove(Element key) {
|
||||
SoftReference<CommentHelper> value = map.remove(key);
|
||||
return value == null ? null : value.get();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public CommentHelper put(Element key, CommentHelper value) {
|
||||
SoftReference<CommentHelper> nvalue = wkMap.put(key, new SoftReference<>(value));
|
||||
return nvalue == null ? null : nvalue.get();
|
||||
SoftReference<CommentHelper> prev = map.put(key, new SoftReference<>(value));
|
||||
return prev == null ? null : prev.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommentHelper get(Object key) {
|
||||
SoftReference<CommentHelper> value = wkMap.get(key);
|
||||
SoftReference<CommentHelper> value = map.get(key);
|
||||
return value == null ? null : value.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return wkMap.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return wkMap.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
wkMap.clear();
|
||||
}
|
||||
|
||||
public CommentHelper computeIfAbsent(Element key) {
|
||||
if (wkMap.containsKey(key)) {
|
||||
SoftReference<CommentHelper> value = wkMap.get(key);
|
||||
SoftReference<CommentHelper> refValue = map.get(key);
|
||||
if (refValue != null) {
|
||||
CommentHelper value = refValue.get();
|
||||
if (value != null) {
|
||||
CommentHelper cvalue = value.get();
|
||||
if (cvalue != null) {
|
||||
return cvalue;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
CommentHelper newValue = new CommentHelper(utils.configuration, key, utils.getTreePath(key),
|
||||
utils.getDocCommentTree(key));
|
||||
wkMap.put(key, new SoftReference<>(newValue));
|
||||
map.put(key, new SoftReference<>(newValue));
|
||||
return newValue;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void putAll(Map<? extends Element, ? extends CommentHelper> map) {
|
||||
for (Map.Entry<? extends Element, ? extends CommentHelper> entry : map.entrySet()) {
|
||||
put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Element> keySet() {
|
||||
return wkMap.keySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Entry<Element, CommentHelper>> entrySet() {
|
||||
Set<Entry<Element, CommentHelper>> out = new LinkedHashSet<>();
|
||||
for (Element e : wkMap.keySet()) {
|
||||
SimpleEntry<Element, CommentHelper> n = new SimpleEntry<>(e, get(e));
|
||||
out.add(n);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -399,14 +399,14 @@ public class Start {
|
||||
Throwable t = e.getCause();
|
||||
dumpStack(t == null ? e : t);
|
||||
return ERROR;
|
||||
} catch (OptionException toe) {
|
||||
if (toe.message != null)
|
||||
messager.printError(toe.message);
|
||||
} catch (OptionException oe) {
|
||||
if (oe.message != null)
|
||||
messager.printError(oe.message);
|
||||
|
||||
toe.m.run();
|
||||
Throwable t = toe.getCause();
|
||||
dumpStack(t == null ? toe : t);
|
||||
return toe.result;
|
||||
oe.m.run();
|
||||
Throwable t = oe.getCause();
|
||||
dumpStack(t == null ? oe : t);
|
||||
return oe.result;
|
||||
} catch (ToolException exc) {
|
||||
if (exc.message != null) {
|
||||
messager.printError(exc.message);
|
||||
@ -733,7 +733,7 @@ public class Start {
|
||||
}
|
||||
|
||||
if (Doclet.class.isAssignableFrom(docletClass)) {
|
||||
messager.setLocale(locale);
|
||||
messager.setLocale(Locale.getDefault()); // use default locale for console messages
|
||||
try {
|
||||
Object o = docletClass.getConstructor().newInstance();
|
||||
doclet = (Doclet) o;
|
||||
@ -818,10 +818,6 @@ public class Start {
|
||||
messager.printErrorUsingKey(key, args);
|
||||
}
|
||||
|
||||
void warn(String key, Object... args) {
|
||||
messager.printWarningUsingKey(key, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the locale if specified on the command line
|
||||
* else return null and if locale option is not used
|
||||
@ -841,21 +837,4 @@ public class Start {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search the locale for specified language, specified country and
|
||||
* specified variant.
|
||||
*/
|
||||
private Locale searchLocale(String language, String country,
|
||||
String variant) {
|
||||
for (Locale loc : Locale.getAvailableLocales()) {
|
||||
if (loc.getLanguage().equals(language) &&
|
||||
(country == null || loc.getCountry().equals(country)) &&
|
||||
(variant == null || loc.getVariant().equals(variant))) {
|
||||
return loc;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -47,6 +47,21 @@ import jdk.tools.jlink.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* Plugin to generate java.lang.invoke classes.
|
||||
*
|
||||
* The plugin reads in a file generated by running any application with
|
||||
* {@code -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true}. This is done
|
||||
* automatically during build, see make/GenerateLinkOptData.gmk. See
|
||||
* build/tools/classlist/HelloClasslist.java for the training application.
|
||||
*
|
||||
* HelloClasslist tries to reflect common use of java.lang.invoke during early
|
||||
* startup and warmup in various applications. To ensure a good default
|
||||
* trade-off between static footprint and startup the application should be
|
||||
* relatively conservative.
|
||||
*
|
||||
* When using jlink to build a custom application runtime, generating a trace
|
||||
* file using {@code -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true} and
|
||||
* feeding that into jlink using {@code --generate-jli-classes=@trace_file} can
|
||||
* help improve startup time.
|
||||
*/
|
||||
public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
|
||||
@ -112,59 +127,6 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
return PluginsResourceBundle.getArgument(NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default Species forms to generate.
|
||||
*
|
||||
* This list was derived from running a small startup benchmark.
|
||||
* A better long-term solution is to define and run a set of quick
|
||||
* generators and extracting this list as a step in the build process.
|
||||
*/
|
||||
public static Set<String> defaultSpecies() {
|
||||
return Set.of("LL", "L3", "L4", "L5", "L6", "L7", "L7I",
|
||||
"L7II", "L7IIL", "L8", "L9", "L10", "L10I", "L10II", "L10IIL",
|
||||
"L11", "L12", "L13", "LI", "D", "L3I", "LIL", "LLI", "LLIL",
|
||||
"LILL", "I", "LLILL");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default invoker forms to generate.
|
||||
*/
|
||||
private static Set<String> defaultInvokers() {
|
||||
return Set.of("LL_L", "LL_I", "LLLL_L", "LLLL_I", "LLIL_L", "LLIL_I",
|
||||
"L6_L");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the default call site forms to generate (linkToTargetMethod).
|
||||
*/
|
||||
private static Set<String> defaultCallSiteTypes() {
|
||||
return Set.of("L5_L", "LIL3_L", "ILL_L");
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the list of default DirectMethodHandle methods to generate.
|
||||
*/
|
||||
private static Map<String, Set<String>> defaultDMHMethods() {
|
||||
return Map.of(
|
||||
DMH_INVOKE_INTERFACE, Set.of("LL_L", "L3_I", "L3_V"),
|
||||
DMH_INVOKE_VIRTUAL, Set.of("LL_L", "LLI_I", "L3_V"),
|
||||
DMH_INVOKE_SPECIAL, Set.of("LL_I", "LL_L", "LLF_L", "LLD_L",
|
||||
"L3_I", "L3_L", "L4_L", "L5_L", "L6_L", "L7_L", "L8_L",
|
||||
"LLI_I", "LLI_L", "LLIL_I", "LLIL_L", "LLII_I", "LLII_L",
|
||||
"L3I_L", "L3I_I", "L3ILL_L", "LLILI_I", "LLIIL_L", "LLIILL_L",
|
||||
"LLIILL_I", "LLIIL_I", "LLILIL_I", "LLILILL_I", "LLILII_I",
|
||||
"LLI3_I", "LLI3L_I", "LLI3LL_I", "LLI3_L", "LLI4_I"),
|
||||
DMH_INVOKE_STATIC, Set.of("LII_I", "LIL_I", "LILIL_I", "LILII_I",
|
||||
"L_I", "L_L", "L_V", "LD_L", "LF_L", "LI_I", "LII_L", "LLI_L",
|
||||
"LL_I", "LLILL_L", "LLIL3_L", "LL_V", "LL_L", "L3_I", "L3_L",
|
||||
"L3_V", "L4_I", "L4_L", "L5_L", "L6_L", "L7_L", "L8_L", "L9_L",
|
||||
"L10_L", "L10I_L", "L10II_L", "L10IIL_L", "L11_L", "L12_L",
|
||||
"L13_L", "L14_L", "L14I_L", "L14II_L"),
|
||||
DMH_NEW_INVOKE_SPECIAL, Set.of("L_L", "LL_L"),
|
||||
DMH_INVOKE_SPECIAL_IFC, Set.of("L5_I")
|
||||
);
|
||||
}
|
||||
|
||||
private static int DMH_INVOKE_VIRTUAL_TYPE = 0;
|
||||
private static int DMH_INVOKE_INTERFACE_TYPE = 4;
|
||||
|
||||
@ -201,19 +163,8 @@ public final class GenerateJLIClassesPlugin implements Plugin {
|
||||
}
|
||||
|
||||
public void initialize(ResourcePool in) {
|
||||
// Start with the default configuration
|
||||
defaultSpecies().stream().forEach(this::addSpeciesType);
|
||||
|
||||
defaultInvokers().stream().forEach(this::validateMethodType);
|
||||
|
||||
defaultCallSiteTypes().stream().forEach(this::addCallSiteType);
|
||||
|
||||
defaultDMHMethods().entrySet().stream().forEach(e -> {
|
||||
e.getValue().stream().forEach(type -> addDMHMethodType(e.getKey(), type));
|
||||
});
|
||||
|
||||
// Extend the default configuration with the contents in the supplied
|
||||
// input file - if none was supplied we look for the default file
|
||||
// Load configuration from the contents in the supplied input file
|
||||
// - if none was supplied we look for the default file
|
||||
if (mainArgument == null || !mainArgument.startsWith("@")) {
|
||||
try (InputStream traceFile =
|
||||
this.getClass().getResourceAsStream(DEFAULT_TRACE_FILE)) {
|
||||
|
@ -1,4 +1,4 @@
|
||||
## Unicode Common Local Data Repository (CLDR) v35.1
|
||||
## Unicode Common Local Data Repository (CLDR) v36
|
||||
|
||||
### CLDR License
|
||||
|
||||
|
@ -177,6 +177,7 @@ ctw_3 = \
|
||||
applications/ctw/modules/jdk_compiler.java \
|
||||
applications/ctw/modules/jdk_internal_vm_compiler.java \
|
||||
applications/ctw/modules/jdk_localedata.java \
|
||||
applications/ctw/modules/jdk_localedata_2.java \
|
||||
applications/ctw/modules/jdk_scripting_nashorn.java \
|
||||
|
||||
tier1_gc = \
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 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
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary run CTW for all classes from jdk.localedata module
|
||||
* @summary run CTW for some classes from jdk.localedata module
|
||||
*
|
||||
* @library /test/lib / /testlibrary/ctw/src
|
||||
* @modules java.base/jdk.internal.access
|
||||
@ -35,5 +35,5 @@
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run driver/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.localedata
|
||||
* @run driver/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.localedata 0% 50%
|
||||
*/
|
||||
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary run CTW for some classes from jdk.localedata module
|
||||
*
|
||||
* @library /test/lib / /testlibrary/ctw/src
|
||||
* @modules java.base/jdk.internal.access
|
||||
* java.base/jdk.internal.jimage
|
||||
* java.base/jdk.internal.misc
|
||||
* java.base/jdk.internal.reflect
|
||||
* @modules jdk.localedata
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
* @run driver/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:jdk.localedata 50% 100%
|
||||
*/
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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
|
||||
@ -60,11 +60,6 @@ public class TestJFREvents {
|
||||
DockerTestUtils.buildJdkDockerImage(imageName, "Dockerfile-BasicTest", "jdk-docker");
|
||||
|
||||
try {
|
||||
// leave one CPU for system and tools, otherwise this test may be unstable
|
||||
int maxNrOfAvailableCpus = availableCPUs - 1;
|
||||
for (int i=1; i < maxNrOfAvailableCpus; i = i * 2) {
|
||||
testCPUInfo(i, i);
|
||||
}
|
||||
|
||||
long MB = 1024*1024;
|
||||
testMemory("200m", "" + 200*MB);
|
||||
@ -79,18 +74,26 @@ public class TestJFREvents {
|
||||
}
|
||||
}
|
||||
|
||||
// This test case is currently not in use.
|
||||
// Once new Container events are available, this test case can be used to test
|
||||
// processor-related configuration such as active processor count (see JDK-8203359).
|
||||
private static void cpuTestCase() throws Exception {
|
||||
// leave one CPU for system and tools, otherwise this test may be unstable
|
||||
int maxNrOfAvailableCpus = availableCPUs - 1;
|
||||
for (int i=1; i < maxNrOfAvailableCpus; i = i * 2) {
|
||||
testCPUInfo("jdk.ContainerConfiguration", i, i);
|
||||
}
|
||||
}
|
||||
|
||||
private static void testCPUInfo(int valueToSet, int expectedValue) throws Exception {
|
||||
private static void testCPUInfo(String eventName, int valueToSet, int expectedValue) throws Exception {
|
||||
Common.logNewTestCase("CPUInfo: --cpus = " + valueToSet);
|
||||
String fieldName = "activeProcessorCount";
|
||||
DockerTestUtils.dockerRunJava(
|
||||
commonDockerOpts()
|
||||
.addDockerOpts("--cpus=" + valueToSet)
|
||||
.addClassOptions("jdk.CPUInformation"))
|
||||
.shouldHaveExitValue(0);
|
||||
// The following assertion is currently disabled due to JFR reporting incorrect values.
|
||||
// JFR reports values for the host system as opposed to values for the container.
|
||||
// @ignore 8219999
|
||||
// .shouldContain("cores = " + expectedValue");
|
||||
.addClassOptions(eventName))
|
||||
.shouldHaveExitValue(0)
|
||||
.shouldContain(fieldName + " = " + expectedValue);
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8237837
|
||||
* @summary Shenandoah: assert(mem == __null) failed: only one safepoint
|
||||
* @key gc
|
||||
* @requires vm.flavor == "server"
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
*
|
||||
* @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -Xcomp -XX:CompileOnly=BarrierInInfiniteLoop::test -XX:CompileCommand=quiet BarrierInInfiniteLoop
|
||||
*
|
||||
*/
|
||||
|
||||
public class BarrierInInfiniteLoop {
|
||||
private static Object field1 = new Object();
|
||||
private static Object field2 = new Object();
|
||||
|
||||
public static void main(String[] args) {
|
||||
test(false);
|
||||
}
|
||||
|
||||
private static void test(boolean flag) {
|
||||
if (flag) {
|
||||
for (;;) {
|
||||
field1 = field2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test 8238385
|
||||
* @summary CTW: C2 (Shenandoah) compilation fails with "Range check dependent CastII node was not removed"
|
||||
* @key gc
|
||||
* @requires vm.gc.Shenandoah & !vm.graal.enabled
|
||||
* @modules java.base/jdk.internal.misc:+open
|
||||
*
|
||||
* @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:-TieredCompilation -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC
|
||||
* FoldIfAfterExpansion
|
||||
*
|
||||
*/
|
||||
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
public class FoldIfAfterExpansion {
|
||||
private static int[] field1 = new int[100];
|
||||
private static int[] field2 = new int[100];
|
||||
private static int[] field3;
|
||||
private static volatile int barrier;
|
||||
|
||||
static final jdk.internal.misc.Unsafe UNSAFE = Unsafe.getUnsafe();
|
||||
|
||||
public static void main(String[] args) {
|
||||
for (int i = 0; i < 20_000; i++) {
|
||||
test(true, 10, false, true);
|
||||
test(false, 10, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
private static Object test(boolean flag, int i, boolean flag2, boolean flag3) {
|
||||
int[] array;
|
||||
if (flag) {
|
||||
barrier = 1;
|
||||
array = field1;
|
||||
final int length = array.length;
|
||||
if (flag2) {
|
||||
field3 = array;
|
||||
}
|
||||
} else {
|
||||
barrier = 1;
|
||||
array = field1;
|
||||
final int length = array.length;
|
||||
if (flag2) {
|
||||
field3 = array;
|
||||
}
|
||||
}
|
||||
|
||||
array = field1;
|
||||
|
||||
if (flag3) {
|
||||
if (i < 0 || i >= array.length) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
long l = (long)i;
|
||||
l = l * UNSAFE.ARRAY_INT_INDEX_SCALE + UNSAFE.ARRAY_INT_BASE_OFFSET;
|
||||
UNSAFE.putInt(array, l, i);
|
||||
} else {
|
||||
if (i < 0 || i >= array.length) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
long l = (long)i;
|
||||
l = l * UNSAFE.ARRAY_INT_INDEX_SCALE + UNSAFE.ARRAY_INT_BASE_OFFSET;
|
||||
UNSAFE.putInt(array, l, i);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -46,6 +46,8 @@ public class VMDeprecatedOptions {
|
||||
{"InitialRAMFraction", "64"},
|
||||
{"TLABStats", "false"},
|
||||
{"AllowRedefinitionToAddDeleteMethods", "true"},
|
||||
{"PrintVMQWaitTime", "true"},
|
||||
{"UseNewFieldLayout", "true"},
|
||||
|
||||
// deprecated alias flags (see also aliased_jvm_flags):
|
||||
{"DefaultMaxRAMFraction", "4"},
|
||||
|
157
test/hotspot/jtreg/runtime/FieldLayout/FieldDensityTest.java
Normal file
157
test/hotspot/jtreg/runtime/FieldLayout/FieldDensityTest.java
Normal file
@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8237767
|
||||
* @summary Verify behaviour of field layout algorithm
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
* @run main/othervm FieldDensityTest
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @requires vm.bits == "64"
|
||||
* @library /test/lib
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
* @run main/othervm -XX:+UseCompressedOops -XX:+UseCompressedClassPointers FieldDensityTest
|
||||
* @run main/othervm -XX:+UseCompressedOops -XX:-UseCompressedClassPointers FieldDensityTest
|
||||
*/
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import jdk.internal.misc.Unsafe;
|
||||
|
||||
import jdk.test.lib.Asserts;
|
||||
|
||||
public class FieldDensityTest {
|
||||
|
||||
static int OOP_SIZE_IN_BYTES = 0;
|
||||
|
||||
static {
|
||||
if (System.getProperty("sun.arch.data.model").equals("64")) {
|
||||
if (System.getProperty("java.vm.compressedOopsMode") == null) {
|
||||
OOP_SIZE_IN_BYTES = 8;
|
||||
} else {
|
||||
OOP_SIZE_IN_BYTES = 4;
|
||||
}
|
||||
} else {
|
||||
OOP_SIZE_IN_BYTES = 4;
|
||||
}
|
||||
}
|
||||
|
||||
static class FieldInfo {
|
||||
public Field field;
|
||||
public long offset;
|
||||
|
||||
FieldInfo(Field field, long offset) {
|
||||
this.field = field;
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
static void checkFieldsContiguity(FieldInfo[] fieldInfo) {
|
||||
Arrays.sort(fieldInfo, new SortByOffset());
|
||||
for (int i = 0 ; i < fieldInfo.length - 2; i++) {
|
||||
int size = sizeInBytesFromType(fieldInfo[i].field.getType());
|
||||
Asserts.assertEquals((int)(fieldInfo[i].offset + size), (int)fieldInfo[i+1].offset,
|
||||
"Empty slot between fields, should not happen");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int sizeInBytesFromType(Class type) {
|
||||
if (!type.isPrimitive()) {
|
||||
return OOP_SIZE_IN_BYTES;
|
||||
}
|
||||
switch(type.getTypeName()) {
|
||||
case "boolean":
|
||||
case "byte": return 1;
|
||||
case "char":
|
||||
case "short": return 2;
|
||||
case "int":
|
||||
case "float": return 4;
|
||||
case "long":
|
||||
case "double": return 8;
|
||||
default:
|
||||
throw new RuntimeException("Unrecognized signature");
|
||||
}
|
||||
}
|
||||
|
||||
static class SortByOffset implements Comparator<FieldInfo> {
|
||||
public int compare(FieldInfo a, FieldInfo b)
|
||||
{
|
||||
return (int)(a.offset - b.offset);
|
||||
}
|
||||
}
|
||||
|
||||
static class E {
|
||||
public byte b0;
|
||||
}
|
||||
|
||||
static class F extends E {
|
||||
public byte b1;
|
||||
}
|
||||
|
||||
static class G extends F {
|
||||
public byte b2;
|
||||
}
|
||||
|
||||
static class H extends G {
|
||||
public byte b3;
|
||||
}
|
||||
|
||||
public static class A {
|
||||
public int i;
|
||||
public byte b;
|
||||
public long l;
|
||||
public Object o;
|
||||
}
|
||||
|
||||
public static class B extends A {
|
||||
public byte b0, b1, b2;
|
||||
}
|
||||
|
||||
static void testFieldsContiguity(Class c) {
|
||||
Unsafe unsafe = Unsafe.getUnsafe();
|
||||
Field[] fields = c.getFields();
|
||||
FieldInfo[] fieldsInfo = new FieldInfo[fields.length];
|
||||
int i = 0;
|
||||
for (Field f : fields) {
|
||||
long offset = unsafe.objectFieldOffset(f);
|
||||
fieldsInfo[i] = new FieldInfo(f, offset);
|
||||
i++;
|
||||
}
|
||||
FieldInfo.checkFieldsContiguity(fieldsInfo);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
H h = new H();
|
||||
testFieldsContiguity(h.getClass());
|
||||
B b = new B();
|
||||
testFieldsContiguity(b.getClass());
|
||||
}
|
||||
}
|
@ -99,9 +99,11 @@ public class CompileTheWorld {
|
||||
} catch (Throwable t){
|
||||
t.printStackTrace(ERR);
|
||||
} finally {
|
||||
try {
|
||||
OUT.close();
|
||||
} catch (Throwable ignore) {
|
||||
if (OUT != System.out) {
|
||||
try {
|
||||
OUT.close();
|
||||
} catch (Throwable ignore) {
|
||||
}
|
||||
}
|
||||
// <clinit> might have started new threads
|
||||
System.exit(passed ? 0 : 1);
|
||||
|
@ -150,6 +150,9 @@ public class Compiler {
|
||||
} else {
|
||||
compileAtLevel(compLevel);
|
||||
}
|
||||
|
||||
// Make the method eligible for sweeping sooner
|
||||
WHITE_BOX.deoptimizeMethod(method);
|
||||
}
|
||||
|
||||
private void waitCompilation() {
|
||||
|
@ -49,7 +49,7 @@ import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
public class Test {
|
||||
private static String UNSUPPORTED_OPTION_MESSAGE = "-XX:TieredCompilation not supported in this VM";
|
||||
private static String UNSUPPORTED_OPTION_MESSAGE = "-XX:+TieredCompilation not supported in this VM";
|
||||
private static String REGEXP = "^[0-9.]+: \\[compile level=\\d";
|
||||
public static void main(String[] args) throws Exception {
|
||||
{
|
||||
@ -59,7 +59,7 @@ public class Test {
|
||||
"-XX:+PrintTieredEvents",
|
||||
"-version");
|
||||
var output = new OutputAnalyzer(pb.start());
|
||||
if (output.getStdout().contains(UNSUPPORTED_OPTION_MESSAGE)) {
|
||||
if (output.getStderr().contains(UNSUPPORTED_OPTION_MESSAGE)) {
|
||||
throw new SkippedException(UNSUPPORTED_OPTION_MESSAGE);
|
||||
}
|
||||
output.shouldHaveExitValue(0)
|
||||
|
@ -913,9 +913,6 @@ com/sun/jdi/RepStep.java 8043571 generic-
|
||||
|
||||
com/sun/jdi/NashornPopFrameTest.java 8225620 generic-all
|
||||
|
||||
com/sun/jdi/JdwpListenTest.java 8234935 windows-all
|
||||
com/sun/jdi/JdwpAttachTest.java 8234935 windows-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_time
|
||||
|
@ -25,6 +25,7 @@ import com.sun.jdi.Bootstrap;
|
||||
import com.sun.jdi.VirtualMachine;
|
||||
import com.sun.jdi.connect.Connector;
|
||||
import com.sun.jdi.connect.ListeningConnector;
|
||||
import jdk.test.lib.Platform;
|
||||
import jdk.test.lib.apps.LingeredApp;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
@ -33,7 +34,6 @@ import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
@ -54,8 +54,6 @@ import java.util.concurrent.Executors;
|
||||
*/
|
||||
public class JdwpAttachTest {
|
||||
|
||||
private static final boolean IsWindows = System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
|
||||
// Set to true to perform testing of attach from wrong address (expected to fail).
|
||||
// It's off by default as it caused significant test time increase\
|
||||
// (tests <number_of_addresses> * <number_of_addresses> cases, each case fails by timeout).
|
||||
@ -115,7 +113,7 @@ public class JdwpAttachTest {
|
||||
}
|
||||
log(" Listening port: " + port);
|
||||
|
||||
log(" Attaching from " + connectAddress);
|
||||
log(" Attaching to " + connectAddress);
|
||||
try {
|
||||
ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
executor.submit((Callable<Exception>)() -> {
|
||||
@ -155,6 +153,12 @@ public class JdwpAttachTest {
|
||||
list.add(addr);
|
||||
}
|
||||
|
||||
private static boolean isTeredo(Inet6Address addr) {
|
||||
// Teredo prefix is 2001::/32 (i.e. first 4 bytes are 2001:0000)
|
||||
byte[] bytes = addr.getAddress();
|
||||
return bytes[0] == 0x20 && bytes[1] == 0x01 && bytes[2] == 0x00 && bytes[3] == 0x00;
|
||||
}
|
||||
|
||||
private static List<InetAddress> getAddresses() {
|
||||
List<InetAddress> result = new LinkedList<>();
|
||||
try {
|
||||
@ -173,6 +177,12 @@ public class JdwpAttachTest {
|
||||
// On other platforms test both symbolic and numeric scopes.
|
||||
if (addr instanceof Inet6Address) {
|
||||
Inet6Address addr6 = (Inet6Address)addr;
|
||||
// Teredo clients cause intermittent errors on listen ("bind failed")
|
||||
// and attach ("no route to host").
|
||||
// Teredo is supposed to be a temporary measure, but some test machines have it.
|
||||
if (isTeredo(addr6)) {
|
||||
continue;
|
||||
}
|
||||
NetworkInterface scopeIface = addr6.getScopedInterface();
|
||||
if (scopeIface != null && scopeIface.getName() != null) {
|
||||
// On some test machines VPN creates link local addresses
|
||||
@ -190,7 +200,7 @@ public class JdwpAttachTest {
|
||||
throw new RuntimeException("Unexpected", e);
|
||||
}
|
||||
|
||||
if (IsWindows) {
|
||||
if (Platform.isWindows()) {
|
||||
// don't add addresses with symbolic scope
|
||||
continue;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2019, 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
|
||||
@ -26,6 +26,7 @@ import com.sun.jdi.VirtualMachine;
|
||||
import com.sun.jdi.connect.AttachingConnector;
|
||||
import com.sun.jdi.connect.Connector;
|
||||
import com.sun.jdi.connect.IllegalConnectorArgumentsException;
|
||||
import jdk.test.lib.Platform;
|
||||
import lib.jdb.Debuggee;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -52,8 +53,6 @@ import java.util.Map;
|
||||
*/
|
||||
public class JdwpListenTest {
|
||||
|
||||
private static final boolean IsWindows = System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
|
||||
// Set to true to allow testing of attach from wrong address (expected to fail).
|
||||
// It's off by default as it causes test time increase and test interference (see JDK-8231915).
|
||||
private static boolean allowNegativeTesting = false;
|
||||
@ -89,7 +88,7 @@ public class JdwpListenTest {
|
||||
|
||||
private static void listenTest(String listenAddress, String connectAddress, boolean expectedResult)
|
||||
throws IOException {
|
||||
log("\nTest: listen at " + listenAddress + ", attaching from " + connectAddress
|
||||
log("\nTest: listen at " + listenAddress + ", attaching to " + connectAddress
|
||||
+ ", expected: " + (expectedResult ? "SUCCESS" : "FAILURE"));
|
||||
if (!expectedResult && !allowNegativeTesting) {
|
||||
log("SKIPPED: negative testing is disabled");
|
||||
@ -99,7 +98,7 @@ public class JdwpListenTest {
|
||||
log("Starting listening debuggee at " + listenAddress);
|
||||
try (Debuggee debuggee = Debuggee.launcher("HelloWorld").setAddress(listenAddress + ":0").launch()) {
|
||||
log("Debuggee is listening on " + listenAddress + ":" + debuggee.getAddress());
|
||||
log("Connecting from " + connectAddress + ", expected: " + (expectedResult ? "SUCCESS" : "FAILURE"));
|
||||
log("Connecting to " + connectAddress + ", expected: " + (expectedResult ? "SUCCESS" : "FAILURE"));
|
||||
try {
|
||||
VirtualMachine vm = attach(connectAddress, debuggee.getAddress());
|
||||
vm.dispose();
|
||||
@ -120,6 +119,12 @@ public class JdwpListenTest {
|
||||
list.add(addr);
|
||||
}
|
||||
|
||||
private static boolean isTeredo(Inet6Address addr) {
|
||||
// Teredo prefix is 2001::/32 (i.e. first 4 bytes are 2001:0000)
|
||||
byte[] bytes = addr.getAddress();
|
||||
return bytes[0] == 0x20 && bytes[1] == 0x01 && bytes[2] == 0x00 && bytes[3] == 0x00;
|
||||
}
|
||||
|
||||
private static List<InetAddress> getAddresses() {
|
||||
List<InetAddress> result = new LinkedList<>();
|
||||
try {
|
||||
@ -138,6 +143,12 @@ public class JdwpListenTest {
|
||||
// On other platforms test both symbolic and numeric scopes.
|
||||
if (addr instanceof Inet6Address) {
|
||||
Inet6Address addr6 = (Inet6Address)addr;
|
||||
// Teredo clients cause intermittent errors on listen ("bind failed")
|
||||
// and attach ("no route to host").
|
||||
// Teredo is supposed to be a temporary measure, but some test machines have it.
|
||||
if (isTeredo(addr6)) {
|
||||
continue;
|
||||
}
|
||||
NetworkInterface scopeIface = addr6.getScopedInterface();
|
||||
if (scopeIface != null && scopeIface.getName() != null) {
|
||||
// On some test machines VPN creates link local addresses
|
||||
@ -155,7 +166,7 @@ public class JdwpListenTest {
|
||||
throw new RuntimeException("Unexpected", e);
|
||||
}
|
||||
|
||||
if (IsWindows) {
|
||||
if (Platform.isWindows()) {
|
||||
// don't add addresses with symbolic scope
|
||||
continue;
|
||||
}
|
||||
|
231
test/jdk/java/net/httpclient/ssltest/Cert.java
Normal file
231
test/jdk/java/net/httpclient/ssltest/Cert.java
Normal file
@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The certificates used by this test.
|
||||
* They are generated by script gen-certs.sh.
|
||||
*/
|
||||
public enum Cert {
|
||||
|
||||
/*
|
||||
* Version: 3 (0x2)
|
||||
* Serial Number:
|
||||
* 65:24:13:3c:7a:98:0c:16:a2:91:9c:8e:42:84:cf:be:be:d2:f1:42
|
||||
* Signature Algorithm: sha256WithRSAEncryption
|
||||
* Issuer: CN = evil
|
||||
* Validity
|
||||
* Not Before: Feb 8 03:59:27 2020 GMT
|
||||
* Not After : Feb 5 03:59:27 2030 GMT
|
||||
* Subject: CN = evil
|
||||
* X509v3 extensions:
|
||||
* X509v3 Subject Key Identifier:
|
||||
* 09:D0:E8:51:6C:0F:88:59:47:D1:FD:05:C2:00:10:D6:A4:80:04:07
|
||||
* X509v3 Authority Key Identifier:
|
||||
* keyid:09:D0:E8:51:6C:0F:88:59:47:D1:FD:05:C2:00:10:D6:A4:80:04:07
|
||||
*/
|
||||
BAD_CERT(
|
||||
"RSA",
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIC7jCCAdagAwIBAgIUZSQTPHqYDBaikZyOQoTPvr7S8UIwDQYJKoZIhvcNAQEL\n" +
|
||||
"BQAwDzENMAsGA1UEAwwEZXZpbDAeFw0yMDAyMDgwMzU5MjdaFw0zMDAyMDUwMzU5\n" +
|
||||
"MjdaMA8xDTALBgNVBAMMBGV2aWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n" +
|
||||
"AoIBAQCmirsTOW1G+LoI/Aj59lMk3KLywAbXASeTdnBoWkchuJ0QJWO/5b5kgf6Q\n" +
|
||||
"VFfe9lXof9psGIKaCGq6KsI0uqj7+7y++//l+E6GB8UshVB8MXc1SLFe8AxPYhWC\n" +
|
||||
"TXaKWyWGl7PXvugzbByFrf4IwE9+6phYkvl/zHvaMKqdwnkpXuyuBgT3BiYTSNsx\n" +
|
||||
"k1Ma+s5rqiwsOODSzwhadwmU9T4z11KypYb/DixJgHvUET4gTB+i3ll+PllVdQtX\n" +
|
||||
"zBLpEuj5HadK0PsqlOIok3eoSU+MpRqsz0gFEQ95y+Les3MlBeQ7fVKBz8GbrFDB\n" +
|
||||
"Atzca+iknEh8fkLIUUuCjTjUtLvfAgMBAAGjQjBAMB0GA1UdDgQWBBQJ0OhRbA+I\n" +
|
||||
"WUfR/QXCABDWpIAEBzAfBgNVHSMEGDAWgBQJ0OhRbA+IWUfR/QXCABDWpIAEBzAN\n" +
|
||||
"BgkqhkiG9w0BAQsFAAOCAQEAQMfPfYfVSSdsiEUOlVg6M5D90HRONzqlg/v0RqQI\n" +
|
||||
"fb3uufXJs20dg8iamVORXIIeUpGv1OQ2Rx4ndnV3bRLK6ep3gswIkOnD8z/CeNgl\n" +
|
||||
"odZPvWyklHTMenGqU2TR3ceFep/DvQkrP4aZWyr3e2fjatKR/s4pXgBwHs/hR76O\n" +
|
||||
"vDYLRDyCG/+MtUClFsc9HLedbU4Wp8JyaafFZ63/VjaIcvdHoDGNILRu5AIN/JVM\n" +
|
||||
"Sgz4blkWJxS1dlqBYwxvbpJWrHUcktsa3Bzw2zWOkTVGQJi3pMvzRBkgliNaXPi3\n" +
|
||||
"qcPViqgzVoB4QdOQBnvDtQ9+8Nt/dQY1VJFSBLxZQIefiQ==\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCmirsTOW1G+LoI\n" +
|
||||
"/Aj59lMk3KLywAbXASeTdnBoWkchuJ0QJWO/5b5kgf6QVFfe9lXof9psGIKaCGq6\n" +
|
||||
"KsI0uqj7+7y++//l+E6GB8UshVB8MXc1SLFe8AxPYhWCTXaKWyWGl7PXvugzbByF\n" +
|
||||
"rf4IwE9+6phYkvl/zHvaMKqdwnkpXuyuBgT3BiYTSNsxk1Ma+s5rqiwsOODSzwha\n" +
|
||||
"dwmU9T4z11KypYb/DixJgHvUET4gTB+i3ll+PllVdQtXzBLpEuj5HadK0PsqlOIo\n" +
|
||||
"k3eoSU+MpRqsz0gFEQ95y+Les3MlBeQ7fVKBz8GbrFDBAtzca+iknEh8fkLIUUuC\n" +
|
||||
"jTjUtLvfAgMBAAECggEATyu2QS5Un5+QOMMvtTx/TA/DOulElyNKYBS23TTFiedM\n" +
|
||||
"ayeLIuehuf/+NziRSUILlupouGhyda04p2W6SvzNZnTGxnffr8B5+8dn2YFKwK93\n" +
|
||||
"PxJel4ZAI+C53ubaSm2IClLFwPNVSVTEvlv3XsulPu1hHQJJr5JS8meeRD72AE8G\n" +
|
||||
"brKbLlq6OGey6u9teao0m4Wo05MzaEoOx4fztPP4BiJJobuPYrdthUwfXJ2mQYeg\n" +
|
||||
"fJKl+JeLUnAXmq8e+6Zs88NzGK8Gmd2TvGnUahxSDtXHuRkB2lOrGFrEJKkAXDBx\n" +
|
||||
"2q8r3vvcay6+k95fS2HOvggFDALS37BGckWg4+HYuQKBgQDXkxw0u2G7rCYbF691\n" +
|
||||
"jil++DLNUzejZonAvA/cceVHShfAMlWCBf58cLNsY33rkRsFazhrdDoDAFqKxejB\n" +
|
||||
"xWM8U7UHiHZSznuXTL0YbUombfz+0lp/KwXcirnB7O3AdIW4lfMo/ozeMMIuEzsL\n" +
|
||||
"G/MDvbNSdawEso/qtxFvz87ctQKBgQDFxcCSyWb/SQVr3RkZkO3BW2efuANxNeUh\n" +
|
||||
"35L4inWTa8ml8UL4SrTrkfUHzu5TnBGbSb2n8CdkPnInA81dKagX6LXuONeLkX/e\n" +
|
||||
"RXyWIwWRiBkpYSaw2OGApl49DRvk2kCzwoVRWwh8qfhpC0P6AClFRaVAovYcTxm3\n" +
|
||||
"vhCJL3jmwwKBgGMLvTbhLStMEgn6nOwXECu9H6JE7NhPgVUjUupHDj/t4/GzbqQZ\n" +
|
||||
"2u4T3ewb3jwAZHjd5YNBWHIOlIsUGTgGV+zczN0ULsEnC5Pddzgk5p+3gzkVLu0k\n" +
|
||||
"uEG3H1fhYu882j+P7bPVGKXxoxYGUedtxP7gBucJF6rk28jMqd9EjFfNAoGBAKcc\n" +
|
||||
"ASwGodDzknEh0SOZIkxPP6/lfIMcVw/YKgd4dwCqAykEQuIpvdWO7sw6PYbISNg9\n" +
|
||||
"5tMQSTiayznMLKqbmD0blR5FSVvVBYZ6kFsMHJhrt1cPj/G+UEy0RsyvVvJ4uFMr\n" +
|
||||
"+hpUIUe1FwErU7TajgTKZGfJSsuAyupG3xIL2syhAoGALv+ulZAY/gUKH8NigsXo\n" +
|
||||
"pFPTpiXMyTD/O4RUH/5LcxDELVZ8cnV2q3qEX+ep24y0AtNiBx4oHpZ/vIxtwBCR\n" +
|
||||
"JKU2xmIGC6NyQMRSzfmNgi0X450rgKbTAxn/LAU8syXmNpBUrFZ8+02pQvWzxqfU\n" +
|
||||
"zGaMEK3+f1sq8Byzau/qhKU="),
|
||||
|
||||
/*
|
||||
* Version: 3 (0x2)
|
||||
* Serial Number:
|
||||
* 70:41:2f:71:43:d1:67:b5:29:c6:3e:ce:62:ba:d5:aa:4a:f1:f7:f0
|
||||
* Signature Algorithm: sha256WithRSAEncryption
|
||||
* Issuer: CN = localhost
|
||||
* Validity
|
||||
* Not Before: Feb 8 03:59:18 2020 GMT
|
||||
* Not After : Feb 5 03:59:18 2030 GMT
|
||||
* Subject: CN = localhost
|
||||
* X509v3 extensions:
|
||||
* X509v3 Subject Key Identifier:
|
||||
* 12:65:C7:4B:D8:77:D8:55:6E:2D:AF:C4:F8:09:FE:08:F4:22:EA:D5
|
||||
* X509v3 Authority Key Identifier:
|
||||
* keyid:12:65:C7:4B:D8:77:D8:55:6E:2D:AF:C4:F8:09:FE:08:F4:22:EA:D5
|
||||
*/
|
||||
GOOD_CERT(
|
||||
"RSA",
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIC+DCCAeCgAwIBAgIUcEEvcUPRZ7Upxj7OYrrVqkrx9/AwDQYJKoZIhvcNAQEL\n" +
|
||||
"BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTIwMDIwODAzNTkxOFoXDTMwMDIw\n" +
|
||||
"NTAzNTkxOFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF\n" +
|
||||
"AAOCAQ8AMIIBCgKCAQEAtSOmfkF0zjPeZ4DDsJZO3OaDq+XHtPLB+xvri1iuL9b+\n" +
|
||||
"dZDXOqPZ5+koWM9NzDR6Um+IN46oTU+8eJw+hYcZaE9tzS9kH+6qOBk/827yEyVa\n" +
|
||||
"jh9Wqw164xj16QPyQJuHEeeDJ7elNfaOQXRu2UqZB9suKbolqsHe42hbg0/tbln7\n" +
|
||||
"C8C6qEJOpnEaapFHi3/3AeoQQ57zywqrzopeiiuUDWmBhXY30ve33RrJl/OIM1sB\n" +
|
||||
"QSoVCPcaF0mXaDwUTYIksxelon1K9PJa76p9ybGnsxkYfCAGZ8O+fTjJfQONU+Gu\n" +
|
||||
"zOmcyXL5D5O/nI8lxN8hbZwVIAYXLYRUonECIOJ/iQIDAQABo0IwQDAdBgNVHQ4E\n" +
|
||||
"FgQUEmXHS9h32FVuLa/E+An+CPQi6tUwHwYDVR0jBBgwFoAUEmXHS9h32FVuLa/E\n" +
|
||||
"+An+CPQi6tUwDQYJKoZIhvcNAQELBQADggEBAFatzXsT9YZ0TF66G6apSbbs6mH9\n" +
|
||||
"PMVE9IuE4yv2zyKofSMmDHFdmfNdkMHWkIxcZKuiL00IPFL76LAb9DWNQVy4otq6\n" +
|
||||
"3+n0CCi808gDNUMYMQLlXVooZsByXuMuokyg29F5mWEH4rswU6ru33lAB7CT7BuN\n" +
|
||||
"z5/eUhxTcXcJV6pLgcEM68NIc755PULevmqmd8SrVgcFjkxAFOsYd9L86wYLdiPO\n" +
|
||||
"uXfN/EjLMGHG2gpEqHEzQpEEAA/IsCJ1HQ8vvGkeggUIXPrwlIMbQcz/8WBSDel5\n" +
|
||||
"hvVRmADJCLf/0IwxKsSOMWZ4OMmcXMjxnae3lWPQomlzWHMZlFraG2rE/Vo=\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC1I6Z+QXTOM95n\n" +
|
||||
"gMOwlk7c5oOr5ce08sH7G+uLWK4v1v51kNc6o9nn6ShYz03MNHpSb4g3jqhNT7x4\n" +
|
||||
"nD6FhxloT23NL2Qf7qo4GT/zbvITJVqOH1arDXrjGPXpA/JAm4cR54Mnt6U19o5B\n" +
|
||||
"dG7ZSpkH2y4puiWqwd7jaFuDT+1uWfsLwLqoQk6mcRpqkUeLf/cB6hBDnvPLCqvO\n" +
|
||||
"il6KK5QNaYGFdjfS97fdGsmX84gzWwFBKhUI9xoXSZdoPBRNgiSzF6WifUr08lrv\n" +
|
||||
"qn3JsaezGRh8IAZnw759OMl9A41T4a7M6ZzJcvkPk7+cjyXE3yFtnBUgBhcthFSi\n" +
|
||||
"cQIg4n+JAgMBAAECggEAD2O4AYIOKna9ro2CEr6ydJIhHbmn/feiA3Obz3r5UZcy\n" +
|
||||
"h0qG/rRtDwcAJot2UKMkwVw4dn/oTKk5mgWsSivwPKyC56vfFddxHtMGW+hRKM9D\n" +
|
||||
"ok+HTYEXr7OvMNzk+Bg+oYbJ3dX8c1k/PNBnmo578e7tPR5TlO5jwW5cWAuyYG2f\n" +
|
||||
"+YUCqMNe02yZvvlvK1kOSSgqlNH0S14/hVZTYkyxXMCCrkxPFXh5j8w6ZUzVipXg\n" +
|
||||
"99EYcRdq7dA3XVBSgQQ4m5772FIIzlBn8LdIIfw3VQrtZ9HapowLk6QdcHSHBKMK\n" +
|
||||
"0rqb1PlG2ynD2n8hKn4MssJ+tkzvbGrQcLjL/+XHAQKBgQDmiOIke90T8puq3FkN\n" +
|
||||
"NlgdBA9Zem5U2t3TvtQa36cuO/paYrLaVK5U0ucNZ9d4i6avdyp8TyKJrUHDcazi\n" +
|
||||
"QkDpjxb0KBhisutDZ4o1JFW4ZtB3zwIGIYWBBIE1kRIc0ucYoAurSdOmAsKq6XJQ\n" +
|
||||
"B0CQYBJPrTHq5niCl0tKPtrISwKBgQDJJfNcKSz46zdnqsNZAmL+q+cMQf4txiCS\n" +
|
||||
"v0JefOeKKlwNcYWxRgf1yTNENamKKh8wyqOhc/OkxXjglRo9BFMt6BFFARzDddWE\n" +
|
||||
"Wo18cyLc2WvTTv2FCZ0J/eF1jPTGJsTpCU6Prbt4XPjZpzSTF2cQR7CxLp15FsJm\n" +
|
||||
"2LMcQ8ma+wKBgQC72So8hFme2X+S+D3wECo4aoh/Zs3kgvtigQqgY0H84I6de/M1\n" +
|
||||
"CO+M2tW/DLB8336RV87cwDbqbK07rrMrIsV2C0yu4sUMF7Kwl/v8VYEr40tXdOy3\n" +
|
||||
"RjVc7ejDV1Sk/A2m+TLI/j1h9rndPqARKfeoLUB+gCg+ulHUR6fn9dOchQKBgByx\n" +
|
||||
"uj6qbQzxWQ0D0iwvZ/nWgfZAr8bN3bWxbQFXphwSoOEWEbFRQS9xzUtssEvSaHKo\n" +
|
||||
"ZaFRji8yMGUxP/X2WPtSgKwsVXMYqyXfWRGoxw9kQLp7KTVCQtG7Et+XBRADVdG8\n" +
|
||||
"jyV17ilkcedyr9BP5VbwMyeDc9ljQsYzIZHlpavjAoGAct8Wktj0hegCoTxSukU1\n" +
|
||||
"SkJ7t4376sSfxVbbUrH86Y1Z55le1O+VkGtqETmk+Q8qf5Ymnal3W9zZ0O9mOE04\n" +
|
||||
"otFbiB3ifUbpBAipyxS06SIFwMctmSk2EqBcXa3nZ9eUGqx0JhoQahfyDkFzfwJY\n" +
|
||||
"hiBTWnlMjCiJ40yRYAWDzZg="),
|
||||
|
||||
/*
|
||||
* Version: 3 (0x2)
|
||||
* Serial Number:
|
||||
* 3f:62:91:39:7e:02:e9:77:20:61:ce:7e:a2:3c:c0:6c:3f:2e:08:49
|
||||
* Signature Algorithm: sha256WithRSAEncryption
|
||||
* Issuer: CN = UNKOWN
|
||||
* Validity
|
||||
* Not Before: Feb 8 04:00:04 2020 GMT
|
||||
* Not After : Feb 5 04:00:04 2030 GMT
|
||||
* Subject: CN = unknown
|
||||
* X509v3 extensions:
|
||||
* X509v3 Subject Key Identifier:
|
||||
* F7:D7:AE:80:DF:EC:7A:60:5A:E8:62:60:70:03:B6:BD:23:05:19:62
|
||||
* X509v3 Authority Key Identifier:
|
||||
* keyid:F7:D7:AE:80:DF:EC:7A:60:5A:E8:62:60:70:03:B6:BD:23:05:19:62
|
||||
* X509v3 Subject Alternative Name:
|
||||
* IP Address:127.0.0.1
|
||||
*/
|
||||
LOOPBACK_CERT(
|
||||
"RSA",
|
||||
"-----BEGIN CERTIFICATE-----\n" +
|
||||
"MIIDBTCCAe2gAwIBAgIUP2KROX4C6XcgYc5+ojzAbD8uCEkwDQYJKoZIhvcNAQEL\n" +
|
||||
"BQAwEjEQMA4GA1UEAwwHdW5rbm93bjAeFw0yMDAyMDgwNDAwMDRaFw0zMDAyMDUw\n" +
|
||||
"NDAwMDRaMBIxEDAOBgNVBAMMB3Vua25vd24wggEiMA0GCSqGSIb3DQEBAQUAA4IB\n" +
|
||||
"DwAwggEKAoIBAQC8dBwc+nhzuGOcqmeQkcms6JrUPDPcvq6gEEH3dxorzngfxrsl\n" +
|
||||
"lfM6SPJBV4A7HVEcsGhcMoPzzpFVISi3XyLkGuw2WnEW6nKcB2QgaS0Ub8PoDZ7P\n" +
|
||||
"erWGOIjHF1slKxX40tZBiEp1oJANDq7CzSGWiyTorCjbX6OiWZCbhQkw+SpXrAdD\n" +
|
||||
"fzjEAr3y8cgsC7qqTxoz/T9C1+UMmzc88kpAqih7jj2L/i6387dBmV+zrMsNyO0Q\n" +
|
||||
"UPGACzMiSZV3tiwYA6cvDY3WS3fCwLSYUWdHi1orerHQuGOHLK4eyPVDcvuQdUJ/\n" +
|
||||
"T0+jbNZa51scqrBUT/aDlCMCxFUY3vquz2xfAgMBAAGjUzBRMB0GA1UdDgQWBBT3\n" +
|
||||
"166A3+x6YFroYmBwA7a9IwUZYjAfBgNVHSMEGDAWgBT3166A3+x6YFroYmBwA7a9\n" +
|
||||
"IwUZYjAPBgNVHREECDAGhwR/AAABMA0GCSqGSIb3DQEBCwUAA4IBAQBcfcv2J73T\n" +
|
||||
"nHFsCPU3WM6UW2uE8BIM/s/VbjkV1nalFyHi/TU6CN01sDymTABhzIlx5N6PW0HP\n" +
|
||||
"Z0q1C7l1nsoQHwmJO+avOHu3ZjDrLMpU6wTQLEemTd3R5HTyA3/I/FUVFHeuLwJg\n" +
|
||||
"L7OLNc8ouT1hkiIZD+xKwfCEdT3o+ldB+9L4WYRJPt2W3bf3W/yM8JmwW8uf6+U3\n" +
|
||||
"V46xiE5GoOKoIkeAkBAaIbepsZH9rPb7alBSgYgwQYDft9wuGMeNcvPvgVsXjA7I\n" +
|
||||
"RafJVdxVinVMEaOjckIZ5WlrR5667aIJapZH1r7/tiSQCRaJcILx7pL4x8C+x34z\n" +
|
||||
"dPHbbyP/Rdq9\n" +
|
||||
"-----END CERTIFICATE-----",
|
||||
"MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC8dBwc+nhzuGOc\n" +
|
||||
"qmeQkcms6JrUPDPcvq6gEEH3dxorzngfxrsllfM6SPJBV4A7HVEcsGhcMoPzzpFV\n" +
|
||||
"ISi3XyLkGuw2WnEW6nKcB2QgaS0Ub8PoDZ7PerWGOIjHF1slKxX40tZBiEp1oJAN\n" +
|
||||
"Dq7CzSGWiyTorCjbX6OiWZCbhQkw+SpXrAdDfzjEAr3y8cgsC7qqTxoz/T9C1+UM\n" +
|
||||
"mzc88kpAqih7jj2L/i6387dBmV+zrMsNyO0QUPGACzMiSZV3tiwYA6cvDY3WS3fC\n" +
|
||||
"wLSYUWdHi1orerHQuGOHLK4eyPVDcvuQdUJ/T0+jbNZa51scqrBUT/aDlCMCxFUY\n" +
|
||||
"3vquz2xfAgMBAAECggEAEcYNpLoGxDs+wdbcf6kQUUt61st6xLYDODtwTUuhX0JQ\n" +
|
||||
"2AZhPjE/SF764ijDgk/Ih6EnppJpGYSA9ntzIKBLZSIY5yNuiQ/BkW+tBNWGl+fW\n" +
|
||||
"nTszoDPdjPQmCkjsorvGjbos1O9qvl9PVrvsxZidM1qaN4uNKuuBPl2eItzQOhsM\n" +
|
||||
"YFbmw1nqSX31gukv9a6yM2VgDUiGMlEGwkOphutbqt+wTO+9hEopGZHB7mNc5NO9\n" +
|
||||
"foWVVI1rzS2yR2d85lsG4YBqBMDp2s2cBofIAe/SSSpBYPR4RfEBDpSaVceR4+cL\n" +
|
||||
"Lq52DhLVe/zgVj7LEGdyTZTQxw414sRBIz8KXcRIkQKBgQDon26R0/vToZcxgnpr\n" +
|
||||
"ososGh+iTov883DCxX30sntl/GbyUhg50q7Tq5mXGyzodoFHGTL+bOcU3g5O4MOV\n" +
|
||||
"6HlTFe1dUjyC7M0ah6NaCSsl4SPTxtWjeHMBMhNisInDAO+ju4MJAhgoHuYL6p39\n" +
|
||||
"NDmKSDtpaegFz1Q64C1Ea9fsFwKBgQDPZFvQNjSCm06ObsfXLZKS6IEqgGbihMfM\n" +
|
||||
"cv/HjIpAKXNp/Y6Y/YmdFBpdHDkOJ9BXwJqTuMuM69BuldvNXkkY7zrhPFPawWyF\n" +
|
||||
"O/N1aMNCT89AreBwXMYmgG9yLm1EF1FOuz2oAnWWpcUHBups+cZQikYSQxcOSqrL\n" +
|
||||
"bNTEWffG+QKBgDTk+8lhAGQQ3EY/uwJ6k6oPjp3jamVsHXnMWmWnp/N6vxXeoO+U\n" +
|
||||
"/nfXDyeS4FVDjQXTrwq3TJwsGejJpu+RWvUPiVes+WFz4vdjXDt+1jbYyMLA9Zck\n" +
|
||||
"LlJZRpssNUcIEXWTj6oetct5qymOgbovg93zqr6/fCjGCgsRKnniY8ilAoGAcWGH\n" +
|
||||
"hGQt/v1TTDEqVexXRrOP8iFyngJDjPWN+pVN+9ftfhOeAuwRcOvNofvNAX0ovODS\n" +
|
||||
"YVJVDfzZ3atWGIekZNpdEUg++8hlQM3OwvB8V2N0hgLJQgSmW+Q5iW3yVJh+3hEl\n" +
|
||||
"mxWFHdAQ0E+ql9tR3TRLLK67CxgtGbus8o/RE1kCgYAuf9o6Q++l8H0vNZTnzBNu\n" +
|
||||
"bt0QnLxyh7RuViYuCkzLK+jGftgadVfsRgnOKvxQkMzcXfBgpV5JcVKXtaxDhPxM\n" +
|
||||
"xHwblgOEGlrD4tAwvtPw3GLhmD4Shy8zcT0Lwto81fquskA5yyDGJxbq9CMzWk3w\n" +
|
||||
"dSOT2C7lwW+hkycUio/fTQ==");
|
||||
|
||||
public final String keyAlgo;
|
||||
public final String certStr;
|
||||
public final String keyStr;
|
||||
|
||||
private Cert(String keyAlgo, String certStr, String keyStr) {
|
||||
this.keyAlgo = keyAlgo;
|
||||
this.certStr = certStr;
|
||||
this.keyStr = keyStr;
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user