< prev index next >
src/share/vm/opto/library_call.cpp
Print this page
*** 198,213 ****
CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) {
return generate_method_call(method_id, true, false);
}
Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls);
! 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);
! bool inline_string_equals();
Node* round_double_node(Node* n);
bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
bool inline_math_native(vmIntrinsics::ID id);
bool inline_trig(vmIntrinsics::ID id);
bool inline_math(vmIntrinsics::ID id);
--- 198,217 ----
CallJavaNode* generate_method_call_virtual(vmIntrinsics::ID method_id) {
return generate_method_call(method_id, true, false);
}
Node * load_field_from_object(Node * fromObj, const char * fieldName, const char * fieldTypeString, bool is_exact, bool is_static, ciInstanceKlass * fromKls);
! Node* make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae);
! bool inline_string_compareTo(StrIntrinsicNode::ArgEnc ae);
! bool inline_string_indexOf(StrIntrinsicNode::ArgEnc ae);
! bool inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae);
! bool inline_string_indexOfChar();
! bool inline_string_equals(StrIntrinsicNode::ArgEnc ae);
! bool inline_string_toBytesU();
! bool inline_string_getCharsU();
! bool inline_string_copy(bool compress);
! bool inline_string_char_access(bool is_store);
Node* round_double_node(Node* n);
bool runtime_math(const TypeFunc* call_type, address funcAddr, const char* funcName);
bool inline_math_native(vmIntrinsics::ID id);
bool inline_trig(vmIntrinsics::ID id);
bool inline_math(vmIntrinsics::ID id);
*** 249,259 ****
bool inline_native_subtype_check();
bool inline_native_newArray();
bool inline_native_getLength();
bool inline_array_copyOf(bool is_copyOfRange);
! bool inline_array_equals();
void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark);
bool inline_native_clone(bool is_virtual);
bool inline_native_Reflection_getCallerClass();
// Helper function for inlining native object hash method
bool inline_native_hashcode(bool is_virtual, bool is_static);
--- 253,263 ----
bool inline_native_subtype_check();
bool inline_native_newArray();
bool inline_native_getLength();
bool inline_array_copyOf(bool is_copyOfRange);
! bool inline_array_equals(StrIntrinsicNode::ArgEnc ae);
void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array, bool card_mark);
bool inline_native_clone(bool is_virtual);
bool inline_native_Reflection_getCallerClass();
// Helper function for inlining native object hash method
bool inline_native_hashcode(bool is_virtual, bool is_static);
*** 296,305 ****
--- 300,310 ----
bool inline_updateBytesCRC32C();
bool inline_updateDirectByteBufferCRC32C();
bool inline_updateBytesAdler32();
bool inline_updateByteBufferAdler32();
bool inline_multiplyToLen();
+ bool inline_hasNegatives();
bool inline_squareToLen();
bool inline_mulAdd();
bool inline_montgomeryMultiply();
bool inline_montgomerySquare();
*** 455,464 ****
--- 460,470 ----
}
bool LibraryCallKit::try_to_inline(int predicate) {
// Handle symbolic names for otherwise undistinguished boolean switches:
const bool is_store = true;
+ const bool is_compress = true;
const bool is_native_ptr = true;
const bool is_static = true;
const bool is_volatile = true;
if (!jvms()->has_method()) {
*** 509,521 ****
case vmIntrinsics::_subtractExactI: return inline_math_subtractExactI(false /* subtract */);
case vmIntrinsics::_subtractExactL: return inline_math_subtractExactL(false /* subtract */);
case vmIntrinsics::_arraycopy: return inline_arraycopy();
! case vmIntrinsics::_compareTo: return inline_string_compareTo();
! case vmIntrinsics::_indexOf: return inline_string_indexOf();
! case vmIntrinsics::_equals: return inline_string_equals();
case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, !is_volatile);
case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, !is_volatile);
case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, !is_volatile);
case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile);
--- 515,549 ----
case vmIntrinsics::_subtractExactI: return inline_math_subtractExactI(false /* subtract */);
case vmIntrinsics::_subtractExactL: return inline_math_subtractExactL(false /* subtract */);
case vmIntrinsics::_arraycopy: return inline_arraycopy();
! case vmIntrinsics::_compareToL: return inline_string_compareTo(StrIntrinsicNode::LL);
! case vmIntrinsics::_compareToU: return inline_string_compareTo(StrIntrinsicNode::UU);
! case vmIntrinsics::_compareToLU: return inline_string_compareTo(StrIntrinsicNode::LU);
! case vmIntrinsics::_compareToUL: return inline_string_compareTo(StrIntrinsicNode::UL);
!
! case vmIntrinsics::_indexOfL: return inline_string_indexOf(StrIntrinsicNode::LL);
! case vmIntrinsics::_indexOfU: return inline_string_indexOf(StrIntrinsicNode::UU);
! case vmIntrinsics::_indexOfUL: return inline_string_indexOf(StrIntrinsicNode::UL);
! case vmIntrinsics::_indexOfIL: return inline_string_indexOfI(StrIntrinsicNode::LL);
! case vmIntrinsics::_indexOfIU: return inline_string_indexOfI(StrIntrinsicNode::UU);
! case vmIntrinsics::_indexOfIUL: return inline_string_indexOfI(StrIntrinsicNode::UL);
! case vmIntrinsics::_indexOfU_char: return inline_string_indexOfChar();
!
! case vmIntrinsics::_equalsL: return inline_string_equals(StrIntrinsicNode::LL);
! case vmIntrinsics::_equalsU: return inline_string_equals(StrIntrinsicNode::UU);
!
! case vmIntrinsics::_toBytesStringU: return inline_string_toBytesU();
! case vmIntrinsics::_getCharsStringU: return inline_string_getCharsU();
! case vmIntrinsics::_getCharStringU: return inline_string_char_access(!is_store);
! case vmIntrinsics::_putCharStringU: return inline_string_char_access( is_store);
!
! case vmIntrinsics::_compressStringC:
! case vmIntrinsics::_compressStringB: return inline_string_copy( is_compress);
! case vmIntrinsics::_inflateStringC:
! case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress);
case vmIntrinsics::_getObject: return inline_unsafe_access(!is_native_ptr, !is_store, T_OBJECT, !is_volatile);
case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_native_ptr, !is_store, T_BOOLEAN, !is_volatile);
case vmIntrinsics::_getByte: return inline_unsafe_access(!is_native_ptr, !is_store, T_BYTE, !is_volatile);
case vmIntrinsics::_getShort: return inline_unsafe_access(!is_native_ptr, !is_store, T_SHORT, !is_volatile);
*** 614,624 ****
case vmIntrinsics::_copyMemory: return inline_unsafe_copyMemory();
case vmIntrinsics::_newArray: return inline_native_newArray();
case vmIntrinsics::_getLength: return inline_native_getLength();
case vmIntrinsics::_copyOf: return inline_array_copyOf(false);
case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true);
! case vmIntrinsics::_equalsC: return inline_array_equals();
case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual());
case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check();
case vmIntrinsics::_isInstance:
--- 642,653 ----
case vmIntrinsics::_copyMemory: return inline_unsafe_copyMemory();
case vmIntrinsics::_newArray: return inline_native_newArray();
case vmIntrinsics::_getLength: return inline_native_getLength();
case vmIntrinsics::_copyOf: return inline_array_copyOf(false);
case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true);
! case vmIntrinsics::_equalsB: return inline_array_equals(StrIntrinsicNode::LL);
! case vmIntrinsics::_equalsC: return inline_array_equals(StrIntrinsicNode::UU);
case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual());
case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check();
case vmIntrinsics::_isInstance:
*** 684,693 ****
--- 713,723 ----
case vmIntrinsics::_ghash_processBlocks:
return inline_ghash_processBlocks();
case vmIntrinsics::_encodeISOArray:
+ case vmIntrinsics::_encodeByteISOArray:
return inline_encodeISOArray();
case vmIntrinsics::_updateCRC32:
return inline_updateCRC32();
case vmIntrinsics::_updateBytesCRC32:
*** 708,717 ****
--- 738,750 ----
case vmIntrinsics::_profileBoolean:
return inline_profileBoolean();
case vmIntrinsics::_isCompileConstant:
return inline_isCompileConstant();
+ case vmIntrinsics::_hasNegatives:
+ return inline_hasNegatives();
+
default:
// If you get here, it may be that someone has added a new intrinsic
// to the list in vmSymbols.hpp without implementing it here.
#ifndef PRODUCT
if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) {
*** 873,921 ****
return threadObj;
}
//------------------------------make_string_method_node------------------------
! // 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;
!
! // 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);
!
! // 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 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 StrCompNode(control(), memory(TypeAryPtr::CHARS),
! str1_start, str1_len, str2_start, str2_len);
break;
case Op_StrEquals:
! result = new StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
! str1_start, str2_start, str1_len);
break;
default:
ShouldNotReachHere();
return NULL;
}
--- 906,933 ----
return threadObj;
}
//------------------------------make_string_method_node------------------------
! // Helper method for String intrinsic functions. This version is called with
! // str1 and str2 pointing to byte[] nodes containing Latin1 or UTF16 encoded
! // characters (depending on 'is_byte'). cnt1 and cnt2 are pointing to Int nodes
! // containing the lengths of str1 and str2.
! Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae) {
Node* result = NULL;
switch (opcode) {
case Op_StrIndexOf:
! result = new StrIndexOfNode(control(), memory(TypeAryPtr::BYTES),
! str1_start, cnt1, str2_start, cnt2, ae);
break;
case Op_StrComp:
! result = new StrCompNode(control(), memory(TypeAryPtr::BYTES),
! str1_start, cnt1, str2_start, cnt2, ae);
break;
case Op_StrEquals:
! result = new StrEqualsNode(control(), memory(TypeAryPtr::BYTES),
! str1_start, str2_start, cnt1, ae);
break;
default:
ShouldNotReachHere();
return NULL;
}
*** 924,1056 ****
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 StrIndexOfNode(control(), memory(TypeAryPtr::CHARS),
! str1_start, cnt1, str2_start, cnt2);
! break;
! case Op_StrComp:
! result = new StrCompNode(control(), memory(TypeAryPtr::CHARS),
! str1_start, cnt1, str2_start, cnt2);
! break;
! case Op_StrEquals:
! result = new StrEqualsNode(control(), memory(TypeAryPtr::CHARS),
! str1_start, str2_start, cnt1);
! 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);
! }
! //------------------------------inline_string_compareTo------------------------
! // public int java.lang.String.compareTo(String anotherString);
! bool LibraryCallKit::inline_string_compareTo() {
! Node* receiver = null_check(argument(0));
! Node* arg = null_check(argument(1));
! if (stopped()) {
! return true;
! }
! set_result(make_string_method_node(Op_StrComp, receiver, arg));
return true;
}
//------------------------------inline_string_equals------------------------
! bool LibraryCallKit::inline_string_equals() {
! Node* receiver = null_check_receiver();
! // NOTE: Do not null check argument for String.equals() because spec
! // allows to specify NULL as argument.
! Node* argument = this->argument(1);
! if (stopped()) {
! return true;
! }
// paths (plus control) merge
! RegionNode* region = new RegionNode(5);
Node* phi = new PhiNode(region, TypeInt::BOOL);
- // does source == target string?
- Node* cmp = _gvn.transform(new CmpPNode(receiver, argument));
- Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
-
- Node* if_eq = generate_slow_guard(bol, NULL);
- if (if_eq != NULL) {
- // receiver == argument
- phi->init_req(2, intcon(1));
- region->init_req(2, if_eq);
- }
-
- // get String klass for instanceOf
- ciInstanceKlass* klass = env()->String_klass();
-
if (!stopped()) {
! Node* inst = gen_instanceof(argument, makecon(TypeKlassPtr::make(klass)));
! Node* cmp = _gvn.transform(new CmpINode(inst, intcon(1)));
! Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne));
!
! Node* inst_false = generate_guard(bol, NULL, PROB_MIN);
! //instanceOf == true, fallthrough
! if (inst_false != NULL) {
! phi->init_req(3, intcon(0));
! region->init_req(3, inst_false);
! }
! }
!
! if (!stopped()) {
! const TypeOopPtr* string_type = TypeOopPtr::make_from_klass(klass);
!
! // Properly cast the argument to String
! argument = _gvn.transform(new CheckCastPPNode(control(), argument, string_type));
! // This path is taken only when argument's type is String:NotNull.
! argument = cast_not_null(argument, false);
!
! 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);
!
! // 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 CmpINode(receiver_cnt, argument_cnt));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne));
Node* if_ne = generate_slow_guard(bol, NULL);
if (if_ne != NULL) {
! phi->init_req(4, intcon(0));
! region->init_req(4, if_ne);
}
// Check for count == 0 is done by assembler code for StrEquals.
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());
}
}
--- 936,994 ----
C->set_has_split_ifs(true); // Has chance for split-if optimization
return _gvn.transform(result);
}
! //------------------------------inline_string_compareTo------------------------
! bool LibraryCallKit::inline_string_compareTo(StrIntrinsicNode::ArgEnc ae) {
! Node* arg1 = argument(0);
! Node* arg2 = argument(1);
! // Get start addr and length of first argument
! Node* arg1_start = array_element_address(arg1, intcon(0), T_BYTE);
! Node* arg1_cnt = load_array_length(arg1);
!
! // Get start addr and length of second argument
! Node* arg2_start = array_element_address(arg2, intcon(0), T_BYTE);
! Node* arg2_cnt = load_array_length(arg2);
! Node* result = make_string_method_node(Op_StrComp, arg1_start, arg1_cnt, arg2_start, arg2_cnt, ae);
! set_result(result);
return true;
}
//------------------------------inline_string_equals------------------------
! bool LibraryCallKit::inline_string_equals(StrIntrinsicNode::ArgEnc ae) {
! Node* arg1 = argument(0);
! Node* arg2 = argument(1);
// paths (plus control) merge
! RegionNode* region = new RegionNode(3);
Node* phi = new PhiNode(region, TypeInt::BOOL);
if (!stopped()) {
! // Get start addr and length of first argument
! Node* arg1_start = array_element_address(arg1, intcon(0), T_BYTE);
! Node* arg1_cnt = load_array_length(arg1);
!
! // Get start addr and length of second argument
! Node* arg2_start = array_element_address(arg2, intcon(0), T_BYTE);
! Node* arg2_cnt = load_array_length(arg2);
! // Check for arg1_cnt != arg2_cnt
! Node* cmp = _gvn.transform(new CmpINode(arg1_cnt, arg2_cnt));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::ne));
Node* if_ne = generate_slow_guard(bol, NULL);
if (if_ne != NULL) {
! phi->init_req(2, intcon(0));
! region->init_req(2, if_ne);
}
// Check for count == 0 is done by assembler code for StrEquals.
if (!stopped()) {
! Node* equals = make_string_method_node(Op_StrEquals, arg1_start, arg1_cnt, arg2_start, arg2_cnt, ae);
phi->init_req(1, equals);
region->init_req(1, control());
}
}
*** 1061,1353 ****
set_result(_gvn.transform(phi));
return true;
}
//------------------------------inline_array_equals----------------------------
! bool LibraryCallKit::inline_array_equals() {
Node* arg1 = argument(0);
Node* arg2 = argument(1);
! set_result(_gvn.transform(new AryEqNode(control(), memory(TypeAryPtr::CHARS), arg1, arg2)));
return true;
}
! // Java version of String.indexOf(constant string)
! // class StringDecl {
! // StringDecl(char[] ca) {
! // offset = 0;
! // count = ca.length;
! // value = ca;
! // }
! // int offset;
! // int count;
! // char[] value;
! // }
! //
! // static int string_indexOf_J(StringDecl string_object, char[] target_object,
! // int targetOffset, int cache_i, int md2) {
! // int cache = cache_i;
! // int sourceOffset = string_object.offset;
! // int sourceCount = string_object.count;
! // int targetCount = target_object.length;
! //
! // int targetCountLess1 = targetCount - 1;
! // int sourceEnd = sourceOffset + sourceCount - targetCountLess1;
! //
! // char[] source = string_object.value;
! // char[] target = target_object;
! // int lastChar = target[targetCountLess1];
! //
! // outer_loop:
! // for (int i = sourceOffset; i < sourceEnd; ) {
! // int src = source[i + targetCountLess1];
! // if (src == lastChar) {
! // // With random strings and a 4-character alphabet,
! // // reverse matching at this point sets up 0.8% fewer
! // // frames, but (paradoxically) makes 0.3% more probes.
! // // Since those probes are nearer the lastChar probe,
! // // there is may be a net D$ win with reverse matching.
! // // But, reversing loop inhibits unroll of inner loop
! // // for unknown reason. So, does running outer loop from
! // // (sourceOffset - targetCountLess1) to (sourceOffset + sourceCount)
! // for (int j = 0; j < targetCountLess1; j++) {
! // if (target[targetOffset + j] != source[i+j]) {
! // if ((cache & (1 << source[i+j])) == 0) {
! // if (md2 < j+1) {
! // i += j+1;
! // continue outer_loop;
! // }
! // }
! // i += md2;
! // continue outer_loop;
! // }
! // }
! // return i - sourceOffset;
! // }
! // if ((cache & (1 << src)) == 0) {
! // i += targetCountLess1;
! // } // using "i += targetCount;" and an "else i++;" causes a jump to jump.
! // i++;
! // }
! // return -1;
! // }
!
! //------------------------------string_indexOf------------------------
! Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_array, jint targetOffset_i,
! jint cache_i, jint md2_i) {
! Node* no_ctrl = NULL;
! float likely = PROB_LIKELY(0.9);
! float unlikely = PROB_UNLIKELY(0.9);
! const int nargs = 0; // no arguments to push back for uncommon trap in predicate
! 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();
! const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin));
! const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot);
! // String.value field is known to be @Stable.
! if (UseImplicitStableValues) {
! target = cast_array_to_stable(target, target_type);
}
!
! IdealKit kit(this, false, true);
! #define __ kit.
! Node* zero = __ ConI(0);
! Node* one = __ ConI(1);
! Node* cache = __ ConI(cache_i);
! Node* md2 = __ ConI(md2_i);
! Node* lastChar = __ ConI(target_array->char_at(target_length - 1));
! Node* targetCountLess1 = __ ConI(target_length - 1);
! Node* targetOffset = __ ConI(targetOffset_i);
! Node* sourceEnd = __ SubI(__ AddI(sourceOffset, sourceCount), targetCountLess1);
!
! IdealVariable rtn(kit), i(kit), j(kit); __ declarations_done();
! Node* outer_loop = __ make_label(2 /* goto */);
! Node* return_ = __ make_label(1);
!
! __ set(rtn,__ ConI(-1));
! __ loop(this, nargs, i, sourceOffset, BoolTest::lt, sourceEnd); {
! Node* i2 = __ AddI(__ value(i), targetCountLess1);
! // pin to prohibit loading of "next iteration" value which may SEGV (rare)
! Node* src = load_array_element(__ ctrl(), source, i2, TypeAryPtr::CHARS);
! __ if_then(src, BoolTest::eq, lastChar, unlikely); {
! __ loop(this, nargs, j, zero, BoolTest::lt, targetCountLess1); {
! Node* tpj = __ AddI(targetOffset, __ value(j));
! Node* targ = load_array_element(no_ctrl, target, tpj, target_type);
! Node* ipj = __ AddI(__ value(i), __ value(j));
! Node* src2 = load_array_element(no_ctrl, source, ipj, TypeAryPtr::CHARS);
! __ if_then(targ, BoolTest::ne, src2); {
! __ if_then(__ AndI(cache, __ LShiftI(one, src2)), BoolTest::eq, zero); {
! __ if_then(md2, BoolTest::lt, __ AddI(__ value(j), one)); {
! __ increment(i, __ AddI(__ value(j), one));
! __ goto_(outer_loop);
! } __ end_if(); __ dead(j);
! }__ end_if(); __ dead(j);
! __ increment(i, md2);
! __ goto_(outer_loop);
! }__ end_if();
! __ increment(j, one);
! }__ end_loop(); __ dead(j);
! __ set(rtn, __ SubI(__ value(i), sourceOffset)); __ dead(i);
! __ goto_(return_);
! }__ end_if();
! __ if_then(__ AndI(cache, __ LShiftI(one, src)), BoolTest::eq, zero, likely); {
! __ increment(i, targetCountLess1);
! }__ end_if();
! __ increment(i, one);
! __ bind(outer_loop);
! }__ end_loop(); __ dead(i);
! __ bind(return_);
!
! // Final sync IdealKit and GraphKit.
! final_sync(kit);
! Node* result = __ value(rtn);
! #undef __
! C->set_has_loops(true);
! return result;
}
//------------------------------inline_string_indexOf------------------------
! bool LibraryCallKit::inline_string_indexOf() {
! Node* receiver = argument(0);
! Node* arg = argument(1);
!
! Node* result;
! if (Matcher::has_match_rule(Op_StrIndexOf) &&
! UseSSE42Intrinsics) {
! // Generate SSE4.2 version of indexOf
! // We currently only have match rules that use SSE4.2
!
! receiver = null_check(receiver);
! arg = null_check(arg);
! if (stopped()) {
! return true;
}
// Make the merge point
RegionNode* result_rgn = new RegionNode(4);
Node* result_phi = new PhiNode(result_rgn, TypeInt::INT);
- Node* no_ctrl = NULL;
! // 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, arg);
! Node* substr_offset = load_String_offset(no_ctrl, arg);
! Node* substr_start = array_element_address(substr, substr_offset, T_CHAR);
!
! // Get length of source string
! Node* substr_cnt = load_String_length(no_ctrl, arg);
// Check for substr count > string count
! Node* cmp = _gvn.transform(new CmpINode(substr_cnt, source_cnt));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::gt));
Node* if_gt = generate_slow_guard(bol, NULL);
if (if_gt != NULL) {
result_phi->init_req(2, intcon(-1));
result_rgn->init_req(2, if_gt);
}
if (!stopped()) {
// Check for substr count == 0
! cmp = _gvn.transform(new CmpINode(substr_cnt, intcon(0)));
bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
Node* if_zero = generate_slow_guard(bol, NULL);
if (if_zero != NULL) {
result_phi->init_req(3, intcon(0));
result_rgn->init_req(3, if_zero);
}
}
if (!stopped()) {
! 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());
}
set_control(_gvn.transform(result_rgn));
record_for_igvn(result_rgn);
! result = _gvn.transform(result_phi);
! } else { // Use LibraryCallKit::string_indexOf
! // don't intrinsify if argument isn't a constant string.
! if (!arg->is_Con()) {
return false;
}
! const TypeOopPtr* str_type = _gvn.type(arg)->isa_oopptr();
! if (str_type == NULL) {
! return false;
}
! ciInstanceKlass* klass = env()->String_klass();
! ciObject* str_const = str_type->const_oop();
! if (str_const == NULL || str_const->klass() != klass) {
! return false;
}
- ciInstance* str = str_const->as_instance();
- assert(str != NULL, "must be instance");
! 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()) {
return false;
}
- receiver = null_check(receiver, T_OBJECT);
- // NOTE: No null check on the argument is needed since it's a constant String oop.
- if (stopped()) {
return true;
}
! // The null string as a pattern always returns 0 (match at beginning of string)
! if (c == 0) {
! set_result(intcon(0));
return true;
}
! // Generate default indexOf
! jchar lastChar = pat->char_at(o + (c - 1));
! int cache = 0;
! int i;
! for (i = 0; i < c - 1; i++) {
! assert(i < pat->length(), "out of range");
! cache |= (1 << (pat->char_at(o + i) & (sizeof(cache) * BitsPerByte - 1)));
}
! int md2 = c;
! for (i = 0; i < c - 1; i++) {
! assert(i < pat->length(), "out of range");
! if (pat->char_at(o + i) == lastChar) {
! md2 = (c - 1) - i;
}
}
! result = string_indexOf(receiver, pat, o, cache, md2);
}
- set_result(result);
return true;
}
//--------------------------round_double_node--------------------------------
// Round a double node if necessary.
--- 999,1464 ----
set_result(_gvn.transform(phi));
return true;
}
//------------------------------inline_array_equals----------------------------
! bool LibraryCallKit::inline_array_equals(StrIntrinsicNode::ArgEnc ae) {
! assert(ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::LL, "unsupported array types");
Node* arg1 = argument(0);
Node* arg2 = argument(1);
!
! const TypeAryPtr* mtype = (ae == StrIntrinsicNode::UU) ? TypeAryPtr::CHARS : TypeAryPtr::BYTES;
! set_result(_gvn.transform(new AryEqNode(control(), memory(mtype), arg1, arg2, ae)));
return true;
}
! //------------------------------inline_hasNegatives------------------------------
! bool LibraryCallKit::inline_hasNegatives() {
! if (too_many_traps(Deoptimization::Reason_intrinsic)) return false;
! assert(callee()->signature()->size() == 3, "hasNegatives has 3 parameters");
! // no receiver since it is static method
! Node* ba = argument(0);
! Node* offset = argument(1);
! Node* len = argument(2);
! RegionNode* bailout = new RegionNode(1);
! record_for_igvn(bailout);
! // offset must not be negative.
! generate_negative_guard(offset, bailout);
! // offset + length must not exceed length of ba.
! generate_limit_guard(offset, len, load_array_length(ba), bailout);
! if (bailout->req() > 1) {
! PreserveJVMState pjvms(this);
! set_control(_gvn.transform(bailout));
! uncommon_trap(Deoptimization::Reason_intrinsic,
! Deoptimization::Action_maybe_recompile);
}
! if (!stopped()) {
! Node* ba_start = array_element_address(ba, offset, T_BYTE);
! Node* result = new HasNegativesNode(control(), memory(TypeAryPtr::BYTES), ba_start, len);
! set_result(_gvn.transform(result));
! }
! return true;
}
//------------------------------inline_string_indexOf------------------------
! bool LibraryCallKit::inline_string_indexOf(StrIntrinsicNode::ArgEnc ae) {
! if (!Matcher::has_match_rule(Op_StrIndexOf) || !UseSSE42Intrinsics) {
! return false;
}
+ Node* src = argument(0);
+ Node* tgt = argument(1);
// Make the merge point
RegionNode* result_rgn = new RegionNode(4);
Node* result_phi = new PhiNode(result_rgn, TypeInt::INT);
! // Get start addr and length of source string
! Node* src_start = array_element_address(src, intcon(0), T_BYTE);
! Node* src_count = load_array_length(src);
!
! // Get start addr and length of substring
! Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE);
! Node* tgt_count = load_array_length(tgt);
!
! if (ae == StrIntrinsicNode::UU || ae == StrIntrinsicNode::UL) {
! // Divide src size by 2 if String is UTF16 encoded
! src_count = _gvn.transform(new RShiftINode(src_count, intcon(1)));
! }
! if (ae == StrIntrinsicNode::UU) {
! // Divide substring size by 2 if String is UTF16 encoded
! tgt_count = _gvn.transform(new RShiftINode(tgt_count, intcon(1)));
! }
// Check for substr count > string count
! Node* cmp = _gvn.transform(new CmpINode(tgt_count, src_count));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::gt));
Node* if_gt = generate_slow_guard(bol, NULL);
if (if_gt != NULL) {
result_phi->init_req(2, intcon(-1));
result_rgn->init_req(2, if_gt);
}
if (!stopped()) {
// Check for substr count == 0
! cmp = _gvn.transform(new CmpINode(tgt_count, intcon(0)));
bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq));
Node* if_zero = generate_slow_guard(bol, NULL);
if (if_zero != NULL) {
result_phi->init_req(3, intcon(0));
result_rgn->init_req(3, if_zero);
}
}
if (!stopped()) {
! Node* result = make_string_method_node(Op_StrIndexOf, src_start, src_count, tgt_start, tgt_count, ae);
result_phi->init_req(1, result);
result_rgn->init_req(1, control());
}
set_control(_gvn.transform(result_rgn));
record_for_igvn(result_rgn);
! set_result(_gvn.transform(result_phi));
!
! return true;
! }
! //-----------------------------inline_string_indexOf-----------------------
! bool LibraryCallKit::inline_string_indexOfI(StrIntrinsicNode::ArgEnc ae) {
! if (!Matcher::has_match_rule(Op_StrIndexOf) || !UseSSE42Intrinsics) {
return false;
}
! assert(callee()->signature()->size() == 5, "String.indexOf() has 5 arguments");
! Node* src = argument(0); // byte[]
! Node* src_count = argument(1);
! Node* tgt = argument(2); // byte[]
! Node* tgt_count = argument(3);
! Node* from_index = argument(4);
!
! // Java code which calls this method has range checks for from_index value.
! src_count = _gvn.transform(new SubINode(src_count, from_index));
!
! // Multiply byte array index by 2 if String is UTF16 encoded
! Node* src_offset = (ae == StrIntrinsicNode::LL) ? from_index : _gvn.transform(new LShiftINode(from_index, intcon(1)));
! Node* src_start = array_element_address(src, src_offset, T_BYTE);
! Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE);
!
! Node* result = make_string_method_node(Op_StrIndexOf, src_start, src_count, tgt_start, tgt_count, ae);
!
! // The result is index relative to from_index if substring was found, -1 otherwise.
! // Generate code which will fold into cmove.
! RegionNode* region = new RegionNode(3);
! Node* phi = new PhiNode(region, TypeInt::INT);
!
! Node* cmp = _gvn.transform(new CmpINode(result, intcon(0)));
! Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::lt));
!
! Node* if_lt = generate_slow_guard(bol, NULL);
! if (if_lt != NULL) {
! // result == -1
! phi->init_req(2, result);
! region->init_req(2, if_lt);
}
! if (!stopped()) {
! result = _gvn.transform(new AddINode(result, from_index));
! phi->init_req(1, result);
! region->init_req(1, control());
}
! set_control(_gvn.transform(region));
! record_for_igvn(region);
! set_result(_gvn.transform(phi));
! return true;
! }
! //-----------------------------inline_string_indexOfChar-----------------------
! bool LibraryCallKit::inline_string_indexOfChar() {
! if (!Matcher::has_match_rule(Op_StrIndexOfChar) || !(UseSSE > 4)) {
return false;
}
+ assert(callee()->signature()->size() == 4, "String.indexOfChar() has 4 arguments");
+ Node* src = argument(0); // byte[]
+ Node* tgt = argument(1); // tgt is int ch
+ Node* from_index = argument(2);
+ Node* max = argument(3);
+
+ Node* src_offset = _gvn.transform(new LShiftINode(from_index, intcon(1)));
+ Node* src_start = array_element_address(src, src_offset, T_BYTE);
+
+ Node* src_count = _gvn.transform(new SubINode(max, from_index));
+
+ RegionNode* region = new RegionNode(3);
+ Node* phi = new PhiNode(region, TypeInt::INT);
+
+ Node* result = new StrIndexOfCharNode(control(), memory(TypeAryPtr::BYTES), src_start, src_count, tgt, StrIntrinsicNode::none);
+ C->set_has_split_ifs(true); // Has chance for split-if optimization
+ _gvn.transform(result);
+
+ Node* cmp = _gvn.transform(new CmpINode(result, intcon(0)));
+ Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::lt));
+
+ Node* if_lt = generate_slow_guard(bol, NULL);
+ if (if_lt != NULL) {
+ // result == -1
+ phi->init_req(2, result);
+ region->init_req(2, if_lt);
+ }
+ if (!stopped()) {
+ result = _gvn.transform(new AddINode(result, from_index));
+ phi->init_req(1, result);
+ region->init_req(1, control());
+ }
+ set_control(_gvn.transform(region));
+ record_for_igvn(region);
+ set_result(_gvn.transform(phi));
return true;
+ }
+ //---------------------------inline_string_copy---------------------
+ // compressIt == true --> generate a compressed copy operation (compress char[]/byte[] to byte[])
+ // int StringUTF16.compress(char[] src, int srcOff, byte[] dst, int dstOff, int len)
+ // int StringUTF16.compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len)
+ // compressIt == false --> generate an inflated copy operation (inflate byte[] to char[]/byte[])
+ // void StringLatin1.inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len)
+ // void StringLatin1.inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len)
+ bool LibraryCallKit::inline_string_copy(bool compress) {
+ int nargs = 5; // 2 oops, 3 ints
+ assert(callee()->signature()->size() == nargs, "string copy has 5 arguments");
+
+ Node* src = argument(0);
+ Node* src_offset = argument(1);
+ Node* dst = argument(2);
+ Node* dst_offset = argument(3);
+ Node* length = argument(4);
+
+ // Check for allocation before we add nodes that would confuse
+ // tightly_coupled_allocation()
+ AllocateArrayNode* alloc = tightly_coupled_allocation(dst, NULL);
+
+ // Figure out the size and type of the elements we will be copying.
+ const Type* src_type = src->Value(&_gvn);
+ const Type* dst_type = dst->Value(&_gvn);
+ BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+ BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+ assert((compress && dst_elem == T_BYTE && (src_elem == T_BYTE || src_elem == T_CHAR)) ||
+ (!compress && src_elem == T_BYTE && (dst_elem == T_BYTE || dst_elem == T_CHAR)),
+ "Unsupported array types for inline_string_copy");
+
+ // Convert char[] offsets to byte[] offsets
+ if (compress && src_elem == T_BYTE) {
+ src_offset = _gvn.transform(new LShiftINode(src_offset, intcon(1)));
+ } else if (!compress && dst_elem == T_BYTE) {
+ dst_offset = _gvn.transform(new LShiftINode(dst_offset, intcon(1)));
+ }
+
+ Node* src_start = array_element_address(src, src_offset, src_elem);
+ Node* dst_start = array_element_address(dst, dst_offset, dst_elem);
+ // 'src_start' points to src array + scaled offset
+ // 'dst_start' points to dst array + scaled offset
+ Node* count;
+ if (compress) {
+ count = compress_string(src_start, dst_start, length);
+ } else {
+ inflate_string(src_start, dst_start, length);
}
! if (alloc != NULL) {
! if (alloc->maybe_set_complete(&_gvn)) {
! // "You break it, you buy it."
! InitializeNode* init = alloc->initialization();
! assert(init->is_complete(), "we just did this");
! init->set_complete_with_arraycopy();
! assert(dst->is_CheckCastPP(), "sanity");
! assert(dst->in(0)->in(0) == init, "dest pinned");
! }
! // Do not let stores that initialize this object be reordered with
! // a subsequent store that would make this object accessible by
! // other threads.
! // Record what AllocateNode this StoreStore protects so that
! // escape analysis can go from the MemBarStoreStoreNode to the
! // AllocateNode and eliminate the MemBarStoreStoreNode if possible
! // based on the escape status of the AllocateNode.
! insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress));
! }
! if (compress) {
! set_result(_gvn.transform(count));
! }
return true;
+ }
+
+ #ifdef _LP64
+ #define XTOP ,top() /*additional argument*/
+ #else //_LP64
+ #define XTOP /*no additional argument*/
+ #endif //_LP64
+
+ //------------------------inline_string_toBytesU--------------------------
+ // public static byte[] StringUTF16.toBytes(char[] value, int off, int len)
+ bool LibraryCallKit::inline_string_toBytesU() {
+ // Get the arguments.
+ Node* value = argument(0);
+ Node* offset = argument(1);
+ Node* length = argument(2);
+
+ Node* newcopy = NULL;
+
+ // Set the original stack and the reexecute bit for the interpreter to reexecute
+ // the bytecode that invokes StringUTF16.toBytes() if deoptimization happens.
+ { PreserveReexecuteState preexecs(this);
+ jvms()->set_should_reexecute(true);
+
+ // Check if a null path was taken unconditionally.
+ value = null_check(value);
+
+ RegionNode* bailout = new RegionNode(1);
+ record_for_igvn(bailout);
+
+ // Make sure that resulting byte[] length does not overflow Integer.MAX_VALUE
+ generate_negative_guard(length, bailout);
+ generate_limit_guard(length, intcon(0), intcon(max_jint/2), bailout);
+
+ if (bailout->req() > 1) {
+ PreserveJVMState pjvms(this);
+ set_control(_gvn.transform(bailout));
+ uncommon_trap(Deoptimization::Reason_intrinsic,
+ Deoptimization::Action_maybe_recompile);
+ }
+ if (stopped()) return true;
+
+ // Range checks are done by caller.
+
+ Node* size = _gvn.transform(new LShiftINode(length, intcon(1)));
+ Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_BYTE)));
+ newcopy = new_array(klass_node, size, 0); // no arguments to push
+ AllocateArrayNode* alloc = tightly_coupled_allocation(newcopy, NULL);
+
+ // Calculate starting addresses.
+ Node* src_start = array_element_address(value, offset, T_CHAR);
+ Node* dst_start = basic_plus_adr(newcopy, arrayOopDesc::base_offset_in_bytes(T_BYTE));
+
+ // Check if src array address is aligned to HeapWordSize (dst is always aligned)
+ const TypeInt* toffset = gvn().type(offset)->is_int();
+ bool aligned = toffset->is_con() && ((toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
+
+ // Figure out which arraycopy runtime method to call (disjoint, uninitialized).
+ const char* copyfunc_name = "arraycopy";
+ address copyfunc_addr = StubRoutines::select_arraycopy_function(T_CHAR, aligned, true, copyfunc_name, true);
+ Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
+ OptoRuntime::fast_arraycopy_Type(),
+ copyfunc_addr, copyfunc_name, TypeRawPtr::BOTTOM,
+ src_start, dst_start, ConvI2X(length) XTOP);
+ // Do not let reads from the cloned object float above the arraycopy.
+ if (alloc != NULL) {
+ if (alloc->maybe_set_complete(&_gvn)) {
+ // "You break it, you buy it."
+ InitializeNode* init = alloc->initialization();
+ assert(init->is_complete(), "we just did this");
+ init->set_complete_with_arraycopy();
+ assert(newcopy->is_CheckCastPP(), "sanity");
+ assert(newcopy->in(0)->in(0) == init, "dest pinned");
+ }
+ // Do not let stores that initialize this object be reordered with
+ // a subsequent store that would make this object accessible by
+ // other threads.
+ // Record what AllocateNode this StoreStore protects so that
+ // escape analysis can go from the MemBarStoreStoreNode to the
+ // AllocateNode and eliminate the MemBarStoreStoreNode if possible
+ // based on the escape status of the AllocateNode.
+ insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress));
+ } else {
+ insert_mem_bar(Op_MemBarCPUOrder);
}
+ } // original reexecute is set back here
! C->set_has_split_ifs(true); // Has chance for split-if optimization
! if (!stopped()) {
! set_result(newcopy);
}
+ return true;
+ }
! //------------------------inline_string_getCharsU--------------------------
! // public void StringUTF16.getChars(byte[] value, int srcBegin, int srcEnd, char dst[], int dstBegin)
! bool LibraryCallKit::inline_string_getCharsU() {
! if (too_many_traps(Deoptimization::Reason_intrinsic)) return false;
!
! // Get the arguments.
! Node* value = argument(0);
! Node* src_begin = argument(1);
! Node* src_end = argument(2); // exclusive offset (i < src_end)
! Node* dst = argument(3);
! Node* dst_begin = argument(4);
!
! // Check for allocation before we add nodes that would confuse
! // tightly_coupled_allocation()
! AllocateArrayNode* alloc = tightly_coupled_allocation(dst, NULL);
!
! // Check if a null path was taken unconditionally.
! value = null_check(value);
! dst = null_check(dst);
! if (stopped()) {
! return true;
! }
!
! // Range checks are done by caller.
!
! // Get length and convert char[] offset to byte[] offset
! Node* length = _gvn.transform(new SubINode(src_end, src_begin));
! src_begin = _gvn.transform(new LShiftINode(src_begin, intcon(1)));
!
! if (!stopped()) {
! // Calculate starting addresses.
! Node* src_start = array_element_address(value, src_begin, T_BYTE);
! Node* dst_start = array_element_address(dst, dst_begin, T_CHAR);
!
! // Check if array addresses are aligned to HeapWordSize
! const TypeInt* tsrc = gvn().type(src_begin)->is_int();
! const TypeInt* tdst = gvn().type(dst_begin)->is_int();
! bool aligned = tsrc->is_con() && ((tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) &&
! tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0);
!
! // Figure out which arraycopy runtime method to call (disjoint, uninitialized).
! const char* copyfunc_name = "arraycopy";
! address copyfunc_addr = StubRoutines::select_arraycopy_function(T_CHAR, aligned, true, copyfunc_name, true);
! Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
! OptoRuntime::fast_arraycopy_Type(),
! copyfunc_addr, copyfunc_name, TypeRawPtr::BOTTOM,
! src_start, dst_start, ConvI2X(length) XTOP);
! // Do not let reads from the cloned object float above the arraycopy.
! if (alloc != NULL) {
! if (alloc->maybe_set_complete(&_gvn)) {
! // "You break it, you buy it."
! InitializeNode* init = alloc->initialization();
! assert(init->is_complete(), "we just did this");
! init->set_complete_with_arraycopy();
! assert(dst->is_CheckCastPP(), "sanity");
! assert(dst->in(0)->in(0) == init, "dest pinned");
! }
! // Do not let stores that initialize this object be reordered with
! // a subsequent store that would make this object accessible by
! // other threads.
! // Record what AllocateNode this StoreStore protects so that
! // escape analysis can go from the MemBarStoreStoreNode to the
! // AllocateNode and eliminate the MemBarStoreStoreNode if possible
! // based on the escape status of the AllocateNode.
! insert_mem_bar(Op_MemBarStoreStore, alloc->proj_out(AllocateNode::RawAddress));
! } else {
! insert_mem_bar(Op_MemBarCPUOrder);
}
}
! C->set_has_split_ifs(true); // Has chance for split-if optimization
! return true;
! }
!
! //----------------------inline_string_char_access----------------------------
! // Store/Load char to/from byte[] array.
! // static void StringUTF16.putChar(byte[] val, int index, int c)
! // static char StringUTF16.getChar(byte[] val, int index)
! bool LibraryCallKit::inline_string_char_access(bool is_store) {
! Node* value = argument(0);
! Node* index = argument(1);
! Node* ch = is_store ? argument(2) : NULL;
!
! // This intrinsic accesses byte[] array as char[] array. Computing the offsets
! // correctly requires matched array shapes.
! assert (arrayOopDesc::base_offset_in_bytes(T_CHAR) == arrayOopDesc::base_offset_in_bytes(T_BYTE),
! "sanity: byte[] and char[] bases agree");
! assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2,
! "sanity: byte[] and char[] scales agree");
!
! Node* adr = array_element_address(value, index, T_CHAR);
! if (is_store) {
! (void) store_to_memory(control(), adr, ch, T_CHAR, TypeAryPtr::BYTES, MemNode::unordered);
! } else {
! ch = make_load(control(), adr, TypeInt::CHAR, T_CHAR, MemNode::unordered);
! set_result(ch);
}
return true;
}
//--------------------------round_double_node--------------------------------
// Round a double node if necessary.
*** 4185,4200 ****
}
set_result(_gvn.transform(result));
return true;
}
- #ifdef _LP64
- #define XTOP ,top() /*additional argument*/
- #else //_LP64
- #define XTOP /*no additional argument*/
- #endif //_LP64
-
//----------------------inline_unsafe_copyMemory-------------------------
// public native void sun.misc.Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes);
bool LibraryCallKit::inline_unsafe_copyMemory() {
if (callee()->is_static()) return false; // caller must have the capability!
null_check_receiver(); // null-check receiver
--- 4296,4305 ----
*** 4999,5012 ****
}
// Figure out the size and type of the elements we will be copying.
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
! if (src_elem != T_CHAR || dst_elem != T_BYTE) {
return false;
}
! Node* src_start = array_element_address(src, src_offset, src_elem);
Node* dst_start = array_element_address(dst, dst_offset, dst_elem);
// 'src_start' points to src array + scaled offset
// 'dst_start' points to dst array + scaled offset
const TypeAryPtr* mtype = TypeAryPtr::BYTES;
--- 5104,5118 ----
}
// Figure out the size and type of the elements we will be copying.
BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
BasicType dst_elem = dst_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
! if (!((src_elem == T_CHAR) || (src_elem== T_BYTE)) || dst_elem != T_BYTE) {
return false;
}
!
! Node* src_start = array_element_address(src, src_offset, T_CHAR);
Node* dst_start = array_element_address(dst, dst_offset, dst_elem);
// 'src_start' points to src array + scaled offset
// 'dst_start' points to dst array + scaled offset
const TypeAryPtr* mtype = TypeAryPtr::BYTES;
*** 5120,5130 ****
return true;
}
//-------------inline_squareToLen------------------------------------
bool LibraryCallKit::inline_squareToLen() {
! assert(UseSquareToLenIntrinsic, "not implementated on this platform");
address stubAddr = StubRoutines::squareToLen();
if (stubAddr == NULL) {
return false; // Intrinsic's stub is not implemented on this platform
}
--- 5226,5236 ----
return true;
}
//-------------inline_squareToLen------------------------------------
bool LibraryCallKit::inline_squareToLen() {
! assert(UseSquareToLenIntrinsic, "not implemented on this platform");
address stubAddr = StubRoutines::squareToLen();
if (stubAddr == NULL) {
return false; // Intrinsic's stub is not implemented on this platform
}
*** 5166,5176 ****
return true;
}
//-------------inline_mulAdd------------------------------------------
bool LibraryCallKit::inline_mulAdd() {
! assert(UseMulAddIntrinsic, "not implementated on this platform");
address stubAddr = StubRoutines::mulAdd();
if (stubAddr == NULL) {
return false; // Intrinsic's stub is not implemented on this platform
}
--- 5272,5282 ----
return true;
}
//-------------inline_mulAdd------------------------------------------
bool LibraryCallKit::inline_mulAdd() {
! assert(UseMulAddIntrinsic, "not implemented on this platform");
address stubAddr = StubRoutines::mulAdd();
if (stubAddr == NULL) {
return false; // Intrinsic's stub is not implemented on this platform
}
< prev index next >