• Home
    • View
    • Login
    This page
    • Normal
    • Export PDF
    • Page Information

    Loading...
  1. Dashboard
  2. Undefined Space
  3. Multi-Language VM
  4. InterfaceInjection

Page History

Versions Compared

Old Version 3

changes.mady.by.user John Rose

Saved on Jan 24, 2009

compared with

New Version 4

changes.mady.by.user John Rose

Saved on Jan 24, 2009

  • Previous Change: Difference between versions 2 and 3
  • Next Change: Difference between versions 4 and 5
  • View Page History

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

See InterfaceCalls for a discussion of how interface call sites work.

Each klass structure already includes (allocated inline) a 2-dimensional ragged table of its statically defined interfaces. The spine of the table has pairs, <oop iklass, offset_t itable>. The spine is terminated by a tuple <NULL, 0>.. The itable offsets are relative to the enclosing klass (the receiver type).

Each itable is an array of the form methodOop targetN, where N is the number of methods in the interface.

...

There is one extension record for one interface injection event. They are linked through "next" fields (in an arbitrary order), and the incoming interface klass is matched against their "key" fields. A matching extension record has N additional words, all methodOops; those N words are exactly like a statically defined embedded itable. The extension records are actually just system arrays (type Object[]) whose lengths are 2+N, with key at element 0, "next" link at element 1, and the first and last implementation methods (if any) at elements 2 and through 2+N-1.

In order to pack these dynamic itables, MethodHandles must be lowered to methodOops. For the special case of direct method handles, the original methodOop can be reused. For other (adapted or bound) method handles, a new methodOop must be created to wrap the method handle. This is a dark and dirty secret that nobody but the JVM will know about. (See the auto-generation of invoke methods in methodOop.cpp of meth.patch.)

...

When the linear-table and linked-list lookups fail, the invoking code needs to back up to a safe place, call the (C code of the) JVM, find out whether an injection is to be made, and either patch the klass (for next time) or throw an error. The tricky part is finding a backoff point where it's safe to call out of Java.

...

This needs a linked list search and a whole new negative logic side. As with invokeinterface, if the initial searches fail, there needs to be a backoff and upcall to the JVM, to possibly inject the interface. Since negative interface checks are too common to handle this way (via an upcall) some negative filtering needs to be put in. We could do it in a couple of ways:

  • Wiki Markup
    Interface {{klass}}es which are not injectable (the vast majority) should have bits in their header which identifies them as such, so that instanceof can return false more quickly.  A good way to do this is, I think, is to add a second {{
    Interface klasses which are not injectable (the vast majority) should have bits in their header which identifies them as such, so that instanceof can return false more quickly. A good way to do this is, I think, is to add a second
    Klass::secondary_super_cache}} just for injectable interfaces; then the secondary_super_offset for an interface will take one of two distinct values (instead of the single value it takes today), depending on which secondary_super_cache it uses.  This simultaneously makes it easy to detect injectables (by {{secondary_super_offset == offsetof(&secondary_super_cache\[1]))}} and also allocates a word in every {{klass}} to optimize the lookup of injected interfaces.
  • (Can delay this for the POC.) Introduce a negative super type cache: Klass::secondary_non_super_cache. Use it as a first resort, to avoid upcalls on negative type tests of injectables.

negative injection record on each klass

Somehow we must record on each klass which interfaces have refused to inject. (They are the guys that show up in secondary_non_super_cache.) Probably a chunky linked list: A linked list of arrays, like the extension records above. Or something else; I don't know. The important thing is not to ask the same injection question twice; record yesses as extension records and noes as entries on the negative injection list.

...

(Can delay this a while; we'll get a GC guy to help fix it.) References to interface klasses {{klass}}es on both positive and negative sides should be weak, so that the GC can delete entries for unreachable interfaces.

...

(Can delay this, as long as we expose the API only to privileged code, like Unsafe.) Needs some analysis, especially in the case of non-public interfaces. Perhaps we punt on non-public interfaces, but probably there's a more permissive solution, such as allowing injection if the target class itself would have been able to access the interface. (Or, maybe non-public interfaces are an important use case, precisely for adding new aspects to classes that would not be able to add them to themselves.)

...

Overview
Content Tools
ThemeBuilder

Terms of Use
• License: GPLv2
• Privacy • Trademarks • Contact Us

Powered by a free Atlassian Confluence Open Source Project License granted to https://www.atlassian.com/software/views/opensource-community-additional-license-offer. Evaluate Confluence today.

  • Kolekti ThemeBuilder Powered by Atlassian Confluence 8.5.21
  • Kolekti ThemeBuilder printed.by.atlassian.confluence
  • Report a bug
  • Atlassian News
Atlassian
Kolekti ThemeBuilder EngineAtlassian Confluence
{"serverDuration": 347, "requestCorrelationId": "c29f0abf9a8919b2"}