< prev index next >
src/share/vm/opto/library_call.cpp
Print this page
@@ -1116,18 +1116,38 @@
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)));
+ src_count = _gvn.transform(new SubINode(src_count, from_index));
Node* src_start = array_element_address(src, src_offset, T_BYTE);
Node* tgt_start = array_element_address(tgt, intcon(0), T_BYTE);
+ RegionNode* bailout = new RegionNode(1);
+ record_for_igvn(bailout);
+
+ // Range checks
+ generate_negative_guard(src_offset, bailout);
+ generate_negative_guard(src_count, bailout);
+ generate_negative_guard(tgt_count, bailout);
+ Node* src_byte_count = _gvn.transform(new LShiftINode(src_count, intcon(1)));
+ Node* tgt_byte_count = _gvn.transform(new LShiftINode(tgt_count, intcon(1)));
+ generate_limit_guard(src_offset, (ae == StrIntrinsicNode::LL) ? src_count : src_byte_count, load_array_length(src), bailout);
+ generate_limit_guard(intcon(0), (ae == StrIntrinsicNode::UU) ? tgt_byte_count : tgt_count, load_array_length(tgt), 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;
+ }
+
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);
@@ -1166,13 +1186,31 @@
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* bailout = new RegionNode(1);
+ record_for_igvn(bailout);
+
+ // Range checks
+ generate_negative_guard(src_offset, bailout);
+ generate_negative_guard(src_count, bailout);
+ Node* byte_length = _gvn.transform(new LShiftINode(src_count, intcon(1)));
+ generate_limit_guard(src_offset, byte_length, load_array_length(src), 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;
+ }
+
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
@@ -1226,10 +1264,31 @@
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");
+ RegionNode* bailout = new RegionNode(1);
+ record_for_igvn(bailout);
+
+ // Range checks
+ generate_negative_guard(src_offset, bailout);
+ generate_negative_guard(dst_offset, bailout);
+ generate_negative_guard(length, bailout);
+ Node* byte_length = _gvn.transform(new LShiftINode(length, intcon(1)));
+ generate_limit_guard(src_offset, (compress && src_elem == T_BYTE) ? byte_length : length, load_array_length(src), bailout);
+ generate_limit_guard(dst_offset, (!compress && dst_elem == T_BYTE) ? byte_length : length, load_array_length(dst), 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;
+ }
+
// 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)));
@@ -1295,23 +1354,26 @@
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
+ // Range checks
generate_negative_guard(length, bailout);
+ generate_negative_guard(offset, bailout);
+ generate_limit_guard(offset, length, load_array_length(value), bailout);
+ // Make sure that resulting byte[] length does not overflow Integer.MAX_VALUE
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.
+ if (stopped()) {
+ return true;
+ }
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);
@@ -1382,16 +1444,35 @@
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)));
+ RegionNode* bailout = new RegionNode(1);
+ record_for_igvn(bailout);
+
+ // Range checks
+ generate_negative_guard(length, bailout);
+ generate_negative_guard(src_begin, bailout);
+ generate_negative_guard(dst_begin, bailout);
+ Node* byte_length = _gvn.transform(new LShiftINode(length, intcon(1)));
+ generate_limit_guard(src_begin, byte_length, load_array_length(value), bailout);
+ generate_limit_guard(dst_begin, length, load_array_length(dst), 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;
+ }
+
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);
< prev index next >