Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8238369: [lworld] Incorrect layout of inline type in flattened array. #265

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -164,7 +164,7 @@ oop FlatArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) {

jint FlatArrayKlass::array_layout_helper(InlineKlass* vk) {
BasicType etype = T_INLINE_TYPE;
int esize = upper_log2(vk->raw_value_byte_size());
int esize = upper_log2(vk->get_exact_size_in_bytes());
int hsize = arrayOopDesc::base_offset_in_bytes(etype);

int lh = Klass::array_layout_helper(_lh_array_tag_vt_value, true, hsize, etype, esize);
@@ -87,44 +87,6 @@ int InlineKlass::first_field_offset_old() {
return base_offset;
}

int InlineKlass::raw_value_byte_size() {
int heapOopAlignedSize = nonstatic_field_size() << LogBytesPerHeapOop;
// If bigger than 64 bits or needs oop alignment, then use jlong aligned
// which for values should be jlong aligned, asserts in raw_field_copy otherwise
if (heapOopAlignedSize >= longSize || contains_oops()) {
return heapOopAlignedSize;
}
// Small primitives...
// If a few small basic type fields, return the actual size, i.e.
// 1 byte = 1
// 2 byte = 2
// 3 byte = 4, because pow2 needed for element stores
int first_offset = first_field_offset();
int last_offset = 0; // find the last offset, add basic type size
int last_tsz = 0;
for (AllFieldStream fs(this); !fs.done(); fs.next()) {
if (fs.access_flags().is_static()) {
continue;
} else if (fs.offset() > last_offset) {
BasicType type = Signature::basic_type(fs.signature());
if (is_java_primitive(type)) {
last_tsz = type2aelembytes(type);
} else if (type == T_INLINE_TYPE) {
// Not just primitives. Layout aligns embedded value, so use jlong aligned it is
return heapOopAlignedSize;
} else {
guarantee(0, "Unknown type %d", type);
}
assert(last_tsz != 0, "Invariant");
last_offset = fs.offset();
}
}
// Assumes VT with no fields are meaningless and illegal
last_offset += last_tsz;
assert(last_offset > first_offset && last_tsz, "Invariant");
return 1 << upper_log2(last_offset - first_offset);
}

instanceOop InlineKlass::allocate_instance(TRAPS) {
int size = size_helper(); // Query before forming handle.

@@ -183,7 +145,7 @@ bool InlineKlass::flatten_array() {
return false;
}
// Too big
int elem_bytes = raw_value_byte_size();
int elem_bytes = get_exact_size_in_bytes();
if ((FlatArrayElementMaxSize >= 0) && (elem_bytes > FlatArrayElementMaxSize)) {
return false;
}
@@ -182,9 +182,6 @@ class InlineKlass: public InstanceKlass {
// returning to Java (i.e.: inline_copy)
instanceOop allocate_instance_buffer(TRAPS);

// minimum number of bytes occupied by nonstatic fields, HeapWord aligned or pow2
int raw_value_byte_size();

address data_for_oop(oop o) const;
oop oop_for_data(address data) const;

@@ -33,7 +33,10 @@
* @library /test/lib
* @compile -XDallowWithFieldOperator InlineTypeDensity.java
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xint -XX:FlatArrayElementMaxSize=-1
* @run main/othervm -Xint -XX:FlatArrayElementMaxSize=-1 -XX:+UseCompressedOops
* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI InlineTypeDensity
* @run main/othervm -Xint -XX:FlatArrayElementMaxSize=-1 -XX:-UseCompressedOops
* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
* -XX:+WhiteBoxAPI InlineTypeDensity
* @run main/othervm -Xcomp -XX:FlatArrayElementMaxSize=-1
@@ -47,6 +50,7 @@
public class InlineTypeDensity {

private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
private static final boolean VM_FLAG_FORCENONTEARABLE = WHITE_BOX.getStringVMFlag("ForceNonTearable").equals("*");

public InlineTypeDensity() {
if (WHITE_BOX.getIntxVMFlag("FlatArrayElementMaxSize") != -1) {
@@ -229,8 +233,82 @@ public void ensureArraySizeWin() {
Asserts.assertLessThan(flatArraySize, objectArraySize, "Flat array accounts for more heap than object array + elements !");
}

static inline class MyByte { byte v = 0; }
static inline class MyShort { short v = 0; }
static inline class MyInt { int v = 0; }
static inline class MyLong { long v = 0; }

void assertArraySameSize(Object a, Object b, int nofElements) {
long aSize = WHITE_BOX.getObjectSize(a);
long bSize = WHITE_BOX.getObjectSize(b);
Asserts.assertEquals(aSize, bSize,
a + "(" + aSize + " bytes) not equivalent size " +
b + "(" + bSize + " bytes)" +
(nofElements >= 0 ? " (array of " + nofElements + " elements)" : ""));
}

void testByteArraySizesSame(int[] testSizes) {
for (int testSize : testSizes) {
byte[] ba = new byte[testSize];
MyByte[] mba = new MyByte[testSize];
assertArraySameSize(ba, mba, testSize);
}
}

void testShortArraySizesSame(int[] testSizes) {
for (int testSize : testSizes) {
short[] sa = new short[testSize];
MyShort[] msa = new MyShort[testSize];
assertArraySameSize(sa, msa, testSize);
}
}

void testIntArraySizesSame(int[] testSizes) {
for (int testSize : testSizes) {
int[] ia = new int[testSize];
MyInt[] mia = new MyInt[testSize];
assertArraySameSize(ia, mia, testSize);
}
}

void testLongArraySizesSame(int[] testSizes) {
for (int testSize : testSizes) {
long[] la = new long[testSize];
MyLong[] mla = new MyLong[testSize];
assertArraySameSize(la, mla, testSize);
}
}

public void testPrimitiveArraySizesSame() {
int[] testSizes = new int[] { 0, 1, 2, 3, 4, 7, 10, 257 };
testByteArraySizesSame(testSizes);
testShortArraySizesSame(testSizes);
testIntArraySizesSame(testSizes);
testLongArraySizesSame(testSizes);
}

static inline class bbValue { byte b = 0; byte b2 = 0;}
static inline class bsValue { byte b = 0; short s = 0;}
static inline class siValue { short s = 0; int i = 0;}
static inline class ssiValue { short s = 0; short s2 = 0; int i = 0;}
static inline class blValue { byte b = 0; long l = 0; }

// Expect aligned array addressing to nearest pow2
void testAlignedSize() {
int testSize = 10;
if (!VM_FLAG_FORCENONTEARABLE) {
assertArraySameSize(new short[testSize], new bbValue[testSize], testSize);
assertArraySameSize(new long[testSize], new siValue[testSize], testSize);
assertArraySameSize(new long[testSize], new ssiValue[testSize], testSize);
assertArraySameSize(new long[testSize*2], new blValue[testSize], testSize);
}
assertArraySameSize(new int[testSize], new bsValue[testSize], testSize);
}

public void test() {
ensureArraySizeWin();
testPrimitiveArraySizesSame();
testAlignedSize();
}

public static void main(String[] args) {