Skip to content
Permalink
Browse files
8265518: C1: Intrinsic support for Preconditions.checkIndex
Reviewed-by: dfuchs, iveresov
  • Loading branch information
Yi Yang committed Jun 12, 2021
1 parent a466b49 commit 5cee23a9ed0b7fe2657be7492d9c1f78fcd02ebf
@@ -207,7 +207,8 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
case vmIntrinsics::_putCharUnaligned:
case vmIntrinsics::_putIntUnaligned:
case vmIntrinsics::_putLongUnaligned:
case vmIntrinsics::_checkIndex:
case vmIntrinsics::_Preconditions_checkIndex:
case vmIntrinsics::_Preconditions_checkLongIndex:
case vmIntrinsics::_updateCRC32:
case vmIntrinsics::_updateBytesCRC32:
case vmIntrinsics::_updateByteBufferCRC32:
@@ -485,22 +485,6 @@ void LIRGenerator::array_range_check(LIR_Opr array, LIR_Opr index,
}
}


void LIRGenerator::nio_range_check(LIR_Opr buffer, LIR_Opr index, LIR_Opr result, CodeEmitInfo* info) {
CodeStub* stub = new RangeCheckStub(info, index);
if (index->is_constant()) {
cmp_mem_int(lir_cond_belowEqual, buffer, java_nio_Buffer::limit_offset(), index->as_jint(), info);
__ branch(lir_cond_belowEqual, stub); // forward branch
} else {
cmp_reg_mem(lir_cond_aboveEqual, index, buffer,
java_nio_Buffer::limit_offset(), T_INT, info);
__ branch(lir_cond_aboveEqual, stub); // forward branch
}
__ move(index, result);
}



void LIRGenerator::arithmetic_op(Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, LIR_Opr tmp_op, CodeEmitInfo* info) {
LIR_Opr result_op = result;
LIR_Opr left_op = left;
@@ -1859,40 +1843,71 @@ void LIRGenerator::do_LoadField(LoadField* x) {
info ? new CodeEmitInfo(info) : NULL, info);
}

// int/long jdk.internal.util.Preconditions.checkIndex
void LIRGenerator::do_PreconditionsCheckIndex(Intrinsic* x, BasicType type) {
assert(x->number_of_arguments() == 3, "wrong type");
LIRItem index(x->argument_at(0), this);
LIRItem length(x->argument_at(1), this);
LIRItem oobef(x->argument_at(2), this);

//------------------------java.nio.Buffer.checkIndex------------------------

// int java.nio.Buffer.checkIndex(int)
void LIRGenerator::do_NIOCheckIndex(Intrinsic* x) {
// NOTE: by the time we are in checkIndex() we are guaranteed that
// the buffer is non-null (because checkIndex is package-private and
// only called from within other methods in the buffer).
assert(x->number_of_arguments() == 2, "wrong type");
LIRItem buf (x->argument_at(0), this);
LIRItem index(x->argument_at(1), this);
buf.load_item();
index.load_item();
length.load_item();
oobef.load_item();

LIR_Opr result = rlock_result(x);
if (GenerateRangeChecks) {
CodeEmitInfo* info = state_for(x);
CodeStub* stub = new RangeCheckStub(info, index.result());
if (index.result()->is_constant()) {
cmp_mem_int(lir_cond_belowEqual, buf.result(), java_nio_Buffer::limit_offset(), index.result()->as_jint(), info);
__ branch(lir_cond_belowEqual, stub);
} else {
cmp_reg_mem(lir_cond_aboveEqual, index.result(), buf.result(),
java_nio_Buffer::limit_offset(), T_INT, info);
__ branch(lir_cond_aboveEqual, stub);
// x->state() is created from copy_state_for_exception, it does not contains arguments
// we should prepare them before entering into interpreter mode due to deoptimization.
ValueStack* state = x->state();
for (int i = 0; i < x->number_of_arguments(); i++) {
Value arg = x->argument_at(i);
state->push(arg->type(), arg);
}
CodeEmitInfo* info = state_for(x, state);

LIR_Opr len = length.result();
LIR_Opr zero = NULL;
if (type == T_INT) {
zero = LIR_OprFact::intConst(0);
if (length.result()->is_constant()){
len = LIR_OprFact::intConst(length.result()->as_jint());
}
__ move(index.result(), result);
} else {
// Just load the index into the result register
__ move(index.result(), result);
assert(type == T_LONG, "sanity check");
zero = LIR_OprFact::longConst(0);
if (length.result()->is_constant()){
len = LIR_OprFact::longConst(length.result()->as_jlong());
}
}
// C1 can not handle the case that comparing index with constant value while condition
// is neither lir_cond_equal nor lir_cond_notEqual, see LIR_Assembler::comp_op.
LIR_Opr zero_reg = new_register(type);
__ move(zero, zero_reg);
#if defined(X86) && !defined(_LP64)
// BEWARE! On 32-bit x86 cmp clobbers its left argument so we need a temp copy.
LIR_Opr index_copy = new_register(index.type());
// index >= 0
__ move(index.result(), index_copy);
__ cmp(lir_cond_less, index_copy, zero_reg);
__ branch(lir_cond_less, new DeoptimizeStub(info, Deoptimization::Reason_range_check,
Deoptimization::Action_make_not_entrant));
// index < length
__ move(index.result(), index_copy);
__ cmp(lir_cond_greaterEqual, index_copy, len);
__ branch(lir_cond_greaterEqual, new DeoptimizeStub(info, Deoptimization::Reason_range_check,
Deoptimization::Action_make_not_entrant));
#else
// index >= 0
__ cmp(lir_cond_less, index.result(), zero_reg);
__ branch(lir_cond_less, new DeoptimizeStub(info, Deoptimization::Reason_range_check,
Deoptimization::Action_make_not_entrant));
// index < length
__ cmp(lir_cond_greaterEqual, index.result(), len);
__ branch(lir_cond_greaterEqual, new DeoptimizeStub(info, Deoptimization::Reason_range_check,
Deoptimization::Action_make_not_entrant));
#endif
__ move(index.result(), result);
}


//------------------------array access--------------------------------------


@@ -3115,8 +3130,12 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
case vmIntrinsics::_fmaD: do_FmaIntrinsic(x); break;
case vmIntrinsics::_fmaF: do_FmaIntrinsic(x); break;

// java.nio.Buffer.checkIndex
case vmIntrinsics::_checkIndex: do_NIOCheckIndex(x); break;
case vmIntrinsics::_Preconditions_checkIndex:
do_PreconditionsCheckIndex(x, T_INT);
break;
case vmIntrinsics::_Preconditions_checkLongIndex:
do_PreconditionsCheckIndex(x, T_LONG);
break;

case vmIntrinsics::_compareAndSetReference:
do_CompareAndSwap(x, objectType);
@@ -260,7 +260,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
void do_LibmIntrinsic(Intrinsic* x);
void do_ArrayCopy(Intrinsic* x);
void do_CompareAndSwap(Intrinsic* x, ValueType* type);
void do_NIOCheckIndex(Intrinsic* x);
void do_PreconditionsCheckIndex(Intrinsic* x, BasicType type);
void do_FPIntrinsics(Intrinsic* x);
void do_Reference_get(Intrinsic* x);
void do_update_CRC32(Intrinsic* x);
@@ -348,8 +348,6 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {

// this loads the length and compares against the index
void array_range_check (LIR_Opr array, LIR_Opr index, CodeEmitInfo* null_check_info, CodeEmitInfo* range_check_info);
// For java.nio.Buffer.checkIndex
void nio_range_check (LIR_Opr buffer, LIR_Opr index, LIR_Opr result, CodeEmitInfo* info);

void arithmetic_op_int (Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, LIR_Opr tmp);
void arithmetic_op_long (Bytecodes::Code code, LIR_Opr result, LIR_Opr left, LIR_Opr right, CodeEmitInfo* info = NULL);
@@ -153,9 +153,6 @@
product(bool, InlineSynchronizedMethods, true, \
"Inline synchronized methods") \
\
product(bool, InlineNIOCheckIndex, true, DIAGNOSTIC, \
"Intrinsify java.nio.Buffer.checkIndex") \
\
develop(bool, CanonicalizeNodes, true, \
"Canonicalize graph nodes") \
\
@@ -4647,26 +4647,6 @@ void java_lang_AssertionStatusDirectives::set_deflt(oop o, bool val) {
o->bool_field_put(_deflt_offset, val);
}


// Support for intrinsification of java.nio.Buffer.checkIndex

int java_nio_Buffer::_limit_offset;

#define BUFFER_FIELDS_DO(macro) \
macro(_limit_offset, k, "limit", int_signature, false)

void java_nio_Buffer::compute_offsets() {
InstanceKlass* k = vmClasses::nio_Buffer_klass();
assert(k != NULL, "must be loaded in 1.4+");
BUFFER_FIELDS_DO(FIELD_COMPUTE_OFFSET);
}

#if INCLUDE_CDS
void java_nio_Buffer::serialize_offsets(SerializeClosure* f) {
BUFFER_FIELDS_DO(FIELD_SERIALIZE_OFFSET);
}
#endif

int java_util_concurrent_locks_AbstractOwnableSynchronizer::_owner_offset;

#define AOS_FIELDS_DO(macro) \
@@ -66,7 +66,6 @@ class RecordComponent;
f(java_lang_reflect_Constructor) \
f(java_lang_reflect_Field) \
f(java_lang_reflect_RecordComponent) \
f(java_nio_Buffer) \
f(reflect_ConstantPool) \
f(reflect_UnsafeStaticFieldAccessorImpl) \
f(java_lang_reflect_Parameter) \
@@ -1584,16 +1583,6 @@ class java_lang_AssertionStatusDirectives: AllStatic {
};


class java_nio_Buffer: AllStatic {
private:
static int _limit_offset;

public:
static int limit_offset() { CHECK_INIT(_limit_offset); }
static void compute_offsets();
static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN;
};

class java_util_concurrent_locks_AbstractOwnableSynchronizer : AllStatic {
private:
static int _owner_offset;
@@ -88,7 +88,8 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) {
case vmIntrinsics::_dlog10:
case vmIntrinsics::_dexp:
case vmIntrinsics::_dpow:
case vmIntrinsics::_checkIndex:
case vmIntrinsics::_Preconditions_checkIndex:
case vmIntrinsics::_Preconditions_checkLongIndex:
case vmIntrinsics::_Reference_get:
case vmIntrinsics::_updateCRC32:
case vmIntrinsics::_updateBytesCRC32:
@@ -467,11 +468,6 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) {
case vmIntrinsics::_copyMemory:
if (!InlineArrayCopy || !InlineUnsafeOps) return true;
break;
#ifdef COMPILER1
case vmIntrinsics::_checkIndex:
if (!InlineNIOCheckIndex) return true;
break;
#endif // COMPILER1
#ifdef COMPILER2
case vmIntrinsics::_clone:
case vmIntrinsics::_copyOf:
@@ -341,10 +341,6 @@ class methodHandle;
do_intrinsic(_Preconditions_checkLongIndex, jdk_internal_util_Preconditions, checkIndex_name, Preconditions_checkLongIndex_signature, F_S) \
do_signature(Preconditions_checkLongIndex_signature, "(JJLjava/util/function/BiFunction;)J") \
\
do_class(java_nio_Buffer, "java/nio/Buffer") \
do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \
do_name( checkIndex_name, "checkIndex") \
\
do_class(java_lang_StringCoding, "java/lang/StringCoding") \
do_intrinsic(_hasNegatives, java_lang_StringCoding, hasNegatives_name, hasNegatives_signature, F_S) \
do_name( hasNegatives_name, "hasNegatives") \
@@ -124,6 +124,7 @@
template(java_io_FileInputStream, "java/io/FileInputStream") \
template(java_io_ByteArrayInputStream, "java/io/ByteArrayInputStream") \
template(java_io_Serializable, "java/io/Serializable") \
template(java_nio_Buffer, "java/nio/Buffer") \
template(java_util_Arrays, "java/util/Arrays") \
template(java_util_Objects, "java/util/Objects") \
template(java_util_Properties, "java/util/Properties") \
@@ -482,6 +483,7 @@
template(use_unaligned_access_name, "UNALIGNED_ACCESS") \
template(data_cache_line_flush_size_name, "DATA_CACHE_LINE_FLUSH_SIZE") \
template(during_unsafe_access_name, "during_unsafe_access") \
template(checkIndex_name, "checkIndex") \
\
/* name symbols needed by intrinsics */ \
VM_INTRINSICS_DO(VM_INTRINSIC_IGNORE, VM_SYMBOL_IGNORE, template, VM_SYMBOL_IGNORE, VM_ALIAS_IGNORE) \
@@ -34,9 +34,9 @@
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM.BufferPool;
import jdk.internal.vm.annotation.ForceInline;
import jdk.internal.vm.annotation.IntrinsicCandidate;

import java.io.FileDescriptor;
import java.util.Objects;
import java.util.Spliterator;

/**
@@ -737,11 +737,8 @@ final int nextPutIndex(int nb) { // package-private
* IndexOutOfBoundsException} if it is not smaller than the limit
* or is smaller than zero.
*/
@IntrinsicCandidate
final int checkIndex(int i) { // package-private
if ((i < 0) || (i >= limit))
throw new IndexOutOfBoundsException();
return i;
return Objects.checkIndex(i, limit);
}

final int checkIndex(int i, int nb) { // package-private
Loading

1 comment on commit 5cee23a

@openjdk-notifier

This comment has been minimized.

Copy link

@openjdk-notifier openjdk-notifier bot commented on 5cee23a Jun 12, 2021

Please sign in to comment.