Skip to content

Commit cc1f08e

Browse files
author
David Simms
committed
8238369: [lworld] Incorrect layout of inline type in flattened array.
Reviewed-by: fparain
1 parent 928c29e commit cc1f08e

File tree

4 files changed

+81
-44
lines changed

4 files changed

+81
-44
lines changed

src/hotspot/share/oops/flatArrayKlass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ oop FlatArrayKlass::multi_allocate(int rank, jint* last_size, TRAPS) {
164164

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

170170
int lh = Klass::array_layout_helper(_lh_array_tag_vt_value, true, hsize, etype, esize);

src/hotspot/share/oops/inlineKlass.cpp

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -87,44 +87,6 @@ int InlineKlass::first_field_offset_old() {
8787
return base_offset;
8888
}
8989

90-
int InlineKlass::raw_value_byte_size() {
91-
int heapOopAlignedSize = nonstatic_field_size() << LogBytesPerHeapOop;
92-
// If bigger than 64 bits or needs oop alignment, then use jlong aligned
93-
// which for values should be jlong aligned, asserts in raw_field_copy otherwise
94-
if (heapOopAlignedSize >= longSize || contains_oops()) {
95-
return heapOopAlignedSize;
96-
}
97-
// Small primitives...
98-
// If a few small basic type fields, return the actual size, i.e.
99-
// 1 byte = 1
100-
// 2 byte = 2
101-
// 3 byte = 4, because pow2 needed for element stores
102-
int first_offset = first_field_offset();
103-
int last_offset = 0; // find the last offset, add basic type size
104-
int last_tsz = 0;
105-
for (AllFieldStream fs(this); !fs.done(); fs.next()) {
106-
if (fs.access_flags().is_static()) {
107-
continue;
108-
} else if (fs.offset() > last_offset) {
109-
BasicType type = Signature::basic_type(fs.signature());
110-
if (is_java_primitive(type)) {
111-
last_tsz = type2aelembytes(type);
112-
} else if (type == T_INLINE_TYPE) {
113-
// Not just primitives. Layout aligns embedded value, so use jlong aligned it is
114-
return heapOopAlignedSize;
115-
} else {
116-
guarantee(0, "Unknown type %d", type);
117-
}
118-
assert(last_tsz != 0, "Invariant");
119-
last_offset = fs.offset();
120-
}
121-
}
122-
// Assumes VT with no fields are meaningless and illegal
123-
last_offset += last_tsz;
124-
assert(last_offset > first_offset && last_tsz, "Invariant");
125-
return 1 << upper_log2(last_offset - first_offset);
126-
}
127-
12890
instanceOop InlineKlass::allocate_instance(TRAPS) {
12991
int size = size_helper(); // Query before forming handle.
13092

@@ -183,7 +145,7 @@ bool InlineKlass::flatten_array() {
183145
return false;
184146
}
185147
// Too big
186-
int elem_bytes = raw_value_byte_size();
148+
int elem_bytes = get_exact_size_in_bytes();
187149
if ((FlatArrayElementMaxSize >= 0) && (elem_bytes > FlatArrayElementMaxSize)) {
188150
return false;
189151
}

src/hotspot/share/oops/inlineKlass.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,6 @@ class InlineKlass: public InstanceKlass {
182182
// returning to Java (i.e.: inline_copy)
183183
instanceOop allocate_instance_buffer(TRAPS);
184184

185-
// minimum number of bytes occupied by nonstatic fields, HeapWord aligned or pow2
186-
int raw_value_byte_size();
187-
188185
address data_for_oop(oop o) const;
189186
oop oop_for_data(address data) const;
190187

test/hotspot/jtreg/runtime/valhalla/inlinetypes/InlineTypeDensity.java

Lines changed: 79 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@
3333
* @library /test/lib
3434
* @compile -XDallowWithFieldOperator InlineTypeDensity.java
3535
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
36-
* @run main/othervm -Xint -XX:FlatArrayElementMaxSize=-1
36+
* @run main/othervm -Xint -XX:FlatArrayElementMaxSize=-1 -XX:+UseCompressedOops
37+
* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
38+
* -XX:+WhiteBoxAPI InlineTypeDensity
39+
* @run main/othervm -Xint -XX:FlatArrayElementMaxSize=-1 -XX:-UseCompressedOops
3740
* -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
3841
* -XX:+WhiteBoxAPI InlineTypeDensity
3942
* @run main/othervm -Xcomp -XX:FlatArrayElementMaxSize=-1
@@ -47,6 +50,7 @@
4750
public class InlineTypeDensity {
4851

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

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

236+
static inline class MyByte { byte v = 0; }
237+
static inline class MyShort { short v = 0; }
238+
static inline class MyInt { int v = 0; }
239+
static inline class MyLong { long v = 0; }
240+
241+
void assertArraySameSize(Object a, Object b, int nofElements) {
242+
long aSize = WHITE_BOX.getObjectSize(a);
243+
long bSize = WHITE_BOX.getObjectSize(b);
244+
Asserts.assertEquals(aSize, bSize,
245+
a + "(" + aSize + " bytes) not equivalent size " +
246+
b + "(" + bSize + " bytes)" +
247+
(nofElements >= 0 ? " (array of " + nofElements + " elements)" : ""));
248+
}
249+
250+
void testByteArraySizesSame(int[] testSizes) {
251+
for (int testSize : testSizes) {
252+
byte[] ba = new byte[testSize];
253+
MyByte[] mba = new MyByte[testSize];
254+
assertArraySameSize(ba, mba, testSize);
255+
}
256+
}
257+
258+
void testShortArraySizesSame(int[] testSizes) {
259+
for (int testSize : testSizes) {
260+
short[] sa = new short[testSize];
261+
MyShort[] msa = new MyShort[testSize];
262+
assertArraySameSize(sa, msa, testSize);
263+
}
264+
}
265+
266+
void testIntArraySizesSame(int[] testSizes) {
267+
for (int testSize : testSizes) {
268+
int[] ia = new int[testSize];
269+
MyInt[] mia = new MyInt[testSize];
270+
assertArraySameSize(ia, mia, testSize);
271+
}
272+
}
273+
274+
void testLongArraySizesSame(int[] testSizes) {
275+
for (int testSize : testSizes) {
276+
long[] la = new long[testSize];
277+
MyLong[] mla = new MyLong[testSize];
278+
assertArraySameSize(la, mla, testSize);
279+
}
280+
}
281+
282+
public void testPrimitiveArraySizesSame() {
283+
int[] testSizes = new int[] { 0, 1, 2, 3, 4, 7, 10, 257 };
284+
testByteArraySizesSame(testSizes);
285+
testShortArraySizesSame(testSizes);
286+
testIntArraySizesSame(testSizes);
287+
testLongArraySizesSame(testSizes);
288+
}
289+
290+
static inline class bbValue { byte b = 0; byte b2 = 0;}
291+
static inline class bsValue { byte b = 0; short s = 0;}
292+
static inline class siValue { short s = 0; int i = 0;}
293+
static inline class ssiValue { short s = 0; short s2 = 0; int i = 0;}
294+
static inline class blValue { byte b = 0; long l = 0; }
295+
296+
// Expect aligned array addressing to nearest pow2
297+
void testAlignedSize() {
298+
int testSize = 10;
299+
if (!VM_FLAG_FORCENONTEARABLE) {
300+
assertArraySameSize(new short[testSize], new bbValue[testSize], testSize);
301+
assertArraySameSize(new long[testSize], new siValue[testSize], testSize);
302+
assertArraySameSize(new long[testSize], new ssiValue[testSize], testSize);
303+
assertArraySameSize(new long[testSize*2], new blValue[testSize], testSize);
304+
}
305+
assertArraySameSize(new int[testSize], new bsValue[testSize], testSize);
306+
}
307+
232308
public void test() {
233309
ensureArraySizeWin();
310+
testPrimitiveArraySizesSame();
311+
testAlignedSize();
234312
}
235313

236314
public static void main(String[] args) {

0 commit comments

Comments
 (0)