-
Notifications
You must be signed in to change notification settings - Fork 738
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
Implement X86 codegen support for dynamic array clone #4179
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6558,6 +6558,7 @@ static void genInitObjectHeader(TR::Node *node, | |
TR::Register *objectReg, | ||
TR::Register *tempReg, | ||
bool isZeroInitialized, | ||
bool isDynamicAllocation, | ||
TR::CodeGenerator *cg) | ||
{ | ||
TR::Compilation *comp = cg->comp(); | ||
|
@@ -6567,12 +6568,7 @@ static void genInitObjectHeader(TR::Node *node, | |
(!TR::Compiler->om.generateCompressedObjectHeaders() || | ||
(cg->comp()->compileRelocatableCode() && cg->comp()->getOption(TR_UseSymbolValidationManager))); | ||
|
||
// This code was moved to this point so that the romClass can be used by the AOT | ||
// portion without calling the method again. | ||
// | ||
J9ROMClass *romClass = 0; | ||
TR_ASSERT(clazz, "Cannot have a null OpaqueClassBlock\n"); | ||
romClass = TR::Compiler->cls.romClassOf(clazz); | ||
TR_ASSERT((isDynamicAllocation || clazz), "Cannot have a null clazz while not doing dynamic array allocation\n"); | ||
|
||
// -------------------------------------------------------------------------------- | ||
// | ||
|
@@ -6584,8 +6580,16 @@ static void genInitObjectHeader(TR::Node *node, | |
|
||
TR::Register * clzReg = classReg; | ||
|
||
// For dynamic array allocation, load the array class from the component class and store into clzReg | ||
if (isDynamicAllocation) | ||
{ | ||
TR_ASSERT((node->getOpCodeValue() == TR::anewarray), "Dynamic allocation currently only supports reference arrays"); | ||
TR_ASSERT(classReg, "must have a classReg for dynamic allocation"); | ||
clzReg = tempReg; | ||
generateRegMemInstruction(LRegMem(), node, clzReg, generateX86MemoryReference(classReg, offsetof(J9Class, arrayClass), cg), cg); | ||
} | ||
// TODO: should be able to use a TR_ClassPointer relocation without this stuff (along with class validation) | ||
if (cg->needClassAndMethodPointerRelocations() && !comp->getOption(TR_UseSymbolValidationManager)) | ||
else if (cg->needClassAndMethodPointerRelocations() && !comp->getOption(TR_UseSymbolValidationManager)) | ||
{ | ||
TR::Register *vmThreadReg = cg->getVMThreadRegister(); | ||
if (node->getOpCodeValue() == TR::newarray) | ||
|
@@ -6601,13 +6605,6 @@ static void genInitObjectHeader(TR::Node *node, | |
tempReg, cg); | ||
clzReg = tempReg; | ||
} | ||
else if (node->getOpCodeValue() == TR::anewarray) | ||
{ | ||
TR_ASSERT(classReg, "must have a classReg for TR::anewarray in AOT mode"); | ||
generateRegMemInstruction(LRegMem(), node, tempReg, | ||
generateX86MemoryReference(classReg, offsetof(J9Class, arrayClass), cg), cg); | ||
clzReg = tempReg; | ||
} | ||
else | ||
{ | ||
TR_ASSERT((node->getOpCodeValue() == TR::New) | ||
|
@@ -6661,6 +6658,7 @@ static void genInitObjectHeader(TR::Node *node, | |
|
||
#ifndef J9VM_INTERP_FLAGS_IN_CLASS_SLOT | ||
// Enable macro once GC-Helper is fixed | ||
J9ROMClass *romClass = TR::Compiler->cls.romClassOf(clazz); | ||
if (romClass) | ||
{ | ||
orFlags |= romClass->instanceShape; | ||
|
@@ -6682,23 +6680,39 @@ static void genInitObjectHeader(TR::Node *node, | |
// | ||
// -------------------------------------------------------------------------------- | ||
// | ||
J9Class *j9class = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz); | ||
bool initReservable = J9CLASS_EXTENDED_FLAGS(j9class) & J9ClassReservableLockWordInit; | ||
if (!isZeroInitialized || initReservable) | ||
// For dynamic array allocation, in case (very unlikely) the object array has a lock word, we just initialized it to 0 conservatively. | ||
// In this case, if the original array is reserved, initializating the cloned object's lock word to 0 will force the | ||
// locking to go to the slow locking path. | ||
if (isDynamicAllocation) | ||
{ | ||
TR::LabelSymbol *doneLabel = generateLabelSymbol(cg); | ||
generateRegMemInstruction(LRegMem(), node, tempReg, generateX86MemoryReference(clzReg, offsetof(J9ArrayClass, lockOffset), cg), cg); | ||
generateRegImmInstruction(CMPRegImm4(), node, tempReg, (int32_t)-1, cg); | ||
generateLabelInstruction (JE4, node, doneLabel, cg); | ||
generateMemImmInstruction(SMemImm4(TR::Compiler->target.is64Bit() && !fej9->generateCompressedLockWord()), | ||
node, generateX86MemoryReference(objectReg, tempReg, 0, cg), 0, cg); | ||
generateLabelInstruction(LABEL, node, doneLabel, cg); | ||
} | ||
else | ||
{ | ||
bool initLw = (node->getOpCodeValue() != TR::New) || initReservable; | ||
int lwOffset = fej9->getByteOffsetToLockword(clazz); | ||
if (lwOffset == -1) | ||
initLw = false; | ||
|
||
if (initLw) | ||
J9Class *j9class = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz); | ||
bool initReservable = J9CLASS_EXTENDED_FLAGS(j9class) & J9ClassReservableLockWordInit; | ||
if (!isZeroInitialized || initReservable) | ||
{ | ||
int32_t initialLwValue = 0; | ||
if (initReservable) | ||
initialLwValue = OBJECT_HEADER_LOCK_RESERVED; | ||
bool initLw = (node->getOpCodeValue() != TR::New) || initReservable; | ||
int lwOffset = fej9->getByteOffsetToLockword(clazz); | ||
if (lwOffset == -1) | ||
initLw = false; | ||
|
||
TR_X86OpCodes op = (TR::Compiler->target.is64Bit() && fej9->generateCompressedLockWord()) ? S4MemImm4 : SMemImm4(); | ||
generateMemImmInstruction(op, node, generateX86MemoryReference(objectReg, lwOffset, cg), initialLwValue, cg); | ||
if (initLw) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think some comments about lock word handling are warranted along with a description of the interaction with lock reservation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added more comments to address lock reservation case. |
||
{ | ||
int32_t initialLwValue = 0; | ||
if (initReservable) | ||
initialLwValue = OBJECT_HEADER_LOCK_RESERVED; | ||
|
||
generateMemImmInstruction(SMemImm4(TR::Compiler->target.is64Bit() && !fej9->generateCompressedLockWord()), | ||
node, generateX86MemoryReference(objectReg, lwOffset, cg), initialLwValue, cg); | ||
} | ||
} | ||
} | ||
} | ||
|
@@ -6716,13 +6730,14 @@ static void genInitArrayHeader( | |
int32_t arrayletDataOffset, | ||
TR::Register *tempReg, | ||
bool isZeroInitialized, | ||
bool isDynamicAllocation, | ||
TR::CodeGenerator *cg) | ||
{ | ||
TR_J9VMBase *fej9 = (TR_J9VMBase *)(cg->fe()); | ||
|
||
// Initialize the object header | ||
// | ||
genInitObjectHeader(node, clazz, classReg, objectReg, tempReg, isZeroInitialized, cg); | ||
genInitObjectHeader(node, clazz, classReg, objectReg, tempReg, isZeroInitialized, isDynamicAllocation, cg); | ||
|
||
int32_t arraySizeOffset = fej9->getOffsetOfContiguousArraySizeField(); | ||
|
||
|
@@ -7293,7 +7308,6 @@ J9::X86::TreeEvaluator::VMnewEvaluator( | |
TR_OpaqueClassBlock *clazz = NULL; | ||
TR::Register *classReg = NULL; | ||
bool isArrayNew = false; | ||
|
||
int32_t allocationSize = 0; | ||
int32_t objectSize = 0; | ||
int32_t elementSize = 0; | ||
|
@@ -7347,7 +7361,11 @@ J9::X86::TreeEvaluator::VMnewEvaluator( | |
objectSize = comp->canAllocateInline(node, clazz); | ||
if (objectSize < 0) | ||
return NULL; | ||
|
||
// Currently dynamic allocation is only supported on reference array. | ||
// We are performing dynamic array allocation if both object size and | ||
// class block cannot be statically determined. | ||
bool dynamicArrayAllocation = (node->getOpCodeValue() == TR::anewarray) | ||
&& (objectSize == 0) && (clazz == NULL); | ||
allocationSize = objectSize; | ||
|
||
static long count = 0; | ||
|
@@ -7392,6 +7410,9 @@ J9::X86::TreeEvaluator::VMnewEvaluator( | |
elementSize = (int32_t)TR::Compiler->om.sizeofReferenceAddress(); | ||
|
||
classReg = node->getSecondChild()->getRegister(); | ||
// For dynamic array allocation, need to evaluate second child | ||
if (!classReg && dynamicArrayAllocation) | ||
classReg = cg->evaluate(node->getSecondChild()); | ||
} | ||
|
||
isArrayNew = true; | ||
|
@@ -7683,9 +7704,8 @@ J9::X86::TreeEvaluator::VMnewEvaluator( | |
// -------------------------------------------------------------------------------- | ||
// Initialize the header | ||
// -------------------------------------------------------------------------------- | ||
if (fej9->inlinedAllocationsMustBeVerified() | ||
&& !comp->getOption(TR_UseSymbolValidationManager) | ||
&& node->getOpCodeValue() == TR::anewarray) | ||
// If dynamic array allocation, must pass in classReg to initialize the array header | ||
if ((fej9->inlinedAllocationsMustBeVerified() && !comp->getOption(TR_UseSymbolValidationManager) && node->getOpCodeValue() == TR::anewarray) || dynamicArrayAllocation) | ||
{ | ||
genInitArrayHeader( | ||
node, | ||
|
@@ -7697,6 +7717,7 @@ J9::X86::TreeEvaluator::VMnewEvaluator( | |
dataOffset, | ||
tempReg, | ||
monitorSlotIsInitialized, | ||
true, | ||
cg); | ||
} | ||
else if (isArrayNew) | ||
|
@@ -7711,11 +7732,12 @@ J9::X86::TreeEvaluator::VMnewEvaluator( | |
dataOffset, | ||
tempReg, | ||
monitorSlotIsInitialized, | ||
false, | ||
cg); | ||
} | ||
else | ||
{ | ||
genInitObjectHeader(node, clazz, classReg, targetReg, tempReg, monitorSlotIsInitialized, cg); | ||
genInitObjectHeader(node, clazz, classReg, targetReg, tempReg, monitorSlotIsInitialized, false, cg); | ||
} | ||
|
||
if (fej9->inlinedAllocationsMustBeVerified() && (node->getOpCodeValue() == TR::New || | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we assert here that
node->getOpCodeValue() == TR::anewarray
? Just becauseif (isDynamicAllocation)
sounds more generic, but onlyanewarray
is handled.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done