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

Fix Adjust APIs #3753

Merged
merged 1 commit into from
Jun 3, 2019
Merged

Fix Adjust APIs #3753

merged 1 commit into from
Jun 3, 2019

Conversation

charliegracie
Copy link
Contributor

JitBuilder math APIs like Add, Mul, etc. require that the left and
right operands have the same type or if the left is a pointer that
the right is an Int32 or Int64. Currently a VMRegister wrapping a
int8_t * will fail when Adjust is called since
_integerTypeForAdjustment will be Int8. It is incorrect to limit
the adjustBy amount to the primite type of the pointer since a user
may want to adjust the value by a large value. The solution is to
adjust by an Int64 not matter what the primitive register type is.

This PR includes a new test called vmregister which verifies that
VMRegisters wrapping a pInt8 work. This test failed before this
PR. The Operand[Array,Stack]Tests verify that the code continues
to work for larger types.

Signed-off-by: Charlie Gracie charlie.gracie@gmail.com

@charliegracie
Copy link
Contributor Author

@genie-omr build all

@charliegracie
Copy link
Contributor Author

FYI @Leonardo2718 and @mstoodle

@charliegracie
Copy link
Contributor Author

@Leonardo2718 any thoughts?

@mstoodle
Copy link
Contributor

Shouldn't the right thing to be adjust by a Word sized integer? Int64 would only be the right choice on 64-bit platforms...

@charliegracie
Copy link
Contributor Author

@mstoodle the virtual void Adjust(TR::IlBuilder *b, int64_t amount) has an int64_t parameter. To match the API signature and make sure that values are not truncated I believe the code needs to use ConstInt64.

@mstoodle
Copy link
Contributor

We could change that to a size_t or assert if a value that can't be represented in 32-bits it provided on a 32-bit platform.

The resulting IL will be ill-formed if you add a 64-bit value to a 32-bit address.

@Leonardo2718
Copy link
Contributor

The resulting IL will be ill-formed if you add a 64-bit value to a 32-bit address.

True.

@charliegracie
Copy link
Contributor Author

@genie-omr build all

@charliegracie
Copy link
Contributor Author

@genie-omr build all

@charliegracie
Copy link
Contributor Author

@genie-omr build xlinux

@charliegracie
Copy link
Contributor Author

@mstoodle I updated the code. Can you take another look?

@charliegracie
Copy link
Contributor Author

ping?

@charliegracie
Copy link
Contributor Author

ping @mstoodle

@mstoodle
Copy link
Contributor

mstoodle commented May 14, 2019

Sorry for the delay here, @charliegracie . Every time I start reviewing the changes in OMRVirtualMachineRegister I get stuck wondering about the real point of this code. The cascade of if statements looking progressively "deeper" into pointer types strike me as over complicated for what VirtualMachineRegister is supposed to be. Then I inevitably get distracted without circling back to a conclusion. Not fair to you; sorry!

At its core level, a VirtualMachineRegister was supposed to represent some kind of "state" variable stored at some address. The "at some address" part is where the "double" PointerTo() expectation comes from in the common case of a state register that points somewhere (like a PC or an SP): OMRVirtualMachineRegister needs to store the address of the actual state variable so that it can store to that address indirectly when Commit() is called.

In our private exchange, you pointed out that it's through OMRVirtualMachineRegisterInStruct that the problem actually appears, and I think that's what is causing the root problem here: in the constructor for OMRVirtualMachineRegisterInStruct, it uses the same "double pointer type" decoding logic as in OMRVMReg and I think that's wrong. For OMRVirtualMachineRegisterInStruct, I think it should be setting _integerTypeForAdjustments Word for any field that is a pointer, and to the field type for anything else. I believe that should resolve your core problem and is the most correct fix.

Sorry again for the delay to fully wrap my brain around the issue and the back-and-forth on the proper solution!

@mstoodle mstoodle self-assigned this May 15, 2019
Copy link
Contributor

@mstoodle mstoodle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hopefully straight-forward changes....Thanks @charliegracie!

_integerTypeForAdjustments = pointerToRegisterType->baseType();
if (_integerTypeForAdjustments->isPointer())
TR::IlType *registerBaseType = pointerToRegisterType->baseType();
if (registerBaseType->isPointer())
Copy link
Contributor

@mstoodle mstoodle May 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these conditionals can stay the way they are (keeping _integerTypeForAdjustments). I prefer the register know what type to use based on the type of the register rather than relying on the datatype of the adjustment value passed in.

