Skip to content
Permalink
Browse files
8262377: Parallel class resolution loses constant pool error
Co-authored-by: Vladimir Ivanov <vlivanov@openjdk.org>
Co-authored-by: Coleen Phillimore <coleenp@openjdk.org>
Co-authored-by: Ioi Lam <iklam@openjdk.org>
Reviewed-by: dholmes, iklam, hseigel, kvn
  • Loading branch information
3 people committed Mar 10, 2021
1 parent b482733 commit 57f16f9fe5b4cf7cdbfeaff11689673cb73cbd03
Show file tree
Hide file tree
Showing 14 changed files with 359 additions and 107 deletions.
@@ -658,6 +658,8 @@ ciConstant ciEnv::get_constant_by_index_impl(const constantPoolHandle& cpool,
assert (constant->is_instance(), "must be an instance, or not? ");
return ciConstant(T_OBJECT, constant);
}
} else if (tag.is_unresolved_klass_in_error()) {
return ciConstant();
} else if (tag.is_klass() || tag.is_unresolved_klass()) {
// 4881222: allow ldc to take a class type
ciKlass* klass = get_klass_by_index_impl(cpool, index, ignore_will_link, accessor);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2021, 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
@@ -233,6 +233,11 @@ class ciBytecodeStream : StackObj {
return tag.is_unresolved_klass();
}

bool is_unresolved_klass_in_error() const {
constantTag tag = get_constant_pool_tag(get_klass_index());
return tag.is_unresolved_klass_in_error();
}

// If this bytecode is one of get_field, get_static, put_field,
// or put_static, get the referenced field.
ciField* get_field(bool& will_link);
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2021, 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
@@ -721,23 +721,28 @@ void ciTypeFlow::StateVector::do_jsr(ciBytecodeStream* str) {
// ciTypeFlow::StateVector::do_ldc
void ciTypeFlow::StateVector::do_ldc(ciBytecodeStream* str) {
ciConstant con = str->get_constant();
BasicType basic_type = con.basic_type();
if (basic_type == T_ILLEGAL) {
// OutOfMemoryError in the CI while loading constant
push_null();
outer()->record_failure("ldc did not link");
return;
}
if (is_reference_type(basic_type)) {
ciObject* obj = con.as_object();
if (obj->is_null_object()) {
push_null();
if (con.is_valid()) {
BasicType basic_type = con.basic_type();
if (is_reference_type(basic_type)) {
ciObject* obj = con.as_object();
if (obj->is_null_object()) {
push_null();
} else {
assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass");
push_object(obj->klass());
}
} else {
assert(obj->is_instance() || obj->is_array(), "must be java_mirror of klass");
push_object(obj->klass());
push_translate(ciType::make(basic_type));
}
} else {
push_translate(ciType::make(basic_type));
if (str->is_unresolved_klass_in_error()) {
trap(str, NULL, Deoptimization::make_trap_request(Deoptimization::Reason_unhandled,
Deoptimization::Action_none));
} else {
// OutOfMemoryError in the CI while loading constant
push_null();
outer()->record_failure("ldc did not link");
}
}
}

@@ -2168,6 +2173,8 @@ bool ciTypeFlow::can_trap(ciBytecodeStream& str) {
case Bytecodes::_ldc:
case Bytecodes::_ldc_w:
case Bytecodes::_ldc2_w:
return str.is_unresolved_klass_in_error();

case Bytecodes::_aload_0:
// These bytecodes can trap for rewriting. We need to assume that
// they do not throw exceptions to make the monitor analysis work.
@@ -1958,13 +1958,15 @@ int java_lang_Throwable::_backtrace_offset;
int java_lang_Throwable::_detailMessage_offset;
int java_lang_Throwable::_stackTrace_offset;
int java_lang_Throwable::_depth_offset;
int java_lang_Throwable::_cause_offset;
int java_lang_Throwable::_static_unassigned_stacktrace_offset;

#define THROWABLE_FIELDS_DO(macro) \
macro(_backtrace_offset, k, "backtrace", object_signature, false); \
macro(_detailMessage_offset, k, "detailMessage", string_signature, false); \
macro(_stackTrace_offset, k, "stackTrace", java_lang_StackTraceElement_array, false); \
macro(_depth_offset, k, "depth", int_signature, false); \
macro(_cause_offset, k, "cause", throwable_signature, false); \
macro(_static_unassigned_stacktrace_offset, k, "UNASSIGNED_STACK", java_lang_StackTraceElement_array, true)

void java_lang_Throwable::compute_offsets() {
@@ -2005,6 +2007,9 @@ oop java_lang_Throwable::message(oop throwable) {
return throwable->obj_field(_detailMessage_offset);
}

oop java_lang_Throwable::cause(oop throwable) {
return throwable->obj_field(_cause_offset);
}

// Return Symbol for detailed_message or NULL
Symbol* java_lang_Throwable::detail_message(oop throwable) {
@@ -499,6 +499,7 @@ class java_lang_Throwable: AllStatic {
static int _detailMessage_offset;
static int _stackTrace_offset;
static int _depth_offset;
static int _cause_offset;
static int _static_unassigned_stacktrace_offset;

// StackTrace (programmatic access, new since 1.4)
@@ -516,6 +517,7 @@ class java_lang_Throwable: AllStatic {
static int get_detailMessage_offset() { CHECK_INIT(_detailMessage_offset); }
// Message
static oop message(oop throwable);
static oop cause(oop throwable);
static void set_message(oop throwable, oop value);
static Symbol* detail_message(oop throwable);
static void print_stack_element(outputStream *st, Method* method, int bci);
@@ -33,27 +33,42 @@
#include "runtime/safepoint.hpp"
#include "utilities/hashtable.inline.hpp"

// add new entry to the table
// create new error entry
void ResolutionErrorTable::add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int cp_index,
Symbol* error, Symbol* message)
Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg)
{
assert_locked_or_safepoint(SystemDictionary_lock);
assert(!pool.is_null() && error != NULL, "adding NULL obj");

ResolutionErrorEntry* entry = new_entry(hash, pool(), cp_index, error, message);
ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::new_entry(hash, pool());
entry->set_cp_index(cp_index);
entry->set_error(error);
entry->set_message(message);
entry->set_nest_host_error(NULL);
entry->set_cause(cause);
entry->set_cause_msg(cause_msg);

add_entry(index, entry);
}

// add new entry to the table
// create new nest host error entry
void ResolutionErrorTable::add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int cp_index,
const char* message)
{
assert_locked_or_safepoint(SystemDictionary_lock);
assert(!pool.is_null() && message != NULL, "adding NULL obj");

ResolutionErrorEntry* entry = new_entry(hash, pool(), cp_index, message);
ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::new_entry(hash, pool());
entry->set_cp_index(cp_index);
entry->set_nest_host_error(message);
entry->set_error(NULL);
entry->set_message(NULL);
entry->set_cause(NULL);
entry->set_cause_msg(NULL);

add_entry(index, entry);
}

@@ -87,35 +102,22 @@ void ResolutionErrorEntry::set_message(Symbol* c) {
}
}

void ResolutionErrorEntry::set_nest_host_error(const char* message) {
_nest_host_error = message;
void ResolutionErrorEntry::set_cause(Symbol* c) {
_cause = c;
if (_cause != NULL) {
_cause->increment_refcount();
}
}

// create new error entry
ResolutionErrorEntry* ResolutionErrorTable::new_entry(int hash, ConstantPool* pool,
int cp_index, Symbol* error,
Symbol* message)
{
ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::new_entry(hash, pool);
entry->set_cp_index(cp_index);
entry->set_error(error);
entry->set_message(message);
entry->set_nest_host_error(NULL);

return entry;
void ResolutionErrorEntry::set_cause_msg(Symbol* c) {
_cause_msg = c;
if (_cause_msg != NULL) {
_cause_msg->increment_refcount();
}
}

// create new nest host error entry
ResolutionErrorEntry* ResolutionErrorTable::new_entry(int hash, ConstantPool* pool,
int cp_index, const char* message)
{
ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::new_entry(hash, pool);
entry->set_cp_index(cp_index);
entry->set_nest_host_error(message);
entry->set_error(NULL);
entry->set_message(NULL);

return entry;
void ResolutionErrorEntry::set_nest_host_error(const char* message) {
_nest_host_error = message;
}

void ResolutionErrorTable::free_entry(ResolutionErrorEntry *entry) {
@@ -126,6 +128,12 @@ void ResolutionErrorTable::free_entry(ResolutionErrorEntry *entry) {
if (entry->message() != NULL) {
entry->message()->decrement_refcount();
}
if (entry->cause() != NULL) {
entry->cause()->decrement_refcount();
}
if (entry->cause_msg() != NULL) {
entry->cause_msg()->decrement_refcount();
}
if (entry->nest_host_error() != NULL) {
FREE_C_HEAP_ARRAY(char, entry->nest_host_error());
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2021, 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
@@ -41,15 +41,12 @@ const int CPCACHE_INDEX_MANGLE_VALUE = 1000000;

class ResolutionErrorTable : public Hashtable<ConstantPool*, mtClass> {

private:
void free_entry(ResolutionErrorEntry *entry);

public:
ResolutionErrorTable(int table_size);

ResolutionErrorEntry* new_entry(int hash, ConstantPool* pool, int cp_index,
Symbol* error, Symbol* message);
ResolutionErrorEntry* new_entry(int hash, ConstantPool* pool, int cp_index,
const char* message);
void free_entry(ResolutionErrorEntry *entry);

ResolutionErrorEntry* bucket(int i) {
return (ResolutionErrorEntry*)Hashtable<ConstantPool*, mtClass>::bucket(i);
}
@@ -64,7 +61,8 @@ class ResolutionErrorTable : public Hashtable<ConstantPool*, mtClass> {
}

void add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int which, Symbol* error, Symbol* message);
const constantPoolHandle& pool, int which, Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg);

void add_entry(int index, unsigned int hash,
const constantPoolHandle& pool, int which, const char* message);
@@ -99,6 +97,8 @@ class ResolutionErrorEntry : public HashtableEntry<ConstantPool*, mtClass> {
int _cp_index;
Symbol* _error;
Symbol* _message;
Symbol* _cause;
Symbol* _cause_msg;
const char* _nest_host_error;

public:
@@ -113,6 +113,12 @@ class ResolutionErrorEntry : public HashtableEntry<ConstantPool*, mtClass> {
Symbol* message() const { return _message; }
void set_message(Symbol* c);

Symbol* cause() const { return _cause; }
void set_cause(Symbol* c);

Symbol* cause_msg() const { return _cause_msg; }
void set_cause_msg(Symbol* c);

const char* nest_host_error() const { return _nest_host_error; }
void set_nest_host_error(const char* message);

@@ -1982,12 +1982,16 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name,
// Add entry to resolution error table to record the error when the first
// attempt to resolve a reference to a class has failed.
void SystemDictionary::add_resolution_error(const constantPoolHandle& pool, int which,
Symbol* error, Symbol* message) {
Symbol* error, Symbol* message,
Symbol* cause, Symbol* cause_msg) {
unsigned int hash = resolution_errors()->compute_hash(pool, which);
int index = resolution_errors()->hash_to_index(hash);
{
MutexLocker ml(Thread::current(), SystemDictionary_lock);
resolution_errors()->add_entry(index, hash, pool, which, error, message);
ResolutionErrorEntry* entry = resolution_errors()->find_entry(index, hash, pool, which);
if (entry == NULL) {
resolution_errors()->add_entry(index, hash, pool, which, error, message, cause, cause_msg);
}
}
}

@@ -1998,14 +2002,16 @@ void SystemDictionary::delete_resolution_error(ConstantPool* pool) {

// Lookup resolution error table. Returns error if found, otherwise NULL.
Symbol* SystemDictionary::find_resolution_error(const constantPoolHandle& pool, int which,
Symbol** message) {
Symbol** message, Symbol** cause, Symbol** cause_msg) {
unsigned int hash = resolution_errors()->compute_hash(pool, which);
int index = resolution_errors()->hash_to_index(hash);
{
MutexLocker ml(Thread::current(), SystemDictionary_lock);
ResolutionErrorEntry* entry = resolution_errors()->find_entry(index, hash, pool, which);
if (entry != NULL) {
*message = entry->message();
*cause = entry->cause();
*cause_msg = entry->cause_msg();
return entry->error();
} else {
return NULL;
@@ -277,10 +277,10 @@ class SystemDictionary : AllStatic {
// Record the error when the first attempt to resolve a reference from a constant
// pool entry to a class fails.
static void add_resolution_error(const constantPoolHandle& pool, int which, Symbol* error,
Symbol* message);
Symbol* message, Symbol* cause = NULL, Symbol* cause_msg = NULL);
static void delete_resolution_error(ConstantPool* pool);
static Symbol* find_resolution_error(const constantPoolHandle& pool, int which,
Symbol** message);
Symbol** message, Symbol** cause, Symbol** cause_msg);


// Record a nest host resolution/validation error
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@@ -535,13 +535,14 @@
template(object_object_signature, "(Ljava/lang/Object;)Ljava/lang/Object;") \
template(string_void_signature, "(Ljava/lang/String;)V") \
template(string_int_signature, "(Ljava/lang/String;)I") \
template(throwable_signature, "Ljava/lang/Throwable;") \
template(throwable_void_signature, "(Ljava/lang/Throwable;)V") \
template(void_throwable_signature, "()Ljava/lang/Throwable;") \
template(throwable_throwable_signature, "(Ljava/lang/Throwable;)Ljava/lang/Throwable;") \
template(class_void_signature, "(Ljava/lang/Class;)V") \
template(class_int_signature, "(Ljava/lang/Class;)I") \
template(class_long_signature, "(Ljava/lang/Class;)J") \
template(class_boolean_signature, "(Ljava/lang/Class;)Z") \
template(throwable_throwable_signature, "(Ljava/lang/Throwable;)Ljava/lang/Throwable;") \
template(throwable_string_void_signature, "(Ljava/lang/Throwable;Ljava/lang/String;)V") \
template(string_array_void_signature, "([Ljava/lang/String;)V") \
template(string_array_string_array_void_signature, "([Ljava/lang/String;[Ljava/lang/String;)V") \

0 comments on commit 57f16f9

Please sign in to comment.