mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-16 17:14:41 +02:00
8214917: CTW testlibrary shouldn't ignore errors raised by the library itself
Reviewed-by: kvn, roland
This commit is contained in:
parent
bb6f1e7700
commit
5ff302e6bb
17 changed files with 20 additions and 367 deletions
|
@ -453,37 +453,6 @@ JImageLocationRef ClassLoader::jimage_find_resource(JImageFile* jf,
|
|||
return ((*JImageFindResource)(jf, module_name, get_jimage_version_string(), file_name, &size));
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
bool ctw_visitor(JImageFile* jimage,
|
||||
const char* module_name, const char* version, const char* package,
|
||||
const char* name, const char* extension, void* arg) {
|
||||
if (strcmp(extension, "class") == 0) {
|
||||
Thread* THREAD = Thread::current();
|
||||
ResourceMark rm(THREAD);
|
||||
char* path = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, JIMAGE_MAX_PATH);
|
||||
jio_snprintf(path, JIMAGE_MAX_PATH - 1, "%s/%s.class", package, name);
|
||||
ClassLoader::compile_the_world_in(path, *(Handle*)arg, THREAD);
|
||||
return !HAS_PENDING_EXCEPTION;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClassPathImageEntry::compile_the_world(Handle loader, TRAPS) {
|
||||
tty->print_cr("CompileTheWorld : Compiling all classes in %s", name());
|
||||
tty->cr();
|
||||
(*JImageResourceIterator)(_jimage, (JImageResourceVisitor_t)ctw_visitor, (void *)&loader);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
tty->print_cr("\nCompileTheWorld : Ran out of memory\n");
|
||||
tty->print_cr("Increase class metadata storage if a limit was set");
|
||||
} else {
|
||||
tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ClassPathImageEntry::is_modules_image() const {
|
||||
return ClassLoader::is_modules_image(name());
|
||||
}
|
||||
|
@ -1751,247 +1720,6 @@ void ClassLoader::create_javabase() {
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
|
||||
// CompileTheWorld
|
||||
//
|
||||
// Iterates over all class path entries and forces compilation of all methods
|
||||
// in all classes found. Currently, only zip/jar archives are searched.
|
||||
//
|
||||
// The classes are loaded by the Java level bootstrap class loader, and the
|
||||
// initializer is called. If DelayCompilationDuringStartup is true (default),
|
||||
// the interpreter will run the initialization code. Note that forcing
|
||||
// initialization in this way could potentially lead to initialization order
|
||||
// problems, in which case we could just force the initialization bit to be set.
|
||||
|
||||
|
||||
// We need to iterate over the contents of a zip/jar file, so we replicate the
|
||||
// jzcell and jzfile definitions from zip_util.h but rename jzfile to real_jzfile,
|
||||
// since jzfile already has a void* definition.
|
||||
//
|
||||
// Note that this is only used in debug mode.
|
||||
//
|
||||
// HotSpot integration note:
|
||||
// Matches zip_util.h 1.14 99/06/01 from jdk1.3 beta H build
|
||||
|
||||
|
||||
// JDK 1.3 version
|
||||
typedef struct real_jzentry { /* Zip file entry */
|
||||
char *name; /* entry name */
|
||||
jint time; /* modification time */
|
||||
jint size; /* size of uncompressed data */
|
||||
jint csize; /* size of compressed data (zero if uncompressed) */
|
||||
jint crc; /* crc of uncompressed data */
|
||||
char *comment; /* optional zip file comment */
|
||||
jbyte *extra; /* optional extra data */
|
||||
jint pos; /* position of LOC header (if negative) or data */
|
||||
} real_jzentry;
|
||||
|
||||
typedef struct real_jzfile { /* Zip file */
|
||||
char *name; /* zip file name */
|
||||
jint refs; /* number of active references */
|
||||
jint fd; /* open file descriptor */
|
||||
void *lock; /* read lock */
|
||||
char *comment; /* zip file comment */
|
||||
char *msg; /* zip error message */
|
||||
void *entries; /* array of hash cells */
|
||||
jint total; /* total number of entries */
|
||||
unsigned short *table; /* Hash chain heads: indexes into entries */
|
||||
jint tablelen; /* number of hash eads */
|
||||
real_jzfile *next; /* next zip file in search list */
|
||||
jzentry *cache; /* we cache the most recently freed jzentry */
|
||||
/* Information on metadata names in META-INF directory */
|
||||
char **metanames; /* array of meta names (may have null names) */
|
||||
jint metacount; /* number of slots in metanames array */
|
||||
/* If there are any per-entry comments, they are in the comments array */
|
||||
char **comments;
|
||||
} real_jzfile;
|
||||
|
||||
void ClassPathDirEntry::compile_the_world(Handle loader, TRAPS) {
|
||||
// For now we only compile all methods in all classes in zip/jar files
|
||||
tty->print_cr("CompileTheWorld : Skipped classes in %s", _dir);
|
||||
tty->cr();
|
||||
}
|
||||
|
||||
void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) {
|
||||
real_jzfile* zip = (real_jzfile*) _zip;
|
||||
tty->print_cr("CompileTheWorld : Compiling all classes in %s", zip->name);
|
||||
tty->cr();
|
||||
// Iterate over all entries in zip file
|
||||
for (int n = 0; ; n++) {
|
||||
real_jzentry * ze = (real_jzentry *)((*GetNextEntry)(_zip, n));
|
||||
if (ze == NULL) break;
|
||||
ClassLoader::compile_the_world_in(ze->name, loader, CHECK);
|
||||
}
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
tty->print_cr("\nCompileTheWorld : Ran out of memory\n");
|
||||
tty->print_cr("Increase class metadata storage if a limit was set");
|
||||
} else {
|
||||
tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLoader::compile_the_world() {
|
||||
EXCEPTION_MARK;
|
||||
HandleMark hm(THREAD);
|
||||
ResourceMark rm(THREAD);
|
||||
|
||||
assert(has_jrt_entry(), "Compile The World not supported with exploded module build");
|
||||
|
||||
// Find bootstrap loader
|
||||
Handle system_class_loader (THREAD, SystemDictionary::java_system_loader());
|
||||
jlong start = os::javaTimeMillis();
|
||||
|
||||
// Compile the world for the modular java runtime image
|
||||
_jrt_entry->compile_the_world(system_class_loader, CATCH);
|
||||
|
||||
// Iterate over all bootstrap class path appended entries
|
||||
ClassPathEntry* e = _first_append_entry;
|
||||
while (e != NULL) {
|
||||
assert(!e->is_modules_image(), "A modular java runtime image is present on the list of appended entries");
|
||||
e->compile_the_world(system_class_loader, CATCH);
|
||||
e = e->next();
|
||||
}
|
||||
jlong end = os::javaTimeMillis();
|
||||
tty->print_cr("CompileTheWorld : Done (%d classes, %d methods, " JLONG_FORMAT " ms)",
|
||||
_compile_the_world_class_counter, _compile_the_world_method_counter, (end - start));
|
||||
{
|
||||
// Print statistics as if before normal exit:
|
||||
extern void print_statistics();
|
||||
print_statistics();
|
||||
}
|
||||
vm_exit(0);
|
||||
}
|
||||
|
||||
int ClassLoader::_compile_the_world_class_counter = 0;
|
||||
int ClassLoader::_compile_the_world_method_counter = 0;
|
||||
static int _codecache_sweep_counter = 0;
|
||||
|
||||
// Filter out all exceptions except OOMs
|
||||
static void clear_pending_exception_if_not_oom(TRAPS) {
|
||||
if (HAS_PENDING_EXCEPTION &&
|
||||
!PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
}
|
||||
// The CHECK at the caller will propagate the exception out
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the given method should be compiled when doing compile-the-world.
|
||||
*
|
||||
* TODO: This should be a private method in a CompileTheWorld class.
|
||||
*/
|
||||
static bool can_be_compiled(const methodHandle& m, int comp_level) {
|
||||
assert(CompileTheWorld, "must be");
|
||||
|
||||
// It's not valid to compile a native wrapper for MethodHandle methods
|
||||
// that take a MemberName appendix since the bytecode signature is not
|
||||
// correct.
|
||||
vmIntrinsics::ID iid = m->intrinsic_id();
|
||||
if (MethodHandles::is_signature_polymorphic(iid) && MethodHandles::has_member_arg(iid)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return CompilationPolicy::can_be_compiled(m, comp_level);
|
||||
}
|
||||
|
||||
void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) {
|
||||
if (string_ends_with(name, ".class")) {
|
||||
// We have a .class file
|
||||
int len = (int)strlen(name);
|
||||
char buffer[2048];
|
||||
strncpy(buffer, name, len - 6);
|
||||
buffer[len-6] = 0;
|
||||
// If the file has a period after removing .class, it's not really a
|
||||
// valid class file. The class loader will check everything else.
|
||||
if (strchr(buffer, '.') == NULL) {
|
||||
_compile_the_world_class_counter++;
|
||||
if (_compile_the_world_class_counter > CompileTheWorldStopAt) return;
|
||||
|
||||
// Construct name without extension
|
||||
TempNewSymbol sym = SymbolTable::new_symbol(buffer, CHECK);
|
||||
// Use loader to load and initialize class
|
||||
Klass* k = SystemDictionary::resolve_or_null(sym, loader, Handle(), THREAD);
|
||||
if (k != NULL && !HAS_PENDING_EXCEPTION) {
|
||||
k->initialize(THREAD);
|
||||
}
|
||||
bool exception_occurred = HAS_PENDING_EXCEPTION;
|
||||
clear_pending_exception_if_not_oom(CHECK);
|
||||
if (CompileTheWorldPreloadClasses && k != NULL) {
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
ConstantPool::preload_and_initialize_all_classes(ik->constants(), THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
// If something went wrong in preloading we just ignore it
|
||||
clear_pending_exception_if_not_oom(CHECK);
|
||||
tty->print_cr("Preloading failed for (%d) %s", _compile_the_world_class_counter, buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (_compile_the_world_class_counter >= CompileTheWorldStartAt) {
|
||||
if (k == NULL || exception_occurred) {
|
||||
// If something went wrong (e.g. ExceptionInInitializerError) we skip this class
|
||||
tty->print_cr("CompileTheWorld (%d) : Skipping %s", _compile_the_world_class_counter, buffer);
|
||||
} else {
|
||||
tty->print_cr("CompileTheWorld (%d) : %s", _compile_the_world_class_counter, buffer);
|
||||
// Preload all classes to get around uncommon traps
|
||||
// Iterate over all methods in class
|
||||
int comp_level = CompilationPolicy::policy()->initial_compile_level();
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
for (int n = 0; n < ik->methods()->length(); n++) {
|
||||
methodHandle m (THREAD, ik->methods()->at(n));
|
||||
if (can_be_compiled(m, comp_level)) {
|
||||
if (++_codecache_sweep_counter == CompileTheWorldSafepointInterval) {
|
||||
// Give sweeper a chance to keep up with CTW
|
||||
VM_CTWThreshold op;
|
||||
VMThread::execute(&op);
|
||||
_codecache_sweep_counter = 0;
|
||||
}
|
||||
// Force compilation
|
||||
CompileBroker::compile_method(m, InvocationEntryBci, comp_level,
|
||||
methodHandle(), 0, CompileTask::Reason_CTW, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
clear_pending_exception_if_not_oom(CHECK);
|
||||
tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string());
|
||||
} else {
|
||||
_compile_the_world_method_counter++;
|
||||
}
|
||||
if (TieredCompilation && TieredStopAtLevel >= CompLevel_full_optimization) {
|
||||
// Clobber the first compile and force second tier compilation
|
||||
CompiledMethod* nm = m->code();
|
||||
if (nm != NULL && !m->is_method_handle_intrinsic()) {
|
||||
// Throw out the code so that the code cache doesn't fill up
|
||||
nm->make_not_entrant();
|
||||
}
|
||||
CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_full_optimization,
|
||||
methodHandle(), 0, CompileTask::Reason_CTW, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
clear_pending_exception_if_not_oom(CHECK);
|
||||
tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string());
|
||||
} else {
|
||||
_compile_the_world_method_counter++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string());
|
||||
}
|
||||
|
||||
CompiledMethod* nm = m->code();
|
||||
if (nm != NULL && !m->is_method_handle_intrinsic()) {
|
||||
// Throw out the code so that the code cache doesn't fill up
|
||||
nm->make_not_entrant();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif //PRODUCT
|
||||
|
||||
// Please keep following two functions at end of this file. With them placed at top or in middle of the file,
|
||||
// they could get inlined by agressive compiler, an unknown trick, see bug 6966589.
|
||||
void PerfClassTraceTime::initialize() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue