- Loading...
...
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 {{Wiki Markup methodOop target\[N]}}, where {{N}} is the number of methods in the interface.
Interface dispatch (for polymorphic call sites) searches the spine of the table, and dips into the matching itable, picking out the target method corresponding to the index (in 0..N-1) of the abstract method in the interface.
...
The meth.patch code already uses the oop-in-a-constant-pool technique for autogenerated MethodHandle.invoke methods (of which there is an infinite variety).
<clinit> of an interface is less than minimal. It should be safe to reuse the _bootstrap_method oop in instanceKlass for storing the injector for injectable interfaces.<clinit> method on the injectable interface. This is done by invoking InterfaceInjector.setInjector(InterfaceInjector) from <clinit>.0x0040 - JVM_ACC_VOLATILE for fields, JVM_ACC_BRIDGE for methods0x0080 - JVM_ACC_TRANSIENT for fields, JVM_ACC_VARARGS for methods0x0100 - JVM_ACC_NATIVE for methodssetInjector-method.invokeinterface...
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:
...
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.Klass::secondary_non_super_cache. Use it as a first resort, to avoid upcalls on negative type tests of injectables....
Bottom line, per case:
1. always check for extension records
2. always use the negative cache (after fast positive tests), and customize the code in the JIT (GraphKit::gen_subtype_check)
3. customize in the JIT; negative cache buys nothing
4. customize in the JIT if possible; negative cache buys nothing
5. let the JIT do its thing for intrinsics; use the negative cache for Class.isInstance and Class.isAssignableFrom