Skip to content

Commit

Permalink
Merge pull request #10462 from Leonardo2718/valhalla-flattening
Browse files Browse the repository at this point in the history
Implement initial JIT support for Valhalla flattened value type fields
  • Loading branch information
andrewcraik committed Sep 16, 2020
2 parents 1df35ac + f4f609f commit dd8db7c
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 164 deletions.
49 changes: 49 additions & 0 deletions runtime/compiler/compile/J9SymbolReferenceTable.cpp
Expand Up @@ -250,6 +250,55 @@ J9::SymbolReferenceTable::findOrCreateAcmpHelperSymbolRef(TR::ResolvedMethodSymb
}


TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreateGetFlattenableFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol)
{
return findOrCreateRuntimeHelper(TR_getFlattenableField, true, true, true);
}


TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreateWithFlattenableFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol)
{
return findOrCreateRuntimeHelper(TR_withFlattenableField, true, true, true);
}


TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreatePutFlattenableFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol)
{
return findOrCreateRuntimeHelper(TR_putFlattenableField, true, true, true);
}


TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreateGetFlattenableStaticFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol)
{
return findOrCreateRuntimeHelper(TR_getFlattenableStaticField, true, true, true);
}


TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreatePutFlattenableStaticFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol)
{
return findOrCreateRuntimeHelper(TR_putFlattenableStaticField, true, true, true);
}


TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreateLoadFlattenableArrayElementSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol)
{
return findOrCreateRuntimeHelper(TR_ldFlattenableArrayElement, true, false, true);
}


TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreateStoreFlattenableArrayElementSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol)
{
return findOrCreateRuntimeHelper(TR_strFlattenableArrayElement, true, false, true);
}


TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreateFloatSymbol(TR::ResolvedMethodSymbol * owningMethodSymbol, int32_t cpIndex)
{
Expand Down
12 changes: 11 additions & 1 deletion runtime/compiler/compile/J9SymbolReferenceTable.hpp
Expand Up @@ -110,7 +110,17 @@ class SymbolReferenceTable : public OMR::SymbolReferenceTableConnector
TR::SymbolReference * findOrCreateWriteBarrierClassStoreRealTimeGCSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = 0);
TR::SymbolReference * findOrCreateWriteBarrierBatchStoreSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = 0);

TR::SymbolReference * findOrCreateAcmpHelperSymbolRef(TR::ResolvedMethodSymbol * owningMEthodSymbol = NULL);
TR::SymbolReference * findOrCreateAcmpHelperSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = NULL);

// these helpers are guarenteed to never throw if the receiving object is not null,
// so we explicit generate NULLCHKs and assume the helpers will never throw
TR::SymbolReference * findOrCreateGetFlattenableFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = NULL);
TR::SymbolReference * findOrCreateWithFlattenableFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = NULL);
TR::SymbolReference * findOrCreatePutFlattenableFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = NULL);
TR::SymbolReference * findOrCreateGetFlattenableStaticFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = NULL);
TR::SymbolReference * findOrCreatePutFlattenableStaticFieldSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = NULL);
TR::SymbolReference * findOrCreateLoadFlattenableArrayElementSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = NULL);
TR::SymbolReference * findOrCreateStoreFlattenableArrayElementSymbolRef(TR::ResolvedMethodSymbol * owningMethodSymbol = NULL);

TR::SymbolReference * findOrCreateShadowSymbol(TR::ResolvedMethodSymbol * owningMethodSymbol, int32_t cpIndex, bool isStore);
TR::SymbolReference * findOrFabricateShadowSymbol(TR::ResolvedMethodSymbol * owningMethodSymbol, TR::Symbol::RecognizedField recognizedField, TR::DataType type, uint32_t offset, bool isVolatile, bool isPrivate, bool isFinal, char* name = NULL);
Expand Down
218 changes: 67 additions & 151 deletions runtime/compiler/env/j9fieldsInfo.cpp
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2019 IBM Corp. and others
* Copyright (c) 2000, 2020 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 @@ -72,10 +72,6 @@ TR_VMField::TR_VMField(TR::Compilation * comp, J9Class *aClazz, J9ROMFieldShape
offset = 0;
else
offset = comp->fej9()->getInstanceFieldOffset((TR_OpaqueClassBlock *)aClazz, name, (uint32_t)(nameLength-1), signature, (uint32_t)(sigLength-1));

#ifdef DEBUG
/////print(stderr);
#endif
}


Expand All @@ -86,27 +82,13 @@ void TR_VMField::print(TR_FrontEnd *fe, TR::FILE *outFile)


