8253525: Implement getInstanceSize/sizeOf intrinsics
Reviewed-by: kvn, sspitsyn
This commit is contained in:
parent
ea576ddbd4
commit
b4d0186718
@ -228,6 +228,8 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) {
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
case vmIntrinsics::_getObjectSize:
|
||||
break;
|
||||
default:
|
||||
return false; // Intrinsics not on the previous list are not available.
|
||||
}
|
||||
|
@ -1323,6 +1323,108 @@ void LIRGenerator::do_currentThread(Intrinsic* x) {
|
||||
LIR_OprFact::address(new LIR_Address(temp, T_OBJECT)), reg);
|
||||
}
|
||||
|
||||
void LIRGenerator::do_getObjectSize(Intrinsic* x) {
|
||||
assert(x->number_of_arguments() == 3, "wrong type");
|
||||
LIR_Opr result_reg = rlock_result(x);
|
||||
|
||||
LIRItem value(x->argument_at(2), this);
|
||||
value.load_item();
|
||||
|
||||
LIR_Opr klass = new_register(T_METADATA);
|
||||
__ move(new LIR_Address(value.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, NULL);
|
||||
LIR_Opr layout = new_register(T_INT);
|
||||
__ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout);
|
||||
|
||||
LabelObj* L_done = new LabelObj();
|
||||
LabelObj* L_array = new LabelObj();
|
||||
|
||||
__ cmp(lir_cond_lessEqual, layout, 0);
|
||||
__ branch(lir_cond_lessEqual, L_array->label());
|
||||
|
||||
// Instance case: the layout helper gives us instance size almost directly,
|
||||
// but we need to mask out the _lh_instance_slow_path_bit.
|
||||
__ convert(Bytecodes::_i2l, layout, result_reg);
|
||||
|
||||
assert((int) Klass::_lh_instance_slow_path_bit < BytesPerLong, "clear bit");
|
||||
jlong mask = ~(jlong) right_n_bits(LogBytesPerLong);
|
||||
__ logical_and(result_reg, LIR_OprFact::longConst(mask), result_reg);
|
||||
|
||||
__ branch(lir_cond_always, L_done->label());
|
||||
|
||||
// Array case: size is round(header + element_size*arraylength).
|
||||
// Since arraylength is different for every array instance, we have to
|
||||
// compute the whole thing at runtime.
|
||||
|
||||
__ branch_destination(L_array->label());
|
||||
|
||||
int round_mask = MinObjAlignmentInBytes - 1;
|
||||
|
||||
// Figure out header sizes first.
|
||||
LIR_Opr hss = LIR_OprFact::intConst(Klass::_lh_header_size_shift);
|
||||
LIR_Opr hsm = LIR_OprFact::intConst(Klass::_lh_header_size_mask);
|
||||
|
||||
LIR_Opr header_size = new_register(T_INT);
|
||||
__ move(layout, header_size);
|
||||
LIR_Opr tmp = new_register(T_INT);
|
||||
__ unsigned_shift_right(header_size, hss, header_size, tmp);
|
||||
__ logical_and(header_size, hsm, header_size);
|
||||
__ add(header_size, LIR_OprFact::intConst(round_mask), header_size);
|
||||
|
||||
// Figure out the array length in bytes
|
||||
assert(Klass::_lh_log2_element_size_shift == 0, "use shift in place");
|
||||
LIR_Opr l2esm = LIR_OprFact::intConst(Klass::_lh_log2_element_size_mask);
|
||||
__ logical_and(layout, l2esm, layout);
|
||||
|
||||
LIR_Opr length_int = new_register(T_INT);
|
||||
__ move(new LIR_Address(value.result(), arrayOopDesc::length_offset_in_bytes(), T_INT), length_int);
|
||||
|
||||
#ifdef _LP64
|
||||
LIR_Opr length = new_register(T_LONG);
|
||||
__ convert(Bytecodes::_i2l, length_int, length);
|
||||
#endif
|
||||
|
||||
// Shift-left awkwardness. Normally it is just:
|
||||
// __ shift_left(length, layout, length);
|
||||
// But C1 cannot perform shift_left with non-constant count, so we end up
|
||||
// doing the per-bit loop dance here. x86_32 also does not know how to shift
|
||||
// longs, so we have to act on ints.
|
||||
LabelObj* L_shift_loop = new LabelObj();
|
||||
LabelObj* L_shift_exit = new LabelObj();
|
||||
|
||||
__ branch_destination(L_shift_loop->label());
|
||||
__ cmp(lir_cond_equal, layout, 0);
|
||||
__ branch(lir_cond_equal, L_shift_exit->label());
|
||||
|
||||
#ifdef _LP64
|
||||
__ shift_left(length, 1, length);
|
||||
#else
|
||||
__ shift_left(length_int, 1, length_int);
|
||||
#endif
|
||||
|
||||
__ sub(layout, LIR_OprFact::intConst(1), layout);
|
||||
|
||||
__ branch(lir_cond_always, L_shift_loop->label());
|
||||
__ branch_destination(L_shift_exit->label());
|
||||
|
||||
// Mix all up, round, and push to the result.
|
||||
#ifdef _LP64
|
||||
LIR_Opr header_size_long = new_register(T_LONG);
|
||||
__ convert(Bytecodes::_i2l, header_size, header_size_long);
|
||||
__ add(length, header_size_long, length);
|
||||
if (round_mask != 0) {
|
||||
__ logical_and(length, LIR_OprFact::longConst(~round_mask), length);
|
||||
}
|
||||
__ move(length, result_reg);
|
||||
#else
|
||||
__ add(length_int, header_size, length_int);
|
||||
if (round_mask != 0) {
|
||||
__ logical_and(length_int, LIR_OprFact::intConst(~round_mask), length_int);
|
||||
}
|
||||
__ convert(Bytecodes::_i2l, length_int, result_reg);
|
||||
#endif
|
||||
|
||||
__ branch_destination(L_done->label());
|
||||
}
|
||||
|
||||
void LIRGenerator::do_RegisterFinalizer(Intrinsic* x) {
|
||||
assert(x->number_of_arguments() == 1, "wrong type");
|
||||
@ -3044,6 +3146,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) {
|
||||
case vmIntrinsics::_isPrimitive: do_isPrimitive(x); break;
|
||||
case vmIntrinsics::_getClass: do_getClass(x); break;
|
||||
case vmIntrinsics::_currentThread: do_currentThread(x); break;
|
||||
case vmIntrinsics::_getObjectSize: do_getObjectSize(x); break;
|
||||
|
||||
case vmIntrinsics::_dlog: // fall through
|
||||
case vmIntrinsics::_dlog10: // fall through
|
||||
|
@ -253,6 +253,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
|
||||
void do_isPrimitive(Intrinsic* x);
|
||||
void do_getClass(Intrinsic* x);
|
||||
void do_currentThread(Intrinsic* x);
|
||||
void do_getObjectSize(Intrinsic* x);
|
||||
void do_FmaIntrinsic(Intrinsic* x);
|
||||
void do_MathIntrinsic(Intrinsic* x);
|
||||
void do_LibmIntrinsic(Intrinsic* x);
|
||||
|
@ -524,6 +524,10 @@ class methodHandle;
|
||||
do_name( isCompileConstant_name, "isCompileConstant") \
|
||||
do_alias( isCompileConstant_signature, object_boolean_signature) \
|
||||
\
|
||||
do_intrinsic(_getObjectSize, sun_instrument_InstrumentationImpl, getObjectSize_name, getObjectSize_signature, F_RN) \
|
||||
do_name( getObjectSize_name, "getObjectSize0") \
|
||||
do_alias( getObjectSize_signature, long_object_long_signature) \
|
||||
\
|
||||
/* unsafe memory references (there are a lot of them...) */ \
|
||||
do_signature(getReference_signature, "(Ljava/lang/Object;J)Ljava/lang/Object;") \
|
||||
do_signature(putReference_signature, "(Ljava/lang/Object;JLjava/lang/Object;)V") \
|
||||
|
@ -139,6 +139,7 @@
|
||||
template(sun_net_www_ParseUtil, "sun/net/www/ParseUtil") \
|
||||
template(java_util_Iterator, "java/util/Iterator") \
|
||||
template(java_lang_Record, "java/lang/Record") \
|
||||
template(sun_instrument_InstrumentationImpl, "sun/instrument/InstrumentationImpl") \
|
||||
\
|
||||
template(jdk_internal_loader_NativeLibraries, "jdk/internal/loader/NativeLibraries") \
|
||||
template(jdk_internal_loader_BuiltinClassLoader, "jdk/internal/loader/BuiltinClassLoader") \
|
||||
@ -521,6 +522,7 @@
|
||||
template(int_array_signature, "[I") \
|
||||
template(object_void_signature, "(Ljava/lang/Object;)V") \
|
||||
template(object_int_signature, "(Ljava/lang/Object;)I") \
|
||||
template(long_object_long_signature, "(JLjava/lang/Object;)J") \
|
||||
template(object_boolean_signature, "(Ljava/lang/Object;)Z") \
|
||||
template(object_object_signature, "(Ljava/lang/Object;)Ljava/lang/Object;") \
|
||||
template(string_void_signature, "(Ljava/lang/String;)V") \
|
||||
|
@ -649,6 +649,7 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
|
||||
case vmIntrinsics::_profileBoolean:
|
||||
case vmIntrinsics::_isCompileConstant:
|
||||
case vmIntrinsics::_Preconditions_checkIndex:
|
||||
case vmIntrinsics::_getObjectSize:
|
||||
break;
|
||||
|
||||
case vmIntrinsics::_VectorUnaryOp:
|
||||
|
@ -661,6 +661,9 @@ bool LibraryCallKit::try_to_inline(int predicate) {
|
||||
case vmIntrinsics::_VectorExtract:
|
||||
return inline_vector_extract();
|
||||
|
||||
case vmIntrinsics::_getObjectSize:
|
||||
return inline_getObjectSize();
|
||||
|
||||
default:
|
||||
// If you get here, it may be that someone has added a new intrinsic
|
||||
// to the list in vmSymbols.hpp without implementing it here.
|
||||
@ -6692,3 +6695,119 @@ bool LibraryCallKit::inline_isCompileConstant() {
|
||||
set_result(n->is_Con() ? intcon(1) : intcon(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------- inline_getObjectSize --------------------------------------
|
||||
//
|
||||
// Calculate the runtime size of the object/array.
|
||||
// native long sun.instrument.InstrumentationImpl.getObjectSize0(long nativeAgent, Object objectToSize);
|
||||
//
|
||||
bool LibraryCallKit::inline_getObjectSize() {
|
||||
Node* obj = argument(3);
|
||||
Node* klass_node = load_object_klass(obj);
|
||||
|
||||
jint layout_con = Klass::_lh_neutral_value;
|
||||
Node* layout_val = get_layout_helper(klass_node, layout_con);
|
||||
int layout_is_con = (layout_val == NULL);
|
||||
|
||||
if (layout_is_con) {
|
||||
// Layout helper is constant, can figure out things at compile time.
|
||||
|
||||
if (Klass::layout_helper_is_instance(layout_con)) {
|
||||
// Instance case: layout_con contains the size itself.
|
||||
Node *size = longcon(Klass::layout_helper_size_in_bytes(layout_con));
|
||||
set_result(size);
|
||||
} else {
|
||||
// Array case: size is round(header + element_size*arraylength).
|
||||
// Since arraylength is different for every array instance, we have to
|
||||
// compute the whole thing at runtime.
|
||||
|
||||
Node* arr_length = load_array_length(obj);
|
||||
|
||||
int round_mask = MinObjAlignmentInBytes - 1;
|
||||
int hsize = Klass::layout_helper_header_size(layout_con);
|
||||
int eshift = Klass::layout_helper_log2_element_size(layout_con);
|
||||
|
||||
if ((round_mask & ~right_n_bits(eshift)) == 0) {
|
||||
round_mask = 0; // strength-reduce it if it goes away completely
|
||||
}
|
||||
assert((hsize & right_n_bits(eshift)) == 0, "hsize is pre-rounded");
|
||||
Node* header_size = intcon(hsize + round_mask);
|
||||
|
||||
Node* lengthx = ConvI2X(arr_length);
|
||||
Node* headerx = ConvI2X(header_size);
|
||||
|
||||
Node* abody = lengthx;
|
||||
if (eshift != 0) {
|
||||
abody = _gvn.transform(new LShiftXNode(lengthx, intcon(eshift)));
|
||||
}
|
||||
Node* size = _gvn.transform( new AddXNode(headerx, abody) );
|
||||
if (round_mask != 0) {
|
||||
size = _gvn.transform( new AndXNode(size, MakeConX(~round_mask)) );
|
||||
}
|
||||
size = ConvX2L(size);
|
||||
set_result(size);
|
||||
}
|
||||
} else {
|
||||
// Layout helper is not constant, need to test for array-ness at runtime.
|
||||
|
||||
enum { _instance_path = 1, _array_path, PATH_LIMIT };
|
||||
RegionNode* result_reg = new RegionNode(PATH_LIMIT);
|
||||
PhiNode* result_val = new PhiNode(result_reg, TypeLong::LONG);
|
||||
record_for_igvn(result_reg);
|
||||
|
||||
Node* array_ctl = generate_array_guard(klass_node, NULL);
|
||||
if (array_ctl != NULL) {
|
||||
// Array case: size is round(header + element_size*arraylength).
|
||||
// Since arraylength is different for every array instance, we have to
|
||||
// compute the whole thing at runtime.
|
||||
|
||||
PreserveJVMState pjvms(this);
|
||||
set_control(array_ctl);
|
||||
Node* arr_length = load_array_length(obj);
|
||||
|
||||
int round_mask = MinObjAlignmentInBytes - 1;
|
||||
Node* mask = intcon(round_mask);
|
||||
|
||||
Node* hss = intcon(Klass::_lh_header_size_shift);
|
||||
Node* hsm = intcon(Klass::_lh_header_size_mask);
|
||||
Node* header_size = _gvn.transform(new URShiftINode(layout_val, hss));
|
||||
header_size = _gvn.transform(new AndINode(header_size, hsm));
|
||||
header_size = _gvn.transform(new AddINode(header_size, mask));
|
||||
|
||||
// There is no need to mask or shift this value.
|
||||
// The semantics of LShiftINode include an implicit mask to 0x1F.
|
||||
assert(Klass::_lh_log2_element_size_shift == 0, "use shift in place");
|
||||
Node* elem_shift = layout_val;
|
||||
|
||||
Node* lengthx = ConvI2X(arr_length);
|
||||
Node* headerx = ConvI2X(header_size);
|
||||
|
||||
Node* abody = _gvn.transform(new LShiftXNode(lengthx, elem_shift));
|
||||
Node* size = _gvn.transform(new AddXNode(headerx, abody));
|
||||
if (round_mask != 0) {
|
||||
size = _gvn.transform(new AndXNode(size, MakeConX(~round_mask)));
|
||||
}
|
||||
size = ConvX2L(size);
|
||||
|
||||
result_reg->init_req(_array_path, control());
|
||||
result_val->init_req(_array_path, size);
|
||||
}
|
||||
|
||||
if (!stopped()) {
|
||||
// Instance case: the layout helper gives us instance size almost directly,
|
||||
// but we need to mask out the _lh_instance_slow_path_bit.
|
||||
Node* size = ConvI2X(layout_val);
|
||||
assert((int) Klass::_lh_instance_slow_path_bit < BytesPerLong, "clear bit");
|
||||
Node* mask = MakeConX(~(intptr_t) right_n_bits(LogBytesPerLong));
|
||||
size = _gvn.transform(new AndXNode(size, mask));
|
||||
size = ConvX2L(size);
|
||||
|
||||
result_reg->init_req(_instance_path, control());
|
||||
result_val->init_req(_instance_path, size);
|
||||
}
|
||||
|
||||
set_result(result_reg, result_val);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -344,5 +344,7 @@ class LibraryCallKit : public GraphKit {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool inline_getObjectSize();
|
||||
};
|
||||
|
||||
|
@ -230,6 +230,7 @@ module java.base {
|
||||
jdk.internal.jvmstat,
|
||||
jdk.management.agent;
|
||||
exports jdk.internal.vm.annotation to
|
||||
java.instrument,
|
||||
jdk.internal.vm.ci,
|
||||
jdk.incubator.vector,
|
||||
jdk.incubator.foreign,
|
||||
|
@ -44,6 +44,7 @@ import java.util.Set;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import jdk.internal.module.Modules;
|
||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
|
||||
/*
|
||||
* Copyright 2003 Wily Technology, Inc.
|
||||
@ -392,6 +393,7 @@ public class InstrumentationImpl implements Instrumentation {
|
||||
private native Class[]
|
||||
getInitiatedClasses0(long nativeAgent, ClassLoader loader);
|
||||
|
||||
@IntrinsicCandidate
|
||||
private native long
|
||||
getObjectSize0(long nativeAgent, Object objectToSize);
|
||||
|
||||
|
@ -539,6 +539,11 @@ public class CheckGraalIntrinsics extends GraalTest {
|
||||
"jdk/internal/vm/vector/VectorSupport.unaryOp(ILjava/lang/Class;Ljava/lang/Class;ILjava/lang/Object;Ljava/util/function/Function;)Ljava/lang/Object;");
|
||||
}
|
||||
|
||||
if (isJDK16OrHigher()) {
|
||||
add(toBeInvestigated,
|
||||
"sun/instrument/InstrumentationImpl.getObjectSize0(JLjava/lang/Object;)J");
|
||||
}
|
||||
|
||||
/*
|
||||
* The intrinsics down here are known to be implemented but they are not always enabled on
|
||||
* the HotSpot side (e.g., because they require certain CPU features). So, we are ignoring
|
||||
|
413
test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java
Normal file
413
test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java
Normal file
@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Red Hat, Inc. 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8253525
|
||||
* @summary Test for fInst.getObjectSize with 32-bit compressed oops
|
||||
* @library /test/lib
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run build GetObjectSizeIntrinsicsTest
|
||||
* @run shell MakeJAR.sh basicAgent
|
||||
*
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
*
|
||||
* @run main/othervm -Xmx128m
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xint
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xbatch -XX:TieredStopAtLevel=1
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xbatch -XX:-TieredCompilation
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test for fInst.getObjectSize with zero-based compressed oops
|
||||
* @library /test/lib
|
||||
* @requires vm.bits == 64
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run build GetObjectSizeIntrinsicsTest
|
||||
* @run shell MakeJAR.sh basicAgent
|
||||
*
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
*
|
||||
* @run main/othervm -Xmx4g
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xint
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx4g
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xbatch -XX:TieredStopAtLevel=1
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx4g
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xbatch -XX:-TieredCompilation
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test for fInst.getObjectSize without compressed oops
|
||||
* @library /test/lib
|
||||
* @requires vm.bits == 64
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run build GetObjectSizeIntrinsicsTest
|
||||
* @run shell MakeJAR.sh basicAgent
|
||||
*
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
*
|
||||
* @run main/othervm -Xmx128m -XX:-UseCompressedOops
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xint
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m -XX:-UseCompressedOops
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xbatch -XX:TieredStopAtLevel=1
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m -XX:-UseCompressedOops
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -Xbatch -XX:-TieredCompilation
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test for fInst.getObjectSize with 32-bit compressed oops
|
||||
* @library /test/lib
|
||||
* @requires vm.debug
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run build GetObjectSizeIntrinsicsTest
|
||||
* @run shell MakeJAR.sh basicAgent
|
||||
*
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
*
|
||||
* @run main/othervm -Xmx128m
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:FastAllocateSizeLimit=0
|
||||
* -Xint
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:FastAllocateSizeLimit=0
|
||||
* -Xbatch -XX:TieredStopAtLevel=1
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:FastAllocateSizeLimit=0
|
||||
* -Xbatch -XX:-TieredCompilation
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test for fInst.getObjectSize with zero-based compressed oops
|
||||
* @library /test/lib
|
||||
* @requires vm.bits == 64
|
||||
* @requires vm.debug
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run build GetObjectSizeIntrinsicsTest
|
||||
* @run shell MakeJAR.sh basicAgent
|
||||
*
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
*
|
||||
* @run main/othervm -Xmx4g
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:FastAllocateSizeLimit=0
|
||||
* -Xint
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx4g
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:FastAllocateSizeLimit=0
|
||||
* -Xbatch -XX:TieredStopAtLevel=1
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx4g
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:FastAllocateSizeLimit=0
|
||||
* -Xbatch -XX:-TieredCompilation
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test for fInst.getObjectSize without compressed oops
|
||||
* @library /test/lib
|
||||
* @requires vm.bits == 64
|
||||
* @requires vm.debug
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run build GetObjectSizeIntrinsicsTest
|
||||
* @run shell MakeJAR.sh basicAgent
|
||||
*
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
*
|
||||
* @run main/othervm -Xmx128m -XX:-UseCompressedOops
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:FastAllocateSizeLimit=0
|
||||
* -Xint
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m -XX:-UseCompressedOops
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:FastAllocateSizeLimit=0
|
||||
* -Xbatch -XX:TieredStopAtLevel=1
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m -XX:-UseCompressedOops
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:FastAllocateSizeLimit=0
|
||||
* -Xbatch -XX:-TieredCompilation
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test for fInst.getObjectSize with 32-bit compressed oops
|
||||
* @library /test/lib
|
||||
* @requires vm.bits == 64
|
||||
* @requires vm.debug
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run build GetObjectSizeIntrinsicsTest
|
||||
* @run shell MakeJAR.sh basicAgent
|
||||
*
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
*
|
||||
* @run main/othervm -Xmx128m
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:ObjectAlignmentInBytes=32
|
||||
* -Xint
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:ObjectAlignmentInBytes=32
|
||||
* -Xbatch -XX:TieredStopAtLevel=1
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx128m
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:ObjectAlignmentInBytes=32
|
||||
* -Xbatch -XX:-TieredCompilation
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Test for fInst.getObjectSize with zero-based compressed oops
|
||||
* @library /test/lib
|
||||
* @requires vm.bits == 64
|
||||
* @requires vm.debug
|
||||
*
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* @run build GetObjectSizeIntrinsicsTest
|
||||
* @run shell MakeJAR.sh basicAgent
|
||||
*
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
*
|
||||
* @run main/othervm -Xmx4g
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:ObjectAlignmentInBytes=32
|
||||
* -Xint
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx4g
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:ObjectAlignmentInBytes=32
|
||||
* -Xbatch -XX:TieredStopAtLevel=1
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*
|
||||
* @run main/othervm -Xmx4g
|
||||
* -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:ObjectAlignmentInBytes=32
|
||||
* -Xbatch -XX:-TieredCompilation
|
||||
* -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import jdk.test.lib.Platform;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
public class GetObjectSizeIntrinsicsTest extends ASimpleInstrumentationTestCase {
|
||||
|
||||
static final Boolean compressedOops = WhiteBox.getWhiteBox().getBooleanVMFlag("UseCompressedOops");
|
||||
static final int REF_SIZE = (compressedOops == null || compressedOops == true) ? 4 : 8;
|
||||
|
||||
static final Long align = WhiteBox.getWhiteBox().getIntxVMFlag("ObjectAlignmentInBytes");
|
||||
static final int OBJ_ALIGN = (align == null ? 8 : align.intValue());
|
||||
|
||||
public GetObjectSizeIntrinsicsTest(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
public static void main(String[] args)throws Throwable {
|
||||
new GetObjectSizeIntrinsicsTest(args[0]).runTest();
|
||||
}
|
||||
|
||||
public static final int ITERS = 200_000;
|
||||
|
||||
public static void assertEquals(long expected, long actual) {
|
||||
if (expected != actual) {
|
||||
throw new IllegalStateException(
|
||||
"Error: expected: " + expected + " (" + Long.toHexString(expected) +
|
||||
"), actual: " + actual + " (" + Long.toHexString(actual) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertNotEquals(long notExpected, long actual) {
|
||||
if (notExpected == actual) {
|
||||
throw new IllegalStateException(
|
||||
"Error: not expected: " + notExpected + " (" + Long.toHexString(notExpected) +
|
||||
"), actual: " + actual + " (" + Long.toHexString(actual) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
public static void assertFail() {
|
||||
throw new IllegalStateException("Should not be here");
|
||||
}
|
||||
|
||||
protected final void doRunTest() throws Throwable {
|
||||
testSize_newObject();
|
||||
testSize_localObject();
|
||||
testSize_fieldObject();
|
||||
|
||||
testSize_newSmallByteArray();
|
||||
testSize_localSmallByteArray();
|
||||
testSize_fieldSmallByteArray();
|
||||
|
||||
testSize_newSmallObjArray();
|
||||
testSize_localSmallObjArray();
|
||||
testSize_fieldSmallObjArray();
|
||||
|
||||
testNulls();
|
||||
}
|
||||
|
||||
private static int roundUp(int v, int a) {
|
||||
return (v + a - 1) / a * a;
|
||||
}
|
||||
|
||||
private void testSize_newObject() {
|
||||
int expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN);
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
assertEquals(expected, fInst.getObjectSize(new Object()));
|
||||
}
|
||||
}
|
||||
|
||||
private void testSize_localObject() {
|
||||
int expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN);
|
||||
Object o = new Object();
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
assertEquals(expected, fInst.getObjectSize(o));
|
||||
}
|
||||
}
|
||||
|
||||
static Object staticO = new Object();
|
||||
|
||||
private void testSize_fieldObject() {
|
||||
int expected = roundUp(Platform.is64bit() ? 16 : 8, OBJ_ALIGN);
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
assertEquals(expected, fInst.getObjectSize(staticO));
|
||||
}
|
||||
}
|
||||
|
||||
private void testSize_newSmallByteArray() {
|
||||
int expected = roundUp(1024 + 16, OBJ_ALIGN);
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
assertEquals(expected, fInst.getObjectSize(new byte[1024]));
|
||||
}
|
||||
}
|
||||
|
||||
private void testSize_localSmallByteArray() {
|
||||
byte[] arr = new byte[1024];
|
||||
int expected = roundUp(arr.length + 16, OBJ_ALIGN);
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
assertEquals(expected, fInst.getObjectSize(arr));
|
||||
}
|
||||
}
|
||||
|
||||
static byte[] smallArr = new byte[1024];
|
||||
|
||||
private void testSize_fieldSmallByteArray() {
|
||||
int expected = roundUp(smallArr.length + 16, OBJ_ALIGN);
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
assertEquals(expected, fInst.getObjectSize(smallArr));
|
||||
}
|
||||
}
|
||||
|
||||
private void testSize_newSmallObjArray() {
|
||||
int expected = roundUp(1024*REF_SIZE + 16, OBJ_ALIGN);
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
assertEquals(expected, fInst.getObjectSize(new Object[1024]));
|
||||
}
|
||||
}
|
||||
|
||||
private void testSize_localSmallObjArray() {
|
||||
Object[] arr = new Object[1024];
|
||||
int expected = roundUp(arr.length*REF_SIZE + 16, OBJ_ALIGN);
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
assertEquals(expected, fInst.getObjectSize(arr));
|
||||
}
|
||||
}
|
||||
|
||||
static Object[] smallObjArr = new Object[1024];
|
||||
|
||||
private void testSize_fieldSmallObjArray() {
|
||||
int expected = roundUp(smallArr.length*REF_SIZE + 16, OBJ_ALIGN);
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
assertEquals(expected, fInst.getObjectSize(smallObjArr));
|
||||
}
|
||||
}
|
||||
|
||||
private void testNulls() {
|
||||
for (int c = 0; c < ITERS; c++) {
|
||||
try {
|
||||
fInst.getObjectSize(null);
|
||||
assertFail();
|
||||
} catch (NullPointerException e) {
|
||||
// expected
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user