@@ -161,7 +161,8 @@ class VirtualMachineRegister : public TR::VirtualMachineState
virtual void Adjust(TR::IlBuilder *b, TR::IlValue *amount)
{
TR::IlValue *off=b->Mul(amount,
b-> ConstInteger(_integerTypeForAdjustments, _adjustByStep));
b-> ConstInteger(b->typeDictionary()->PrimitiveType(amount->getDataType()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is more dangerous, I think, because it requires the client to set up the type properly for every call to this Adjust service.

Copy link
Contributor

@mstoodle mstoodle May 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably best to add a b->ConvertTo(_integerTypeForAdjustments, amount) here too rather than just using amount directly.

_integerTypeForAdjustments = _integerTypeForAdjustments->baseType();
if (_integerTypeForAdjustments->isPointer())
registerBaseType = registerBaseType->baseType();
if (registerBaseType->isPointer())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should dig into two levels of pointer here: it starts from the field type, which should only require one level of pointer to primitive type to do the right thing (i.e. if it's a pointer type use Word otherwise use the field's primitive type).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible this change may induce some required changes in our samples, but I would hope not.

@charliegracie charliegracie force-pushed the vmregister branch 2 times, most recently from 946ee39 to 9ab435e Compare May 22, 2019 01:24
@charliegracie
Copy link
Contributor Author

@mstoodle I made most of the changes you suggested but now my test is failing. I have purposely left out the ConvertTo call you suggested as it would not help for the failure I am seeing. When I run the new vmregister test (which does not use VirtualMachineRegisterInStruct) I get the following assertion which is being generated because of the Adjust call:

Step 1: initialize JIT
Step 2: define type dictionary
Step 3: compile method builder
Assertion failed at /Users/charliegracie/vs_workspaces/omr/compiler/ilgen/OMRIlBuilder.cpp:1116: leftType == rightType || isAddressBump || isRevAddressBump
	binaryOp requires both left and right operands to have same type or one is address and other is Int32/64
compiling /Users/charliegracie/vs_workspaces/omr/jitbuilder/release/cpp/samples/VMRegister.cpp:81:test at level: warm

.......
frame #7: 0x0000000000148e94 vmregister`OMR::IlBuilder::binaryOpNodeFromNodes(TR::ILOpCodes, TR::Node*, TR::Node*) + 340
    frame #8: 0x0000000000148f1d vmregister`OMR::IlBuilder::binaryOpFromNodes(TR::ILOpCodes, TR::Node*, TR::Node*) + 61
    frame #9: 0x00000000001472ca vmregister`OMR::IlBuilder::Add(TR::IlValue*, TR::IlValue*) + 378
    frame #10: 0x0000000000174791 vmregister`OMR::VirtualMachineRegister::adjust(TR::IlBuilder*, TR::IlValue*) + 145
    frame #11: 0x000000000001a166 vmregister`OMR::VirtualMachineRegister::Adjust(TR::IlBuilder*, long long) + 86
    frame #12: 0x0000000000019bff vmregister`OMR::JitBuilder::VirtualMachineRegister::Adjust(OMR::JitBuilder::IlBuilder*, unsigned long) + 111
    frame #13: 0x00000000000033fc vmregister`VMRegisterMethod::buildIL() + 684
.....

@mstoodle
Copy link
Contributor

I think OMRVirtualMachineRegister is digging too deeply into its pointerToRegister type too :( .

To have adjust() work with the Word type, right now you have to provide a triple pointer, which doesn't make sense to me: you're adjusting the value that's one level of indirection away (i.e. you provided the address of the register you're modelling and I don't think you should be touching any values pointed at by the register). I am not enough of a git wizard to track back why that change was introduced, but the code right now does not make sense to me.

These VirtualMachineRegister classes should be looking at as many as 2 levels of indirection (pointer types). If the provided type is pointer to pointer to any type, then the adjustment type should be Word because when you adjust the register value you're adjusting a pointer. If the type is pointer to non-pointer integer type, then similarly the adjustment type should be the non-pointer integer type. For any type that doesn't fit those two patterns, one probably shouldn't be using adjust but rather rolling your own because I'm not sure we could predict what is for certain the "right" thing to do. Well, I suppose we could add float/double variants of adjust but not sure they would be used much.

I am, however, fairly certain something will break if we change the _integerTypeForAdjustments logic in OMR::VirtualMachineRegister's constructor (maybe in T4: @jduimovich or Lua: @Leonardo2718 ... Any of this ring bells for you guys? )

@charliegracie
Copy link
Contributor Author

@genie-omr build all

@charliegracie
Copy link
Contributor Author

@mstoodle I think I got it :) If all of the tests pass I think I wrapped my head around everything and have the correct changes now

TR::IlValue *Const(int32_t value) { return ConstInt32(value); }
TR::IlValue *Const(int64_t value) { return ConstInt64(value); }

template <typename T>
Copy link
Contributor

@mstoodle mstoodle May 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you consider moving this change into a separate commit, since it doesn't contribute to the main change you're making at this point?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A separate commit in this PR or a new PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mstoodle I will just pull it out of this PR completely

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, missed the question....either would have been fine, but since it's not related to the PR, feels like a separate PR is most appropriate.

@mstoodle
Copy link
Contributor

Basically looks good to me at this point. @Leonardo2718 do you want to do a once over to see if anything still stands out to you?

Copy link
Contributor

@Leonardo2718 Leonardo2718 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

JitBuilder math APIs like Add, Mul, etc. require that the left and
right operands have the same type or if the left is a pointer that
the right is an Int32 or Int64. Currently a VMRegister wrapping a
int8_t * will fail when Adjust is called since _integerTypeForAdjustment
will be Int8. It is incorrect to limit the adjustBy amount to the
primitive type of the pointer since a user may want to adjust the
value by a large value. The Adjust API now takes a `size_t` amount
parameter and creates the correct constant for adjustment. This PR
includes a new test called vmregister which verifies that VMRegisters
wrapping a pInt8 work. This test failed before this PR. The
Operand[Array,Stack]Tests verify that the code continues to work
for larger types.

Signed-off-by: Charlie Gracie <charlie.gracie@gmail.com>
@charliegracie
Copy link
Contributor Author

@genie-omr build all

@charliegracie
Copy link
Contributor Author

@mstoodle and @Leonardo2718 I have removed the new APIs that were no longer used.

@mstoodle
Copy link
Contributor

mstoodle commented Jun 3, 2019

LGTM , merging. Thanks @charliegracie !!

@mstoodle mstoodle merged commit f1a0533 into eclipse-omr:master Jun 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants