< prev index next >

## src/share/vm/opto/library_call.cpp

Print this page

    @@ -286,10 +286,12 @@
       bool inline_encodeISOArray();
       bool inline_updateCRC32();
       bool inline_updateBytesCRC32();
       bool inline_updateByteBufferCRC32();
       bool inline_multiplyToLen();
    +  bool inline_squareToLen();
    +  bool inline_mulAdd();

       bool inline_profileBoolean();
     };

    @@ -488,10 +490,18 @@

       case vmIntrinsics::_multiplyToLen:
         if (!UseMultiplyToLenIntrinsic) return NULL;
         break;

    +  case vmIntrinsics::_squareToLen:
    +    if (!UseSquareToLenIntrinsic) return NULL;
    +    break;
    +
    +  case vmIntrinsics::_mulAdd:
    +    if (!UseMulAddIntrinsic) return NULL;
    +    break;
    +
       case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt:
       case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
         if (!UseAESIntrinsics) return NULL;
         // these two require the predicated logic
         predicates = 1;

    @@ -886,10 +896,16 @@
         return inline_digestBase_implCompressMB(predicate);

       case vmIntrinsics::_multiplyToLen:
         return inline_multiplyToLen();

    +  case vmIntrinsics::_squareToLen:
    +    return inline_squareToLen();
    +
    +  case vmIntrinsics::_mulAdd:
    +    return inline_mulAdd();
    +
       case vmIntrinsics::_encodeISOArray:
         return inline_encodeISOArray();

       case vmIntrinsics::_updateCRC32:
         return inline_updateCRC32();

    @@ -5146,10 +5162,153 @@
       C->set_has_split_ifs(true); // Has chance for split-if optimization
       set_result(z);
       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
    +  }
    +  const char* stubName = "squareToLen";
    +
    +  assert(callee()->signature()->size() == 3, "squareToLen has 3 parameters");
    +
    +  Node* x   = argument(0);
    +  Node* len = argument(1);
    +  Node* z   = argument(2);
    +
    +  const Type* x_type = x->Value(&_gvn);
    +  const TypeAryPtr* top_x = x_type->isa_aryptr();
    +  if (top_x  == NULL || top_x->klass()  == NULL) {
    +    // failed array check
    +    return false;
    +  }
    +
    +  BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
    +  if (x_elem != T_INT) {
    +    return false;
    +  }
    +
    +  // Set the original stack and the reexecute bit for the interpreter to reexecute
    +  // the bytecode that invokes BigInteger.squareToLen() if deoptimization happens
    +  // on the return from z array allocation in runtime.
    +  { PreserveReexecuteState preexecs(this);
    +    jvms()->set_should_reexecute(true);
    +
    +    Node* x_start = array_element_address(x, intcon(0), x_elem);
    +    // 'x_start' points to x array + scaled len
    +
    +    // Allocate the result array
    +    Node* zlen = _gvn.transform(new AddINode(len, len));
    +    ciKlass* klass = ciTypeArrayKlass::make(T_INT);
    +    Node* klass_node = makecon(TypeKlassPtr::make(klass));
    +
    +    IdealKit ideal(this);
    +
    +#define __ ideal.
    +     Node* one = __ ConI(1);
    +     Node* zero = __ ConI(0);
    +     IdealVariable need_alloc(ideal), z_alloc(ideal);  __ declarations_done();
    +     __ set(need_alloc, zero);
    +     __ set(z_alloc, z);
    +     __ if_then(z, BoolTest::eq, null()); {
    +       __ increment (need_alloc, one);
    +     } __ else_(); {
    +       // Update graphKit memory and control from IdealKit.
    +       sync_kit(ideal);
    +       Node* zlen_arg = load_array_length(z);
    +       // Update IdealKit memory and control from graphKit.
    +       __ sync_kit(this);
    +       __ if_then(zlen_arg, BoolTest::lt, zlen); {
    +         __ increment (need_alloc, one);
    +       } __ end_if();
    +     } __ end_if();
    +
    +     __ if_then(__ value(need_alloc), BoolTest::ne, zero); {
    +       // Update graphKit memory and control from IdealKit.
    +       sync_kit(ideal);
    +       Node * narr = new_array(klass_node, zlen, 1);
    +       // Update IdealKit memory and control from graphKit.
    +       __ sync_kit(this);
    +       __ set(z_alloc, narr);
    +     } __ end_if();
    +
    +     sync_kit(ideal);
    +     z = __ value(z_alloc);
    +     // Can't use TypeAryPtr::INTS which uses Bottom offset.
    +     _gvn.set_type(z, TypeOopPtr::make_from_klass(klass));
    +     // Final sync IdealKit and GraphKit.
    +     final_sync(ideal);
    +#undef __
    +
    +    Node* z_start = array_element_address(z, intcon(0), T_INT);
    +
    +    Node*  call = make_runtime_call(RC_LEAF|RC_NO_FP,
    +                                 OptoRuntime::squareToLen_Type(),
    +                                 stubAddr, stubName, TypePtr::BOTTOM,
    +                                 x_start, len, z_start, zlen);
    +  } // original reexecute is set back here
    +
    +  C->set_has_split_ifs(true); // Has chance for split-if optimization
    +  set_result(z);
    +  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
    +  }
    +  const char* stubName = "mulAdd";
    +
    +  assert(callee()->signature()->size() == 5, "mulAdd has 5 parameters");
    +
    +  Node* out      = argument(0);
    +  Node* in       = argument(1);
    +  Node* offset   = argument(2);
    +  Node* len      = argument(3);
    +  Node* k        = argument(4);
    +
    +  const Type* out_type = out->Value(&_gvn);
    +  const Type* in_type = in->Value(&_gvn);
    +  const TypeAryPtr* top_out = out_type->isa_aryptr();
    +  const TypeAryPtr* top_in = in_type->isa_aryptr();
    +  if (top_out  == NULL || top_out->klass()  == NULL ||
    +      top_in == NULL || top_in->klass() == NULL) {
    +    // failed array check
    +    return false;
    +  }
    +
    +  BasicType out_elem = out_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
    +  BasicType in_elem = in_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
    +  if (out_elem != T_INT || in_elem != T_INT) {
    +    return false;
    +  }
    +
    +   Node* outlen = load_array_length(out);
    +   Node* new_offset = _gvn.transform(new SubINode(outlen, offset));
    +   Node* out_start = array_element_address(out, intcon(0), out_elem);
    +   // 'out_start' points to out array + scaled len
    +   Node* in_start = array_element_address(in, intcon(0), in_elem);
    +   // 'in_start' points to in array + scaled len
    +
    +   Node*  call = make_runtime_call(RC_LEAF|RC_NO_FP,
    +                                   OptoRuntime::mulAdd_Type(),
    +                                   stubAddr, stubName, TypePtr::BOTTOM,
    +                                   out_start,in_start, new_offset, len, k);
    +  Node* result = _gvn.transform(new ProjNode(call, TypeFunc::Parms));
    +  set_result(result);
    +  return true;
    +}
    +

     /**
      * Calculate CRC32 for byte.
      * int java.util.zip.CRC32.update(int crc, int b)
      */

< prev index next >