--- old/src/share/vm/c1/c1_GraphBuilder.cpp 2016-06-06 10:38:20.315685958 +0200 +++ new/src/share/vm/c1/c1_GraphBuilder.cpp 2016-06-06 10:38:20.195685963 +0200 @@ -3415,66 +3415,66 @@ return NULL; } -void GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) { +bool GraphBuilder::build_graph_for_intrinsic(ciMethod* callee) { vmIntrinsics::ID id = callee->intrinsic_id(); assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); // Some intrinsics need special IR nodes. switch(id) { - case vmIntrinsics::_getObject : append_unsafe_get_obj(callee, T_OBJECT, false); return; - case vmIntrinsics::_getBoolean : append_unsafe_get_obj(callee, T_BOOLEAN, false); return; - case vmIntrinsics::_getByte : append_unsafe_get_obj(callee, T_BYTE, false); return; - case vmIntrinsics::_getShort : append_unsafe_get_obj(callee, T_SHORT, false); return; - case vmIntrinsics::_getChar : append_unsafe_get_obj(callee, T_CHAR, false); return; - case vmIntrinsics::_getInt : append_unsafe_get_obj(callee, T_INT, false); return; - case vmIntrinsics::_getLong : append_unsafe_get_obj(callee, T_LONG, false); return; - case vmIntrinsics::_getFloat : append_unsafe_get_obj(callee, T_FLOAT, false); return; - case vmIntrinsics::_getDouble : append_unsafe_get_obj(callee, T_DOUBLE, false); return; - case vmIntrinsics::_putObject : append_unsafe_put_obj(callee, T_OBJECT, false); return; - case vmIntrinsics::_putBoolean : append_unsafe_put_obj(callee, T_BOOLEAN, false); return; - case vmIntrinsics::_putByte : append_unsafe_put_obj(callee, T_BYTE, false); return; - case vmIntrinsics::_putShort : append_unsafe_put_obj(callee, T_SHORT, false); return; - case vmIntrinsics::_putChar : append_unsafe_put_obj(callee, T_CHAR, false); return; - case vmIntrinsics::_putInt : append_unsafe_put_obj(callee, T_INT, false); return; - case vmIntrinsics::_putLong : append_unsafe_put_obj(callee, T_LONG, false); return; - case vmIntrinsics::_putFloat : append_unsafe_put_obj(callee, T_FLOAT, false); return; - case vmIntrinsics::_putDouble : append_unsafe_put_obj(callee, T_DOUBLE, false); return; - case vmIntrinsics::_getShortUnaligned : append_unsafe_get_obj(callee, T_SHORT, false); return; - case vmIntrinsics::_getCharUnaligned : append_unsafe_get_obj(callee, T_CHAR, false); return; - case vmIntrinsics::_getIntUnaligned : append_unsafe_get_obj(callee, T_INT, false); return; - case vmIntrinsics::_getLongUnaligned : append_unsafe_get_obj(callee, T_LONG, false); return; - case vmIntrinsics::_putShortUnaligned : append_unsafe_put_obj(callee, T_SHORT, false); return; - case vmIntrinsics::_putCharUnaligned : append_unsafe_put_obj(callee, T_CHAR, false); return; - case vmIntrinsics::_putIntUnaligned : append_unsafe_put_obj(callee, T_INT, false); return; - case vmIntrinsics::_putLongUnaligned : append_unsafe_put_obj(callee, T_LONG, false); return; - case vmIntrinsics::_getObjectVolatile : append_unsafe_get_obj(callee, T_OBJECT, true); return; - case vmIntrinsics::_getBooleanVolatile : append_unsafe_get_obj(callee, T_BOOLEAN, true); return; - case vmIntrinsics::_getByteVolatile : append_unsafe_get_obj(callee, T_BYTE, true); return; - case vmIntrinsics::_getShortVolatile : append_unsafe_get_obj(callee, T_SHORT, true); return; - case vmIntrinsics::_getCharVolatile : append_unsafe_get_obj(callee, T_CHAR, true); return; - case vmIntrinsics::_getIntVolatile : append_unsafe_get_obj(callee, T_INT, true); return; - case vmIntrinsics::_getLongVolatile : append_unsafe_get_obj(callee, T_LONG, true); return; - case vmIntrinsics::_getFloatVolatile : append_unsafe_get_obj(callee, T_FLOAT, true); return; - case vmIntrinsics::_getDoubleVolatile : append_unsafe_get_obj(callee, T_DOUBLE, true); return; - case vmIntrinsics::_putObjectVolatile : append_unsafe_put_obj(callee, T_OBJECT, true); return; - case vmIntrinsics::_putBooleanVolatile : append_unsafe_put_obj(callee, T_BOOLEAN, true); return; - case vmIntrinsics::_putByteVolatile : append_unsafe_put_obj(callee, T_BYTE, true); return; - case vmIntrinsics::_putShortVolatile : append_unsafe_put_obj(callee, T_SHORT, true); return; - case vmIntrinsics::_putCharVolatile : append_unsafe_put_obj(callee, T_CHAR, true); return; - case vmIntrinsics::_putIntVolatile : append_unsafe_put_obj(callee, T_INT, true); return; - case vmIntrinsics::_putLongVolatile : append_unsafe_put_obj(callee, T_LONG, true); return; - case vmIntrinsics::_putFloatVolatile : append_unsafe_put_obj(callee, T_FLOAT, true); return; - case vmIntrinsics::_putDoubleVolatile : append_unsafe_put_obj(callee, T_DOUBLE, true); return; + case vmIntrinsics::_getObject : append_unsafe_get_obj(callee, T_OBJECT, false); return true; + case vmIntrinsics::_getBoolean : append_unsafe_get_obj(callee, T_BOOLEAN, false); return true; + case vmIntrinsics::_getByte : append_unsafe_get_obj(callee, T_BYTE, false); return true; + case vmIntrinsics::_getShort : append_unsafe_get_obj(callee, T_SHORT, false); return true; + case vmIntrinsics::_getChar : append_unsafe_get_obj(callee, T_CHAR, false); return true; + case vmIntrinsics::_getInt : append_unsafe_get_obj(callee, T_INT, false); return true; + case vmIntrinsics::_getLong : append_unsafe_get_obj(callee, T_LONG, false); return true; + case vmIntrinsics::_getFloat : append_unsafe_get_obj(callee, T_FLOAT, false); return true; + case vmIntrinsics::_getDouble : append_unsafe_get_obj(callee, T_DOUBLE, false); return true; + case vmIntrinsics::_putObject : append_unsafe_put_obj(callee, T_OBJECT, false); return true; + case vmIntrinsics::_putBoolean : append_unsafe_put_obj(callee, T_BOOLEAN, false); return true; + case vmIntrinsics::_putByte : append_unsafe_put_obj(callee, T_BYTE, false); return true; + case vmIntrinsics::_putShort : append_unsafe_put_obj(callee, T_SHORT, false); return true; + case vmIntrinsics::_putChar : append_unsafe_put_obj(callee, T_CHAR, false); return true; + case vmIntrinsics::_putInt : append_unsafe_put_obj(callee, T_INT, false); return true; + case vmIntrinsics::_putLong : append_unsafe_put_obj(callee, T_LONG, false); return true; + case vmIntrinsics::_putFloat : append_unsafe_put_obj(callee, T_FLOAT, false); return true; + case vmIntrinsics::_putDouble : append_unsafe_put_obj(callee, T_DOUBLE, false); return true; + case vmIntrinsics::_getShortUnaligned : append_unsafe_get_obj(callee, T_SHORT, false); return true; + case vmIntrinsics::_getCharUnaligned : append_unsafe_get_obj(callee, T_CHAR, false); return true; + case vmIntrinsics::_getIntUnaligned : append_unsafe_get_obj(callee, T_INT, false); return true; + case vmIntrinsics::_getLongUnaligned : append_unsafe_get_obj(callee, T_LONG, false); return true; + case vmIntrinsics::_putShortUnaligned : append_unsafe_put_obj(callee, T_SHORT, false); return true; + case vmIntrinsics::_putCharUnaligned : append_unsafe_put_obj(callee, T_CHAR, false); return true; + case vmIntrinsics::_putIntUnaligned : append_unsafe_put_obj(callee, T_INT, false); return true; + case vmIntrinsics::_putLongUnaligned : append_unsafe_put_obj(callee, T_LONG, false); return true; + case vmIntrinsics::_getObjectVolatile : append_unsafe_get_obj(callee, T_OBJECT, true); return true; + case vmIntrinsics::_getBooleanVolatile : append_unsafe_get_obj(callee, T_BOOLEAN, true); return true; + case vmIntrinsics::_getByteVolatile : append_unsafe_get_obj(callee, T_BYTE, true); return true; + case vmIntrinsics::_getShortVolatile : append_unsafe_get_obj(callee, T_SHORT, true); return true; + case vmIntrinsics::_getCharVolatile : append_unsafe_get_obj(callee, T_CHAR, true); return true; + case vmIntrinsics::_getIntVolatile : append_unsafe_get_obj(callee, T_INT, true); return true; + case vmIntrinsics::_getLongVolatile : append_unsafe_get_obj(callee, T_LONG, true); return true; + case vmIntrinsics::_getFloatVolatile : append_unsafe_get_obj(callee, T_FLOAT, true); return true; + case vmIntrinsics::_getDoubleVolatile : append_unsafe_get_obj(callee, T_DOUBLE, true); return true; + case vmIntrinsics::_putObjectVolatile : append_unsafe_put_obj(callee, T_OBJECT, true); return true; + case vmIntrinsics::_putBooleanVolatile : append_unsafe_put_obj(callee, T_BOOLEAN, true); return true; + case vmIntrinsics::_putByteVolatile : append_unsafe_put_obj(callee, T_BYTE, true); return true; + case vmIntrinsics::_putShortVolatile : append_unsafe_put_obj(callee, T_SHORT, true); return true; + case vmIntrinsics::_putCharVolatile : append_unsafe_put_obj(callee, T_CHAR, true); return true; + case vmIntrinsics::_putIntVolatile : append_unsafe_put_obj(callee, T_INT, true); return true; + case vmIntrinsics::_putLongVolatile : append_unsafe_put_obj(callee, T_LONG, true); return true; + case vmIntrinsics::_putFloatVolatile : append_unsafe_put_obj(callee, T_FLOAT, true); return true; + case vmIntrinsics::_putDoubleVolatile : append_unsafe_put_obj(callee, T_DOUBLE, true); return true; case vmIntrinsics::_compareAndSwapLong: case vmIntrinsics::_compareAndSwapInt: - case vmIntrinsics::_compareAndSwapObject: append_unsafe_CAS(callee); return; + case vmIntrinsics::_compareAndSwapObject: append_unsafe_CAS(callee); return true; case vmIntrinsics::_getAndAddInt: - case vmIntrinsics::_getAndAddLong : append_unsafe_get_and_set_obj(callee, true); return; + case vmIntrinsics::_getAndAddLong : append_unsafe_get_and_set_obj(callee, true); return true; case vmIntrinsics::_getAndSetInt : case vmIntrinsics::_getAndSetLong : - case vmIntrinsics::_getAndSetObject : append_unsafe_get_and_set_obj(callee, false); return; - case vmIntrinsics::_getCharStringU : append_char_access(callee, false); return; - case vmIntrinsics::_putCharStringU : append_char_access(callee, true); return; + case vmIntrinsics::_getAndSetObject : append_unsafe_get_and_set_obj(callee, false); return true; + case vmIntrinsics::_getCharStringU : return append_char_access(callee, false); + case vmIntrinsics::_putCharStringU : return append_char_access(callee, true); default: break; } @@ -3514,6 +3514,7 @@ if (callee != method() && profile_return() && result_type->is_object_kind()) { profile_return_type(result, callee); } + return true; } bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) { @@ -3536,8 +3537,7 @@ return false; } } - build_graph_for_intrinsic(callee); - return true; + return build_graph_for_intrinsic(callee); } @@ -4212,7 +4212,7 @@ compilation()->set_has_unsafe_access(true); } -void GraphBuilder::append_char_access(ciMethod* callee, bool is_store) { +bool GraphBuilder::append_char_access(ciMethod* callee, bool is_store) { // 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), @@ -4220,6 +4220,7 @@ assert (type2aelembytes(T_CHAR) == type2aelembytes(T_BYTE)*2, "sanity: byte[] and char[] scales agree"); + ValueStack* state_copy = state()->copy(); ValueStack* state_before = copy_state_indexed_access(); compilation()->set_has_access_indexed(true); Values* args = state()->pop_arguments(callee->arg_size()); @@ -4231,10 +4232,19 @@ store->set_flag(Instruction::NeedsRangeCheckFlag, false); _memory->store_value(value); } else { + // Bail when getChar over constants is requested: constant folding would + // reject folding mismatched char access over byte[]. A normal inlining for getChar + // Java method would constant fold nicely instead. + if(array->type()->as_StableArrayConstant() != NULL && + index->type()->as_IntConstant() != NULL) { + set_state(state_copy); + return false; + } Instruction* load = append(new LoadIndexed(array, index, NULL, T_CHAR, state_before)); load->set_flag(Instruction::NeedsRangeCheckFlag, false); push(load->type(), load); } + return true; } void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool success) {