Skip to content

Commit

Permalink
Merge pull request #6695 from thomaslittletrainx/master
Browse files Browse the repository at this point in the history
Check if array Class contain unflattened flattenables and set default values for unflattened fields
  • Loading branch information
gacholio committed Aug 30, 2019
2 parents 262021a + cd27a49 commit 41b062d
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 19 deletions.
19 changes: 19 additions & 0 deletions runtime/gc_modron_startup/mgcalloc.cpp
Expand Up @@ -47,6 +47,7 @@
#include "MemorySubSpace.hpp"
#include "MixedObjectAllocationModel.hpp"
#include "ObjectAccessBarrier.hpp"
#include "ObjectAccessBarrierAPI.hpp"
#include "ObjectAllocationInterface.hpp"
#include "ObjectModel.hpp"

Expand Down Expand Up @@ -328,6 +329,15 @@ J9AllocateIndexableObjectNoGC(J9VMThread *vmThread, J9Class *clazz, uint32_t num
env->_isInNoGCAllocationCall = false;
}
}
/* TODO: Need to implement a more optimal path for cases where barriers are not required or where a batch barrier can be used. */
if ((NULL != objectPtr) && J9_ARE_ALL_BITS_SET(clazz->classFlags, J9ClassContainsUnflattenedFlattenables)) {
MM_ObjectAccessBarrierAPI objectAccessBarrier(vmThread);
J9Class * elementClass = ((J9ArrayClass *) clazz)->componentType;
j9object_t defaultValue = elementClass->flattenedClassCache->defaultValue;
for (UDATA index = 0; index < numberOfIndexedFields; index++) {
objectAccessBarrier.inlineIndexableObjectStoreObject(vmThread, objectPtr, index, defaultValue);
}
}

return objectPtr;
}
Expand Down Expand Up @@ -592,6 +602,15 @@ J9AllocateIndexableObject(J9VMThread *vmThread, J9Class *clazz, uint32_t numberO
dumpStackFrames(vmThread);
TRIGGER_J9HOOK_MM_PRIVATE_OUT_OF_MEMORY(extensions->privateHookInterface, vmThread->omrVMThread, j9time_hires_clock(), J9HOOK_MM_PRIVATE_OUT_OF_MEMORY, memorySpace, memorySpace->getName());
}
/* TODO: Need to implement a more optimal path for cases where barriers are not required or where a batch barrier can be used. */
if ((NULL != objectPtr) && J9_ARE_ALL_BITS_SET(clazz->classFlags, J9ClassContainsUnflattenedFlattenables)) {
MM_ObjectAccessBarrierAPI objectAccessBarrier(vmThread);
J9Class * elementClass = ((J9ArrayClass *) clazz)->componentType;
j9object_t defaultValue = elementClass->flattenedClassCache->defaultValue;
for (UDATA index = 0; index < numberOfIndexedFields; index++) {
objectAccessBarrier.inlineIndexableObjectStoreObject(vmThread, objectPtr, index, defaultValue);
}
}

#if defined(J9VM_GC_THREAD_LOCAL_HEAP)
if (extensions->fvtest_disableInlineAllocation || extensions->instrumentableAllocateHookEnabled || extensions->disableInlineCacheForAllocationThreshold ) {
Expand Down
45 changes: 26 additions & 19 deletions runtime/vm/BytecodeInterpreter.hpp
Expand Up @@ -1045,6 +1045,25 @@ obj:;
return instance;
}

/* Allocate an array instance
*
* @returns the allocated array instance
*/
VMINLINE j9object_t
inlineArrayAllocation(J9Class *arrayClass, U_32 size, bool initializeSlots = true, bool memoryBarrier = true, bool sizeCheck = true)
{
j9object_t instance = NULL;
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
if (J9_IS_J9CLASS_FLATTENED(arrayClass)) {
instance = _objectAllocate.inlineAllocateIndexableValueTypeObject(_currentThread, arrayClass, size, initializeSlots, memoryBarrier, sizeCheck);
} else
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
{
instance = _objectAllocate.inlineAllocateIndexableObject(_currentThread, arrayClass, size, initializeSlots, memoryBarrier, sizeCheck);
}
return instance;
}

/**
* Perform a non-instrumentable allocation of an indexable class.
* If inline allocation fails, the out of line allocator will be called.
Expand All @@ -1062,14 +1081,11 @@ obj:;
allocateIndexableObject(REGISTER_ARGS_LIST, J9Class *arrayClass, U_32 size, bool initializeSlots = true, bool memoryBarrier = true, bool sizeCheck = true)
{
j9object_t instance = NULL;

#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
if (J9_IS_J9CLASS_FLATTENED(arrayClass)) {
instance = _objectAllocate.inlineAllocateIndexableValueTypeObject(_currentThread, arrayClass, (U_32)size, initializeSlots, memoryBarrier, sizeCheck);
} else
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
if (J9_ARE_NO_BITS_SET(arrayClass->classFlags, J9ClassContainsUnflattenedFlattenables))
#endif
{
instance = _objectAllocate.inlineAllocateIndexableObject(_currentThread, arrayClass, (U_32)size, initializeSlots, memoryBarrier, sizeCheck);
instance = inlineArrayAllocation(arrayClass, size, initializeSlots, memoryBarrier, sizeCheck);
}

if (NULL == instance) {
Expand Down Expand Up @@ -3112,14 +3128,7 @@ done:;
if (flags & J9AccClassArray) {
U_32 size = J9INDEXABLEOBJECT_SIZE(_currentThread, original);

#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
if (J9_IS_J9CLASS_FLATTENED(objectClass)) {
copy = _objectAllocate.inlineAllocateIndexableValueTypeObject(_currentThread, objectClass, size, false, false, false);
} else
#endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
{
copy = _objectAllocate.inlineAllocateIndexableObject(_currentThread, objectClass, size, false, false, false);
}
copy = inlineArrayAllocation(objectClass, size, false, false, false);

if (NULL == copy) {
pushObjectInSpecialFrame(REGISTER_ARGS, original);
Expand Down Expand Up @@ -7539,12 +7548,10 @@ done:;
if (J9_EXPECTED(NULL != arrayClass)) {
j9object_t instance = NULL;
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
if (J9_IS_J9CLASS_FLATTENED(arrayClass)) {
instance = _objectAllocate.inlineAllocateIndexableValueTypeObject(_currentThread, arrayClass, (U_32)size);
} else
#endif /* J9VM_OPT_VALHALLA_VALUE_TYPES */
if (J9_ARE_NO_BITS_SET(arrayClass->classFlags, J9ClassContainsUnflattenedFlattenables))
#endif
{
instance = _objectAllocate.inlineAllocateIndexableObject(_currentThread, arrayClass, (U_32)size);
instance = inlineArrayAllocation(arrayClass, (U_32) size);
}

