| Summary: | [otdre] implement base-super calls | ||
|---|---|---|---|
| Product: | [Tools] Objectteams | Reporter: | Stephan Herrmann <stephan.herrmann> |
| Component: | OTJ | Assignee: | Stephan Herrmann <stephan.herrmann> |
| Status: | RESOLVED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | stephan.herrmann |
| Version: | 2.4 | ||
| Target Milestone: | 2.5 M6 | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | |||
| Bug Depends on: | |||
| Bug Blocks: | 484164, 490231 | ||
|
Description
Stephan Herrmann
Brainstorming a solution:
We need to distinguish between
(1) super-base method is unbound: it can be directly called using invokespecial
(2) super-base method is bound: it's code will have been moved to _OT$callOrig
For (1) we can devise a strategy using special method ids:
- construct a special boundMethodId for the super-called base method,
e.g. build boundMethodId so that normal Ids are even numbers and Ids
for super access are Id+1.
- let the base-super call add 1 to the boundMethodId
- inside _OT$callOrig dispatch to the super method using invokespecial
- when filling _OT$callOrig we check if a base-super call affects a given
base method
- if so, add a case with Id+1, instead of inlined code this issues an
invokespecial to the super classes "real" base method/
- ensure that this Id+1 is not used in sub base classes
(need another tweak to handle multiple super-base calls at different
levels of the same base method hierarchy).
For (2) we should be fine by generating an invokespecial when the team calls _OT$callOrig. Unfortunately, this invocation is in the static Team._OT$terminalCallNext() (why is it static? can't we override that if needed?)
Or, if using the same modified boundMethodId, inside _OT$callOrig() an odd id directly leads to invoking super._OT$callOrig(..id-1..), but only do this in the class that actually handles id. Hm, still not enough to cope with all forms of dynamic binding for _OT$callOrig and overriding base methods.
Realistically speaking, (2) should be uncommon. So I will probably start by working on (1) and raise exceptions if any of it's assumptions is violated.
Documenting the implementation strategy: Updated the OTDynCallinBindings attribute to support passing more information from compiler to OTDRE: Add a new flag to the "flags" field, BASE_SUPER_CALL, value is 16. This flag is set whenever a bound role method contains at least one base-super call. Modified signatures of o.o.Team#_OT$callNext() and _OT$terminalCallNext(): In both methods pass 3-valued baseCallFlags: - 0 = not a base call - 1 = regular base call - 2 = base-super call If 2, increment the boundMethodId for the call to MyBase._OT$callOrig(..). (I left the previous variant of _OT$callNext() for now to ease migration of my development environment). Compiler changes to support the above: Move argument packing for base calls into BaseCallMessageSend.prepareSuperAccess() where we have the information #isSuperAccess. From this flag create an intLiteral of value 1 or 2 for the call to _OT$callNext(). To compensate for this move, a few methods needed adjustment to understand the different structure of the base call's arguments (TransformStatementsVisitor#isRecursiveCall(), also reporting baseCallDoesntMatchRoleMethodSignature() has been moved right into prepareSuperAccess() (easiest to detect here)). Create the OTSpecialAccessAttribute for base-super only targeting OTRE weaving. Old flag DYN_SUPER_METHOD_ACCESS is now obsolete and has been removed. Setting the new flag BASE_SUPER_CALL had to be delayed, when creating the attribute we don't yet have that information, it is computed only during BCMS.analyseCode(). Changes in OTDRE: Transport the new flag BASE_SUPER_CALL via this (lengthy) chain: - CallinBindingsAttribute extracts BASE_SUPER_CALL from #flags - store in CallinBindingsAttribute.MultiBinding#requireBaseSuperCall - AsmClassVisitor to transfer it from MultiBinding to Binding - store in Binding#requireBaseSuperCall - store in WeavingTask#requireBaseSuperCall - pass it down into ABC#moveCodeToCallOrig() & MoveCodeToCallOrigAdapter() Set IDs issued by Member#getKey() by increments of 2 to create space for intermediate IDs for base-super calls. Create new switch label for boundMethodId+1 only when baseSuperRequired is set in the MoveCodeToCallOrigAdapter: - unpack & load arguments - invokespecial - (box and) return the result With these changes the following tests now pass: - test4513_basecallSuperAccess1 - test4513_basecallSuperAccess2 OTOH, these still fail, witnessing the lack of support for (2) in comment 1: - test4513_basecallSuperAccess4 - test4513_basecallSuperAccess5 (In reply to Stephan Herrmann from comment #2) > OTOH, these still fail, witnessing the lack of support for (2) in comment 1: > - test4513_basecallSuperAccess4 > - test4513_basecallSuperAccess5 I created bug 490231 for those. Marking as fixed (wrt the main part) for 2.5 M6. commit 6b9a43a2b7349cb02a2fed73b3e12ff3351cf5b3 follow-ups (migrate to new signature of Team._OT$callNext()): commit 8eb5372be26833c2f7019b394df1a35a0637c269 commit bf340a97572f633220fa274d8fe48c17bb86d653 commit 7651846f879214113abe3a571fcb0bca30383aea |