Skip to content

Commit e6840cd

Browse files
authored
Merge pull request #19108 from BradleyWood/storefieldv0.44
(0.44) JIT must narrow byte/short/char before storing
2 parents 990420b + 93c0ee9 commit e6840cd

File tree

4 files changed

+79
-4
lines changed

4 files changed

+79
-4
lines changed

runtime/compiler/compile/J9SymbolReferenceTable.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,6 +1838,11 @@ static bool isSignatureTypeBool(const char *fieldSignature, int32_t len)
18381838
return len == 1 && fieldSignature[0] == 'Z';
18391839
}
18401840

1841+
static bool isSignatureTypeChar(const char *fieldSignature, int32_t len)
1842+
{
1843+
return len == 1 && fieldSignature[0] == 'C';
1844+
}
1845+
18411846
static bool isSignatureReturnTypeBool(const char *methodSignature, int32_t len)
18421847
{
18431848
TR_ASSERT(len > 1, "Method signature is unexpectedly short %d", len);
@@ -1863,6 +1868,25 @@ J9::SymbolReferenceTable::isStaticTypeBool(TR::SymbolReference *symRef)
18631868
return isSignatureTypeBool(fieldSignature, len);
18641869
}
18651870

1871+
bool
1872+
J9::SymbolReferenceTable::isFieldTypeChar(TR::SymbolReference *symRef)
1873+
{
1874+
int32_t len;
1875+
const char *fieldSignature = symRef->getOwningMethod(comp())->fieldSignatureChars(symRef->getCPIndex(), len);
1876+
dumpOptDetails(comp(), "got field signature as %.*s\n", len, fieldSignature);
1877+
return isSignatureTypeChar(fieldSignature, len);
1878+
}
1879+
1880+
bool
1881+
J9::SymbolReferenceTable::isStaticTypeChar(TR::SymbolReference *symRef)
1882+
{
1883+
int32_t len;
1884+
const char *fieldSignature = symRef->getOwningMethod(comp())->staticSignatureChars(symRef->getCPIndex(), len);
1885+
dumpOptDetails(comp(), "got static signature as %.*s\n", len, fieldSignature);
1886+
return isSignatureTypeChar(fieldSignature, len);
1887+
}
1888+
1889+
18661890
bool
18671891
J9::SymbolReferenceTable::isReturnTypeBool(TR::SymbolReference *symRef)
18681892
{

runtime/compiler/compile/J9SymbolReferenceTable.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,9 @@ class SymbolReferenceTable : public OMR::SymbolReferenceTableConnector
443443
List<TR::SymbolReference> *dynamicMethodSymrefsByCallSiteIndex(int32_t index);
444444
bool isFieldClassObject(TR::SymbolReference *symRef);
445445
bool isFieldTypeBool(TR::SymbolReference *symRef);
446+
bool isFieldTypeChar(TR::SymbolReference *symRef);
446447
bool isStaticTypeBool(TR::SymbolReference *symRef);
448+
bool isStaticTypeChar(TR::SymbolReference *symRef);
447449
bool isReturnTypeBool(TR::SymbolReference *symRef);
448450

449451
/*

runtime/compiler/ilgen/J9ByteCodeIlGenerator.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@ class TR_J9ByteCodeIlGenerator : public TR_IlGenerator, public TR_J9ByteCodeIter
205205
void storeFlattenableInstance(int32_t);
206206
void storeFlattenableInstanceWithHelper(int32_t);
207207
void storeStatic(int32_t);
208+
TR::Node* narrowIntStoreIfRequired(TR::Node *value, TR::SymbolReference *symRef);
208209
void storeAuto(TR::DataType type, int32_t slot, bool isAdjunct = false);
209210
void storeArrayElement(TR::DataType dt){ storeArrayElement(dt, comp()->il.opCodeForIndirectArrayStore(dt)); }
210211
void storeArrayElement(TR::DataType dt, TR::ILOpCodes opCode, bool checks = true);

runtime/compiler/ilgen/Walker.cpp

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6232,6 +6232,11 @@ TR_J9ByteCodeIlGenerator::genWithField(TR::SymbolReference * symRef, TR_OpaqueCl
62326232
TR::Node *newFieldValue = pop();
62336233
TR::Node *originalObject = pop();
62346234

6235+
if (symRef->getSymbol()->getType().isIntegral())
6236+
{
6237+
newFieldValue = narrowIntStoreIfRequired(newFieldValue, symRef);
6238+
}
6239+
62356240
/*
62366241
* Insert nullchk for the original object as requested by the JVM spec.
62376242
* Especially in case of value type class with a single field, the nullchk is still
@@ -6998,6 +7003,48 @@ TR_J9ByteCodeIlGenerator::storeInstance(int32_t cpIndex)
69987003
storeInstance(symRef);
69997004
}
70007005

7006+
TR::Node*
7007+
TR_J9ByteCodeIlGenerator::narrowIntStoreIfRequired(TR::Node *value, TR::SymbolReference *symRef)
7008+
{
7009+
TR::DataType type = symRef->getSymbol()->getDataType();
7010+
7011+
// Per the JVM spec, putstatic/putfield/withfield opcodes must adhere to field type compatibility.
7012+
// Integer values on the stack must be narrowed when stored into smaller types like bool, byte,
7013+
// char, and short fields. For byte and short fields, narrowing involves conversion from integer
7014+
// to byte/short, then back to integer. For bool and char types, which are unsigned, narrowing
7015+
// entails ANDing the value with a mask matching the type width.
7016+
7017+
switch (type)
7018+
{
7019+
case TR::Int8:
7020+
if (symRefTab()->isStaticTypeBool(symRef))
7021+
{
7022+
value = TR::Node::create(TR::iand, 2, value, TR::Node::create(TR::iconst, 0, 1));
7023+
}
7024+
else
7025+
{
7026+
value = TR::Node::create(TR::i2b, 1, value);
7027+
value = TR::Node::create(TR::b2i, 1, value);
7028+
}
7029+
break;
7030+
case TR::Int16:
7031+
if (symRefTab()->isStaticTypeChar(symRef))
7032+
{
7033+
value = TR::Node::create(TR::iand, 2, value, TR::Node::create(TR::iconst, 0, 0xffff));
7034+
}
7035+
else
7036+
{
7037+
value = TR::Node::create(TR::i2s, 1, value);
7038+
value = TR::Node::create(TR::s2i, 1, value);
7039+
}
7040+
break;
7041+
default:
7042+
break;
7043+
}
7044+
7045+
return value;
7046+
}
7047+
70017048
void
70027049
TR_J9ByteCodeIlGenerator::storeInstance(TR::SymbolReference * symRef)
70037050
{
@@ -7019,8 +7066,8 @@ TR_J9ByteCodeIlGenerator::storeInstance(TR::SymbolReference * symRef)
70197066
}
70207067
else
70217068
{
7022-
if (type == TR::Int8 && symRefTab()->isFieldTypeBool(symRef))
7023-
value = TR::Node::create(TR::iand, 2, value, TR::Node::create(TR::iconst, 0, 1));
7069+
if (type.isIntegral())
7070+
value = narrowIntStoreIfRequired(value, symRef);
70247071
node = TR::Node::createWithSymRef(comp()->il.opCodeForIndirectStore(type), 2, 2, addressNode, value, symRef);
70257072
}
70267073

@@ -7303,8 +7350,9 @@ TR_J9ByteCodeIlGenerator::storeStatic(int32_t cpIndex)
73037350
TR::Node * node;
73047351

73057352
TR_J9VMBase *fej9 = (TR_J9VMBase *)fe();
7306-
if (type == TR::Int8 && symRefTab()->isStaticTypeBool(symRef))
7307-
value = TR::Node::create(TR::iand, 2, value, TR::Node::create(TR::iconst, 0, 1));
7353+
7354+
if (type.isIntegral())
7355+
value = narrowIntStoreIfRequired(value, symRef);
73087356

73097357
if ((type == TR::Address && _generateWriteBarriersForGC) || _generateWriteBarriersForFieldWatch)
73107358
{

0 commit comments

Comments
 (0)