mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-23 20:44:41 +02:00
8141132: JEP 254: Compact Strings
Adopt a more space-efficient internal representation for strings. Co-authored-by: Brent Christian <brent.christian@oracle.com> Co-authored-by: Vivek Deshpande <vivek.r.deshpande@intel.com> Co-authored-by: Charlie Hunt <charlie.hunt@oracle.com> Co-authored-by: Vladimir Kozlov <vladimir.kozlov@oracle.com> Co-authored-by: Roger Riggs <roger.riggs@oracle.com> Co-authored-by: Xueming Shen <xueming.shen@oracle.com> Co-authored-by: Aleksey Shipilev <aleksey.shipilev@oracle.com> Co-authored-by: Sandhya Viswanathan <sandhya.viswanathan@intel.com> Reviewed-by: alanb, bdelsart, coleenp, iklam, jiangli, jrose, kevinw, naoto, pliden, roland, smarks, twisti
This commit is contained in:
parent
4e24e2cc6c
commit
7af927f9c1
74 changed files with 4838 additions and 1683 deletions
|
@ -4266,35 +4266,11 @@ void GraphKit::g1_write_barrier_post(Node* oop_store,
|
|||
#undef __
|
||||
|
||||
|
||||
|
||||
Node* GraphKit::load_String_offset(Node* ctrl, Node* str) {
|
||||
if (java_lang_String::has_offset_field()) {
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* offset_field_type = string_type->add_offset(offset_offset);
|
||||
int offset_field_idx = C->get_alias_index(offset_field_type);
|
||||
return make_load(ctrl,
|
||||
basic_plus_adr(str, str, offset_offset),
|
||||
TypeInt::INT, T_INT, offset_field_idx, MemNode::unordered);
|
||||
} else {
|
||||
return intcon(0);
|
||||
}
|
||||
}
|
||||
|
||||
Node* GraphKit::load_String_length(Node* ctrl, Node* str) {
|
||||
if (java_lang_String::has_count_field()) {
|
||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* count_field_type = string_type->add_offset(count_offset);
|
||||
int count_field_idx = C->get_alias_index(count_field_type);
|
||||
return make_load(ctrl,
|
||||
basic_plus_adr(str, str, count_offset),
|
||||
TypeInt::INT, T_INT, count_field_idx, MemNode::unordered);
|
||||
} else {
|
||||
return load_array_length(load_String_value(ctrl, str));
|
||||
}
|
||||
Node* len = load_array_length(load_String_value(ctrl, str));
|
||||
Node* coder = load_String_coder(ctrl, str);
|
||||
// Divide length by 2 if coder is UTF16
|
||||
return _gvn.transform(new RShiftINode(len, coder));
|
||||
}
|
||||
|
||||
Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
|
||||
|
@ -4302,9 +4278,9 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
|
|||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* value_field_type = string_type->add_offset(value_offset);
|
||||
const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull,
|
||||
TypeAry::make(TypeInt::CHAR,TypeInt::POS),
|
||||
ciTypeArrayKlass::make(T_CHAR), true, 0);
|
||||
const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull,
|
||||
TypeAry::make(TypeInt::BYTE, TypeInt::POS),
|
||||
ciTypeArrayKlass::make(T_BYTE), true, 0);
|
||||
int value_field_idx = C->get_alias_index(value_field_type);
|
||||
Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset),
|
||||
value_type, T_OBJECT, value_field_idx, MemNode::unordered);
|
||||
|
@ -4315,14 +4291,21 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
|
|||
return load;
|
||||
}
|
||||
|
||||
void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) {
|
||||
int offset_offset = java_lang_String::offset_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* offset_field_type = string_type->add_offset(offset_offset);
|
||||
int offset_field_idx = C->get_alias_index(offset_field_type);
|
||||
store_to_memory(ctrl, basic_plus_adr(str, offset_offset),
|
||||
value, T_INT, offset_field_idx, MemNode::unordered);
|
||||
Node* GraphKit::load_String_coder(Node* ctrl, Node* str) {
|
||||
if (java_lang_String::has_coder_field()) {
|
||||
if (!CompactStrings) {
|
||||
return intcon(java_lang_String::CODER_UTF16);
|
||||
}
|
||||
int coder_offset = java_lang_String::coder_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
|
||||
int coder_field_idx = C->get_alias_index(coder_field_type);
|
||||
return make_load(ctrl, basic_plus_adr(str, str, coder_offset),
|
||||
TypeInt::BYTE, T_BYTE, coder_field_idx, MemNode::unordered);
|
||||
} else {
|
||||
return intcon(0); // false
|
||||
}
|
||||
}
|
||||
|
||||
void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
|
||||
|
@ -4330,19 +4313,76 @@ void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
|
|||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* value_field_type = string_type->add_offset(value_offset);
|
||||
|
||||
store_oop_to_object(ctrl, str, basic_plus_adr(str, value_offset), value_field_type,
|
||||
value, TypeAryPtr::CHARS, T_OBJECT, MemNode::unordered);
|
||||
value, TypeAryPtr::BYTES, T_OBJECT, MemNode::unordered);
|
||||
}
|
||||
|
||||
void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
|
||||
int count_offset = java_lang_String::count_offset_in_bytes();
|
||||
void GraphKit::store_String_coder(Node* ctrl, Node* str, Node* value) {
|
||||
int coder_offset = java_lang_String::coder_offset_in_bytes();
|
||||
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
|
||||
false, NULL, 0);
|
||||
const TypePtr* count_field_type = string_type->add_offset(count_offset);
|
||||
int count_field_idx = C->get_alias_index(count_field_type);
|
||||
store_to_memory(ctrl, basic_plus_adr(str, count_offset),
|
||||
value, T_INT, count_field_idx, MemNode::unordered);
|
||||
const TypePtr* coder_field_type = string_type->add_offset(coder_offset);
|
||||
int coder_field_idx = C->get_alias_index(coder_field_type);
|
||||
store_to_memory(ctrl, basic_plus_adr(str, coder_offset),
|
||||
value, T_BYTE, coder_field_idx, MemNode::unordered);
|
||||
}
|
||||
|
||||
Node* GraphKit::compress_string(Node* src, Node* dst, Node* count) {
|
||||
assert(Matcher::match_rule_supported(Op_StrCompressedCopy), "Intrinsic not supported");
|
||||
uint idx = C->get_alias_index(TypeAryPtr::BYTES);
|
||||
StrCompressedCopyNode* str = new StrCompressedCopyNode(control(), memory(idx), src, dst, count);
|
||||
Node* res_mem = _gvn.transform(new SCMemProjNode(str));
|
||||
set_memory(res_mem, idx);
|
||||
return str;
|
||||
}
|
||||
|
||||
void GraphKit::inflate_string(Node* src, Node* dst, Node* count) {
|
||||
assert(Matcher::match_rule_supported(Op_StrInflatedCopy), "Intrinsic not supported");
|
||||
uint idx = C->get_alias_index(TypeAryPtr::BYTES);
|
||||
StrInflatedCopyNode* str = new StrInflatedCopyNode(control(), memory(idx), src, dst, count);
|
||||
set_memory(_gvn.transform(str), idx);
|
||||
}
|
||||
|
||||
void GraphKit::inflate_string_slow(Node* src, Node* dst, Node* start, Node* count) {
|
||||
/**
|
||||
* int i_char = start;
|
||||
* for (int i_byte = 0; i_byte < count; i_byte++) {
|
||||
* dst[i_char++] = (char)(src[i_byte] & 0xff);
|
||||
* }
|
||||
*/
|
||||
add_predicate();
|
||||
RegionNode* head = new RegionNode(3);
|
||||
head->init_req(1, control());
|
||||
gvn().set_type(head, Type::CONTROL);
|
||||
record_for_igvn(head);
|
||||
|
||||
Node* i_byte = new PhiNode(head, TypeInt::INT);
|
||||
i_byte->init_req(1, intcon(0));
|
||||
gvn().set_type(i_byte, TypeInt::INT);
|
||||
record_for_igvn(i_byte);
|
||||
|
||||
Node* i_char = new PhiNode(head, TypeInt::INT);
|
||||
i_char->init_req(1, start);
|
||||
gvn().set_type(i_char, TypeInt::INT);
|
||||
record_for_igvn(i_char);
|
||||
|
||||
Node* mem = PhiNode::make(head, memory(TypeAryPtr::BYTES), Type::MEMORY, TypeAryPtr::BYTES);
|
||||
gvn().set_type(mem, Type::MEMORY);
|
||||
record_for_igvn(mem);
|
||||
set_control(head);
|
||||
set_memory(mem, TypeAryPtr::BYTES);
|
||||
Node* ch = load_array_element(control(), src, i_byte, TypeAryPtr::BYTES);
|
||||
Node* st = store_to_memory(control(), array_element_address(dst, i_char, T_BYTE),
|
||||
AndI(ch, intcon(0xff)), T_CHAR, TypeAryPtr::BYTES, MemNode::unordered);
|
||||
|
||||
IfNode* iff = create_and_map_if(head, Bool(CmpI(i_byte, count), BoolTest::lt), PROB_FAIR, COUNT_UNKNOWN);
|
||||
head->init_req(2, IfTrue(iff));
|
||||
mem->init_req(2, st);
|
||||
i_byte->init_req(2, AddI(i_byte, intcon(1)));
|
||||
i_char->init_req(2, AddI(i_char, intcon(2)));
|
||||
|
||||
set_control(IfFalse(iff));
|
||||
set_memory(st, TypeAryPtr::BYTES);
|
||||
}
|
||||
|
||||
Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue