/* * Copyright (c) 1999, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
//---------------------------make_vm_intrinsic----------------------------
CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
vmIntrinsicID id = m->intrinsic_id();
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
if (!m->is_loaded()) { // Do not attempt to inline unloaded methods. return NULL;
}
{ // For calling is_intrinsic_supported and is_intrinsic_disabled_by_flag // the compiler must transition to '_thread_in_vm' state because both // methods access VM-internal data.
VM_ENTRY_MARK;
methodHandle mh(THREAD, m->get_Method());
is_available = compiler != NULL && compiler->is_intrinsic_supported(mh, is_virtual) &&
!C->directive()->is_intrinsic_disabled(mh) &&
!vmIntrinsics::is_disabled_by_flags(mh);
}
if (is_available) {
assert(id <= vmIntrinsics::LAST_COMPILER_INLINE, "caller responsibility");
assert(id != vmIntrinsics::_Object_init && id != vmIntrinsics::_invoke, "enum out of order?"); returnnew LibraryIntrinsic(m, is_virtual,
vmIntrinsics::predicates_needed(id),
vmIntrinsics::does_virtual_dispatch(id),
id);
} else { return NULL;
}
}
JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
LibraryCallKit kit(jvms, this);
Compile* C = kit.C; int nodes = C->unique(); #ifndef PRODUCT if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { char buf[1000]; constchar* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf));
tty->print_cr("Intrinsic %s", str);
} #endif
ciMethod* callee = kit.callee(); constint bci = kit.bci(); #ifdef ASSERT
Node* ctrl = kit.control(); #endif // Try to inline the intrinsic. if (callee->check_intrinsic_candidate() &&
kit.try_to_inline(_last_predicate)) { constchar *inline_msg = is_virtual() ? "(intrinsic, virtual)"
: "(intrinsic)";
CompileTask::print_inlining_ul(callee, jvms->depth() - 1, bci, inline_msg); if (C->print_intrinsics() || C->print_inlining()) {
C->print_inlining(callee, jvms->depth() - 1, bci, inline_msg);
}
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); if (C->log()) {
C->log()->elem("intrinsic id='%s'%s nodes='%d'",
vmIntrinsics::name_at(intrinsic_id()),
(is_virtual() ? " virtual='1'" : ""),
C->unique() - nodes);
} // Push the result from the inlined method onto the stack.
kit.push_result();
C->print_inlining_update(this); return kit.transfer_exceptions_into_jvms();
}
// The intrinsic bailed out
assert(ctrl == kit.control(), "Control flow was added although the intrinsic bailed out"); if (jvms->has_method()) { // Not a root compile. constchar* msg; if (callee->intrinsic_candidate()) {
msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)";
} else {
msg = is_virtual() ? "failed to inline (intrinsic, virtual), method not annotated"
: "failed to inline (intrinsic), method not annotated";
}
CompileTask::print_inlining_ul(callee, jvms->depth() - 1, bci, msg); if (C->print_intrinsics() || C->print_inlining()) {
C->print_inlining(callee, jvms->depth() - 1, bci, msg);
}
} else { // Root compile
ResourceMark rm;
stringStream msg_stream;
msg_stream.print("Did not generate intrinsic %s%s at bci:%d in",
vmIntrinsics::name_at(intrinsic_id()),
is_virtual() ? " (virtual)" : "", bci); constchar *msg = msg_stream.freeze();
log_debug(jit, inlining)("%s", msg); if (C->print_intrinsics() || C->print_inlining()) {
tty->print("%s", msg);
}
}
C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_failed);
C->print_inlining_update(this);
if (!jvms()->has_method()) { // Root JVMState has a null method.
assert(map()->memory()->Opcode() == Op_Parm, ""); // Insert the memory aliasing node
set_all_memory(reset_memory());
}
assert(merged_memory(), "");
switch (intrinsic_id()) { case vmIntrinsics::_hashCode: return inline_native_hashcode(intrinsic()->is_virtual(), !is_static); case vmIntrinsics::_identityHashCode: return inline_native_hashcode(/*!virtual*/ false, is_static); case vmIntrinsics::_getClass: return inline_native_getClass();
case vmIntrinsics::_ceil: case vmIntrinsics::_floor: case vmIntrinsics::_rint: case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: case vmIntrinsics::_dtan: case vmIntrinsics::_dabs: case vmIntrinsics::_fabs: case vmIntrinsics::_iabs: case vmIntrinsics::_labs: case vmIntrinsics::_datan2: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dsqrt_strict: case vmIntrinsics::_dexp: case vmIntrinsics::_dlog: case vmIntrinsics::_dlog10: case vmIntrinsics::_dpow: case vmIntrinsics::_dcopySign: case vmIntrinsics::_fcopySign: case vmIntrinsics::_dsignum: case vmIntrinsics::_roundF: case vmIntrinsics::_roundD: case vmIntrinsics::_fsignum: return inline_math_native(intrinsic_id());
case vmIntrinsics::_notify: case vmIntrinsics::_notifyAll: return inline_notify(intrinsic_id());
case vmIntrinsics::_addExactI: return inline_math_addExactI(false/* add */); case vmIntrinsics::_addExactL: return inline_math_addExactL(false/* add */); case vmIntrinsics::_decrementExactI: return inline_math_subtractExactI(true/* decrement */); case vmIntrinsics::_decrementExactL: return inline_math_subtractExactL(true/* decrement */); case vmIntrinsics::_incrementExactI: return inline_math_addExactI(true/* increment */); case vmIntrinsics::_incrementExactL: return inline_math_addExactL(true/* increment */); case vmIntrinsics::_multiplyExactI: return inline_math_multiplyExactI(); case vmIntrinsics::_multiplyExactL: return inline_math_multiplyExactL(); case vmIntrinsics::_multiplyHigh: return inline_math_multiplyHigh(); case vmIntrinsics::_unsignedMultiplyHigh: return inline_math_unsignedMultiplyHigh(); case vmIntrinsics::_negateExactI: return inline_math_negateExactI(); case vmIntrinsics::_negateExactL: return inline_math_negateExactL(); case vmIntrinsics::_subtractExactI: return inline_math_subtractExactI(false/* subtract */); case vmIntrinsics::_subtractExactL: return inline_math_subtractExactL(false/* subtract */);
case vmIntrinsics::_arraycopy: return inline_arraycopy();
case vmIntrinsics::_compareToL: return inline_string_compareTo(StrIntrinsicNode::LL); case vmIntrinsics::_compareToU: return inline_string_compareTo(StrIntrinsicNode::UU); case vmIntrinsics::_compareToLU: return inline_string_compareTo(StrIntrinsicNode::LU); case vmIntrinsics::_compareToUL: return inline_string_compareTo(StrIntrinsicNode::UL);
case vmIntrinsics::_indexOfL: return inline_string_indexOf(StrIntrinsicNode::LL); case vmIntrinsics::_indexOfU: return inline_string_indexOf(StrIntrinsicNode::UU); case vmIntrinsics::_indexOfUL: return inline_string_indexOf(StrIntrinsicNode::UL); case vmIntrinsics::_indexOfIL: return inline_string_indexOfI(StrIntrinsicNode::LL); case vmIntrinsics::_indexOfIU: return inline_string_indexOfI(StrIntrinsicNode::UU); case vmIntrinsics::_indexOfIUL: return inline_string_indexOfI(StrIntrinsicNode::UL); case vmIntrinsics::_indexOfU_char: return inline_string_indexOfChar(StrIntrinsicNode::U); case vmIntrinsics::_indexOfL_char: return inline_string_indexOfChar(StrIntrinsicNode::L);
case vmIntrinsics::_equalsL: return inline_string_equals(StrIntrinsicNode::LL); case vmIntrinsics::_equalsU: return inline_string_equals(StrIntrinsicNode::UU);
case vmIntrinsics::_toBytesStringU: return inline_string_toBytesU(); case vmIntrinsics::_getCharsStringU: return inline_string_getCharsU(); case vmIntrinsics::_getCharStringU: return inline_string_char_access(!is_store); case vmIntrinsics::_putCharStringU: return inline_string_char_access( is_store);
case vmIntrinsics::_compressStringC: case vmIntrinsics::_compressStringB: return inline_string_copy( is_compress); case vmIntrinsics::_inflateStringC: case vmIntrinsics::_inflateStringB: return inline_string_copy(!is_compress);
case vmIntrinsics::_getReference: return inline_unsafe_access(!is_store, T_OBJECT, Relaxed, false); case vmIntrinsics::_getBoolean: return inline_unsafe_access(!is_store, T_BOOLEAN, Relaxed, false); case vmIntrinsics::_getByte: return inline_unsafe_access(!is_store, T_BYTE, Relaxed, false); case vmIntrinsics::_getShort: return inline_unsafe_access(!is_store, T_SHORT, Relaxed, false); case vmIntrinsics::_getChar: return inline_unsafe_access(!is_store, T_CHAR, Relaxed, false); case vmIntrinsics::_getInt: return inline_unsafe_access(!is_store, T_INT, Relaxed, false); case vmIntrinsics::_getLong: return inline_unsafe_access(!is_store, T_LONG, Relaxed, false); case vmIntrinsics::_getFloat: return inline_unsafe_access(!is_store, T_FLOAT, Relaxed, false); case vmIntrinsics::_getDouble: return inline_unsafe_access(!is_store, T_DOUBLE, Relaxed, false);
case vmIntrinsics::_putReference: return inline_unsafe_access( is_store, T_OBJECT, Relaxed, false); case vmIntrinsics::_putBoolean: return inline_unsafe_access( is_store, T_BOOLEAN, Relaxed, false); case vmIntrinsics::_putByte: return inline_unsafe_access( is_store, T_BYTE, Relaxed, false); case vmIntrinsics::_putShort: return inline_unsafe_access( is_store, T_SHORT, Relaxed, false); case vmIntrinsics::_putChar: return inline_unsafe_access( is_store, T_CHAR, Relaxed, false); case vmIntrinsics::_putInt: return inline_unsafe_access( is_store, T_INT, Relaxed, false); case vmIntrinsics::_putLong: return inline_unsafe_access( is_store, T_LONG, Relaxed, false); case vmIntrinsics::_putFloat: return inline_unsafe_access( is_store, T_FLOAT, Relaxed, false); case vmIntrinsics::_putDouble: return inline_unsafe_access( is_store, T_DOUBLE, Relaxed, false);
case vmIntrinsics::_getReferenceVolatile: return inline_unsafe_access(!is_store, T_OBJECT, Volatile, false); case vmIntrinsics::_getBooleanVolatile: return inline_unsafe_access(!is_store, T_BOOLEAN, Volatile, false); case vmIntrinsics::_getByteVolatile: return inline_unsafe_access(!is_store, T_BYTE, Volatile, false); case vmIntrinsics::_getShortVolatile: return inline_unsafe_access(!is_store, T_SHORT, Volatile, false); case vmIntrinsics::_getCharVolatile: return inline_unsafe_access(!is_store, T_CHAR, Volatile, false); case vmIntrinsics::_getIntVolatile: return inline_unsafe_access(!is_store, T_INT, Volatile, false); case vmIntrinsics::_getLongVolatile: return inline_unsafe_access(!is_store, T_LONG, Volatile, false); case vmIntrinsics::_getFloatVolatile: return inline_unsafe_access(!is_store, T_FLOAT, Volatile, false); case vmIntrinsics::_getDoubleVolatile: return inline_unsafe_access(!is_store, T_DOUBLE, Volatile, false);
case vmIntrinsics::_putReferenceVolatile: return inline_unsafe_access( is_store, T_OBJECT, Volatile, false); case vmIntrinsics::_putBooleanVolatile: return inline_unsafe_access( is_store, T_BOOLEAN, Volatile, false); case vmIntrinsics::_putByteVolatile: return inline_unsafe_access( is_store, T_BYTE, Volatile, false); case vmIntrinsics::_putShortVolatile: return inline_unsafe_access( is_store, T_SHORT, Volatile, false); case vmIntrinsics::_putCharVolatile: return inline_unsafe_access( is_store, T_CHAR, Volatile, false); case vmIntrinsics::_putIntVolatile: return inline_unsafe_access( is_store, T_INT, Volatile, false); case vmIntrinsics::_putLongVolatile: return inline_unsafe_access( is_store, T_LONG, Volatile, false); case vmIntrinsics::_putFloatVolatile: return inline_unsafe_access( is_store, T_FLOAT, Volatile, false); case vmIntrinsics::_putDoubleVolatile: return inline_unsafe_access( is_store, T_DOUBLE, Volatile, false);
case vmIntrinsics::_getShortUnaligned: return inline_unsafe_access(!is_store, T_SHORT, Relaxed, true); case vmIntrinsics::_getCharUnaligned: return inline_unsafe_access(!is_store, T_CHAR, Relaxed, true); case vmIntrinsics::_getIntUnaligned: return inline_unsafe_access(!is_store, T_INT, Relaxed, true); case vmIntrinsics::_getLongUnaligned: return inline_unsafe_access(!is_store, T_LONG, Relaxed, true);
case vmIntrinsics::_putShortUnaligned: return inline_unsafe_access( is_store, T_SHORT, Relaxed, true); case vmIntrinsics::_putCharUnaligned: return inline_unsafe_access( is_store, T_CHAR, Relaxed, true); case vmIntrinsics::_putIntUnaligned: return inline_unsafe_access( is_store, T_INT, Relaxed, true); case vmIntrinsics::_putLongUnaligned: return inline_unsafe_access( is_store, T_LONG, Relaxed, true);
case vmIntrinsics::_getReferenceAcquire: return inline_unsafe_access(!is_store, T_OBJECT, Acquire, false); case vmIntrinsics::_getBooleanAcquire: return inline_unsafe_access(!is_store, T_BOOLEAN, Acquire, false); case vmIntrinsics::_getByteAcquire: return inline_unsafe_access(!is_store, T_BYTE, Acquire, false); case vmIntrinsics::_getShortAcquire: return inline_unsafe_access(!is_store, T_SHORT, Acquire, false); case vmIntrinsics::_getCharAcquire: return inline_unsafe_access(!is_store, T_CHAR, Acquire, false); case vmIntrinsics::_getIntAcquire: return inline_unsafe_access(!is_store, T_INT, Acquire, false); case vmIntrinsics::_getLongAcquire: return inline_unsafe_access(!is_store, T_LONG, Acquire, false); case vmIntrinsics::_getFloatAcquire: return inline_unsafe_access(!is_store, T_FLOAT, Acquire, false); case vmIntrinsics::_getDoubleAcquire: return inline_unsafe_access(!is_store, T_DOUBLE, Acquire, false);
case vmIntrinsics::_putReferenceRelease: return inline_unsafe_access( is_store, T_OBJECT, Release, false); case vmIntrinsics::_putBooleanRelease: return inline_unsafe_access( is_store, T_BOOLEAN, Release, false); case vmIntrinsics::_putByteRelease: return inline_unsafe_access( is_store, T_BYTE, Release, false); case vmIntrinsics::_putShortRelease: return inline_unsafe_access( is_store, T_SHORT, Release, false); case vmIntrinsics::_putCharRelease: return inline_unsafe_access( is_store, T_CHAR, Release, false); case vmIntrinsics::_putIntRelease: return inline_unsafe_access( is_store, T_INT, Release, false); case vmIntrinsics::_putLongRelease: return inline_unsafe_access( is_store, T_LONG, Release, false); case vmIntrinsics::_putFloatRelease: return inline_unsafe_access( is_store, T_FLOAT, Release, false); case vmIntrinsics::_putDoubleRelease: return inline_unsafe_access( is_store, T_DOUBLE, Release, false);
case vmIntrinsics::_getReferenceOpaque: return inline_unsafe_access(!is_store, T_OBJECT, Opaque, false); case vmIntrinsics::_getBooleanOpaque: return inline_unsafe_access(!is_store, T_BOOLEAN, Opaque, false); case vmIntrinsics::_getByteOpaque: return inline_unsafe_access(!is_store, T_BYTE, Opaque, false); case vmIntrinsics::_getShortOpaque: return inline_unsafe_access(!is_store, T_SHORT, Opaque, false); case vmIntrinsics::_getCharOpaque: return inline_unsafe_access(!is_store, T_CHAR, Opaque, false); case vmIntrinsics::_getIntOpaque: return inline_unsafe_access(!is_store, T_INT, Opaque, false); case vmIntrinsics::_getLongOpaque: return inline_unsafe_access(!is_store, T_LONG, Opaque, false); case vmIntrinsics::_getFloatOpaque: return inline_unsafe_access(!is_store, T_FLOAT, Opaque, false); case vmIntrinsics::_getDoubleOpaque: return inline_unsafe_access(!is_store, T_DOUBLE, Opaque, false);
case vmIntrinsics::_putReferenceOpaque: return inline_unsafe_access( is_store, T_OBJECT, Opaque, false); case vmIntrinsics::_putBooleanOpaque: return inline_unsafe_access( is_store, T_BOOLEAN, Opaque, false); case vmIntrinsics::_putByteOpaque: return inline_unsafe_access( is_store, T_BYTE, Opaque, false); case vmIntrinsics::_putShortOpaque: return inline_unsafe_access( is_store, T_SHORT, Opaque, false); case vmIntrinsics::_putCharOpaque: return inline_unsafe_access( is_store, T_CHAR, Opaque, false); case vmIntrinsics::_putIntOpaque: return inline_unsafe_access( is_store, T_INT, Opaque, false); case vmIntrinsics::_putLongOpaque: return inline_unsafe_access( is_store, T_LONG, Opaque, false); case vmIntrinsics::_putFloatOpaque: return inline_unsafe_access( is_store, T_FLOAT, Opaque, false); case vmIntrinsics::_putDoubleOpaque: return inline_unsafe_access( is_store, T_DOUBLE, Opaque, false);
case vmIntrinsics::_compareAndSetReference: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap, Volatile); case vmIntrinsics::_compareAndSetByte: return inline_unsafe_load_store(T_BYTE, LS_cmp_swap, Volatile); case vmIntrinsics::_compareAndSetShort: return inline_unsafe_load_store(T_SHORT, LS_cmp_swap, Volatile); case vmIntrinsics::_compareAndSetInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap, Volatile); case vmIntrinsics::_compareAndSetLong: return inline_unsafe_load_store(T_LONG, LS_cmp_swap, Volatile);
case vmIntrinsics::_weakCompareAndSetReferencePlain: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Relaxed); case vmIntrinsics::_weakCompareAndSetReferenceAcquire: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Acquire); case vmIntrinsics::_weakCompareAndSetReferenceRelease: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Release); case vmIntrinsics::_weakCompareAndSetReference: return inline_unsafe_load_store(T_OBJECT, LS_cmp_swap_weak, Volatile); case vmIntrinsics::_weakCompareAndSetBytePlain: return inline_unsafe_load_store(T_BYTE, LS_cmp_swap_weak, Relaxed); case vmIntrinsics::_weakCompareAndSetByteAcquire: return inline_unsafe_load_store(T_BYTE, LS_cmp_swap_weak, Acquire); case vmIntrinsics::_weakCompareAndSetByteRelease: return inline_unsafe_load_store(T_BYTE, LS_cmp_swap_weak, Release); case vmIntrinsics::_weakCompareAndSetByte: return inline_unsafe_load_store(T_BYTE, LS_cmp_swap_weak, Volatile); case vmIntrinsics::_weakCompareAndSetShortPlain: return inline_unsafe_load_store(T_SHORT, LS_cmp_swap_weak, Relaxed); case vmIntrinsics::_weakCompareAndSetShortAcquire: return inline_unsafe_load_store(T_SHORT, LS_cmp_swap_weak, Acquire); case vmIntrinsics::_weakCompareAndSetShortRelease: return inline_unsafe_load_store(T_SHORT, LS_cmp_swap_weak, Release); case vmIntrinsics::_weakCompareAndSetShort: return inline_unsafe_load_store(T_SHORT, LS_cmp_swap_weak, Volatile); case vmIntrinsics::_weakCompareAndSetIntPlain: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Relaxed); case vmIntrinsics::_weakCompareAndSetIntAcquire: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Acquire); case vmIntrinsics::_weakCompareAndSetIntRelease: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Release); case vmIntrinsics::_weakCompareAndSetInt: return inline_unsafe_load_store(T_INT, LS_cmp_swap_weak, Volatile); case vmIntrinsics::_weakCompareAndSetLongPlain: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Relaxed); case vmIntrinsics::_weakCompareAndSetLongAcquire: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Acquire); case vmIntrinsics::_weakCompareAndSetLongRelease: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Release); case vmIntrinsics::_weakCompareAndSetLong: return inline_unsafe_load_store(T_LONG, LS_cmp_swap_weak, Volatile);
case vmIntrinsics::_compareAndExchangeReference: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Volatile); case vmIntrinsics::_compareAndExchangeReferenceAcquire: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Acquire); case vmIntrinsics::_compareAndExchangeReferenceRelease: return inline_unsafe_load_store(T_OBJECT, LS_cmp_exchange, Release); case vmIntrinsics::_compareAndExchangeByte: return inline_unsafe_load_store(T_BYTE, LS_cmp_exchange, Volatile); case vmIntrinsics::_compareAndExchangeByteAcquire: return inline_unsafe_load_store(T_BYTE, LS_cmp_exchange, Acquire); case vmIntrinsics::_compareAndExchangeByteRelease: return inline_unsafe_load_store(T_BYTE, LS_cmp_exchange, Release); case vmIntrinsics::_compareAndExchangeShort: return inline_unsafe_load_store(T_SHORT, LS_cmp_exchange, Volatile); case vmIntrinsics::_compareAndExchangeShortAcquire: return inline_unsafe_load_store(T_SHORT, LS_cmp_exchange, Acquire); case vmIntrinsics::_compareAndExchangeShortRelease: return inline_unsafe_load_store(T_SHORT, LS_cmp_exchange, Release); case vmIntrinsics::_compareAndExchangeInt: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Volatile); case vmIntrinsics::_compareAndExchangeIntAcquire: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Acquire); case vmIntrinsics::_compareAndExchangeIntRelease: return inline_unsafe_load_store(T_INT, LS_cmp_exchange, Release); case vmIntrinsics::_compareAndExchangeLong: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Volatile); case vmIntrinsics::_compareAndExchangeLongAcquire: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Acquire); case vmIntrinsics::_compareAndExchangeLongRelease: return inline_unsafe_load_store(T_LONG, LS_cmp_exchange, Release);
case vmIntrinsics::_getAndAddByte: return inline_unsafe_load_store(T_BYTE, LS_get_add, Volatile); case vmIntrinsics::_getAndAddShort: return inline_unsafe_load_store(T_SHORT, LS_get_add, Volatile); case vmIntrinsics::_getAndAddInt: return inline_unsafe_load_store(T_INT, LS_get_add, Volatile); case vmIntrinsics::_getAndAddLong: return inline_unsafe_load_store(T_LONG, LS_get_add, Volatile);
case vmIntrinsics::_getAndSetByte: return inline_unsafe_load_store(T_BYTE, LS_get_set, Volatile); case vmIntrinsics::_getAndSetShort: return inline_unsafe_load_store(T_SHORT, LS_get_set, Volatile); case vmIntrinsics::_getAndSetInt: return inline_unsafe_load_store(T_INT, LS_get_set, Volatile); case vmIntrinsics::_getAndSetLong: return inline_unsafe_load_store(T_LONG, LS_get_set, Volatile); case vmIntrinsics::_getAndSetReference: return inline_unsafe_load_store(T_OBJECT, LS_get_set, Volatile);
case vmIntrinsics::_loadFence: case vmIntrinsics::_storeFence: case vmIntrinsics::_storeStoreFence: case vmIntrinsics::_fullFence: return inline_unsafe_fence(intrinsic_id());
case vmIntrinsics::_onSpinWait: return inline_onspinwait();
case vmIntrinsics::_currentCarrierThread: return inline_native_currentCarrierThread(); case vmIntrinsics::_currentThread: return inline_native_currentThread(); case vmIntrinsics::_setCurrentThread: return inline_native_setCurrentThread();
case vmIntrinsics::_scopedValueCache: return inline_native_scopedValueCache(); case vmIntrinsics::_setScopedValueCache: return inline_native_setScopedValueCache();
#ifdef JFR_HAVE_INTRINSICS case vmIntrinsics::_counterTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, JfrTime::time_function()), "counterTime"); case vmIntrinsics::_getEventWriter: return inline_native_getEventWriter(); #endif case vmIntrinsics::_currentTimeMillis: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis"); case vmIntrinsics::_nanoTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime"); case vmIntrinsics::_writeback0: return inline_unsafe_writeback0(); case vmIntrinsics::_writebackPreSync0: return inline_unsafe_writebackSync0(true); case vmIntrinsics::_writebackPostSync0: return inline_unsafe_writebackSync0(false); case vmIntrinsics::_allocateInstance: return inline_unsafe_allocate(); case vmIntrinsics::_copyMemory: return inline_unsafe_copyMemory(); case vmIntrinsics::_getLength: return inline_native_getLength(); case vmIntrinsics::_copyOf: return inline_array_copyOf(false); case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true); case vmIntrinsics::_equalsB: return inline_array_equals(StrIntrinsicNode::LL); case vmIntrinsics::_equalsC: return inline_array_equals(StrIntrinsicNode::UU); case vmIntrinsics::_Preconditions_checkIndex: return inline_preconditions_checkIndex(T_INT); case vmIntrinsics::_Preconditions_checkLongIndex: return inline_preconditions_checkIndex(T_LONG); case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual());
case vmIntrinsics::_allocateUninitializedArray: return inline_unsafe_newArray(true); case vmIntrinsics::_newArray: return inline_unsafe_newArray(false);
case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check();
case vmIntrinsics::_isInstance: case vmIntrinsics::_getModifiers: case vmIntrinsics::_isInterface: case vmIntrinsics::_isArray: case vmIntrinsics::_isPrimitive: case vmIntrinsics::_isHidden: case vmIntrinsics::_getSuperclass: case vmIntrinsics::_getClassAccessFlags: return inline_native_Class_query(intrinsic_id());
case vmIntrinsics::_floatToRawIntBits: case vmIntrinsics::_floatToIntBits: case vmIntrinsics::_intBitsToFloat: case vmIntrinsics::_doubleToRawLongBits: case vmIntrinsics::_doubleToLongBits: case vmIntrinsics::_longBitsToDouble: case vmIntrinsics::_floatToFloat16: case vmIntrinsics::_float16ToFloat: return inline_fp_conversions(intrinsic_id());
case vmIntrinsics::_floatIsFinite: case vmIntrinsics::_floatIsInfinite: case vmIntrinsics::_doubleIsFinite: case vmIntrinsics::_doubleIsInfinite: return inline_fp_range_check(intrinsic_id());
case vmIntrinsics::_numberOfLeadingZeros_i: case vmIntrinsics::_numberOfLeadingZeros_l: case vmIntrinsics::_numberOfTrailingZeros_i: case vmIntrinsics::_numberOfTrailingZeros_l: case vmIntrinsics::_bitCount_i: case vmIntrinsics::_bitCount_l: case vmIntrinsics::_reverse_i: case vmIntrinsics::_reverse_l: case vmIntrinsics::_reverseBytes_i: case vmIntrinsics::_reverseBytes_l: case vmIntrinsics::_reverseBytes_s: case vmIntrinsics::_reverseBytes_c: return inline_number_methods(intrinsic_id());
case vmIntrinsics::_compress_i: case vmIntrinsics::_compress_l: case vmIntrinsics::_expand_i: case vmIntrinsics::_expand_l: return inline_bitshuffle_methods(intrinsic_id());
case vmIntrinsics::_compareUnsigned_i: case vmIntrinsics::_compareUnsigned_l: return inline_compare_unsigned(intrinsic_id());
case vmIntrinsics::_divideUnsigned_i: case vmIntrinsics::_divideUnsigned_l: case vmIntrinsics::_remainderUnsigned_i: case vmIntrinsics::_remainderUnsigned_l: return inline_divmod_methods(intrinsic_id());
case vmIntrinsics::_getCallerClass: return inline_native_Reflection_getCallerClass();
case vmIntrinsics::_Reference_get: return inline_reference_get(); case vmIntrinsics::_Reference_refersTo0: return inline_reference_refersTo0(false); case vmIntrinsics::_PhantomReference_refersTo0: return inline_reference_refersTo0(true);
case vmIntrinsics::_Class_cast: return inline_Class_cast();
case vmIntrinsics::_aescrypt_encryptBlock: case vmIntrinsics::_aescrypt_decryptBlock: return inline_aescrypt_Block(intrinsic_id());
case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: return inline_cipherBlockChaining_AESCrypt(intrinsic_id());
case vmIntrinsics::_electronicCodeBook_encryptAESCrypt: case vmIntrinsics::_electronicCodeBook_decryptAESCrypt: return inline_electronicCodeBook_AESCrypt(intrinsic_id());
case vmIntrinsics::_counterMode_AESCrypt: return inline_counterMode_AESCrypt(intrinsic_id());
case vmIntrinsics::_galoisCounterMode_AESCrypt: return inline_galoisCounterMode_AESCrypt();
case vmIntrinsics::_md5_implCompress: case vmIntrinsics::_sha_implCompress: case vmIntrinsics::_sha2_implCompress: case vmIntrinsics::_sha5_implCompress: case vmIntrinsics::_sha3_implCompress: return inline_digestBase_implCompress(intrinsic_id());
case vmIntrinsics::_digestBase_implCompressMB: 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::_montgomeryMultiply: return inline_montgomeryMultiply(); case vmIntrinsics::_montgomerySquare: return inline_montgomerySquare();
case vmIntrinsics::_bigIntegerRightShiftWorker: return inline_bigIntegerShift(true); case vmIntrinsics::_bigIntegerLeftShiftWorker: return inline_bigIntegerShift(false);
case vmIntrinsics::_vectorizedMismatch: return inline_vectorizedMismatch();
case vmIntrinsics::_ghash_processBlocks: return inline_ghash_processBlocks(); case vmIntrinsics::_chacha20Block: return inline_chacha20Block(); case vmIntrinsics::_base64_encodeBlock: return inline_base64_encodeBlock(); case vmIntrinsics::_base64_decodeBlock: return inline_base64_decodeBlock(); case vmIntrinsics::_poly1305_processBlocks: return inline_poly1305_processBlocks();
case vmIntrinsics::_encodeISOArray: case vmIntrinsics::_encodeByteISOArray: return inline_encodeISOArray(false); case vmIntrinsics::_encodeAsciiArray: return inline_encodeISOArray(true);
case vmIntrinsics::_updateCRC32: return inline_updateCRC32(); case vmIntrinsics::_updateBytesCRC32: return inline_updateBytesCRC32(); case vmIntrinsics::_updateByteBufferCRC32: return inline_updateByteBufferCRC32();
case vmIntrinsics::_updateBytesCRC32C: return inline_updateBytesCRC32C(); case vmIntrinsics::_updateDirectByteBufferCRC32C: return inline_updateDirectByteBufferCRC32C();
case vmIntrinsics::_updateBytesAdler32: return inline_updateBytesAdler32(); case vmIntrinsics::_updateByteBufferAdler32: return inline_updateByteBufferAdler32();
case vmIntrinsics::_profileBoolean: return inline_profileBoolean(); case vmIntrinsics::_isCompileConstant: return inline_isCompileConstant();
case vmIntrinsics::_countPositives: return inline_countPositives();
case vmIntrinsics::_fmaD: case vmIntrinsics::_fmaF: return inline_fma(intrinsic_id());
case vmIntrinsics::_isDigit: case vmIntrinsics::_isLowerCase: case vmIntrinsics::_isUpperCase: case vmIntrinsics::_isWhitespace: return inline_character_compare(intrinsic_id());
case vmIntrinsics::_min: case vmIntrinsics::_max: case vmIntrinsics::_min_strict: case vmIntrinsics::_max_strict: return inline_min_max(intrinsic_id());
case vmIntrinsics::_maxF: case vmIntrinsics::_minF: case vmIntrinsics::_maxD: case vmIntrinsics::_minD: case vmIntrinsics::_maxF_strict: case vmIntrinsics::_minF_strict: case vmIntrinsics::_maxD_strict: case vmIntrinsics::_minD_strict: return inline_fp_min_max(intrinsic_id());
case vmIntrinsics::_VectorUnaryOp: return inline_vector_nary_operation(1); case vmIntrinsics::_VectorBinaryOp: return inline_vector_nary_operation(2); case vmIntrinsics::_VectorTernaryOp: return inline_vector_nary_operation(3); case vmIntrinsics::_VectorFromBitsCoerced: return inline_vector_frombits_coerced(); case vmIntrinsics::_VectorShuffleIota: return inline_vector_shuffle_iota(); case vmIntrinsics::_VectorMaskOp: return inline_vector_mask_operation(); case vmIntrinsics::_VectorShuffleToVector: return inline_vector_shuffle_to_vector(); case vmIntrinsics::_VectorLoadOp: return inline_vector_mem_operation(/*is_store=*/false); case vmIntrinsics::_VectorLoadMaskedOp: return inline_vector_mem_masked_operation(/*is_store*/false); case vmIntrinsics::_VectorStoreOp: return inline_vector_mem_operation(/*is_store=*/true); case vmIntrinsics::_VectorStoreMaskedOp: return inline_vector_mem_masked_operation(/*is_store=*/true); case vmIntrinsics::_VectorGatherOp: return inline_vector_gather_scatter(/*is_scatter*/ false); case vmIntrinsics::_VectorScatterOp: return inline_vector_gather_scatter(/*is_scatter*/ true); case vmIntrinsics::_VectorReductionCoerced: return inline_vector_reduction(); case vmIntrinsics::_VectorTest: return inline_vector_test(); case vmIntrinsics::_VectorBlend: return inline_vector_blend(); case vmIntrinsics::_VectorRearrange: return inline_vector_rearrange(); case vmIntrinsics::_VectorCompare: return inline_vector_compare(); case vmIntrinsics::_VectorBroadcastInt: return inline_vector_broadcast_int(); case vmIntrinsics::_VectorConvert: return inline_vector_convert(); case vmIntrinsics::_VectorInsert: return inline_vector_insert(); case vmIntrinsics::_VectorExtract: return inline_vector_extract(); case vmIntrinsics::_VectorCompressExpand: return inline_vector_compress_expand(); case vmIntrinsics::_IndexVector: return inline_index_vector();
case vmIntrinsics::_getObjectSize: return inline_getObjectSize();
case vmIntrinsics::_blackhole: return inline_blackhole();
default: // If you get here, it may be that someone has added a new intrinsic // to the list in vmIntrinsics.hpp without implementing it here. #ifndef PRODUCT if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) {
tty->print_cr("*** Warning: Unimplemented intrinsic %s(%d)",
vmIntrinsics::name_at(intrinsic_id()), vmIntrinsics::as_int(intrinsic_id()));
} #endif returnfalse;
}
}
Node* LibraryCallKit::try_to_predicate(int predicate) { if (!jvms()->has_method()) { // Root JVMState has a null method.
assert(map()->memory()->Opcode() == Op_Parm, ""); // Insert the memory aliasing node
set_all_memory(reset_memory());
}
assert(merged_memory(), "");
switch (intrinsic_id()) { case vmIntrinsics::_cipherBlockChaining_encryptAESCrypt: return inline_cipherBlockChaining_AESCrypt_predicate(false); case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt: return inline_cipherBlockChaining_AESCrypt_predicate(true); case vmIntrinsics::_electronicCodeBook_encryptAESCrypt: return inline_electronicCodeBook_AESCrypt_predicate(false); case vmIntrinsics::_electronicCodeBook_decryptAESCrypt: return inline_electronicCodeBook_AESCrypt_predicate(true); case vmIntrinsics::_counterMode_AESCrypt: return inline_counterMode_AESCrypt_predicate(); case vmIntrinsics::_digestBase_implCompressMB: return inline_digestBase_implCompressMB_predicate(predicate); case vmIntrinsics::_galoisCounterMode_AESCrypt: return inline_galoisCounterMode_AESCrypt_predicate();
default: // If you get here, it may be that someone has added a new intrinsic // to the list in vmIntrinsics.hpp without implementing it here. #ifndef PRODUCT if ((PrintMiscellaneous && (Verbose || WizardMode)) || PrintOpto) {
tty->print_cr("*** Warning: Unimplemented predicate for intrinsic %s(%d)",
vmIntrinsics::name_at(intrinsic_id()), vmIntrinsics::as_int(intrinsic_id()));
} #endif
Node* slow_ctl = control();
set_control(top()); // No fast path intrinsic return slow_ctl;
}
}
//------------------------------generate_guard--------------------------- // Helper function for generating guarded fast-slow graph structures. // The given 'test', if true, guards a slow path. If the test fails // then a fast path can be taken. (We generally hope it fails.) // In all cases, GraphKit::control() is updated to the fast path. // The returned value represents the control for the slow path. // The return value is never 'top'; it is either a valid control // or NULL if it is obvious that the slow path can never be taken. // Also, if region and the slow control are not NULL, the slow edge // is appended to the region.
Node* LibraryCallKit::generate_guard(Node* test, RegionNode* region, float true_prob) { if (stopped()) { // Already short circuited. return NULL;
}
// Build an if node and its projections. // If test is true we take the slow path, which we assume is uncommon. if (_gvn.type(test) == TypeInt::ZERO) { // The slow branch is never taken. No need to build this guard. return NULL;
}
Node* if_slow = _gvn.transform(new IfTrueNode(iff)); if (if_slow == top()) { // The slow branch is never taken. No need to build this guard. return NULL;
}
// Make sure that 'position' is a valid limit index, in [0..length]. // There are two equivalent plans for checking this: // A. (offset + copyLength) unsigned<= arrayLength // B. offset <= (arrayLength - copyLength) // We require that all of the values above, except for the sum and // difference, are already known to be non-negative. // Plan A is robust in the face of overflow, if offset and copyLength // are both hugely positive. // // Plan B is less direct and intuitive, but it does not overflow at // all, since the difference of two non-negatives is always // representable. Whenever Java methods must perform the equivalent // check they generally use Plan B instead of Plan A. // For the moment we use Plan A. inline Node* LibraryCallKit::generate_limit_guard(Node* offset,
Node* subseq_length,
Node* array_length,
RegionNode* region) { if (stopped()) return NULL; // already stopped bool zero_offset = _gvn.type(offset) == TypeInt::ZERO; if (zero_offset && subseq_length->eqv_uncast(array_length)) return NULL; // common case of whole-array copy
Node* last = subseq_length; if (!zero_offset) // last += offset
last = _gvn.transform(new AddINode(last, offset));
Node* cmp_lt = _gvn.transform(new CmpUNode(array_length, last));
Node* bol_lt = _gvn.transform(new BoolNode(cmp_lt, BoolTest::lt));
Node* is_over = generate_guard(bol_lt, region, PROB_MIN); return is_over;
}
// Emit range checks for the given String.value byte array void LibraryCallKit::generate_string_range_check(Node* array, Node* offset, Node* count, bool char_count) { if (stopped()) { return; // already stopped
}
RegionNode* bailout = new RegionNode(1);
record_for_igvn(bailout); if (char_count) { // Convert char count to byte count
count = _gvn.transform(new LShiftINode(count, intcon(1)));
}
// Offset and count must not be negative
generate_negative_guard(offset, bailout);
generate_negative_guard(count, bailout); // Offset + count must not exceed length of array
generate_limit_guard(offset, count, load_array_length(array), bailout);
//------------------------------make_string_method_node------------------------ // Helper method for String intrinsic functions. This version is called with // str1 and str2 pointing to byte[] nodes containing Latin1 or UTF16 encoded // characters (depending on 'is_byte'). cnt1 and cnt2 are pointing to Int nodes // containing the lengths of str1 and str2.
Node* LibraryCallKit::make_string_method_node(int opcode, Node* str1_start, Node* cnt1, Node* str2_start, Node* cnt2, StrIntrinsicNode::ArgEnc ae) {
Node* result = NULL; switch (opcode) { case Op_StrIndexOf:
result = new StrIndexOfNode(control(), memory(TypeAryPtr::BYTES),
str1_start, cnt1, str2_start, cnt2, ae); break; case Op_StrComp:
result = new StrCompNode(control(), memory(TypeAryPtr::BYTES),
str1_start, cnt1, str2_start, cnt2, ae); break; case Op_StrEquals: // We already know that cnt1 == cnt2 here (checked in 'inline_string_equals'). // Use the constant length if there is one because optimized match rule may exist.
result = new StrEqualsNode(control(), memory(TypeAryPtr::BYTES),
str1_start, str2_start, cnt2->is_Con() ? cnt2 : cnt1, ae); break; default:
ShouldNotReachHere(); return NULL;
}
// All these intrinsics have checks.
C->set_has_split_ifs(true); // Has chance for split-if optimization
clear_upper_avx();
// Get start addr and length of first argument
Node* arg1_start = array_element_address(arg1, intcon(0), T_BYTE);
Node* arg1_cnt = load_array_length(arg1);
// Get start addr and length of second argument
Node* arg2_start = array_element_address(arg2, intcon(0), T_BYTE);
Node* arg2_cnt = load_array_length(arg2);
// Get start addr and length of first argument
Node* arg1_start = array_element_address(arg1, intcon(0), T_BYTE);
Node* arg1_cnt = load_array_length(arg1);
// Get start addr and length of second argument
Node* arg2_start = array_element_address(arg2, intcon(0), T_BYTE);
Node* arg2_cnt = load_array_length(arg2);
//------------------------------inline_countPositives------------------------------ bool LibraryCallKit::inline_countPositives() { if (too_many_traps(Deoptimization::Reason_intrinsic)) { returnfalse;
}
assert(callee()->signature()->size() == 3, "countPositives has 3 parameters"); // no receiver since it is static method
Node* ba = argument(0);
Node* offset = argument(1);
Node* len = argument(2);
ba = must_be_not_null(ba, true);
// Range checks
generate_string_range_check(ba, offset, len, false); if (stopped()) { returntrue;
}
Node* ba_start = array_element_address(ba, offset, T_BYTE);
Node* result = new CountPositivesNode(control(), memory(TypeAryPtr::BYTES), ba_start, len);
set_result(_gvn.transform(result)); returntrue;
}
if (stopped()) { // Length is known to be always negative during compilation and the IR graph so far constructed is good so return success returntrue;
}
// length is now known positive, add a cast node to make this explicit
jlong upper_bound = _gvn.type(length)->is_integer(bt)->hi_as_long();
Node* casted_length = ConstraintCastNode::make(control(), length, TypeInteger::make(0, upper_bound, Type::WidenMax, bt), ConstraintCastNode::RegularDependency, bt);
casted_length = _gvn.transform(casted_length);
replace_in_map(length, casted_length);
length = casted_length;
// Use an unsigned comparison for the range check itself
Node* rc_cmp = _gvn.transform(CmpNode::make(index, length, bt, true));
BoolTest::mask btest = BoolTest::lt;
Node* rc_bool = _gvn.transform(new BoolNode(rc_cmp, btest));
RangeCheckNode* rc = new RangeCheckNode(control(), rc_bool, PROB_MAX, COUNT_UNKNOWN);
_gvn.set_type(rc, rc->Value(&_gvn)); if (!rc_bool->is_Con()) {
record_for_igvn(rc);
}
set_control(_gvn.transform(new IfTrueNode(rc)));
{
PreserveJVMState pjvms(this);
set_control(_gvn.transform(new IfFalseNode(rc)));
uncommon_trap(Deoptimization::Reason_range_check,
Deoptimization::Action_make_not_entrant);
}
if (stopped()) { // Range check is known to always fail during compilation and the IR graph so far constructed is good so return success returntrue;
}
// index is now known to be >= 0 and < length, cast it
Node* result = ConstraintCastNode::make(control(), index, TypeInteger::make(0, upper_bound, Type::WidenMax, bt), ConstraintCastNode::RegularDependency, bt);
result = _gvn.transform(result);
set_result(result);
replace_in_map(index, result); returntrue;
}
// Range checks
generate_string_range_check(src, src_offset, src_count, ae != StrIntrinsicNode::LL);
generate_string_range_check(tgt, intcon(0), tgt_count, ae == StrIntrinsicNode::UU); if (stopped()) { returntrue;
}
RegionNode* region = new RegionNode(5);
Node* phi = new PhiNode(region, TypeInt::INT);
Node* result = make_indexOf_node(src_start, src_count, tgt_start, tgt_count, region, phi, ae); if (result != NULL) { // The result is index relative to from_index if substring was found, -1 otherwise. // Generate code which will fold into cmove.
Node* cmp = _gvn.transform(new CmpINode(result, intcon(0)));
Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::lt));
Node* if_lt = generate_slow_guard(bol, NULL); if (if_lt != NULL) { // result == -1
phi->init_req(3, result);
region->init_req(3, if_lt);
} if (!stopped()) {
result = _gvn.transform(new AddINode(result, from_index));
phi->init_req(4, result);
region->init_req(4, control());
}
}
// Range checks
generate_string_range_check(src, src_offset, src_count, ae == StrIntrinsicNode::U); if (stopped()) { returntrue;
}
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, ae);
C->set_has_split_ifs(true); // Has chance for split-if optimization
_gvn.transform(result);
Node* if_lt = generate_slow_guard(bol, NULL); if (if_lt != NULL) { // result == -1
phi->init_req(2, result);
region->init_req(2, if_lt);
} if (!stopped()) {
result = _gvn.transform(new AddINode(result, from_index));
phi->init_req(1, result);
region->init_req(1, control());
}
set_control(_gvn.transform(region));
record_for_igvn(region);
set_result(_gvn.transform(phi));
returntrue;
} //---------------------------inline_string_copy--------------------- // compressIt == true --> generate a compressed copy operation (compress char[]/byte[] to byte[]) // int StringUTF16.compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) // int StringUTF16.compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) // compressIt == false --> generate an inflated copy operation (inflate byte[] to char[]/byte[]) // void StringLatin1.inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) // void StringLatin1.inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) bool LibraryCallKit::inline_string_copy(bool compress) { if (too_many_traps(Deoptimization::Reason_intrinsic)) { returnfalse;
} int nargs = 5; // 2 oops, 3 ints
assert(callee()->signature()->size() == nargs, "string copy has 5 arguments");
// Check for allocation before we add nodes that would confuse // tightly_coupled_allocation()
AllocateArrayNode* alloc = tightly_coupled_allocation(dst);
// Figure out the size and type of the elements we will be copying. const Type* src_type = src->Value(&_gvn); const Type* dst_type = dst->Value(&_gvn);
BasicType src_elem = src_type->isa_aryptr()->elem()->array_element_basic_type();
--> --------------------
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.