< 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 >