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

Load default value instance if the class is initialized #15666

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion runtime/compiler/codegen/J9AheadOfTimeCompile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,10 @@ static const char* getNameForMethodRelocation (int type)
return "TR_SpecialRamMethodConst";
case TR_VirtualRamMethodConst:
return "TR_VirtualRamMethodConst";
case TR_ClassAddress:
return "TR_ClassAddress";
case TR_StaticDefaultValueInstance:
return "TR_StaticDefaultValueInstance";
default:
TR_ASSERT(0, "We already cleared one switch, hard to imagine why we would have a different type here");
break;
Expand Down Expand Up @@ -381,6 +385,7 @@ J9::AheadOfTimeCompile::initializeCommonAOTRelocationHeader(TR::IteratedExternal
case TR_StaticRamMethodConst:
case TR_SpecialRamMethodConst:
case TR_VirtualRamMethodConst:
case TR_StaticDefaultValueInstance:
case TR_ClassAddress:
{
TR_RelocationRecordConstantPoolWithIndex *cpiRecord = reinterpret_cast<TR_RelocationRecordConstantPoolWithIndex *>(reloRecord);
Expand Down Expand Up @@ -1464,14 +1469,16 @@ J9::AheadOfTimeCompile::dumpRelocationHeaderData(uint8_t *cursor, bool isVerbose
}
break;

case TR_StaticDefaultValueInstance:
case TR_ClassAddress:
{
TR_RelocationRecordConstantPoolWithIndex *cpiRecord = reinterpret_cast<TR_RelocationRecordConstantPoolWithIndex *>(reloRecord);

self()->traceRelocationOffsets(startOfOffsets, offsetSize, endOfCurrentRecord, orderedPair);
if (isVerbose)
{
traceMsg(self()->comp(), "\n Address Relocation (TR_ClassAddress): inlinedIndex = %d, constantPool = %p, CPI = %d, flags = %x",
traceMsg(self()->comp(), "\n Address Relocation (%s): inlinedIndex = %d, constantPool = %p, CPI = %d, flags = 0x%x",
getNameForMethodRelocation(kind),
cpiRecord->inlinedSiteIndex(reloTarget),
cpiRecord->constantPool(reloTarget),
cpiRecord->cpIndex(reloTarget),
Expand Down
33 changes: 33 additions & 0 deletions runtime/compiler/compile/J9SymbolReferenceTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ J9::SymbolReferenceTable::SymbolReferenceTable(size_t sizeHint, TR::Compilation
_currentThreadDebugEventDataSymbol(0),
_currentThreadDebugEventDataSymbolRefs(c->trMemory()),
_constantPoolAddressSymbolRefs(c->trMemory()),
_defaultValueAddressSlotSymbolRefs(c->trMemory()),
_resolvedFieldShadows(
std::less<ResolvedFieldShadowKey>(),
getTypedAllocator<ResolvedFieldShadowsEntry>(c->allocator())),
Expand Down Expand Up @@ -929,6 +930,38 @@ J9::SymbolReferenceTable::findOrFabricateFlattenedArrayElementFieldShadowSymbol(
return symRef;
}

TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreateDefaultValueSymbolRef(void *defaultValueSlotAddress, int32_t cpIndex)
{
ListIterator<TR::SymbolReference> i(&_defaultValueAddressSlotSymbolRefs);
TR::SymbolReference *symRef;
for (symRef = i.getFirst(); symRef; symRef = i.getNext())
{
if (symRef->getSymbol()->getStaticSymbol()->getStaticAddress() == defaultValueSlotAddress)
{
return symRef;
}
}

TR::StaticSymbol *sym = TR::StaticSymbol::create(trHeapMemory(), TR::Address);

sym->setStaticAddress(defaultValueSlotAddress);

sym->setNotDataAddress();
sym->setStaticDefaultValueInstance();

symRef = new (trHeapMemory()) TR::SymbolReference(self(), sym);

symRef->setCPIndex(cpIndex);
symRef->setOwningMethodIndex(comp()->getMethodSymbol()->getResolvedMethodIndex());

// TODO: Is this required?
aliasBuilder.addressStaticSymRefs().set(symRef->getReferenceNumber());

_defaultValueAddressSlotSymbolRefs.add(symRef);
return symRef;
}

TR::Symbol *
J9::SymbolReferenceTable::createShadowSymbol(
TR::DataType type,
Expand Down
6 changes: 6 additions & 0 deletions runtime/compiler/compile/J9SymbolReferenceTable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,11 @@ class SymbolReferenceTable : public OMR::SymbolReferenceTableConnector
*/
TR::SymbolReference * findOrFabricateFlattenedArrayElementFieldShadowSymbol(TR_OpaqueClassBlock *arrayComponentClass, TR::DataType type, uint32_t fieldOffset, bool isPrivate, const char *fieldName, const char *fieldSignature);

/** \brief
* Returns a symbol reference for default value instance of value class.
*/
TR::SymbolReference * findOrCreateDefaultValueSymbolRef(void *defaultValueSlotAddress, int32_t cpIndex);

TR::SymbolReference * findOrCreateObjectNewInstanceImplSymbol(TR::ResolvedMethodSymbol * owningMethodSymbol);
TR::SymbolReference * findOrCreateDLTBlockSymbolRef();
TR::SymbolReference * findDLTBlockSymbolRef();
Expand Down Expand Up @@ -456,6 +461,7 @@ class SymbolReferenceTable : public OMR::SymbolReferenceTableConnector
TR::Symbol *_currentThreadDebugEventDataSymbol;
List<TR::SymbolReference> _currentThreadDebugEventDataSymbolRefs;
List<TR::SymbolReference> _constantPoolAddressSymbolRefs;
List<TR::SymbolReference> _defaultValueAddressSlotSymbolRefs;

private:

Expand Down
6 changes: 5 additions & 1 deletion runtime/compiler/il/J9SymbolReference.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2021 IBM Corp. and others
* Copyright (c) 2000, 2022 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -338,6 +338,10 @@ SymbolReference::getTypeSignature(int32_t & len, TR_AllocationKind allocKind, bo
len = 1;
return dataTypeToSig[_symbol->getDataType()];
}
if (_symbol->isStaticDefaultValueInstance())
{
return 0;
}

persistentClassInfo =
(comp->getPersistentInfo()->getPersistentCHTable() == NULL) ? NULL :
Expand Down
21 changes: 19 additions & 2 deletions runtime/compiler/ilgen/Walker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6649,18 +6649,35 @@ TR_J9ByteCodeIlGenerator::genAconst_init(TR_OpaqueClassBlock *valueTypeClass, in
traceMsg(comp(), "Handling aconst_init for valueClass %s\n", comp()->getDebug()->getName(valueClassSymRef));
}

loadSymbol(TR::loadaddr, valueClassSymRef);

TR::Node *newValueNode = NULL;
static const char *disableLoadStaticDefaultValueInstance = feGetEnv("TR_DisableLoadStaticDefaultValueInstance");

if (valueClassSymRef->isUnresolved())
{
// IL generation for aconst_init is currently only able to handle value type classes that have been resolved.
// If the class is still unresolved, abort the compilation and track the failure with a static debug counter.
abortForUnresolvedValueTypeOp("aconst_init", "class");
}
else if (!disableLoadStaticDefaultValueInstance &&
comp()->fej9()->isClassInitialized(valueTypeClass))
{
/*
* n4n treetop
* n3n aload 0x1d3298[#358 Static] [flags 0x307 0x40 ]
*/
j9object_t *defaultValueSlotAddress = TR::Compiler->cls.getDefaultValueSlotAddress(comp(), valueTypeClass);

newValueNode = TR::Node::createWithSymRef(TR::aload, 0, comp()->getSymRefTab()->findOrCreateDefaultValueSymbolRef((void *)defaultValueSlotAddress, cpIndex));

if (comp()->getOption(TR_TraceILGen))
{
traceMsg(comp(), "Handling aconst_init for valueClass %s: use pre-allocated defaultValue instance at %p\n", comp()->getDebug()->getName(valueClassSymRef), defaultValueSlotAddress);
}
}
else
{
loadSymbol(TR::loadaddr, valueClassSymRef);

const TR::TypeLayout *typeLayout = comp()->typeLayout(valueTypeClass);
size_t fieldCount = typeLayout->count();

Expand Down
50 changes: 50 additions & 0 deletions runtime/compiler/runtime/RelocationRecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,6 +851,9 @@ TR_RelocationRecord::create(TR_RelocationRecord *storage, TR_RelocationRuntime *
case TR_ValidateJ2IThunkFromMethod:
reloRecord = new (storage) TR_RelocationRecordValidateJ2IThunkFromMethod(reloRuntime, record);
break;
case TR_StaticDefaultValueInstance:
reloRecord = new (storage) TR_RelocationRecordStaticDefaultValueInstance(reloRuntime, record);
break;
default:
// TODO: error condition
printf("Unexpected relo record: %d\n", reloType);fflush(stdout);
Expand Down Expand Up @@ -6366,6 +6369,51 @@ TR_RelocationRecordValidateJ2IThunkFromMethod::methodID(TR_RelocationTarget *rel
return reloTarget->loadUnsigned16b((uint8_t *) &((TR_RelocationRecordValidateJ2IThunkFromMethodBinaryTemplate *)_record)->_methodID);
}


char *
TR_RelocationRecordStaticDefaultValueInstance::name()
{
return "TR_StaticDefaultValueInstance";
}

TR_RelocationErrorCode
TR_RelocationRecordStaticDefaultValueInstance::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation)
{
uintptr_t newConstantPool = computeNewConstantPool(reloRuntime, reloTarget, constantPool(reloTarget));
TR_OpaqueClassBlock *newClassAddress = computeNewClassAddress(reloRuntime, newConstantPool, inlinedSiteIndex(reloTarget), cpIndex(reloTarget));

if (!newClassAddress ||
!reloRuntime->comp()->fej9()->isClassInitialized(newClassAddress))
return TR_RelocationErrorCode::staticDefaultValueInstanceRelocationFailure;

j9object_t *newDefaultValueSlotAddress = TR::Compiler->cls.getDefaultValueSlotAddress(reloRuntime->comp(), newClassAddress);

reloTarget->storeAddressSequence((uint8_t *)newDefaultValueSlotAddress, reloLocation, reloFlags(reloTarget));

RELO_LOG(reloRuntime->reloLogger(), 6, "\tapplyRelocation: newDefaultValueSlotAddress %p\n", newDefaultValueSlotAddress);
return TR_RelocationErrorCode::relocationOK;
}

TR_RelocationErrorCode
TR_RelocationRecordStaticDefaultValueInstance::applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow)
{
uintptr_t newConstantPool = computeNewConstantPool(reloRuntime, reloTarget, constantPool(reloTarget));

TR_OpaqueClassBlock *newClassAddress = computeNewClassAddress(reloRuntime, newConstantPool, inlinedSiteIndex(reloTarget), cpIndex(reloTarget));

if (!newClassAddress ||
!reloRuntime->comp()->fej9()->isClassInitialized(newClassAddress))
return TR_RelocationErrorCode::staticDefaultValueInstanceRelocationFailure;

j9object_t *newDefaultValueSlotAddress = TR::Compiler->cls.getDefaultValueSlotAddress(reloRuntime->comp(), newClassAddress);

reloTarget->storeAddress((uint8_t *)newDefaultValueSlotAddress, reloLocationHigh, reloLocationLow, reloFlags(reloTarget));

RELO_LOG(reloRuntime->reloLogger(), 6, "\tapplyRelocation: newDefaultValueSlotAddress %p\n", newDefaultValueSlotAddress);
return TR_RelocationErrorCode::relocationOK;
}

// The _relocationRecordHeaderSizeTable table should be the last thing in this file
uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRelocationKinds] =
{
sizeof(TR_RelocationRecordConstantPoolBinaryTemplate), // TR_ConstantPool = 0
Expand Down Expand Up @@ -6479,4 +6527,6 @@ uint32_t TR_RelocationRecord::_relocationRecordHeaderSizeTable[TR_NumExternalRel
sizeof(TR_RelocationRecordWithInlinedSiteIndexBinaryTemplate), // TR_InlinedMethodPointer = 108
0, // TR_VMINLMethod = 109
sizeof(TR_RelocationRecordValidateJ2IThunkFromMethodBinaryTemplate), // TR_ValidateJ2IThunkFromMethod = 110
sizeof(TR_RelocationRecordConstantPoolWithIndexBinaryTemplate), // TR_StaticDefaultValueInstance = 111
};
// The _relocationRecordHeaderSizeTable table should be the last thing in this file
11 changes: 11 additions & 0 deletions runtime/compiler/runtime/RelocationRecord.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1918,5 +1918,16 @@ class TR_RelocationRecordValidateJ2IThunkFromMethod : public TR_RelocationRecord
uint16_t methodID(TR_RelocationTarget *reloTarget);
};

class TR_RelocationRecordStaticDefaultValueInstance : public TR_RelocationRecordClassAddress
{
public:
TR_RelocationRecordStaticDefaultValueInstance() {}
TR_RelocationRecordStaticDefaultValueInstance(TR_RelocationRuntime *reloRuntime, TR_RelocationRecordBinaryTemplate *record) : TR_RelocationRecordClassAddress(reloRuntime, record) {}

virtual char *name();
virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocation);
virtual TR_RelocationErrorCode applyRelocation(TR_RelocationRuntime *reloRuntime, TR_RelocationTarget *reloTarget, uint8_t *reloLocationHigh, uint8_t *reloLocationLow);
};

#endif // RELOCATION_RECORD_INCL

4 changes: 3 additions & 1 deletion runtime/compiler/runtime/RelocationRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,9 @@ struct TR_RelocationError
directJNICallRelocationFailure = (56 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION,
ramMethodConstRelocationFailure = (57 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION,

maxRelocationError = (58 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::NO_RELO_ERROR
staticDefaultValueInstanceRelocationFailure = (58 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::RELOCATION,

maxRelocationError = (59 << RELO_ERRORCODE_SHIFT) | TR_RelocationErrorCodeType::NO_RELO_ERROR
};

static uint32_t decode(TR_RelocationErrorCode errorCode) { return static_cast<uint32_t>(errorCode >> RELO_ERRORCODE_SHIFT); }
Expand Down
1 change: 1 addition & 0 deletions runtime/compiler/runtime/Runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2126,6 +2126,7 @@ bool isOrderedPair(U_8 recordType)
case TR_ClassAddress:
case TR_MethodObject:
//case TR_DataAddress:
case TR_StaticDefaultValueInstance:
#endif
#if defined(TR_HOST_32BIT) && defined(TR_HOST_POWER)
case TR_ArrayCopyHelper:
Expand Down