Skip to content

Commit

Permalink
Add structral comparison barriers
Browse files Browse the repository at this point in the history
In #7743 a flag (J9ClassCanSupportFastSubstitutability) is added to each
valueType class if it does not contain any floating point primitives or
references that might potentially contain an unflattened valuetype or a
flattened valuetype that does not contain
J9ClassCanSupportFastSubstitutability.

For these classes a structural comparison can be performed. This is
essentially performing a memory comparison over the length of the
instances, if they are equivalent the result is true, otherwise false.
Since it will only contain scalar primitives and (non value) references,
equality can be determined by simply performing a memory comparison.
Unlike with floating point types or non-flattened valuetypes where
determining equality is more complicated.

A barrier helper is required as these instances may contain references.
In modes where no read barriers are required memcmp can be used.

Signed-off-by: Tobi Ajila <[email protected]>
  • Loading branch information
tajila committed Dec 6, 2019
1 parent d2a7c13 commit 1317684
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 5 deletions.
1 change: 1 addition & 0 deletions runtime/gc/gctable.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ J9MemoryManagerFunctions MemoryManagerFunctions = {
j9gc_objaccess_copyObjectFields,
j9gc_objaccess_copyObjectFieldsToFlattenedArrayElement,
j9gc_objaccess_copyObjectFieldsFromFlattenedArrayElement,
j9gc_objaccess_structuralCompareFlattenedObjects,
j9gc_objaccess_cloneIndexableObject,
j9gc_objaccess_asConstantPoolObject,
#if defined(J9VM_GC_REALTIME)
Expand Down
54 changes: 53 additions & 1 deletion runtime/gc_base/ObjectAccessBarrier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,58 @@ MM_ObjectAccessBarrier::cloneObject(J9VMThread *vmThread, J9Object *srcObject, J
copyObjectFields(vmThread, J9GC_J9OBJECT_CLAZZ_THREAD(srcObject, vmThread), srcObject, objectHeaderSize, destObject, objectHeaderSize);
}

BOOLEAN
MM_ObjectAccessBarrier::structuralCompareFlattenedObjects(J9VMThread *vmThread, J9Class *valueClass, j9object_t lhsObject, j9object_t rhsObject, UDATA startOffset)
{
bool result = true;
const UDATA *descriptionPtr = (UDATA *) valueClass->instanceDescription;
UDATA descriptionBits = 0;

Assert_MM_true(J9_IS_J9CLASS_VALUETYPE(valueClass));

if(((UDATA)descriptionPtr) & 1) {
descriptionBits = ((UDATA)descriptionPtr) >> 1;
} else {
descriptionBits = *descriptionPtr++;
}

UDATA descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;
UDATA offset = 0;
UDATA limit = valueClass->totalInstanceSize;

U_32 firstFieldOffset = (U_32) valueClass->backfillOffset;
if (0 != firstFieldOffset) {
/* subtract padding */
offset += firstFieldOffset;
descriptionBits >>= 1;
descriptionIndex -= 1;
}

while (offset < limit) {
/* Determine if the slot contains an object pointer or not */
if(descriptionBits & 1) {
if (mixedObjectReadObject(vmThread, lhsObject, startOffset + offset, false) != mixedObjectReadObject(vmThread, rhsObject, startOffset + offset, false)) {
result = false;
break;
}

} else {
if (*(fj9object_t *)((UDATA)lhsObject + startOffset + offset) != *(fj9object_t *)((UDATA)rhsObject + startOffset + offset)) {
result = false;
break;
}
}
descriptionBits >>= 1;
if(descriptionIndex-- == 0) {
descriptionBits = *descriptionPtr++;
descriptionIndex = J9_OBJECT_DESCRIPTION_SIZE - 1;
}
offset += sizeof(fj9object_t);
}

return result;
}

/**
* Copy all of the fields of a value class instance to another value class instance.
* The source or destination may be a flattened value within another object, meaning
Expand Down Expand Up @@ -1415,7 +1467,7 @@ MM_ObjectAccessBarrier::copyObjectFields(J9VMThread *vmThread, J9Class *objectCl
}

const UDATA *descriptionPtr = (UDATA *) objectClass->instanceDescription;
UDATA descriptionBits;
UDATA descriptionBits = 0;
if(((UDATA)descriptionPtr) & 1) {
descriptionBits = ((UDATA)descriptionPtr) >> 1;
} else {
Expand Down
1 change: 1 addition & 0 deletions runtime/gc_base/ObjectAccessBarrier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ class MM_ObjectAccessBarrier : public MM_BaseVirtual
virtual j9objectmonitor_t *getLockwordAddress(J9VMThread *vmThread, J9Object *object);
virtual void cloneObject(J9VMThread *vmThread, J9Object *srcObject, J9Object *destObject);
virtual void copyObjectFields(J9VMThread *vmThread, J9Class *valueClass, J9Object *srcObject, UDATA srcOffset, J9Object *destObject, UDATA destOffset);
virtual BOOLEAN structuralCompareFlattenedObjects(J9VMThread *vmThread, J9Class *valueClass, j9object_t lhsObject, j9object_t rhsObject, UDATA startOffset);
virtual void cloneIndexableObject(J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject);
virtual J9Object* asConstantPoolObject(J9VMThread *vmThread, J9Object* toConvert, UDATA allocationFlags);
virtual void storeObjectToInternalVMSlot(J9VMThread *vmThread, J9Object** destSlot, J9Object *value);
Expand Down
10 changes: 10 additions & 0 deletions runtime/gc_base/accessBarrier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,16 @@ j9gc_objaccess_cloneObject(J9VMThread *vmThread, J9Object *srcObject, J9Object *
return barrier->cloneObject(vmThread, srcObject, destObject);
}

/**
*
*/
BOOLEAN
j9gc_objaccess_structuralCompareFlattenedObjects(J9VMThread *vmThread, J9Class *valueClass, j9object_t lhsObject, j9object_t rhsObject, UDATA startOffset)
{
MM_ObjectAccessBarrier *barrier = MM_GCExtensions::getExtensions(vmThread)->accessBarrier;
return barrier->structuralCompareFlattenedObjects(vmThread, valueClass, lhsObject, rhsObject, startOffset);
}

/**
* Called by certain specs to copy objects
*/
Expand Down
1 change: 1 addition & 0 deletions runtime/gc_base/gc_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ extern J9_CFUNC void j9gc_objaccess_cloneObject(J9VMThread *vmThread, j9object_t
extern J9_CFUNC void j9gc_objaccess_copyObjectFields(J9VMThread *vmThread, J9Class *valueClass, J9Object *srcObject, UDATA srcOffset, J9Object *destObject, UDATA destOffset);
extern J9_CFUNC void j9gc_objaccess_copyObjectFieldsToFlattenedArrayElement(J9VMThread *vmThread, J9ArrayClass *arrayClazz, j9object_t srcObject, J9IndexableObject *arrayRef, I_32 index);
extern J9_CFUNC void j9gc_objaccess_copyObjectFieldsFromFlattenedArrayElement(J9VMThread *vmThread, J9ArrayClass *arrayClazz, j9object_t destObject, J9IndexableObject *arrayRef, I_32 index);
extern J9_CFUNC BOOLEAN j9gc_objaccess_structuralCompareFlattenedObjects(J9VMThread *vmThread, J9Class *valueClass, j9object_t lhsObject, j9object_t rhsObject, UDATA startOffset);
extern J9_CFUNC j9object_t j9gc_objaccess_asConstantPoolObject(J9VMThread *vmThread, j9object_t toConvert, UDATA allocationFlags);
extern J9_CFUNC jvmtiIterationControl j9mm_iterate_heaps(J9JavaVM *vm, J9PortLibrary *portLibrary, UDATA flags, jvmtiIterationControl(*func)(J9JavaVM *vm, struct J9MM_IterateHeapDescriptor *heapDesc, void *userData), void *userData);
extern J9_CFUNC int gcStartupHeapManagement(J9JavaVM * vm);
Expand Down
17 changes: 17 additions & 0 deletions runtime/gc_include/ObjectAccessBarrierAPI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,23 @@ class MM_ObjectAccessBarrierAPI
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_copyObjectFieldsFromFlattenedArrayElement(vmThread, arrayClazz, destObject, arrayRef, (I_32)index);
}

VMINLINE BOOLEAN
structuralFlattenedCompareObjects(J9VMThread *vmThread, J9Class *valueClass, j9object_t lhsObject, j9object_t rhsObject, UDATA startOffset)
{
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_structuralCompareFlattenedObjects(vmThread, valueClass, lhsObject, rhsObject, startOffset);
#else /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */
if (j9gc_modron_readbar_none != _readBarrierType) {
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_structuralCompareFlattenedObjects(vmThread, valueClass, lhsObject, rhsObject, startOffset);
} else {
startOffset += valueClass->backfillOffset;
UDATA compareSize = mixedObjectGetDataSize(valueClass) - valueClass->backfillOffset;

return (0 == memcmp((void*)((UDATA)lhsObject + startOffset), (void*)((UDATA)rhsObject + startOffset), (size_t)compareSize));
}
#endif /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */
}

/**
* Copy valueType from sourceObject to destObject
* See MM_ObjectAccessBarrier::copyObjectFields for detailed description
Expand Down
1 change: 1 addition & 0 deletions runtime/oti/j9nonbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -4382,6 +4382,7 @@ typedef struct J9MemoryManagerFunctions {
void ( *j9gc_objaccess_copyObjectFields)(struct J9VMThread *vmThread, J9Class* valueClass, j9object_t srcObject, UDATA srcOffset, j9object_t destObject, UDATA destOffset) ;
void ( *j9gc_objaccess_copyObjectFieldsToFlattenedArrayElement)(struct J9VMThread *vmThread, J9ArrayClass *arrayClazz, j9object_t srcObject, J9IndexableObject *arrayRef, I_32 index) ;
void ( *j9gc_objaccess_copyObjectFieldsFromFlattenedArrayElement)(struct J9VMThread *vmThread, J9ArrayClass *arrayClazz, j9object_t destObject, J9IndexableObject *arrayRef, I_32 index) ;
BOOLEAN ( *j9gc_objaccess_structuralCompareFlattenedObjects)(struct J9VMThread *vmThread, J9Class *valueClass, j9object_t lhsObject, j9object_t rhsObject, UDATA startOffset) ;
void ( *j9gc_objaccess_cloneIndexableObject)(struct J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject) ;
j9object_t ( *j9gc_objaccess_asConstantPoolObject)(struct J9VMThread *vmThread, j9object_t toConvert, UDATA allocationFlags) ;
#if defined(J9VM_GC_REALTIME)
Expand Down
8 changes: 4 additions & 4 deletions runtime/vm/BytecodeInterpreter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5821,7 +5821,7 @@ done:;
} else {
j9object_t value = NULL;
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
J9ArrayClass *arrayrefClass = J9OBJECT_CLAZZ(_currentThread, arrayref);
J9Class *arrayrefClass = J9OBJECT_CLAZZ(_currentThread, arrayref);
if (J9_IS_J9CLASS_FLATTENED(arrayrefClass)) {
j9object_t newObjectRef = _objectAllocate.inlineAllocateObject(_currentThread, ((J9ArrayClass*)arrayrefClass)->leafComponentType, false, false);

Expand All @@ -5840,7 +5840,7 @@ done:;
arrayrefClass = VM_VMHelpers::currentClass(arrayrefClass);
}

_objectAccessBarrier.copyObjectFieldsFromFlattenedArrayElement(_currentThread, arrayrefClass, newObjectRef, (J9IndexableObject *) arrayref, index);
_objectAccessBarrier.copyObjectFieldsFromFlattenedArrayElement(_currentThread, (J9ArrayClass *) arrayrefClass, newObjectRef, (J9IndexableObject *) arrayref, index);
value = newObjectRef;
} else
#endif /* if defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
Expand Down Expand Up @@ -5879,9 +5879,9 @@ done:;
rc = THROW_ARRAY_STORE;
} else {
#if defined(J9VM_OPT_VALHALLA_VALUE_TYPES)
J9ArrayClass *arrayrefClass = J9OBJECT_CLAZZ(_currentThread, arrayref);
J9Class *arrayrefClass = J9OBJECT_CLAZZ(_currentThread, arrayref);
if (J9_IS_J9CLASS_FLATTENED(arrayrefClass)) {
_objectAccessBarrier.copyObjectFieldsToFlattenedArrayElement(_currentThread, arrayrefClass, value, (J9IndexableObject *) arrayref, index);
_objectAccessBarrier.copyObjectFieldsToFlattenedArrayElement(_currentThread, (J9ArrayClass *) arrayrefClass, value, (J9IndexableObject *) arrayref, index);
} else
#endif /* if defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */
{
Expand Down

0 comments on commit 1317684

Please sign in to comment.