提交 277b14e0 编写于 作者: K kvn

6924259: Remove String.count/String.offset

Summary: Allow a version of String class that doesn't have count and offset fields.
Reviewed-by: never, coleenp
上级 d524aa32
/*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2012, 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
......@@ -238,9 +238,12 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst
Register result = dst->as_register();
{
// Get a pointer to the first character of string0 in tmp0 and get string0.count in str0
// Get a pointer to the first character of string1 in tmp1 and get string1.count in str1
// Also, get string0.count-string1.count in o7 and get the condition code set
// Get a pointer to the first character of string0 in tmp0
// and get string0.length() in str0
// Get a pointer to the first character of string1 in tmp1
// and get string1.length() in str1
// Also, get string0.length()-string1.length() in
// o7 and get the condition code set
// Note: some instructions have been hoisted for better instruction scheduling
Register tmp0 = L0;
......@@ -248,27 +251,40 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst
Register tmp2 = L2;
int value_offset = java_lang_String:: value_offset_in_bytes(); // char array
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
int count_offset = java_lang_String:: count_offset_in_bytes();
__ load_heap_oop(str0, value_offset, tmp0);
__ ld(str0, offset_offset, tmp2);
__ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
__ ld(str0, count_offset, str0);
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
if (java_lang_String::has_offset_field()) {
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
int count_offset = java_lang_String:: count_offset_in_bytes();
__ load_heap_oop(str0, value_offset, tmp0);
__ ld(str0, offset_offset, tmp2);
__ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
__ ld(str0, count_offset, str0);
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
} else {
__ load_heap_oop(str0, value_offset, tmp1);
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
__ ld(tmp1, arrayOopDesc::length_offset_in_bytes(), str0);
}
// str1 may be null
add_debug_info_for_null_check_here(info);
__ load_heap_oop(str1, value_offset, tmp1);
__ add(tmp0, tmp2, tmp0);
__ ld(str1, offset_offset, tmp2);
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
__ ld(str1, count_offset, str1);
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
if (java_lang_String::has_offset_field()) {
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
int count_offset = java_lang_String:: count_offset_in_bytes();
__ load_heap_oop(str1, value_offset, tmp1);
__ add(tmp0, tmp2, tmp0);
__ ld(str1, offset_offset, tmp2);
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
__ ld(str1, count_offset, str1);
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
__ add(tmp1, tmp2, tmp1);
} else {
__ load_heap_oop(str1, value_offset, tmp2);
__ add(tmp2, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
__ ld(tmp2, arrayOopDesc::length_offset_in_bytes(), str1);
}
__ subcc(str0, str1, O7);
__ add(tmp1, tmp2, tmp1);
}
{
......@@ -302,7 +318,7 @@ void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst
// Shift base0 and base1 to the end of the arrays, negate limit
__ add(base0, limit, base0);
__ add(base1, limit, base1);
__ neg(limit); // limit = -min{string0.count, strin1.count}
__ neg(limit); // limit = -min{string0.length(), string1.length()}
__ lduh(base0, limit, chr0);
__ bind(Lloop);
......
/*
* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 2012, 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
......@@ -505,19 +505,28 @@ void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst,
// Get addresses of first characters from both Strings
__ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes()));
__ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
__ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
if (java_lang_String::has_offset_field()) {
__ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
__ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
__ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
} else {
__ movl (rax, Address(rsi, arrayOopDesc::length_offset_in_bytes()));
__ lea (rsi, Address(rsi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
}
// rbx, may be NULL
add_debug_info_for_null_check_here(info);
__ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes()));
__ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
__ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
if (java_lang_String::has_offset_field()) {
__ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
__ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
__ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
} else {
__ movl (rbx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));
__ lea (rdi, Address(rdi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
}
// compute minimum length (in rax) and difference of lengths (on top of stack)
__ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
__ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
__ mov (rcx, rbx);
__ subptr(rbx, rax); // subtract lengths
__ push (rbx); // result
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2012, 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
......@@ -143,7 +143,27 @@ compute_optional_offset(int& dest_offset,
}
int java_lang_String::value_offset = 0;
int java_lang_String::offset_offset = 0;
int java_lang_String::count_offset = 0;
int java_lang_String::hash_offset = 0;
bool java_lang_String::initialized = false;
void java_lang_String::compute_offsets() {
assert(!initialized, "offsets should be initialized only once");
klassOop k = SystemDictionary::String_klass();
compute_offset(value_offset, k, vmSymbols::value_name(), vmSymbols::char_array_signature());
compute_optional_offset(offset_offset, k, vmSymbols::offset_name(), vmSymbols::int_signature());
compute_optional_offset(count_offset, k, vmSymbols::count_name(), vmSymbols::int_signature());
compute_optional_offset(hash_offset, k, vmSymbols::hash_name(), vmSymbols::int_signature());
initialized = true;
}
Handle java_lang_String::basic_create(int length, bool tenured, TRAPS) {
assert(initialized, "Must be initialized");
// Create the String object first, so there's a chance that the String
// and the char array it points to end up in the same cache line.
oop obj;
......@@ -2837,10 +2857,6 @@ int java_lang_System::err_offset_in_bytes() {
int java_lang_String::value_offset;
int java_lang_String::offset_offset;
int java_lang_String::count_offset;
int java_lang_String::hash_offset;
int java_lang_Class::_klass_offset;
int java_lang_Class::_array_klass_offset;
int java_lang_Class::_resolved_constructor_offset;
......@@ -3000,12 +3016,6 @@ void JavaClasses::compute_hard_coded_offsets() {
const int x = heapOopSize;
const int header = instanceOopDesc::base_offset_in_bytes();
// Do the String Class
java_lang_String::value_offset = java_lang_String::hc_value_offset * x + header;
java_lang_String::offset_offset = java_lang_String::hc_offset_offset * x + header;
java_lang_String::count_offset = java_lang_String::offset_offset + sizeof (jint);
java_lang_String::hash_offset = java_lang_String::count_offset + sizeof (jint);
// Throwable Class
java_lang_Throwable::backtrace_offset = java_lang_Throwable::hc_backtrace_offset * x + header;
java_lang_Throwable::detailMessage_offset = java_lang_Throwable::hc_detailMessage_offset * x + header;
......@@ -3200,9 +3210,13 @@ void JavaClasses::check_offsets() {
// java.lang.String
CHECK_OFFSET("java/lang/String", java_lang_String, value, "[C");
CHECK_OFFSET("java/lang/String", java_lang_String, offset, "I");
CHECK_OFFSET("java/lang/String", java_lang_String, count, "I");
CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
if (java_lang_String::has_offset_field()) {
CHECK_OFFSET("java/lang/String", java_lang_String, offset, "I");
CHECK_OFFSET("java/lang/String", java_lang_String, count, "I");
}
if (java_lang_String::has_hash_field()) {
CHECK_OFFSET("java/lang/String", java_lang_String, hash, "I");
}
// java.lang.Class
......
/*
* Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2012, 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
......@@ -52,26 +52,36 @@
class java_lang_String : AllStatic {
private:
enum {
hc_value_offset = 0,
hc_offset_offset = 1
//hc_count_offset = 2 -- not a word-scaled offset
//hc_hash_offset = 3 -- not a word-scaled offset
};
static int value_offset;
static int offset_offset;
static int count_offset;
static int hash_offset;
static bool initialized;
static Handle basic_create(int length, bool tenured, TRAPS);
static Handle basic_create_from_unicode(jchar* unicode, int length, bool tenured, TRAPS);
static void set_value( oop string, typeArrayOop buffer) { string->obj_field_put(value_offset, (oop)buffer); }
static void set_offset(oop string, int offset) { string->int_field_put(offset_offset, offset); }
static void set_count( oop string, int count) { string->int_field_put(count_offset, count); }
static void set_value( oop string, typeArrayOop buffer) {
assert(initialized, "Must be initialized");
string->obj_field_put(value_offset, (oop)buffer);
}
static void set_offset(oop string, int offset) {
assert(initialized, "Must be initialized");
if (offset_offset > 0) {
string->int_field_put(offset_offset, offset);
}
}
static void set_count( oop string, int count) {
assert(initialized, "Must be initialized");
if (count_offset > 0) {
string->int_field_put(count_offset, count);
}
}
public:
static void compute_offsets();
// Instance creation
static Handle create_from_unicode(jchar* unicode, int len, TRAPS);
static Handle create_tenured_from_unicode(jchar* unicode, int len, TRAPS);
......@@ -82,23 +92,61 @@ class java_lang_String : AllStatic {
static Handle create_from_platform_dependent_str(const char* str, TRAPS);
static Handle char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS);
static int value_offset_in_bytes() { return value_offset; }
static int count_offset_in_bytes() { return count_offset; }
static int offset_offset_in_bytes() { return offset_offset; }
static int hash_offset_in_bytes() { return hash_offset; }
static bool has_offset_field() {
assert(initialized, "Must be initialized");
return (offset_offset > 0);
}
static bool has_count_field() {
assert(initialized, "Must be initialized");
return (count_offset > 0);
}
static bool has_hash_field() {
assert(initialized, "Must be initialized");
return (hash_offset > 0);
}
static int value_offset_in_bytes() {
assert(initialized && (value_offset > 0), "Must be initialized");
return value_offset;
}
static int count_offset_in_bytes() {
assert(initialized && (count_offset > 0), "Must be initialized");
return count_offset;
}
static int offset_offset_in_bytes() {
assert(initialized && (offset_offset > 0), "Must be initialized");
return offset_offset;
}
static int hash_offset_in_bytes() {
assert(initialized && (hash_offset > 0), "Must be initialized");
return hash_offset;
}
// Accessors
static typeArrayOop value(oop java_string) {
assert(initialized && (value_offset > 0), "Must be initialized");
assert(is_instance(java_string), "must be java_string");
return (typeArrayOop) java_string->obj_field(value_offset);
}
static int offset(oop java_string) {
assert(initialized, "Must be initialized");
assert(is_instance(java_string), "must be java_string");
return java_string->int_field(offset_offset);
if (offset_offset > 0) {
return java_string->int_field(offset_offset);
} else {
return 0;
}
}
static int length(oop java_string) {
assert(initialized, "Must be initialized");
assert(is_instance(java_string), "must be java_string");
return java_string->int_field(count_offset);
if (count_offset > 0) {
return java_string->int_field(count_offset);
} else {
return ((typeArrayOop)java_string->obj_field(value_offset))->length();
}
}
static int utf8_length(oop java_string);
......
......@@ -1971,6 +1971,9 @@ void SystemDictionary::initialize_preloaded_classes(TRAPS) {
// first do Object, String, Class
initialize_wk_klasses_through(WK_KLASS_ENUM_NAME(Class_klass), scan, CHECK);
// Calculate offsets for String and Class classes since they are loaded and
// can be used after this point.
java_lang_String::compute_offsets();
java_lang_Class::compute_offsets();
// Fixup mirrors for classes loaded before java.lang.Class.
......
......@@ -340,6 +340,9 @@
template(park_event_name, "nativeParkEventPointer") \
template(cache_field_name, "cache") \
template(value_name, "value") \
template(offset_name, "offset") \
template(count_name, "count") \
template(hash_name, "hash") \
template(frontCacheEnabled_name, "frontCacheEnabled") \
template(stringCacheEnabled_name, "stringCacheEnabled") \
template(numberOfLeadingZeros_name, "numberOfLeadingZeros") \
......
......@@ -78,8 +78,8 @@ public:
void do_oop(oop* p) {
if (p != NULL) {
oop obj = *p;
if (obj->klass() == SystemDictionary::String_klass()) {
if (obj->klass() == SystemDictionary::String_klass() &&
java_lang_String::has_hash_field()) {
int hash = java_lang_String::hash_string(obj);
obj->int_field_put(hash_offset, hash);
}
......
/*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2012, 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
......@@ -3748,3 +3748,81 @@ void GraphKit::g1_write_barrier_post(Node* oop_store,
final_sync(ideal);
}
#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);
} 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);
} else {
return load_array_length(load_String_value(ctrl, str));
}
}
Node* GraphKit::load_String_value(Node* ctrl, Node* str) {
int value_offset = java_lang_String::value_offset_in_bytes();
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);
int value_field_idx = C->get_alias_index(value_field_type);
return make_load(ctrl, basic_plus_adr(str, str, value_offset),
value_type, T_OBJECT, value_field_idx);
}
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);
}
void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) {
int value_offset = java_lang_String::value_offset_in_bytes();
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);
int value_field_idx = C->get_alias_index(value_field_type);
store_to_memory(ctrl, basic_plus_adr(str, value_offset),
value, T_OBJECT, value_field_idx);
}
void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) {
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);
store_to_memory(ctrl, basic_plus_adr(str, count_offset),
value, T_INT, count_field_idx);
}
/*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2012, 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
......@@ -781,6 +781,14 @@ class GraphKit : public Phase {
Node* new_array(Node* klass_node, Node* count_val, int nargs,
Node* *return_size_val = NULL);
// java.lang.String helpers
Node* load_String_offset(Node* ctrl, Node* str);
Node* load_String_length(Node* ctrl, Node* str);
Node* load_String_value(Node* ctrl, Node* str);
void store_String_offset(Node* ctrl, Node* str, Node* value);
void store_String_length(Node* ctrl, Node* str, Node* value);
void store_String_value(Node* ctrl, Node* str, Node* value);
// Handy for making control flow
IfNode* create_and_map_if(Node* ctrl, Node* tst, float prob, float cnt) {
IfNode* iff = new (C, 2) IfNode(ctrl, tst, prob, cnt);// New IfNode's
......
......@@ -147,7 +147,8 @@ class LibraryCallKit : public GraphKit {
return generate_method_call(method_id, true, false);
}
Node* make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2);
Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2);
Node* make_string_method_node(int opcode, Node* str1, Node* str2);
bool inline_string_compareTo();
bool inline_string_indexOf();
Node* string_indexOf(Node* string_object, ciTypeArray* target_array, jint offset, jint cache_i, jint md2_i);
......@@ -873,48 +874,76 @@ Node* LibraryCallKit::generate_current_thread(Node* &tls_output) {
//------------------------------make_string_method_node------------------------
// Helper method for String intrinsic finctions.
Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* cnt1, Node* str2, Node* cnt2) {
const int value_offset = java_lang_String::value_offset_in_bytes();
const int count_offset = java_lang_String::count_offset_in_bytes();
const int offset_offset = java_lang_String::offset_offset_in_bytes();
// Helper method for String intrinsic functions. This version is called
// with str1 and str2 pointing to String object nodes.
//
Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1, Node* str2) {
Node* no_ctrl = NULL;
ciInstanceKlass* klass = env()->String_klass();
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
const TypeAryPtr* value_type =
TypeAryPtr::make(TypePtr::NotNull,
TypeAry::make(TypeInt::CHAR,TypeInt::POS),
ciTypeArrayKlass::make(T_CHAR), true, 0);
// Get start addr of string and substring
Node* str1_valuea = basic_plus_adr(str1, str1, value_offset);
Node* str1_value = make_load(no_ctrl, str1_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
Node* str1_offseta = basic_plus_adr(str1, str1, offset_offset);
Node* str1_offset = make_load(no_ctrl, str1_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
// Get start addr of string
Node* str1_value = load_String_value(no_ctrl, str1);
Node* str1_offset = load_String_offset(no_ctrl, str1);
Node* str1_start = array_element_address(str1_value, str1_offset, T_CHAR);
Node* str2_valuea = basic_plus_adr(str2, str2, value_offset);
Node* str2_value = make_load(no_ctrl, str2_valuea, value_type, T_OBJECT, string_type->add_offset(value_offset));
Node* str2_offseta = basic_plus_adr(str2, str2, offset_offset);
Node* str2_offset = make_load(no_ctrl, str2_offseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
// Get length of string 1
Node* str1_len = load_String_length(no_ctrl, str1);
Node* str2_value = load_String_value(no_ctrl, str2);
Node* str2_offset = load_String_offset(no_ctrl, str2);
Node* str2_start = array_element_address(str2_value, str2_offset, T_CHAR);
Node* str2_len = NULL;
Node* result = NULL;
switch (opcode) {
case Op_StrIndexOf:
// Get length of string 2
str2_len = load_String_length(no_ctrl, str2);
result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
str1_start, str1_len, str2_start, str2_len);
break;
case Op_StrComp:
// Get length of string 2
str2_len = load_String_length(no_ctrl, str2);
result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
str1_start, str1_len, str2_start, str2_len);
break;
case Op_StrEquals:
result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
str1_start, str2_start, str1_len);
break;
default:
ShouldNotReachHere();
return NULL;
}
// All these intrinsics have checks.
C->set_has_split_ifs(true); // Has chance for split-if optimization
return _gvn.transform(result);
}
// Helper method for String intrinsic functions. This version is called
// with str1 and str2 pointing to char[] nodes, with cnt1 and cnt2 pointing
// to Int nodes containing the lenghts of str1 and str2.
//
Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2) {
Node* result = NULL;
switch (opcode) {
case Op_StrIndexOf:
result = new (C, 6) StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
str1_start, cnt1, str2_start, cnt2);
str1_start, cnt1, str2_start, cnt2);
break;
case Op_StrComp:
result = new (C, 6) StrCompNode(control(), memory(TypeAryPtr::CHARS),
str1_start, cnt1, str2_start, cnt2);
str1_start, cnt1, str2_start, cnt2);
break;
case Op_StrEquals:
result = new (C, 5) StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
str1_start, str2_start, cnt1);
str1_start, str2_start, cnt1);
break;
default:
ShouldNotReachHere();
......@@ -932,10 +961,6 @@ bool LibraryCallKit::inline_string_compareTo() {
if (!Matcher::has_match_rule(Op_StrComp)) return false;
const int value_offset = java_lang_String::value_offset_in_bytes();
const int count_offset = java_lang_String::count_offset_in_bytes();
const int offset_offset = java_lang_String::offset_offset_in_bytes();
_sp += 2;
Node *argument = pop(); // pop non-receiver first: it was pushed second
Node *receiver = pop();
......@@ -952,18 +977,7 @@ bool LibraryCallKit::inline_string_compareTo() {
return true;
}
ciInstanceKlass* klass = env()->String_klass();
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
Node* no_ctrl = NULL;
// Get counts for string and argument
Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
Node* receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
Node* argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
Node* compare = make_string_method_node(Op_StrComp, receiver, receiver_cnt, argument, argument_cnt);
Node* compare = make_string_method_node(Op_StrComp, receiver, argument);
push(compare);
return true;
}
......@@ -973,10 +987,6 @@ bool LibraryCallKit::inline_string_equals() {
if (!Matcher::has_match_rule(Op_StrEquals)) return false;
const int value_offset = java_lang_String::value_offset_in_bytes();
const int count_offset = java_lang_String::count_offset_in_bytes();
const int offset_offset = java_lang_String::offset_offset_in_bytes();
int nargs = 2;
_sp += nargs;
Node* argument = pop(); // pop non-receiver first: it was pushed second
......@@ -1030,24 +1040,31 @@ bool LibraryCallKit::inline_string_equals() {
}
}
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
Node* no_ctrl = NULL;
Node* receiver_cnt;
Node* argument_cnt;
if (!stopped()) {
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
// Properly cast the argument to String
argument = _gvn.transform(new (C, 2) CheckCastPPNode(control(), argument, string_type));
// This path is taken only when argument's type is String:NotNull.
argument = cast_not_null(argument, false);
// Get counts for string and argument
Node* receiver_cnta = basic_plus_adr(receiver, receiver, count_offset);
receiver_cnt = make_load(no_ctrl, receiver_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
Node* no_ctrl = NULL;
// Get start addr of receiver
Node* receiver_val = load_String_value(no_ctrl, receiver);
Node* receiver_offset = load_String_offset(no_ctrl, receiver);
Node* receiver_start = array_element_address(receiver_val, receiver_offset, T_CHAR);
// Get length of receiver
Node* receiver_cnt = load_String_length(no_ctrl, receiver);
Node* argument_cnta = basic_plus_adr(argument, argument, count_offset);
argument_cnt = make_load(no_ctrl, argument_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
// Get start addr of argument
Node* argument_val = load_String_value(no_ctrl, argument);
Node* argument_offset = load_String_offset(no_ctrl, argument);
Node* argument_start = array_element_address(argument_val, argument_offset, T_CHAR);
// Get length of argument
Node* argument_cnt = load_String_length(no_ctrl, argument);
// Check for receiver count != argument count
Node* cmp = _gvn.transform( new(C, 3) CmpINode(receiver_cnt, argument_cnt) );
......@@ -1057,14 +1074,14 @@ bool LibraryCallKit::inline_string_equals() {
phi->init_req(4, intcon(0));
region->init_req(4, if_ne);
}
}
// Check for count == 0 is done by mach node StrEquals.
// Check for count == 0 is done by assembler code for StrEquals.
if (!stopped()) {
Node* equals = make_string_method_node(Op_StrEquals, receiver, receiver_cnt, argument, argument_cnt);
phi->init_req(1, equals);
region->init_req(1, control());
if (!stopped()) {
Node* equals = make_string_method_node(Op_StrEquals, receiver_start, receiver_cnt, argument_start, argument_cnt);
phi->init_req(1, equals);
region->init_req(1, control());
}
}
// post merge
......@@ -1162,20 +1179,9 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
const int nargs = 2; // number of arguments to push back for uncommon trap in predicate
const int value_offset = java_lang_String::value_offset_in_bytes();
const int count_offset = java_lang_String::count_offset_in_bytes();
const int offset_offset = java_lang_String::offset_offset_in_bytes();
ciInstanceKlass* klass = env()->String_klass();
const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
const TypeAryPtr* source_type = TypeAryPtr::make(TypePtr::NotNull, TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0);
Node* sourceOffseta = basic_plus_adr(string_object, string_object, offset_offset);
Node* sourceOffset = make_load(no_ctrl, sourceOffseta, TypeInt::INT, T_INT, string_type->add_offset(offset_offset));
Node* sourceCounta = basic_plus_adr(string_object, string_object, count_offset);
Node* sourceCount = make_load(no_ctrl, sourceCounta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
Node* sourcea = basic_plus_adr(string_object, string_object, value_offset);
Node* source = make_load(no_ctrl, sourcea, source_type, T_OBJECT, string_type->add_offset(value_offset));
Node* source = load_String_value(no_ctrl, string_object);
Node* sourceOffset = load_String_offset(no_ctrl, string_object);
Node* sourceCount = load_String_length(no_ctrl, string_object);
Node* target = _gvn.transform( makecon(TypeOopPtr::make_from_constant(target_array, true)) );
jint target_length = target_array->length();
......@@ -1243,10 +1249,6 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar
//------------------------------inline_string_indexOf------------------------
bool LibraryCallKit::inline_string_indexOf() {
const int value_offset = java_lang_String::value_offset_in_bytes();
const int count_offset = java_lang_String::count_offset_in_bytes();
const int offset_offset = java_lang_String::offset_offset_in_bytes();
_sp += 2;
Node *argument = pop(); // pop non-receiver first: it was pushed second
Node *receiver = pop();
......@@ -1280,12 +1282,21 @@ bool LibraryCallKit::inline_string_indexOf() {
Node* result_phi = new (C, 4) PhiNode(result_rgn, TypeInt::INT);
Node* no_ctrl = NULL;
// Get counts for string and substr
Node* source_cnta = basic_plus_adr(receiver, receiver, count_offset);
Node* source_cnt = make_load(no_ctrl, source_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
// Get start addr of source string
Node* source = load_String_value(no_ctrl, receiver);
Node* source_offset = load_String_offset(no_ctrl, receiver);
Node* source_start = array_element_address(source, source_offset, T_CHAR);
// Get length of source string
Node* source_cnt = load_String_length(no_ctrl, receiver);
// Get start addr of substring
Node* substr = load_String_value(no_ctrl, argument);
Node* substr_offset = load_String_offset(no_ctrl, argument);
Node* substr_start = array_element_address(substr, substr_offset, T_CHAR);
Node* substr_cnta = basic_plus_adr(argument, argument, count_offset);
Node* substr_cnt = make_load(no_ctrl, substr_cnta, TypeInt::INT, T_INT, string_type->add_offset(count_offset));
// Get length of source string
Node* substr_cnt = load_String_length(no_ctrl, argument);
// Check for substr count > string count
Node* cmp = _gvn.transform( new(C, 3) CmpINode(substr_cnt, source_cnt) );
......@@ -1308,7 +1319,7 @@ bool LibraryCallKit::inline_string_indexOf() {
}
if (!stopped()) {
result = make_string_method_node(Op_StrIndexOf, receiver, source_cnt, argument, substr_cnt);
result = make_string_method_node(Op_StrIndexOf, source_start, source_cnt, substr_start, substr_cnt);
result_phi->init_req(1, result);
result_rgn->init_req(1, control());
}
......@@ -1333,11 +1344,19 @@ bool LibraryCallKit::inline_string_indexOf() {
ciInstance* str = str_const->as_instance();
assert(str != NULL, "must be instance");
ciObject* v = str->field_value_by_offset(value_offset).as_object();
int o = str->field_value_by_offset(offset_offset).as_int();
int c = str->field_value_by_offset(count_offset).as_int();
ciObject* v = str->field_value_by_offset(java_lang_String::value_offset_in_bytes()).as_object();
ciTypeArray* pat = v->as_type_array(); // pattern (argument) character array
int o;
int c;
if (java_lang_String::has_offset_field()) {
o = str->field_value_by_offset(java_lang_String::offset_offset_in_bytes()).as_int();
c = str->field_value_by_offset(java_lang_String::count_offset_in_bytes()).as_int();
} else {
o = 0;
c = pat->length();
}
// constant strings have no offset and count == length which
// simplifies the resulting code somewhat so lets optimize for that.
if (o != 0 || c != pat->length()) {
......
/*
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2012, 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
......@@ -528,16 +528,6 @@ PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn, Unique_Node_List*):
}
// Collect the types needed to talk about the various slices of memory
const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(),
false, NULL, 0);
const TypePtr* value_field_type = string_type->add_offset(java_lang_String::value_offset_in_bytes());
const TypePtr* offset_field_type = string_type->add_offset(java_lang_String::offset_offset_in_bytes());
const TypePtr* count_field_type = string_type->add_offset(java_lang_String::count_offset_in_bytes());
value_field_idx = C->get_alias_index(value_field_type);
count_field_idx = C->get_alias_index(count_field_type);
offset_field_idx = C->get_alias_index(offset_field_type);
char_adr_idx = C->get_alias_index(TypeAryPtr::CHARS);
// For each locally allocated StringBuffer see if the usages can be
......@@ -1174,18 +1164,9 @@ void PhaseStringOpts::int_getChars(GraphKit& kit, Node* arg, Node* char_array, N
Node* PhaseStringOpts::copy_string(GraphKit& kit, Node* str, Node* char_array, Node* start) {
Node* string = str;
Node* offset = kit.make_load(kit.control(),
kit.basic_plus_adr(string, string, java_lang_String::offset_offset_in_bytes()),
TypeInt::INT, T_INT, offset_field_idx);
Node* count = kit.make_load(kit.control(),
kit.basic_plus_adr(string, string, java_lang_String::count_offset_in_bytes()),
TypeInt::INT, T_INT, count_field_idx);
const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull,
TypeAry::make(TypeInt::CHAR,TypeInt::POS),
ciTypeArrayKlass::make(T_CHAR), true, 0);
Node* value = kit.make_load(kit.control(),
kit.basic_plus_adr(string, string, java_lang_String::value_offset_in_bytes()),
value_type, T_OBJECT, value_field_idx);
Node* offset = kit.load_String_offset(kit.control(), string);
Node* count = kit.load_String_length(kit.control(), string);
Node* value = kit.load_String_value (kit.control(), string);
// copy the contents
if (offset->is_Con() && count->is_Con() && value->is_Con() && count->get_int() < unroll_string_copy_length) {
......@@ -1342,10 +1323,9 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
arg = phi;
sc->set_argument(argi, arg);
}
// Node* offset = kit.make_load(NULL, kit.basic_plus_adr(arg, arg, offset_offset),
// TypeInt::INT, T_INT, offset_field_idx);
Node* count = kit.make_load(kit.control(), kit.basic_plus_adr(arg, arg, java_lang_String::count_offset_in_bytes()),
TypeInt::INT, T_INT, count_field_idx);
Node* count = kit.load_String_length(kit.control(), arg);
length = __ AddI(length, count);
string_sizes->init_req(argi, NULL);
break;
......@@ -1436,12 +1416,11 @@ void PhaseStringOpts::replace_string_concat(StringConcat* sc) {
}
// Intialize the string
kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::offset_offset_in_bytes()),
__ intcon(0), T_INT, offset_field_idx);
kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::count_offset_in_bytes()),
length, T_INT, count_field_idx);
kit.store_to_memory(kit.control(), kit.basic_plus_adr(result, java_lang_String::value_offset_in_bytes()),
char_array, T_OBJECT, value_field_idx);
if (java_lang_String::has_offset_field()) {
kit.store_String_offset(kit.control(), result, __ intcon(0));
kit.store_String_length(kit.control(), result, length);
}
kit.store_String_value(kit.control(), result, char_array);
// hook up the outgoing control and result
kit.replace_call(sc->end(), result);
......
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2012, 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,9 +41,6 @@ class PhaseStringOpts : public Phase {
// Memory slices needed for code gen
int char_adr_idx;
int value_field_idx;
int count_field_idx;
int offset_field_idx;
// Integer.sizeTable - used for int to String conversion
ciField* size_table_field;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册