TR_VMFieldsInfo::TR_VMFieldsInfo(TR::Compilation * comp, J9Class *aClazz, int buildFields, TR_AllocationKind allocKind)
: _fe(comp->fej9()),
_comp(comp),
_gcDescriptor(allocKind == stackAlloc ? comp->trMemory()->currentStackRegion() : comp->trMemory()->heapMemoryRegion()),
_fields(NULL),
_statics(NULL),
_allocKind(allocKind)
{
_fe = comp->fej9();
_comp = comp;
_allocKind = allocKind;
J9ROMClass *romCl=NULL;
//TR_VMField *field=NULL;
int i=0;
int totalNumFields = 0;
int numBytesInSlot = TR::Compiler->om.sizeofReferenceField();
int numBitsInWord = 8*sizeof(UDATA); // instanceDescription is always a UDATA so number of bits should reflect that

int numSlotsInObject=0;
int countSlots=0;
int bitIndex =0;
UDATA *descriptorPtr = NULL;
UDATA descriptorWord=0;
IDATA numRefs = 0;
IDATA slotsInHeader = 0;
J9ROMFieldWalkState state;
J9ROMFieldShape * currentField;

if (buildFields)
{
// Weird: We can't seem to just use List with stackAlloc? I need to use a subclass??
Expand All @@ -121,38 +103,18 @@ TR_VMFieldsInfo::TR_VMFieldsInfo(TR::Compilation * comp, J9Class *aClazz, int bu
_statics = new (_comp->trMemory(), allocKind) TR_ScratchList<TR_VMField> (_comp->trMemory());
break;
default:
break;
TR_ASSERT_FATAL(false, "Unknown allocation kind %d", allocKind);
}
}
else
{
_fields = NULL;
_statics = NULL;
}
_numRefSlotsInObject = 0;
}

// self
romCl = aClazz->romClass;
TR_ASSERT(!(romCl->modifiers & J9AccClassArray), "Cannot construct TR_VMFieldsInfo for array class %p", aClazz);
currentField = romFieldsStartDo(romCl, &state);
while (currentField)
{
if ((currentField->modifiers & J9AccStatic) == 0)
{
totalNumFields++;
_numRefSlotsInObject += buildField(aClazz, currentField);
}
else
{
buildField(aClazz, currentField);
}
currentField = romFieldsNextDo(&state);
}
TR_ASSERT(!(aClazz->romClass->modifiers & J9AccClassArray), "Cannot construct TR_VMFieldsInfo for array class %p", aClazz);
collectFieldInfo(aClazz);

//supers
int numSupClasses = J9CLASS_DEPTH(aClazz);
const int32_t numSupClasses = J9CLASS_DEPTH(aClazz);
J9Class *supClass = aClazz;
for (i=numSupClasses-1; i>=0; i--)
for (int32_t i = 0; i < numSupClasses-1; i++)
{
supClass = (J9Class*)comp->fej9()->getSuperClass((TR_OpaqueClassBlock*)supClass);

Expand All @@ -166,127 +128,81 @@ TR_VMFieldsInfo::TR_VMFieldsInfo(TR::Compilation * comp, J9Class *aClazz, int bu
TR_ASSERT_FATAL(supClass, "Found NULL supClass in inheritance chain");
}

romCl = supClass->romClass;

// iterate through the fields creating TR_VMField and inserting them into a List

currentField = romFieldsStartDo(romCl, &state);
while (currentField)
{
if ((currentField->modifiers & J9AccStatic) == 0)
{
totalNumFields++;
_numRefSlotsInObject += buildField(supClass, currentField);
}
else
{
buildField(supClass, currentField);
}
currentField = romFieldsNextDo(&state);
}
collectFieldInfo(supClass);
}

// copy the GCData
numSlotsInObject = (aClazz->totalInstanceSize + numBytesInSlot - 1)/numBytesInSlot;
numRefs = 0;
descriptorPtr = aClazz->instanceDescription;

// null terminated
_gcDescriptor = (int32_t *) _comp->trMemory()->allocateMemory((_numRefSlotsInObject+1)*sizeof(int32_t), allocKind);
_gcDescriptor[_numRefSlotsInObject] = 0;
UDATA *descriptorPtr = aClazz->instanceDescription;
UDATA descriptorWord=0;

slotsInHeader = (TR::Compiler->om.objectHeaderSizeInBytes()/numBytesInSlot);
countSlots = slotsInHeader;
bitIndex = 0;
int32_t bitIndex = 0;
if ( ((UDATA) descriptorPtr) & BCT_J9DescriptionImmediate )
{
bitIndex++;
descriptorWord = ((UDATA) descriptorPtr) >> 1;
}
else
{
descriptorWord = descriptorPtr[0];
}
{
descriptorWord = descriptorPtr[0];
}

