Merge pull request #18335 from uschindler/painless_bootsrap_renames
painless: Rename the dynamic call site factory to DefBootstrap
This commit is contained in:
commit
f2cc8486af
|
@ -43,7 +43,7 @@ import java.util.stream.Stream;
|
|||
* or method depending on the receiver's class. For these, we emit an {@code invokedynamic} instruction that,
|
||||
* for each new type encountered will query a corresponding {@code lookupXXX} method to retrieve the appropriate
|
||||
* method. In most cases, the {@code lookupXXX} methods here will only be called once for a given call site, because
|
||||
* caching ({@link DynamicCallSite}) generally works: usually all objects at any call site will be consistently
|
||||
* caching ({@link DefBootstrap}) generally works: usually all objects at any call site will be consistently
|
||||
* the same type (or just a few types). In extreme cases, if there is type explosion, they may be called every
|
||||
* single time, but simplicity is still more valuable than performance in this code.
|
||||
*/
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.lang.invoke.MethodType;
|
|||
import java.lang.invoke.MutableCallSite;
|
||||
|
||||
/**
|
||||
* Painless invokedynamic call site.
|
||||
* Painless invokedynamic bootstrap for the call site.
|
||||
* <p>
|
||||
* Has 5 flavors (passed as static bootstrap parameters): dynamic method call,
|
||||
* dynamic field load (getter), and dynamic field store (setter), dynamic array load,
|
||||
|
@ -41,9 +41,9 @@ import java.lang.invoke.MutableCallSite;
|
|||
*/
|
||||
// NOTE: this class must be public, because generated painless classes are in a different classloader,
|
||||
// and it needs to be accessible by that code.
|
||||
public final class DynamicCallSite {
|
||||
public final class DefBootstrap {
|
||||
|
||||
private DynamicCallSite() {} // no instance!
|
||||
private DefBootstrap() {} // no instance!
|
||||
|
||||
// NOTE: these must be primitive types, see https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokedynamic
|
||||
/** static bootstrap parameter indicating a dynamic method call, e.g. foo.bar(...) */
|
||||
|
@ -57,7 +57,10 @@ public final class DynamicCallSite {
|
|||
/** static bootstrap parameter indicating a dynamic array store, e.g. foo[bar] = baz */
|
||||
public static final int ARRAY_STORE = 4;
|
||||
|
||||
static final class InliningCacheCallSite extends MutableCallSite {
|
||||
/**
|
||||
* CallSite that implements the polymorphic inlining cache (PIC).
|
||||
*/
|
||||
static final class PIC extends MutableCallSite {
|
||||
/** maximum number of types before we go megamorphic */
|
||||
static final int MAX_DEPTH = 5;
|
||||
|
||||
|
@ -65,14 +68,14 @@ public final class DynamicCallSite {
|
|||
private final int flavor;
|
||||
int depth; // pkg-protected for testing
|
||||
|
||||
InliningCacheCallSite(String name, MethodType type, int flavor) {
|
||||
PIC(String name, MethodType type, int flavor) {
|
||||
super(type);
|
||||
this.name = name;
|
||||
this.flavor = flavor;
|
||||
|
||||
MethodHandle fallback = FALLBACK.bindTo(this);
|
||||
fallback = fallback.asCollector(Object[].class, type.parameterCount());
|
||||
fallback = fallback.asType(type);
|
||||
final MethodHandle fallback = FALLBACK.bindTo(this)
|
||||
.asCollector(Object[].class, type.parameterCount())
|
||||
.asType(type);
|
||||
|
||||
setTarget(fallback);
|
||||
}
|
||||
|
@ -109,11 +112,10 @@ public final class DynamicCallSite {
|
|||
* types at this call site and given up on caching).
|
||||
*/
|
||||
Object fallback(Object[] args) throws Throwable {
|
||||
MethodType type = type();
|
||||
Object receiver = args[0];
|
||||
Class<?> receiverClass = receiver.getClass();
|
||||
MethodHandle target = lookup(flavor, receiverClass, name);
|
||||
target = target.asType(type);
|
||||
final MethodType type = type();
|
||||
final Object receiver = args[0];
|
||||
final Class<?> receiverClass = receiver.getClass();
|
||||
final MethodHandle target = lookup(flavor, receiverClass, name).asType(type);
|
||||
|
||||
if (depth >= MAX_DEPTH) {
|
||||
// revert to a vtable call
|
||||
|
@ -124,7 +126,8 @@ public final class DynamicCallSite {
|
|||
MethodHandle test = CHECK_CLASS.bindTo(receiverClass);
|
||||
test = test.asType(test.type().changeParameterType(0, type.parameterType(0)));
|
||||
|
||||
MethodHandle guard = MethodHandles.guardWithTest(test, target, getTarget());
|
||||
final MethodHandle guard = MethodHandles.guardWithTest(test, target, getTarget());
|
||||
|
||||
depth++;
|
||||
|
||||
setTarget(guard);
|
||||
|
@ -139,7 +142,7 @@ public final class DynamicCallSite {
|
|||
CHECK_CLASS = lookup.findStatic(lookup.lookupClass(), "checkClass",
|
||||
MethodType.methodType(boolean.class, Class.class, Object.class));
|
||||
FALLBACK = lookup.findVirtual(lookup.lookupClass(), "fallback",
|
||||
MethodType.methodType(Object.class, Object[].class));
|
||||
MethodType.methodType(Object.class, Object[].class));
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
@ -155,7 +158,7 @@ public final class DynamicCallSite {
|
|||
* see https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html#jvms-6.5.invokedynamic
|
||||
*/
|
||||
public static CallSite bootstrap(Lookup lookup, String name, MethodType type, int flavor) {
|
||||
return new InliningCacheCallSite(name, type, flavor);
|
||||
return new PIC(name, type, flavor);
|
||||
}
|
||||
|
||||
}
|
|
@ -58,7 +58,7 @@ public final class WriterConstants {
|
|||
public final static MethodType DEF_BOOTSTRAP_TYPE =
|
||||
MethodType.methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, int.class);
|
||||
public final static Handle DEF_BOOTSTRAP_HANDLE =
|
||||
new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(DynamicCallSite.class),
|
||||
new Handle(Opcodes.H_INVOKESTATIC, Type.getInternalName(DefBootstrap.class),
|
||||
"bootstrap", DEF_BOOTSTRAP_TYPE.toMethodDescriptorString());
|
||||
|
||||
public final static String DEF_DYNAMIC_LOAD_FIELD_DESC =
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.painless.node;
|
|||
|
||||
import org.elasticsearch.painless.CompilerSettings;
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.DynamicCallSite;
|
||||
import org.elasticsearch.painless.DefBootstrap;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.commons.GeneratorAdapter;
|
||||
|
||||
|
@ -62,13 +62,13 @@ final class LDefArray extends ALink {
|
|||
@Override
|
||||
void load(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
adapter.visitInvokeDynamicInsn(
|
||||
"arrayLoad", DEF_DYNAMIC_ARRAY_LOAD_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.ARRAY_LOAD });
|
||||
"arrayLoad", DEF_DYNAMIC_ARRAY_LOAD_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.ARRAY_LOAD });
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
void store(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
adapter.visitInvokeDynamicInsn(
|
||||
"arrayStore", DEF_DYNAMIC_ARRAY_STORE_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.ARRAY_STORE });
|
||||
"arrayStore", DEF_DYNAMIC_ARRAY_STORE_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.ARRAY_STORE });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.painless.node;
|
|||
|
||||
import org.elasticsearch.painless.CompilerSettings;
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.DynamicCallSite;
|
||||
import org.elasticsearch.painless.DefBootstrap;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.commons.GeneratorAdapter;
|
||||
|
||||
|
@ -84,7 +84,7 @@ final class LDefCall extends ALink {
|
|||
// return value
|
||||
signature.append(definition.defType.type.getDescriptor());
|
||||
|
||||
adapter.visitInvokeDynamicInsn(name, signature.toString(), DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.METHOD_CALL });
|
||||
adapter.visitInvokeDynamicInsn(name, signature.toString(), DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.METHOD_CALL });
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -21,7 +21,7 @@ package org.elasticsearch.painless.node;
|
|||
|
||||
import org.elasticsearch.painless.CompilerSettings;
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.DynamicCallSite;
|
||||
import org.elasticsearch.painless.DefBootstrap;
|
||||
import org.elasticsearch.painless.Variables;
|
||||
import org.objectweb.asm.commons.GeneratorAdapter;
|
||||
|
||||
|
@ -57,11 +57,11 @@ final class LDefField extends ALink {
|
|||
|
||||
@Override
|
||||
void load(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
adapter.visitInvokeDynamicInsn(value, DEF_DYNAMIC_LOAD_FIELD_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.LOAD });
|
||||
adapter.visitInvokeDynamicInsn(value, DEF_DYNAMIC_LOAD_FIELD_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.LOAD });
|
||||
}
|
||||
|
||||
@Override
|
||||
void store(final CompilerSettings settings, final Definition definition, final GeneratorAdapter adapter) {
|
||||
adapter.visitInvokeDynamicInsn(value, DEF_DYNAMIC_STORE_FIELD_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DynamicCallSite.STORE });
|
||||
adapter.visitInvokeDynamicInsn(value, DEF_DYNAMIC_STORE_FIELD_DESC, DEF_BOOTSTRAP_HANDLE, new Object[] { DefBootstrap.STORE });
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,14 +26,14 @@ import java.lang.invoke.MethodType;
|
|||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
public class DynamicCallSiteTests extends ESTestCase {
|
||||
public class DefBootstrapTests extends ESTestCase {
|
||||
|
||||
/** calls toString() on integers, twice */
|
||||
public void testOneType() throws Throwable {
|
||||
CallSite site = DynamicCallSite.bootstrap(MethodHandles.publicLookup(),
|
||||
CallSite site = DefBootstrap.bootstrap(MethodHandles.publicLookup(),
|
||||
"toString",
|
||||
MethodType.methodType(String.class, Object.class),
|
||||
DynamicCallSite.METHOD_CALL);
|
||||
DefBootstrap.METHOD_CALL);
|
||||
MethodHandle handle = site.dynamicInvoker();
|
||||
assertDepthEquals(site, 0);
|
||||
|
||||
|
@ -47,10 +47,10 @@ public class DynamicCallSiteTests extends ESTestCase {
|
|||
}
|
||||
|
||||
public void testTwoTypes() throws Throwable {
|
||||
CallSite site = DynamicCallSite.bootstrap(MethodHandles.publicLookup(),
|
||||
CallSite site = DefBootstrap.bootstrap(MethodHandles.publicLookup(),
|
||||
"toString",
|
||||
MethodType.methodType(String.class, Object.class),
|
||||
DynamicCallSite.METHOD_CALL);
|
||||
DefBootstrap.METHOD_CALL);
|
||||
MethodHandle handle = site.dynamicInvoker();
|
||||
assertDepthEquals(site, 0);
|
||||
|
||||
|
@ -68,11 +68,11 @@ public class DynamicCallSiteTests extends ESTestCase {
|
|||
|
||||
public void testTooManyTypes() throws Throwable {
|
||||
// if this changes, test must be rewritten
|
||||
assertEquals(5, DynamicCallSite.InliningCacheCallSite.MAX_DEPTH);
|
||||
CallSite site = DynamicCallSite.bootstrap(MethodHandles.publicLookup(),
|
||||
assertEquals(5, DefBootstrap.PIC.MAX_DEPTH);
|
||||
CallSite site = DefBootstrap.bootstrap(MethodHandles.publicLookup(),
|
||||
"toString",
|
||||
MethodType.methodType(String.class, Object.class),
|
||||
DynamicCallSite.METHOD_CALL);
|
||||
DefBootstrap.METHOD_CALL);
|
||||
MethodHandle handle = site.dynamicInvoker();
|
||||
assertDepthEquals(site, 0);
|
||||
|
||||
|
@ -91,7 +91,7 @@ public class DynamicCallSiteTests extends ESTestCase {
|
|||
}
|
||||
|
||||
static void assertDepthEquals(CallSite site, int expected) {
|
||||
DynamicCallSite.InliningCacheCallSite dsite = (DynamicCallSite.InliningCacheCallSite) site;
|
||||
DefBootstrap.PIC dsite = (DefBootstrap.PIC) site;
|
||||
assertEquals(expected, dsite.depth);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue