< prev index next > src/hotspot/share/oops/methodData.hpp
Print this page
multi_branch_data_tag,
arg_info_data_tag,
call_type_data_tag,
virtual_call_type_data_tag,
parameters_type_data_tag,
- speculative_trap_data_tag
+ speculative_trap_data_tag,
+ array_store_data_tag,
+ array_load_data_tag,
+ acmp_data_tag
};
enum {
// The trap state breaks down as [recompile:1 | reason:31].
// This further breakdown is defined in deoptimization.cpp.
class BitData;
class CounterData;
class ReceiverTypeData;
class VirtualCallData;
class VirtualCallTypeData;
+ class ArrayStoreData;
class RetData;
class CallTypeData;
class JumpData;
class BranchData;
+ class ACmpData;
class ArrayData;
class MultiBranchData;
class ArgInfoData;
class ParametersTypeData;
class SpeculativeTrapData;
+ class ArrayLoadData;
// ProfileData
//
// A ProfileData object is created to refer to a section of profiling
// data in a structured way.
class ProfileData : public ResourceObj {
friend class TypeEntries;
- friend class ReturnTypeEntry;
+ friend class SingleTypeEntry;
friend class TypeStackSlotEntries;
private:
enum {
tab_width_one = 16,
tab_width_two = 36
virtual bool is_ArgInfoData() const { return false; }
virtual bool is_CallTypeData() const { return false; }
virtual bool is_VirtualCallTypeData()const { return false; }
virtual bool is_ParametersTypeData() const { return false; }
virtual bool is_SpeculativeTrapData()const { return false; }
+ virtual bool is_ArrayStoreData() const { return false; }
+ virtual bool is_ArrayLoadData() const { return false; }
+ virtual bool is_ACmpData() const { return false; }
BitData* as_BitData() const {
assert(is_BitData(), "wrong type");
return is_BitData() ? (BitData*) this : nullptr;
}
SpeculativeTrapData* as_SpeculativeTrapData() const {
assert(is_SpeculativeTrapData(), "wrong type");
return is_SpeculativeTrapData() ? (SpeculativeTrapData*)this : nullptr;
}
+ ArrayStoreData* as_ArrayStoreData() const {
+ assert(is_ArrayStoreData(), "wrong type");
+ return is_ArrayStoreData() ? (ArrayStoreData*)this : nullptr;
+ }
+ ArrayLoadData* as_ArrayLoadData() const {
+ assert(is_ArrayLoadData(), "wrong type");
+ return is_ArrayLoadData() ? (ArrayLoadData*)this : nullptr;
+ }
+ ACmpData* as_ACmpData() const {
+ assert(is_ACmpData(), "wrong type");
+ return is_ACmpData() ? (ACmpData*)this : nullptr;
+ }
// Subclass specific initialization
virtual void post_initialize(BytecodeStream* stream, MethodData* mdo) {}
deprecated_method_callsite_flag = exception_handler_entered_flag + 1
#if INCLUDE_JVMCI
// bytecode threw any exception
, exception_seen_flag = deprecated_method_callsite_flag + 1
#endif
+ , last_bit_data_flag
};
enum { bit_cell_count = 0 }; // no additional data fields needed.
public:
BitData(DataLayout* layout) : ProfileData(layout) {
}
// Accessor
// The null_seen flag bit is specially known to the interpreter.
// Consulting it allows the compiler to avoid setting up null_check traps.
- bool null_seen() { return flag_at(null_seen_flag); }
+ bool null_seen() const { return flag_at(null_seen_flag); }
void set_null_seen() { set_flag_at(null_seen_flag); }
bool deprecated_method_call_site() const { return flag_at(deprecated_method_callsite_flag); }
bool set_deprecated_method_call_site() { return data()->set_flag_at(deprecated_method_callsite_flag); }
bool clear_deprecated_method_call_site() { return data()->clear_flag_at(deprecated_method_callsite_flag); }
}
public:
JumpData(DataLayout* layout) : ProfileData(layout) {
assert(layout->tag() == DataLayout::jump_data_tag ||
- layout->tag() == DataLayout::branch_data_tag, "wrong type");
+ layout->tag() == DataLayout::branch_data_tag ||
+ layout->tag() == DataLayout::acmp_data_tag, "wrong type");
}
virtual bool is_JumpData() const { return true; }
static int static_cell_count() {
void print_data_on(outputStream* st) const;
};
// Type entry used for return from a call. A single cell to record the
// type.
- class ReturnTypeEntry : public TypeEntries {
+ class SingleTypeEntry : public TypeEntries {
private:
enum {
cell_count = 1
};
public:
- ReturnTypeEntry(int base_off)
+ SingleTypeEntry(int base_off)
: TypeEntries(base_off) {}
void post_initialize() {
set_type(type_none());
}
void print_data_on(outputStream* st) const;
};
// Entries to collect type information at a call: contains arguments
- // (TypeStackSlotEntries), a return type (ReturnTypeEntry) and a
+ // (TypeStackSlotEntries), a return type (SingleTypeEntry) and a
// number of cells. Because the number of cells for the return type is
// smaller than the number of cells for the type of an arguments, the
// number of cells is used to tell how many arguments are profiled and
// whether a return value is profiled. See has_arguments() and
// has_return().
static ByteSize argument_type_offset(int i) {
return in_ByteSize(argument_type_local_offset(i) * DataLayout::cell_size);
}
static ByteSize return_only_size() {
- return ReturnTypeEntry::size() + in_ByteSize(header_cell_count() * DataLayout::cell_size);
+ return SingleTypeEntry::size() + in_ByteSize(header_cell_count() * DataLayout::cell_size);
}
};
// CallTypeData
class CallTypeData : public CounterData {
private:
// entries for arguments if any
TypeStackSlotEntries _args;
// entry for return type if any
- ReturnTypeEntry _ret;
+ SingleTypeEntry _ret;
int cell_count_global_offset() const {
return CounterData::static_cell_count() + TypeEntriesAtCall::cell_count_local_offset();
}
public:
CallTypeData(DataLayout* layout) :
CounterData(layout),
_args(CounterData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()),
- _ret(cell_count() - ReturnTypeEntry::static_cell_count())
+ _ret(cell_count() - SingleTypeEntry::static_cell_count())
{
assert(layout->tag() == DataLayout::call_type_data_tag, "wrong type");
// Some compilers (VC++) don't want this passed in member initialization list
_args.set_profile_data(this);
_ret.set_profile_data(this);
const TypeStackSlotEntries* args() const {
assert(has_arguments(), "no profiling of arguments");
return &_args;
}
- const ReturnTypeEntry* ret() const {
+ const SingleTypeEntry* ret() const {
assert(has_return(), "no profiling of return value");
return &_ret;
}
virtual bool is_CallTypeData() const { return true; }
public:
ReceiverTypeData(DataLayout* layout) : CounterData(layout) {
assert(layout->tag() == DataLayout::receiver_type_data_tag ||
layout->tag() == DataLayout::virtual_call_data_tag ||
- layout->tag() == DataLayout::virtual_call_type_data_tag, "wrong type");
+ layout->tag() == DataLayout::virtual_call_type_data_tag ||
+ layout->tag() == DataLayout::array_store_data_tag, "wrong type");
}
virtual bool is_ReceiverTypeData() const { return true; }
static int static_cell_count() {
class VirtualCallTypeData : public VirtualCallData {
private:
// entries for arguments if any
TypeStackSlotEntries _args;
// entry for return type if any
- ReturnTypeEntry _ret;
+ SingleTypeEntry _ret;
int cell_count_global_offset() const {
return VirtualCallData::static_cell_count() + TypeEntriesAtCall::cell_count_local_offset();
}
public:
VirtualCallTypeData(DataLayout* layout) :
VirtualCallData(layout),
_args(VirtualCallData::static_cell_count()+TypeEntriesAtCall::header_cell_count(), number_of_arguments()),
- _ret(cell_count() - ReturnTypeEntry::static_cell_count())
+ _ret(cell_count() - SingleTypeEntry::static_cell_count())
{
assert(layout->tag() == DataLayout::virtual_call_type_data_tag, "wrong type");
// Some compilers (VC++) don't want this passed in member initialization list
_args.set_profile_data(this);
_ret.set_profile_data(this);
const TypeStackSlotEntries* args() const {
assert(has_arguments(), "no profiling of arguments");
return &_args;
}
- const ReturnTypeEntry* ret() const {
+ const SingleTypeEntry* ret() const {
assert(has_return(), "no profiling of return value");
return &_ret;
}
virtual bool is_VirtualCallTypeData() const { return true; }
set_int_at(displacement_off_set, displacement);
}
public:
BranchData(DataLayout* layout) : JumpData(layout) {
- assert(layout->tag() == DataLayout::branch_data_tag, "wrong type");
+ assert(layout->tag() == DataLayout::branch_data_tag || layout->tag() == DataLayout::acmp_data_tag, "wrong type");
}
virtual bool is_BranchData() const { return true; }
static int static_cell_count() {
}
virtual void print_data_on(outputStream* st, const char* extra = nullptr) const;
};
+ class ArrayStoreData : public ReceiverTypeData {
+ private:
+ enum {
+ flat_array_flag = BitData::last_bit_data_flag,
+ null_free_array_flag = flat_array_flag + 1,
+ };
+
+ SingleTypeEntry _array;
+
+ public:
+ ArrayStoreData(DataLayout* layout) :
+ ReceiverTypeData(layout),
+ _array(ReceiverTypeData::static_cell_count()) {
+ assert(layout->tag() == DataLayout::array_store_data_tag, "wrong type");
+ _array.set_profile_data(this);
+ }
+
+ const SingleTypeEntry* array() const {
+ return &_array;
+ }
+
+ virtual bool is_ArrayStoreData() const { return true; }
+
+ static int static_cell_count() {
+ return ReceiverTypeData::static_cell_count() + SingleTypeEntry::static_cell_count();
+ }
+
+ virtual int cell_count() const {
+ return static_cell_count();
+ }
+
+ void set_flat_array() { set_flag_at(flat_array_flag); }
+ bool flat_array() const { return flag_at(flat_array_flag); }
+
+ void set_null_free_array() { set_flag_at(null_free_array_flag); }
+ bool null_free_array() const { return flag_at(null_free_array_flag); }
+
+ // Code generation support
+ static int flat_array_byte_constant() {
+ return flag_number_to_constant(flat_array_flag);
+ }
+
+ static int null_free_array_byte_constant() {
+ return flag_number_to_constant(null_free_array_flag);
+ }
+
+ static ByteSize array_offset() {
+ return cell_offset(ReceiverTypeData::static_cell_count());
+ }
+
+ virtual void clean_weak_klass_links(bool always_clean) {
+ ReceiverTypeData::clean_weak_klass_links(always_clean);
+ _array.clean_weak_klass_links(always_clean);
+ }
+
+ static ByteSize array_store_data_size() {
+ return cell_offset(static_cell_count());
+ }
+
+ virtual void print_data_on(outputStream* st, const char* extra = nullptr) const;
+ };
+
+ class ArrayLoadData : public ProfileData {
+ private:
+ enum {
+ flat_array_flag = DataLayout::first_flag,
+ null_free_array_flag = flat_array_flag + 1,
+ };
+
+ SingleTypeEntry _array;
+ SingleTypeEntry _element;
+
+ public:
+ ArrayLoadData(DataLayout* layout) :
+ ProfileData(layout),
+ _array(0),
+ _element(SingleTypeEntry::static_cell_count()) {
+ assert(layout->tag() == DataLayout::array_load_data_tag, "wrong type");
+ _array.set_profile_data(this);
+ _element.set_profile_data(this);
+ }
+
+ const SingleTypeEntry* array() const {
+ return &_array;
+ }
+
+ const SingleTypeEntry* element() const {
+ return &_element;
+ }
+
+ virtual bool is_ArrayLoadData() const { return true; }
+
+ static int static_cell_count() {
+ return SingleTypeEntry::static_cell_count() * 2;
+ }
+
+ virtual int cell_count() const {
+ return static_cell_count();
+ }
+
+ void set_flat_array() { set_flag_at(flat_array_flag); }
+ bool flat_array() const { return flag_at(flat_array_flag); }
+
+ void set_null_free_array() { set_flag_at(null_free_array_flag); }
+ bool null_free_array() const { return flag_at(null_free_array_flag); }
+
+ // Code generation support
+ static int flat_array_byte_constant() {
+ return flag_number_to_constant(flat_array_flag);
+ }
+
+ static int null_free_array_byte_constant() {
+ return flag_number_to_constant(null_free_array_flag);
+ }
+
+ static ByteSize array_offset() {
+ return cell_offset(0);
+ }
+
+ static ByteSize element_offset() {
+ return cell_offset(SingleTypeEntry::static_cell_count());
+ }
+
+ virtual void clean_weak_klass_links(bool always_clean) {
+ _array.clean_weak_klass_links(always_clean);
+ _element.clean_weak_klass_links(always_clean);
+ }
+
+ static ByteSize array_load_data_size() {
+ return cell_offset(static_cell_count());
+ }
+
+ virtual void print_data_on(outputStream* st, const char* extra = nullptr) const;
+ };
+
+ class ACmpData : public BranchData {
+ private:
+ enum {
+ left_inline_type_flag = DataLayout::first_flag,
+ right_inline_type_flag
+ };
+
+ SingleTypeEntry _left;
+ SingleTypeEntry _right;
+
+ public:
+ ACmpData(DataLayout* layout) :
+ BranchData(layout),
+ _left(BranchData::static_cell_count()),
+ _right(BranchData::static_cell_count() + SingleTypeEntry::static_cell_count()) {
+ assert(layout->tag() == DataLayout::acmp_data_tag, "wrong type");
+ _left.set_profile_data(this);
+ _right.set_profile_data(this);
+ }
+
+ const SingleTypeEntry* left() const {
+ return &_left;
+ }
+
+ const SingleTypeEntry* right() const {
+ return &_right;
+ }
+
+ virtual bool is_ACmpData() const { return true; }
+
+ static int static_cell_count() {
+ return BranchData::static_cell_count() + SingleTypeEntry::static_cell_count() * 2;
+ }
+
+ virtual int cell_count() const {
+ return static_cell_count();
+ }
+
+ void set_left_inline_type() { set_flag_at(left_inline_type_flag); }
+ bool left_inline_type() const { return flag_at(left_inline_type_flag); }
+
+ void set_right_inline_type() { set_flag_at(right_inline_type_flag); }
+ bool right_inline_type() const { return flag_at(right_inline_type_flag); }
+
+ // Code generation support
+ static int left_inline_type_byte_constant() {
+ return flag_number_to_constant(left_inline_type_flag);
+ }
+
+ static int right_inline_type_byte_constant() {
+ return flag_number_to_constant(right_inline_type_flag);
+ }
+
+ static ByteSize left_offset() {
+ return cell_offset(BranchData::static_cell_count());
+ }
+
+ static ByteSize right_offset() {
+ return cell_offset(BranchData::static_cell_count() + SingleTypeEntry::static_cell_count());
+ }
+
+ virtual void clean_weak_klass_links(bool always_clean) {
+ _left.clean_weak_klass_links(always_clean);
+ _right.clean_weak_klass_links(always_clean);
+ }
+
+ static ByteSize acmp_data_size() {
+ return cell_offset(static_cell_count());
+ }
+
+ virtual void print_data_on(outputStream* st, const char* extra = nullptr) const;
+ };
+
// MethodData*
//
// A MethodData* holds information which has been collected about
// a method. Its layout looks like this:
//
< prev index next >