if (NULL == instance) {
Expand Down
3 changes: 3 additions & 0 deletions runtime/vm/createramclass.cpp
Expand Up @@ -2892,6 +2892,9 @@ internalCreateRAMClassFromROMClassImpl(J9VMThread *vmThread, J9ClassLoader *clas
J9ARRAYCLASS_SET_STRIDE(ramClass, J9_VALUETYPE_FLATTENED_SIZE(elementClass));
}
} else {
if (J9_IS_J9CLASS_VALUETYPE(elementClass)) {
ramArrayClass->classFlags |= J9ClassContainsUnflattenedFlattenables;
}
J9ARRAYCLASS_SET_STRIDE(ramClass, (((UDATA) 1) << (((J9ROMArrayClass*)romClass)->arrayShape & 0x0000FFFF)));
}
} else if (J9ROMCLASS_IS_PRIMITIVE_TYPE(ramClass->romClass)) {
Expand Down
Expand Up @@ -1367,6 +1367,79 @@ static public void testCreateLargeNumberOfPoint2D() throws Throwable {
}
}

/*
* Create Array Objects with Point Class without initialization
* The array should be set to a Default Value.
*/
@Test(priority=4)
static public void testDefaultValueInPointArray() throws Throwable {
Object pointArray = Array.newInstance(point2DClass, 10);
for (int i = 0; i < 10; i++) {
Object pointObject = Array.get(pointArray, i);
assertNotNull(pointObject);
}
}

/*
* Create Array Objects with Flattened Line without initialization
* Check the fields of each element in arrays. No field should be NULL.
*/
@Test(priority=4)
static public void testDefaultValueInLineArray() throws Throwable {
Object flattenedLineArray = Array.newInstance(flattenedLine2DClass, 10);
for (int i = 0; i < 10; i++) {
Object lineObject = Array.get(flattenedLineArray, i);
assertNotNull(lineObject);
assertNotNull(getFlatSt.invoke(lineObject));
assertNotNull(getFlatEn.invoke(lineObject));
}
}

/*
* Create Array Objects with triangle class without initialization
* Check the fields of each element in arrays. No field should be NULL.
*/
@Test(priority=4)
static public void testDefaultValueInTriangleArray() throws Throwable {
Object triangleArray = Array.newInstance(triangle2DClass, 10);
for (int i = 0; i < 10; i++) {
Object triangleObject = Array.get(triangleArray, i);
assertNotNull(triangleObject);
assertNotNull(getV1.invoke(triangleObject));
assertNotNull(getV2.invoke(triangleObject));
assertNotNull(getV3.invoke(triangleObject));
}
}

/*
* Create an Array Object with assortedValueWithLongAlignment class without initialization
* Check the fields of each element in arrays. No field should be NULL.
*/
@Test(priority=4)
static public void testDefaultValueInAssortedValueWithLongAlignmentArray() throws Throwable {
Object assortedValueWithLongAlignmentArray = Array.newInstance(assortedValueWithLongAlignmentClass, 10);
for (int i = 0; i < 10; i++) {
Object assortedValueWithLongAlignmentObject = Array.get(assortedValueWithLongAlignmentArray, i);
assertNotNull(assortedValueWithLongAlignmentObject);
for (int j = 0; j < 7; j++) {
assertNotNull(assortedValueWithLongAlignmentGetterAndWither[j][0].invoke(assortedValueWithLongAlignmentObject));
}
}
}

/*
* Create an assortedRefWithLongAlignment Array
* Since it's ref type, the array should be filled with nullptrs
*/
@Test(priority=4)
static public void testDefaultValueInassortedRefWithLongAlignmentArray() throws Throwable {
Object assortedRefWithLongAlignmentArray = Array.newInstance(assortedRefWithLongAlignmentClass, 10);
for (int i = 0; i < 10; i++) {
Object assortedRefWithLongAlignmentObject = Array.get(assortedRefWithLongAlignmentArray, i);
assertNull(assortedRefWithLongAlignmentObject);
}
}

static MethodHandle generateGetter(Class<?> clazz, String fieldName, Class<?> fieldType) {
try {
return lookup.findVirtual(clazz, "get"+fieldName, MethodType.methodType(fieldType));
Expand Down

0 comments on commit 41b062d

Please sign in to comment.