Merge pull request #18335 from uschindler/painless_bootsrap_renames

painless: Rename the dynamic call site factory to DefBootstrap
This commit is contained in:
Robert Muir 2016-05-13 14:05:14 -04:00
commit f2cc8486af
7 changed files with 38 additions and 35 deletions

View File

@ -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.
*/

View File

@ -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);
}
}

View File

@ -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 =

View File

@ -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 });
}
}

View File

@ -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

View File

@ -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 });
}
}

View File

@ -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);
}
}