const int32_t numBytesInSlot = TR::Compiler->om.sizeofReferenceField();
const int32_t numBitsInWord = 8*sizeof(decltype(*(aClazz->instanceDescription)));
const int32_t numSlotsInObject = (aClazz->totalInstanceSize + numBytesInSlot - 1)/numBytesInSlot;
const uintptr_t slotsInHeader = (TR::Compiler->om.objectHeaderSizeInBytes()/numBytesInSlot);
uintptr_t countSlots = slotsInHeader;
while (1)
{
if ( descriptorWord & 0x1 )
{
_gcDescriptor[numRefs++] = countSlots;
}
countSlots++;
if (countSlots >= (slotsInHeader + numSlotsInObject))
{
break;
}
if (bitIndex == (numBitsInWord - 1))
{
descriptorPtr++;
bitIndex = 0;
descriptorWord = *descriptorPtr;
}
else
{
descriptorWord = descriptorWord >> 1;
bitIndex++;
}
if ( descriptorWord & 0x1 )
{
_gcDescriptor.push_back(countSlots);
}
countSlots++;
if (countSlots >= (slotsInHeader + numSlotsInObject))
{
break;
}
if (bitIndex == (numBitsInWord - 1))
{
descriptorPtr++;
bitIndex = 0;
descriptorWord = *descriptorPtr;
}
else
{
descriptorWord = descriptorWord >> 1;
bitIndex++;
}
}
#ifdef DEBUG
/////print(stderr);
#endif
// null terminated
_gcDescriptor.push_back(0);
}

int TR_VMFieldsInfo::buildField(J9Class *aClazz, J9ROMFieldShape *fieldShape)
void
TR_VMFieldsInfo::collectFieldInfo(J9Class *aClazz)
{
TR_VMField *field=NULL;
int numBytesInSlot = TR::Compiler->om.sizeofReferenceField();
if (fieldShape->modifiers & J9AccStatic)
{
if (_statics)
{
field = new (_comp->trMemory(), _allocKind) TR_VMField(_comp, aClazz, fieldShape, _allocKind);
_statics->add(field);
}
return 0;
}
if (_fields)
J9ROMClass *romCl = aClazz->romClass;
J9ROMFieldWalkState state;
J9ROMFieldShape * currentField = romFieldsStartDo(romCl, &state);
while (currentField)
{
field = new (_comp->trMemory(), _allocKind) TR_VMField(_comp, aClazz, fieldShape, _allocKind);
_fields->add(field);
buildField(aClazz, currentField);
currentField = romFieldsNextDo(&state);
}

J9UTF8 *sigUtf8 = J9ROMFIELDSHAPE_SIGNATURE(fieldShape);
return isReferenceSignature((char *)J9UTF8_DATA(sigUtf8));
}

void TR_VMFieldsInfo::print(TR::FILE *outFile)
{
int i=0;

// iterate through the list invoking print on each element
if ( _fields != NULL )
{
ListIterator <TR_VMField> iter(_fields);
for (TR_VMField * field = iter.getFirst(); field != NULL; field = iter.getNext())
{
field->print(_comp->fej9(), outFile);
}
}
// print the gcDescriptor
trfprintf(outFile, "Ptrs at Slots \n");
for (i=0; i<_numRefSlotsInObject; i++)
void
TR_VMFieldsInfo::buildField(J9Class *aClazz, J9ROMFieldShape *fieldShape)
{
TR_VMField *field=NULL;
if ((fieldShape->modifiers & J9AccStatic) && _statics)
{
trfprintf(outFile, "0x%p \n", _gcDescriptor[i]);
}

if ( _statics != NULL )
field = new (_comp->trMemory(), _allocKind) TR_VMField(_comp, aClazz, fieldShape, _allocKind);
_statics->add(field);
}
else if (_fields)
{
ListIterator <TR_VMField> iter(_statics);
for (TR_VMField * field = iter.getFirst(); field != NULL; field = iter.getNext())
{
field->print(_comp->fej9(), outFile);
}
field = new (_comp->trMemory(), _allocKind) TR_VMField(_comp, aClazz, fieldShape, _allocKind);
_fields->add(field);
}
}


}
18 changes: 8 additions & 10 deletions runtime/compiler/env/j9fieldsInfo.h
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2000, 2016 IBM Corp. and others
* Copyright (c) 2000, 2020 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 All @@ -25,6 +25,7 @@

#include "j9field.h"
#include "infra/List.hpp"
#include "infra/vector.hpp"
#include "env/IO.hpp"
#include "env/VMJ9.h"

Expand All @@ -37,19 +38,16 @@ class TR_VMFieldsInfo

List<TR_VMField>* getFields() { return _fields; }
List<TR_VMField>* getStatics() { return _statics; }
UDATA getNumRefSlotsInObject() { return _numRefSlotsInObject; }
int32_t * getGCDescriptor() { return _gcDescriptor; }
void print(TR::FILE *outFile);
int32_t * getGCDescriptor() { return &_gcDescriptor[0]; }

private:
int buildField(J9Class *aClazz, J9ROMFieldShape *fieldShape);
void collectFieldInfo(J9Class *aClazz);
void buildField(J9Class *aClazz, J9ROMFieldShape *fieldShape);
TR_J9VMBase * _fe;
TR::Compilation * _comp;
J9Class * _ramClass;
int32_t * _gcDescriptor;
UDATA _numRefSlotsInObject;
List <TR_VMField>* _fields;
List <TR_VMField>* _statics;
TR::vector<int32_t, TR::Region&> _gcDescriptor;
List<TR_VMField>* _fields;
List<TR_VMField>* _statics;
TR_AllocationKind _allocKind;
};
#endif
Expand Down

0 comments on commit dd8db7c

Please sign in to comment.