8253525: Implement getInstanceSize/sizeOf intrinsics

Reviewed-by: kvn, sspitsyn
This commit is contained in:
Aleksey Shipilev 2020-11-13 08:20:11 +00:00
parent ea576ddbd4
commit b4d0186718
12 changed files with 655 additions and 0 deletions

View File

@ -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.
}

View File

@ -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

View File

@ -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);

View File

@ -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") \

View File

@ -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") \

View File

@ -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:

View File

@ -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;
}

View File

@ -344,5 +344,7 @@ class LibraryCallKit : public GraphKit {
}
#endif
}
bool inline_getObjectSize();
};

View File

@ -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,

View File

@ -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);

View File

@ -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

View 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
}
}
}
}