1.1 --- a/src/share/vm/opto/library_call.cpp Tue Sep 09 19:18:13 2014 +0000 1.2 +++ b/src/share/vm/opto/library_call.cpp Tue Sep 02 12:48:45 2014 -0700 1.3 @@ -322,6 +322,7 @@ 1.4 bool inline_updateCRC32(); 1.5 bool inline_updateBytesCRC32(); 1.6 bool inline_updateByteBufferCRC32(); 1.7 + bool inline_multiplyToLen(); 1.8 }; 1.9 1.10 1.11 @@ -330,8 +331,12 @@ 1.12 vmIntrinsics::ID id = m->intrinsic_id(); 1.13 assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); 1.14 1.15 - if (DisableIntrinsic[0] != '\0' 1.16 - && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) { 1.17 + ccstr disable_intr = NULL; 1.18 + 1.19 + if ((DisableIntrinsic[0] != '\0' 1.20 + && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) || 1.21 + (method_has_option_value("DisableIntrinsic", disable_intr) 1.22 + && strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)) { 1.23 // disabled by a user request on the command line: 1.24 // example: -XX:DisableIntrinsic=_hashCode,_getClass 1.25 return NULL; 1.26 @@ -515,6 +520,10 @@ 1.27 if (!UseAESIntrinsics) return NULL; 1.28 break; 1.29 1.30 + case vmIntrinsics::_multiplyToLen: 1.31 + if (!UseMultiplyToLenIntrinsic) return NULL; 1.32 + break; 1.33 + 1.34 case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: 1.35 case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: 1.36 if (!UseAESIntrinsics) return NULL; 1.37 @@ -912,6 +921,9 @@ 1.38 case vmIntrinsics::_digestBase_implCompressMB: 1.39 return inline_digestBase_implCompressMB(predicate); 1.40 1.41 + case vmIntrinsics::_multiplyToLen: 1.42 + return inline_multiplyToLen(); 1.43 + 1.44 case vmIntrinsics::_encodeISOArray: 1.45 return inline_encodeISOArray(); 1.46 1.47 @@ -5735,6 +5747,106 @@ 1.48 return true; 1.49 } 1.50 1.51 +//-------------inline_multiplyToLen----------------------------------- 1.52 +bool LibraryCallKit::inline_multiplyToLen() { 1.53 + assert(UseMultiplyToLenIntrinsic, "not implementated on this platform"); 1.54 + 1.55 + address stubAddr = StubRoutines::multiplyToLen(); 1.56 + if (stubAddr == NULL) { 1.57 + return false; // Intrinsic's stub is not implemented on this platform 1.58 + } 1.59 + const char* stubName = "multiplyToLen"; 1.60 + 1.61 + assert(callee()->signature()->size() == 5, "multiplyToLen has 5 parameters"); 1.62 + 1.63 + Node* x = argument(1); 1.64 + Node* xlen = argument(2); 1.65 + Node* y = argument(3); 1.66 + Node* ylen = argument(4); 1.67 + Node* z = argument(5); 1.68 + 1.69 + const Type* x_type = x->Value(&_gvn); 1.70 + const Type* y_type = y->Value(&_gvn); 1.71 + const TypeAryPtr* top_x = x_type->isa_aryptr(); 1.72 + const TypeAryPtr* top_y = y_type->isa_aryptr(); 1.73 + if (top_x == NULL || top_x->klass() == NULL || 1.74 + top_y == NULL || top_y->klass() == NULL) { 1.75 + // failed array check 1.76 + return false; 1.77 + } 1.78 + 1.79 + BasicType x_elem = x_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); 1.80 + BasicType y_elem = y_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type(); 1.81 + if (x_elem != T_INT || y_elem != T_INT) { 1.82 + return false; 1.83 + } 1.84 + 1.85 + // Set the original stack and the reexecute bit for the interpreter to reexecute 1.86 + // the bytecode that invokes BigInteger.multiplyToLen() if deoptimization happens 1.87 + // on the return from z array allocation in runtime. 1.88 + { PreserveReexecuteState preexecs(this); 1.89 + jvms()->set_should_reexecute(true); 1.90 + 1.91 + Node* x_start = array_element_address(x, intcon(0), x_elem); 1.92 + Node* y_start = array_element_address(y, intcon(0), y_elem); 1.93 + // 'x_start' points to x array + scaled xlen 1.94 + // 'y_start' points to y array + scaled ylen 1.95 + 1.96 + // Allocate the result array 1.97 + Node* zlen = _gvn.transform(new(C) AddINode(xlen, ylen)); 1.98 + Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_INT))); 1.99 + 1.100 + IdealKit ideal(this); 1.101 + 1.102 +#define __ ideal. 1.103 + Node* one = __ ConI(1); 1.104 + Node* zero = __ ConI(0); 1.105 + IdealVariable need_alloc(ideal), z_alloc(ideal); __ declarations_done(); 1.106 + __ set(need_alloc, zero); 1.107 + __ set(z_alloc, z); 1.108 + __ if_then(z, BoolTest::eq, null()); { 1.109 + __ increment (need_alloc, one); 1.110 + } __ else_(); { 1.111 + // Update graphKit memory and control from IdealKit. 1.112 + sync_kit(ideal); 1.113 + Node* zlen_arg = load_array_length(z); 1.114 + // Update IdealKit memory and control from graphKit. 1.115 + __ sync_kit(this); 1.116 + __ if_then(zlen_arg, BoolTest::lt, zlen); { 1.117 + __ increment (need_alloc, one); 1.118 + } __ end_if(); 1.119 + } __ end_if(); 1.120 + 1.121 + __ if_then(__ value(need_alloc), BoolTest::ne, zero); { 1.122 + // Update graphKit memory and control from IdealKit. 1.123 + sync_kit(ideal); 1.124 + Node * narr = new_array(klass_node, zlen, 1); 1.125 + // Update IdealKit memory and control from graphKit. 1.126 + __ sync_kit(this); 1.127 + __ set(z_alloc, narr); 1.128 + } __ end_if(); 1.129 + 1.130 + sync_kit(ideal); 1.131 + z = __ value(z_alloc); 1.132 + _gvn.set_type(z, TypeAryPtr::INTS); 1.133 + // Final sync IdealKit and GraphKit. 1.134 + final_sync(ideal); 1.135 +#undef __ 1.136 + 1.137 + Node* z_start = array_element_address(z, intcon(0), T_INT); 1.138 + 1.139 + Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, 1.140 + OptoRuntime::multiplyToLen_Type(), 1.141 + stubAddr, stubName, TypePtr::BOTTOM, 1.142 + x_start, xlen, y_start, ylen, z_start, zlen); 1.143 + } // original reexecute is set back here 1.144 + 1.145 + C->set_has_split_ifs(true); // Has chance for split-if optimization 1.146 + set_result(z); 1.147 + return true; 1.148 +} 1.149 + 1.150 + 1.151 /** 1.152 * Calculate CRC32 for byte. 1.153 * int java.util.zip.CRC32.update(int crc, int b)