This commit is contained in:
Jim Laskey 2013-02-19 09:47:02 -04:00
commit b5c0480f54
58 changed files with 361 additions and 259 deletions

View File

@ -87,7 +87,6 @@ import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
/**
* An immutable descriptor of a call site. It is an immutable object that contains all the information about a call
* site: the class performing the lookups, the name of the method being invoked, and the method signature. The library
@ -172,4 +171,4 @@ public interface CallSiteDescriptor {
*/
public CallSiteDescriptor changeMethodType(MethodType newMethodType);
}
}

View File

@ -92,7 +92,6 @@ import java.util.concurrent.atomic.AtomicReference;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.support.AbstractRelinkableCallSite;
/**
* A relinkable call site that maintains a chain of linked method handles. In the default implementation, up to 8 method
* handles can be chained, cascading from one to the other through
@ -209,4 +208,4 @@ public class ChainedCallSite extends AbstractRelinkableCallSite {
throw new AssertionError(e.getMessage(), e); // Can not happen
}
}
}
}

View File

@ -88,7 +88,6 @@ import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
/**
* A convenience default bootstrapper that exposes static bootstrap methods which language runtimes that need the very
* default behavior can use with minimal setup. When first referenced, it will create a dynamic linker with default
@ -141,4 +140,4 @@ public class DefaultBootstrapper {
private static CallSite bootstrapInternal(MethodHandles.Lookup caller, String name, MethodType type) {
return dynamicLinker.link(new MonomorphicCallSite(CallSiteDescriptorFactory.create(caller, name, type)));
}
}
}

View File

@ -97,7 +97,6 @@ import jdk.internal.dynalink.support.LinkRequestImpl;
import jdk.internal.dynalink.support.Lookup;
import jdk.internal.dynalink.support.RuntimeContextLinkRequestImpl;
/**
* The linker for {@link RelinkableCallSite} objects. Users of it (scripting frameworks and language runtimes) have to
* create a linker using the {@link DynamicLinkerFactory} and invoke its link method from the invokedynamic bootstrap
@ -246,14 +245,15 @@ public class DynamicLinker {
}
}
if(unstableDetectionEnabled && relinkCount <= unstableRelinkThreshold && relinkCount++ == unstableRelinkThreshold) {
// Note that we'll increase the relinkCount until threshold+1 and not increase it beyond that. Threshold+1
// is treated as a special value to signal that resetAndRelink has already executed once for the unstable
// call site; we only want the call site to throw away its current linkage once, when it transitions to
// unstable.
callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, relinkCount));
int newRelinkCount = relinkCount;
// Note that the short-circuited "&&" evaluation below ensures we'll increment the relinkCount until
// threshold + 1 but not beyond that. Threshold + 1 is treated as a special value to signal that resetAndRelink
// has already executed once for the unstable call site; we only want the call site to throw away its current
// linkage once, when it transitions to unstable.
if(unstableDetectionEnabled && newRelinkCount <= unstableRelinkThreshold && newRelinkCount++ == unstableRelinkThreshold) {
callSite.resetAndRelink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
} else {
callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, relinkCount));
callSite.relink(guardedInvocation, createRelinkAndInvokeMethod(callSite, newRelinkCount));
}
if(syncOnRelink) {
MutableCallSite.syncAll(new MutableCallSite[] { (MutableCallSite)callSite });

View File

@ -102,7 +102,6 @@ import jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.LinkerServicesImpl;
import jdk.internal.dynalink.support.TypeConverterFactory;
/**
* A factory class for creating {@link DynamicLinker}s. The most usual dynamic linker is a linker that is a composition
* of all {@link GuardingDynamicLinker}s known and pre-created by the caller as well as any
@ -256,14 +255,16 @@ public class DynamicLinkerFactory {
// Gather classes of all precreated (prioritized and fallback) linkers.
// We'll filter out any discovered linkers of the same class.
final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses = new HashSet<>();
final Set<Class<? extends GuardingDynamicLinker>> knownLinkerClasses =
new HashSet<>();
addClasses(knownLinkerClasses, prioritizedLinkers);
addClasses(knownLinkerClasses, fallbackLinkers);
final List<GuardingDynamicLinker> discovered = AutoDiscovery.loadLinkers(classLoader);
// Now, concatenate ...
final List<GuardingDynamicLinker> linkers = new ArrayList<>(prioritizedLinkers.size() + discovered.size()
+ fallbackLinkers.size());
final List<GuardingDynamicLinker> linkers =
new ArrayList<>(prioritizedLinkers.size() + discovered.size()
+ fallbackLinkers.size());
// ... prioritized linkers, ...
linkers.addAll(prioritizedLinkers);
// ... filtered discovered linkers, ...
@ -308,4 +309,4 @@ public class DynamicLinkerFactory {
knownLinkerClasses.add(linker.getClass());
}
}
}
}

View File

@ -87,7 +87,6 @@ import java.lang.invoke.MethodHandle;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.support.AbstractRelinkableCallSite;
/**
* A relinkable call site that implements monomorphic inline caching strategy. After it linked a method, it will keep it
* until either its guard evaluates to false, or its switchpoint is invalidated, at which time it will throw away the
@ -113,4 +112,4 @@ public class MonomorphicCallSite extends AbstractRelinkableCallSite {
public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle relink) {
relink(guardedInvocation, relink);
}
}
}

View File

@ -100,4 +100,4 @@ public class NoSuchDynamicMethodException extends RuntimeException {
public NoSuchDynamicMethodException(String message) {
super(message);
}
}
}

View File

@ -89,7 +89,6 @@ import java.lang.invoke.MutableCallSite;
import java.lang.invoke.VolatileCallSite;
import jdk.internal.dynalink.linker.GuardedInvocation;
/**
* Interface for relinkable call sites. Language runtimes wishing to use this framework must use subclasses of
* {@link CallSite} that also implement this interface as their call sites. There is a readily usable
@ -145,4 +144,4 @@ public interface RelinkableCallSite {
* {@link #resetAndRelink(GuardedInvocation, MethodHandle)}, and finally invoke the target.
*/
public void resetAndRelink(GuardedInvocation guardedInvocation, MethodHandle fallback);
}
}

View File

@ -103,7 +103,6 @@ import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
import jdk.internal.dynalink.support.Guards;
import jdk.internal.dynalink.support.Lookup;
/**
* A base class for both {@link StaticClassLinker} and {@link BeanLinker}. Deals with common aspects of property
* exposure and method calls for both static and instance facets of a class.
@ -128,50 +127,46 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
this.assignableGuard = assignableGuard;
final FacetIntrospector introspector = createFacetIntrospector();
try {
// Add methods and properties
for(Method method: introspector.getMethods()) {
final String name = method.getName();
final MethodHandle methodHandle = introspector.unreflect(method);
// Add method
addMember(name, methodHandle, methods);
// Add the method as a property getter and/or setter
if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) {
// Property getter
setPropertyGetter(Introspector.decapitalize(name.substring(3)), introspector.unreflect(
getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
} else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 &&
method.getReturnType() == boolean.class) {
// Boolean property getter
setPropertyGetter(Introspector.decapitalize(name.substring(2)), introspector.unreflect(
getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
} else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
// Property setter
addMember(Introspector.decapitalize(name.substring(3)), methodHandle, propertySetters);
}
// Add methods and properties
for(Method method: introspector.getMethods()) {
final String name = method.getName();
final MethodHandle methodHandle = introspector.unreflect(method);
// Add method
addMember(name, methodHandle, methods);
// Add the method as a property getter and/or setter
if(name.startsWith("get") && name.length() > 3 && method.getParameterTypes().length == 0) {
// Property getter
setPropertyGetter(Introspector.decapitalize(name.substring(3)), introspector.unreflect(
getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
} else if(name.startsWith("is") && name.length() > 2 && method.getParameterTypes().length == 0 &&
method.getReturnType() == boolean.class) {
// Boolean property getter
setPropertyGetter(Introspector.decapitalize(name.substring(2)), introspector.unreflect(
getMostGenericGetter(method)), ValidationType.INSTANCE_OF);
} else if(name.startsWith("set") && name.length() > 3 && method.getParameterTypes().length == 1) {
// Property setter
addMember(Introspector.decapitalize(name.substring(3)), methodHandle, propertySetters);
}
}
// Add field getter/setters as property getters/setters.
for(Field field: introspector.getFields()) {
final String name = field.getName();
// Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
if(!propertyGetters.containsKey(name)) {
setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS);
}
if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) {
addMember(name, introspector.unreflectSetter(field), propertySetters);
}
// Add field getter/setters as property getters/setters.
for(Field field: introspector.getFields()) {
final String name = field.getName();
// Only add a property getter when one is not defined already as a getXxx()/isXxx() method.
if(!propertyGetters.containsKey(name)) {
setPropertyGetter(name, introspector.unreflectGetter(field), ValidationType.EXACT_CLASS);
}
if(!(Modifier.isFinal(field.getModifiers()) || propertySetters.containsKey(name))) {
addMember(name, introspector.unreflectSetter(field), propertySetters);
}
}
// Add inner classes, but only those for which we don't hide a property with it
for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
final String name = innerClassSpec.getKey();
if(!propertyGetters.containsKey(name)) {
setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS);
}
// Add inner classes, but only those for which we don't hide a property with it
for(Map.Entry<String, MethodHandle> innerClassSpec: introspector.getInnerClassGetters().entrySet()) {
final String name = innerClassSpec.getKey();
if(!propertyGetters.containsKey(name)) {
setPropertyGetter(name, innerClassSpec.getValue(), ValidationType.EXACT_CLASS);
}
} finally {
introspector.close();
}
}
@ -394,10 +389,8 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
IS_METHOD_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
if(nextComponent == null) {
return getClassGuardedInvocationComponent(compositeSetter, type);
} else {
return nextComponent.compose(compositeSetter, getClassGuard(type), clazz,
ValidationType.EXACT_CLASS);
}
return nextComponent.compose(compositeSetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
}
case 3: {
// Must have two arguments: target object and property value
@ -474,10 +467,8 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
IS_ANNOTATED_HANDLE_NOT_NULL, invokeHandleFolded, fallbackFolded), typedGetter);
if(nextComponent == null) {
return getClassGuardedInvocationComponent(compositeGetter, type);
} else {
return nextComponent.compose(compositeGetter, getClassGuard(type), clazz,
ValidationType.EXACT_CLASS);
}
return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
}
case 3: {
// Must have exactly one argument: receiver
@ -521,8 +512,10 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
case NONE: {
return null;
}
default: {
throw new AssertionError();
}
}
throw new AssertionError();
}
private static final MethodHandle IS_DYNAMIC_METHOD_NOT_NULL = Guards.asType(Guards.isNotNull(),
@ -541,32 +534,30 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
if(nextComponent == null) {
// No next component operation; just return a component for this operation.
return getClassGuardedInvocationComponent(linkerServices.asType(getDynamicMethod, type), type);
} else {
// What's below is basically:
// foldArguments(guardWithTest(isNotNull, identity, nextComponent.invocation), getter)
// only with a bunch of method signature adjustments. Basically, execute method getter; if
// it returns a non-null DynamicMethod, use identity to return it, otherwise delegate to
// nextComponent's invocation.
final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type.changeReturnType(
DynamicMethod.class));
// Since it is part of the foldArgument() target, it will have extra args that we need to drop.
final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments(
DYNAMIC_METHOD_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0,
DynamicMethod.class));
final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation();
// The assumption is that getGuardedInvocationComponent() already asType()'d it correctly
assert nextComponentInvocation.type().equals(type);
// Since it is part of the foldArgument() target, we have to drop an extra arg it receives.
final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
DynamicMethod.class);
// Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
IS_DYNAMIC_METHOD_NOT_NULL, returnMethodHandle, nextCombinedInvocation), typedGetter);
return nextComponent.compose(compositeGetter, getClassGuard(type), clazz,
ValidationType.EXACT_CLASS);
}
// What's below is basically:
// foldArguments(guardWithTest(isNotNull, identity, nextComponent.invocation), getter) only with a
// bunch of method signature adjustments. Basically, execute method getter; if it returns a non-null
// DynamicMethod, use identity to return it, otherwise delegate to nextComponent's invocation.
final MethodHandle typedGetter = linkerServices.asType(getDynamicMethod, type.changeReturnType(
DynamicMethod.class));
// Since it is part of the foldArgument() target, it will have extra args that we need to drop.
final MethodHandle returnMethodHandle = linkerServices.asType(MethodHandles.dropArguments(
DYNAMIC_METHOD_IDENTITY, 1, type.parameterList()), type.insertParameterTypes(0,
DynamicMethod.class));
final MethodHandle nextComponentInvocation = nextComponent.getGuardedInvocation().getInvocation();
// The assumption is that getGuardedInvocationComponent() already asType()'d it correctly
assert nextComponentInvocation.type().equals(type);
// Since it is part of the foldArgument() target, we have to drop an extra arg it receives.
final MethodHandle nextCombinedInvocation = MethodHandles.dropArguments(nextComponentInvocation, 0,
DynamicMethod.class);
// Assemble it all into a fold(guard(isNotNull, identity, nextInvocation), get)
final MethodHandle compositeGetter = MethodHandles.foldArguments(MethodHandles.guardWithTest(
IS_DYNAMIC_METHOD_NOT_NULL, returnMethodHandle, nextCombinedInvocation), typedGetter);
return nextComponent.compose(compositeGetter, getClassGuard(type), clazz, ValidationType.EXACT_CLASS);
}
case 3: {
// Must have exactly one argument: receiver
@ -638,7 +629,7 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
* @return the dynamic method (either {@link SimpleDynamicMethod} or {@link OverloadedDynamicMethod}, or null if the
* method with the specified name does not exist.
*/
public DynamicMethod getDynamicMethod(String name) {
DynamicMethod getDynamicMethod(String name) {
return getDynamicMethod(name, methods);
}
@ -687,4 +678,4 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
this.validationType = validationType;
}
}
}
}

View File

@ -89,7 +89,6 @@ import java.util.LinkedList;
import java.util.List;
import jdk.internal.dynalink.support.TypeUtilities;
/**
* Represents overloaded methods applicable to a specific call site signature.
*

View File

@ -99,7 +99,6 @@ import jdk.internal.dynalink.support.Guards;
import jdk.internal.dynalink.support.Lookup;
import jdk.internal.dynalink.support.TypeUtilities;
/**
* A class that provides linking capabilities for a single POJO class. Normally not used directly, but managed by
* {@link BeansLinker}.
@ -176,7 +175,7 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
// dealing with an array, or a list or map, but hey...
// Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
// in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
final GuardedInvocationComponent gic;;
final GuardedInvocationComponent gic;
final boolean isMap;
if(declaredType.isArray()) {
gic = new GuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType));
@ -223,22 +222,22 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
if(nextComponent == null) {
return gic.replaceInvocation(binder.bind(invocation));
} else {
final MethodHandle checkGuard;
if(invocation == GET_LIST_ELEMENT) {
checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
} else if(invocation == GET_MAP_ELEMENT) {
// TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it
// into a GWT that tests if it returned null, and if it did, do another GWT with containsKey()
// that returns constant null (on true), or falls back to next component (on false)
checkGuard = CONTAINS_MAP;
} else {
checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
}
return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
gic.getValidatorClass(), gic.getValidationType());
}
final MethodHandle checkGuard;
if(invocation == GET_LIST_ELEMENT) {
checkGuard = convertArgToInt(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
} else if(invocation == GET_MAP_ELEMENT) {
// TODO: A more complex solution could be devised for maps, one where we do a get() first, and fold it
// into a GWT that tests if it returned null, and if it did, do another GWT with containsKey()
// that returns constant null (on true), or falls back to next component (on false)
checkGuard = CONTAINS_MAP;
} else {
checkGuard = convertArgToInt(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
}
return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
gic.getValidatorClass(), gic.getValidationType());
}
private static String getFixedKey(final CallSiteDescriptor callSiteDescriptor) {
@ -435,13 +434,13 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
if(nextComponent == null) {
return gic.replaceInvocation(binder.bind(invocation));
} else {
final MethodHandle checkGuard = convertArgToInt(invocation == SET_LIST_ELEMENT ? RANGE_CHECK_LIST :
RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
gic.getValidatorClass(), gic.getValidationType());
}
final MethodHandle checkGuard = convertArgToInt(invocation == SET_LIST_ELEMENT ? RANGE_CHECK_LIST :
RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
return nextComponent.compose(MethodHandles.guardWithTest(binder.bindTest(checkGuard),
binder.bind(invocation), nextComponent.getGuardedInvocation().getInvocation()), gi.getGuard(),
gic.getValidatorClass(), gic.getValidationType());
}
private static MethodHandle GET_ARRAY_LENGTH = Lookup.PUBLIC.findStatic(Array.class, "getLength",
@ -490,4 +489,4 @@ class BeanLinker extends AbstractJavaLinker implements TypeBasedGuardingDynamicL
throw new BootstrapMethodError(descriptor.getName() + " must have exactly " + paramCount + " parameters.");
}
}
}
}

View File

@ -93,7 +93,6 @@ import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
/**
* A linker for POJOs. Normally used as the ultimate fallback linker by the {@link DynamicLinkerFactory} so it is given
* the chance to link calls to all objects that no other language runtime recognizes. Specifically, this linker will:
@ -160,6 +159,16 @@ public class BeansLinker implements GuardingDynamicLinker {
return linkers.get(clazz);
}
/*
* Returns true if the object is a Dynalink Java dynamic method.
*
* @param obj the object we want to test for being a dynamic method
* @return true if it is a dynamic method, false otherwise.
*/
public static boolean isDynamicMethod(final Object obj) {
return obj instanceof DynamicMethod;
}
@Override
public GuardedInvocation getGuardedInvocation(LinkRequest request, final LinkerServices linkerServices)
throws Exception {
@ -177,4 +186,4 @@ public class BeansLinker implements GuardingDynamicLinker {
}
return getLinkerForClass(receiver.getClass()).getGuardedInvocation(request, linkerServices);
}
}
}

View File

@ -222,14 +222,14 @@ class CheckRestrictedPackageInternal {
resolveClass(clazz);
}
return clazz;
} else {
return super.loadClass(name, resolve);
}
return super.loadClass(name, resolve);
}
};
}
private static byte[] getTesterClassBytes() {
static byte[] getTesterClassBytes() {
try {
final InputStream in = CheckRestrictedPackage.class.getResourceAsStream("RestrictedPackageTester.class");
try {

View File

@ -89,7 +89,6 @@ import java.lang.invoke.MethodType;
import jdk.internal.dynalink.beans.GuardedInvocationComponent.ValidationType;
import jdk.internal.dynalink.support.Lookup;
/**
* A linker for java.lang.Class objects. Provides a synthetic property "static" that allows access to static fields and
* methods on the class (respecting property getter/setter conventions). Note that Class objects are not recognized by
@ -107,4 +106,4 @@ class ClassLinker extends BeanLinker {
private static final MethodHandle FOR_CLASS = new Lookup(MethodHandles.lookup()).findStatic(StaticClass.class,
"forClass", MethodType.methodType(StaticClass.class, Class.class));
}
}

View File

@ -91,7 +91,6 @@ import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.Guards;
import jdk.internal.dynalink.support.TypeUtilities;
/**
*
* @author Attila Szegedi
@ -206,4 +205,4 @@ final class ClassString {
private static boolean canConvert(LinkerServices ls, Class<?> from, Class<?> to) {
return ls == null ? TypeUtilities.isMethodInvocationConvertible(from, to) : ls.canConvert(from, to);
}
}
}

View File

@ -88,7 +88,6 @@ import java.lang.invoke.MethodType;
import java.util.StringTokenizer;
import jdk.internal.dynalink.linker.LinkerServices;
/**
* Represents a single dynamic method. A "dynamic" method can be bound to a single Java method, or can be bound to all
* overloaded methods of the same name on a class. Getting an invocation of a dynamic method bound to multiple
@ -166,4 +165,4 @@ abstract class DynamicMethod {
public String toString() {
return "[" + getClass().getName() + " " + getName() + "]";
}
}
}

View File

@ -93,7 +93,6 @@ import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.Guards;
/**
* Simple linker that implements the "dyn:call" operation for {@link DynamicMethod} objects - the objects returned by
* "dyn:getMethod" from {@link AbstractJavaLinker}.
@ -102,7 +101,7 @@ class DynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
@Override
public boolean canLinkType(Class<?> type) {
return DynamicMethod.class.isAssignableFrom(type);
};
}
@Override
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) {

View File

@ -94,13 +94,12 @@ import java.util.Collections;
import java.util.Map;
import jdk.internal.dynalink.support.Lookup;
/**
* Base for classes that expose class field and method information to an {@link AbstractJavaLinker}. There are
* subclasses for instance (bean) and static facet of a class.
* @author Attila Szegedi
*/
abstract class FacetIntrospector implements AutoCloseable {
abstract class FacetIntrospector {
private final Class<?> clazz;
private final boolean instance;
private final boolean isRestricted;
@ -181,8 +180,4 @@ abstract class FacetIntrospector implements AutoCloseable {
* @return the edited method handle.
*/
abstract MethodHandle editMethodHandle(MethodHandle mh);
@Override
public void close() {
}
}
}

View File

@ -86,7 +86,6 @@ package jdk.internal.dynalink.beans;
import java.lang.invoke.MethodHandle;
import jdk.internal.dynalink.linker.GuardedInvocation;
/**
* Represents one component for a GuardedInvocation of a potentially composite operation of an
* {@link AbstractJavaLinker}. In addition to holding a guarded invocation, it holds semantic information about its
@ -196,8 +195,8 @@ class GuardedInvocationComponent {
return this;
}
break;
case NONE:
throw new AssertionError(); // Not possible
default:
throw new AssertionError();
}
break;
case EXACT_CLASS:
@ -217,8 +216,8 @@ class GuardedInvocationComponent {
return this;
}
break;
case NONE:
throw new AssertionError(); // Not possible
default:
throw new AssertionError();
}
break;
case IS_ARRAY:
@ -231,10 +230,12 @@ class GuardedInvocationComponent {
break;
case IS_ARRAY:
return this;
case NONE:
throw new AssertionError(); // Not possible
default:
throw new AssertionError();
}
break;
default:
throw new AssertionError();
}
throw new AssertionError("Incompatible composition " + this + " vs " + other);
}

View File

@ -92,7 +92,6 @@ import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.TypeUtilities;
/**
* Utility class that encapsulates the algorithm for choosing the maximally specific methods.
*
@ -141,6 +140,10 @@ class MaximallySpecific {
}
case INDETERMINATE: {
// do nothing
break;
}
default: {
throw new AssertionError();
}
}
}

View File

@ -92,7 +92,6 @@ import jdk.internal.dynalink.beans.ApplicableOverloadedMethods.ApplicabilityTest
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.TypeUtilities;
/**
* Represents an overloaded method.
*
@ -204,14 +203,16 @@ class OverloadedDynamicMethod extends DynamicMethod {
final MethodHandle mh = invokables.iterator().next();
return new SimpleDynamicMethod(mh).getInvocation(callSiteType, linkerServices);
}
default: {
// We have more than one candidate. We have no choice but to link to a method that resolves overloads on
// every invocation (alternatively, we could opportunistically link the one method that resolves for the
// current arguments, but we'd need to install a fairly complex guard for that and when it'd fail, we'd
// go back all the way to candidate selection.
// TODO: cache per call site type
return new OverloadedMethod(invokables, this, callSiteType, linkerServices).getInvoker();
}
}
// We have more than one candidate. We have no choice but to link to a method that resolves overloads on every
// invocation (alternatively, we could opportunistically link the one method that resolves for the current
// arguments, but we'd need to install a fairly complex guard for that and when it'd fail, we'd go back all the
// way to candidate selection.
// TODO: cache per call site type
return new OverloadedMethod(invokables, this, callSiteType, linkerServices).getInvoker();
}
@Override
@ -248,6 +249,8 @@ class OverloadedDynamicMethod extends DynamicMethod {
final boolean varArgs = m.isVarargsCollector();
final int fixedArgLen = methodType.parameterCount() - (varArgs ? 1 : 0);
final int callSiteArgLen = callSiteType.parameterCount();
// Arity checks
if(varArgs) {
if(callSiteArgLen < fixedArgLen) {
return false;
@ -255,32 +258,36 @@ class OverloadedDynamicMethod extends DynamicMethod {
} else if(callSiteArgLen != fixedArgLen) {
return false;
}
// Starting from 1, as receiver type doesn't participate
// Fixed arguments type checks, starting from 1, as receiver type doesn't participate
for(int i = 1; i < fixedArgLen; ++i) {
if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), methodType.parameterType(i))) {
return false;
}
}
if(varArgs) {
final Class<?> varArgArrayType = methodType.parameterType(fixedArgLen);
final Class<?> varArgType = varArgArrayType.getComponentType();
if(fixedArgLen == callSiteArgLen - 1) {
final Class<?> callSiteArgType = callSiteType.parameterType(fixedArgLen);
// Exactly one vararg; check both exact matching and component
// matching.
return isApplicableDynamically(linkerServices, callSiteArgType, varArgArrayType)
|| isApplicableDynamically(linkerServices, callSiteArgType, varArgType);
} else {
for(int i = fixedArgLen; i < callSiteArgLen; ++i) {
if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), varArgType)) {
return false;
}
}
return true;
}
} else {
if(!varArgs) {
// Not vararg; both arity and types matched.
return true;
}
final Class<?> varArgArrayType = methodType.parameterType(fixedArgLen);
final Class<?> varArgType = varArgArrayType.getComponentType();
if(fixedArgLen == callSiteArgLen - 1) {
// Exactly one vararg; check both array type matching and array component type matching.
final Class<?> callSiteArgType = callSiteType.parameterType(fixedArgLen);
return isApplicableDynamically(linkerServices, callSiteArgType, varArgArrayType)
|| isApplicableDynamically(linkerServices, callSiteArgType, varArgType);
}
// Either zero, or more than one vararg; check if all actual vararg types match the vararg array component type.
for(int i = fixedArgLen; i < callSiteArgLen; ++i) {
if(!isApplicableDynamically(linkerServices, callSiteType.parameterType(i), varArgType)) {
return false;
}
}
return true;
}
private static boolean isApplicableDynamically(LinkerServices linkerServices, Class<?> callSiteType,
@ -298,7 +305,7 @@ class OverloadedDynamicMethod extends DynamicMethod {
*
* @param method the method to add.
*/
public void addMethod(SimpleDynamicMethod method) {
void addMethod(SimpleDynamicMethod method) {
addMethod(method.getTarget());
}
@ -310,4 +317,4 @@ class OverloadedDynamicMethod extends DynamicMethod {
public void addMethod(MethodHandle method) {
methods.add(method);
}
}
}

View File

@ -94,7 +94,6 @@ import java.util.concurrent.ConcurrentHashMap;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.Lookup;
/**
* Represents a subset of overloaded methods for a certain method name on a certain class. It can be either a fixarg or
* a vararg subset depending on the subclass. The method is for a fixed number of arguments though (as it is generated
@ -263,4 +262,4 @@ class OverloadedMethod {
b.append(classes[l - 1].getComponentType().getCanonicalName()).append("...");
}
}
}
}

View File

@ -90,7 +90,6 @@ import java.lang.reflect.Array;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.support.Guards;
/**
* A dynamic method bound to exactly one, non-overloaded Java method. Handles varargs.
*
@ -164,14 +163,13 @@ class SimpleDynamicMethod extends DynamicMethod {
// Less actual arguments than number of fixed declared arguments; can't invoke.
return null;
}
// Method handle of the same number of arguments as the call site type
// Method handle has the same number of fixed arguments as the call site type
if(argsLen == fixParamsLen) {
// Method handle that matches the number of actual arguments as the number of fixed arguments
final MethodHandle matchedMethod;
if(varArgs) {
// If vararg, add a zero-length array of the expected type as the last argument to signify no variable
// arguments.
// TODO: check whether collectArguments() would handle this too.
matchedMethod = MethodHandles.insertArguments(fixTarget, fixParamsLen, Array.newInstance(
methodType.parameterType(fixParamsLen).getComponentType(), 0));
} else {
@ -195,22 +193,22 @@ class SimpleDynamicMethod extends DynamicMethod {
// Call site signature guarantees we'll always be passed a single compatible array; just link directly
// to the method.
return createConvertingInvocation(fixTarget, linkerServices, callSiteType);
} else if(!linkerServices.canConvert(callSiteLastArgType, varArgType)) {
}
if(!linkerServices.canConvert(callSiteLastArgType, varArgType)) {
// Call site signature guarantees the argument can definitely not be an array (i.e. it is primitive);
// link immediately to a vararg-packing method handle.
return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType);
} else {
// Call site signature makes no guarantees that the single argument in the vararg position will be
// compatible across all invocations. Need to insert an appropriate guard and fall back to generic
// vararg method when it is not.
return MethodHandles.guardWithTest(Guards.isInstance(varArgType, fixParamsLen, callSiteType),
createConvertingInvocation(fixTarget, linkerServices, callSiteType),
createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType));
}
} else {
// Remaining case: more than one vararg.
return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType);
// Call site signature makes no guarantees that the single argument in the vararg position will be
// compatible across all invocations. Need to insert an appropriate guard and fall back to generic vararg
// method when it is not.
return MethodHandles.guardWithTest(Guards.isInstance(varArgType, fixParamsLen, callSiteType),
createConvertingInvocation(fixTarget, linkerServices, callSiteType),
createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType));
}
// Remaining case: more than one vararg.
return createConvertingInvocation(collectArguments(fixTarget, argsLen), linkerServices, callSiteType);
}
@Override
@ -238,4 +236,4 @@ class SimpleDynamicMethod extends DynamicMethod {
final LinkerServices linkerServices, final MethodType callSiteType) {
return linkerServices.asType(sizedMethod, callSiteType);
}
}
}

View File

@ -135,4 +135,4 @@ public class StaticClass implements Serializable {
private Object readResolve() {
return forClass(clazz);
}
}
}

View File

@ -99,7 +99,6 @@ import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.Lookup;
/**
* Provides a linker for the {@link StaticClass} objects.
* @author Attila Szegedi
@ -201,4 +200,4 @@ class StaticClassLinker implements TypeBasedGuardingDynamicLinker {
private static boolean isClass(Class<?> clazz, Object obj) {
return obj instanceof StaticClass && ((StaticClass)obj).getRepresentedClass() == clazz;
}
}
}

View File

@ -92,7 +92,6 @@ import java.util.List;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.support.Guards;
/**
* Represents a conditionally valid method handle. It is an immutable triple of an invocation method handle, a guard
* method handle that defines the applicability of the invocation handle, and a switch point that can be used for
@ -312,4 +311,4 @@ public class GuardedInvocation {
throw new WrongMethodTypeException("Expected type: " + type + " actual type: " + mh.type());
}
}
}
}

View File

@ -109,4 +109,4 @@ public interface GuardingDynamicLinker {
*/
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices)
throws Exception;
}
}

View File

@ -111,4 +111,4 @@ public interface GuardingTypeConverterFactory {
* @throws Exception if there was an error during creation of the converter
*/
public GuardedInvocation convertToType(Class<?> sourceType, Class<?> targetType) throws Exception;
}
}

View File

@ -146,4 +146,4 @@ public interface LinkRequest {
* specified ones.
*/
public LinkRequest replaceArguments(CallSiteDescriptor callSiteDescriptor, Object[] arguments);
}
}

View File

@ -89,7 +89,6 @@ import java.lang.invoke.MethodType;
import jdk.internal.dynalink.DynamicLinker;
import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
/**
* Interface for services provided to {@link GuardingDynamicLinker} instances by the {@link DynamicLinker} that owns
* them. You can think of it as the interface of the {@link DynamicLinker} that faces the {@link GuardingDynamicLinker}
@ -162,4 +161,4 @@ public interface LinkerServices {
* conversion.
*/
public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2);
}
}

View File

@ -88,7 +88,6 @@ import java.lang.invoke.MethodHandles.Lookup;
import java.util.Objects;
import jdk.internal.dynalink.CallSiteDescriptor;
/**
* A base class for call site descriptor implementations. Provides reconstruction of the name from the tokens, as well
* as a generally useful {@code equals} and {@code hashCode} methods.

View File

@ -88,7 +88,6 @@ import java.lang.invoke.MutableCallSite;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.RelinkableCallSite;
/**
* A basic implementation of the {@link RelinkableCallSite} as a {@link MutableCallSite} subclass.
*
@ -115,4 +114,4 @@ public abstract class AbstractRelinkableCallSite extends MutableCallSite impleme
public void initialize(MethodHandle relinkAndInvoke) {
setTarget(relinkAndInvoke);
}
}
}

View File

@ -89,7 +89,6 @@ import java.util.ServiceLoader;
import jdk.internal.dynalink.DynamicLinkerFactory;
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
/**
* Provides methods for automatic discovery of all guarding dynamic linkers listed in the
* <tt>/META-INF/services/jdk.internal.dynalink.linker.GuardingDynamicLinker</tt> resources of all JAR files for a
@ -131,4 +130,4 @@ public class AutoDiscovery {
}
return list;
}
}
}

View File

@ -113,4 +113,4 @@ public class BottomGuardingDynamicLinker implements TypeBasedGuardingDynamicLink
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) {
return null;
}
}
}

View File

@ -94,7 +94,6 @@ import java.util.StringTokenizer;
import java.util.WeakHashMap;
import jdk.internal.dynalink.CallSiteDescriptor;
/**
* Usable as a default factory for call site descriptor implementations. It is weakly canonicalizing, meaning it will
* return the same immutable call site descriptor for identical inputs, i.e. repeated requests for a descriptor
@ -129,9 +128,8 @@ public class CallSiteDescriptorFactory {
final String[] tokenizedName = tokenizeName(name);
if(isPublicLookup(lookup)) {
return getCanonicalPublicDescriptor(createPublicCallSiteDescriptor(tokenizedName, methodType));
} else {
return new LookupCallSiteDescriptor(tokenizedName, methodType, lookup);
}
return new LookupCallSiteDescriptor(tokenizedName, methodType, lookup);
}
static CallSiteDescriptor getCanonicalPublicDescriptor(final CallSiteDescriptor desc) {
@ -262,4 +260,4 @@ public class CallSiteDescriptorFactory {
public static CallSiteDescriptor insertParameterTypes(CallSiteDescriptor desc, int num, List<Class<?>> ptypesToInsert) {
return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert));
}
}
}

View File

@ -91,7 +91,6 @@ import jdk.internal.dynalink.linker.GuardingDynamicLinker;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
/**
* A {@link GuardingDynamicLinker} that delegates sequentially to a list of other guarding dynamic linkers. The first
* value returned from a component linker other than null is returned. If no component linker returns an invocation,
@ -129,4 +128,4 @@ public class CompositeGuardingDynamicLinker implements GuardingDynamicLinker, Se
}
return null;
}
}
}

View File

@ -93,7 +93,6 @@ import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
/**
* A composite type-based guarding dynamic linker. When a receiver of a not yet seen class is encountered, all linkers
* are queried sequentially on their {@link TypeBasedGuardingDynamicLinker#canLinkType(Class)} method. The linkers
@ -223,4 +222,4 @@ public class CompositeTypeBasedGuardingDynamicLinker implements TypeBasedGuardin
}
}
}
}
}

View File

@ -87,7 +87,6 @@ import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.CallSiteDescriptor;
/**
* A default, fairly light implementation of a call site descriptor used for describing non-standard operations. It does
* not store {@link Lookup} objects but always returns the public lookup from its {@link #getLookup()} method. If you

View File

@ -90,7 +90,6 @@ import java.util.logging.Level;
import java.util.logging.Logger;
import jdk.internal.dynalink.linker.LinkerServices;
/**
* Utility methods for creating typical guards. TODO: introduce reasonable caching of created guards.
*
@ -357,4 +356,4 @@ public class Guards {
return MethodHandles.permuteArguments(MethodHandles.constant(Boolean.TYPE, value),
type.changeReturnType(Boolean.TYPE));
}
}
}

View File

@ -140,4 +140,4 @@ public class LinkRequestImpl implements LinkRequest {
public LinkRequest replaceArguments(CallSiteDescriptor newCallSiteDescriptor, Object[] newArguments) {
return new LinkRequestImpl(newCallSiteDescriptor, callSiteUnstable, newArguments);
}
}
}

View File

@ -91,7 +91,6 @@ import jdk.internal.dynalink.linker.GuardingDynamicLinker;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
/**
* Default implementation of the {@link LinkerServices} interface.
*
@ -138,4 +137,4 @@ public class LinkerServicesImpl implements LinkerServices {
public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest) throws Exception {
return topLevelLinker.getGuardedInvocation(linkRequest, this);
}
}
}

View File

@ -231,9 +231,8 @@ public class Lookup {
m.setAccessible(true);
}
return unreflect(m);
} else {
return lookup.findSpecial(declaringClass, name, type, declaringClass);
}
return lookup.findSpecial(declaringClass, name, type, declaringClass);
} catch(IllegalAccessException e) {
final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription(
declaringClass, name, type));

View File

@ -87,7 +87,6 @@ import java.lang.invoke.MethodHandles.Lookup;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.CallSiteDescriptor;
/**
* A call site descriptor that stores a specific {@link Lookup}. It does not, however, store static bootstrap arguments.
* @author Attila Szegedi

View File

@ -86,7 +86,6 @@ package jdk.internal.dynalink.support;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.CallSiteDescriptor;
class NamedDynCallSiteDescriptor extends UnnamedDynCallSiteDescriptor {
private final String name;

View File

@ -139,4 +139,4 @@ public class RuntimeContextLinkRequestImpl extends LinkRequestImpl {
System.arraycopy(args, runtimeContextArgCount + 1, newargs, 1, newargs.length - 1);
return newargs;
}
}
}

View File

@ -95,7 +95,6 @@ import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkerServices;
/**
* A factory for type converters. This class is the main implementation behind the
* {@link LinkerServices#asType(MethodHandle, MethodType)}. It manages the known {@link GuardingTypeConverterFactory}
@ -317,4 +316,4 @@ public class TypeConverterFactory {
}
/*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class);
}
}

View File

@ -439,4 +439,4 @@ public class TypeUtilities {
public static Class<?> getWrapperType(Class<?> primitiveType) {
return WRAPPER_TYPES.get(primitiveType);
}
}
}

View File

@ -86,7 +86,6 @@ package jdk.internal.dynalink.support;
import java.lang.invoke.MethodType;
import jdk.internal.dynalink.CallSiteDescriptor;
class UnnamedDynCallSiteDescriptor extends AbstractCallSiteDescriptor {
private final MethodType methodType;
private final String op;

View File

@ -7,6 +7,7 @@ import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.FINALIZED;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.INITIALIZED;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOWERED;
import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@ -15,9 +16,9 @@ import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.ir.debug.ASTWriter;
import jdk.nashorn.internal.ir.debug.PrintVisitor;
import jdk.nashorn.internal.ir.visitor.NodeVisitor;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ECMAErrors;

View File

@ -25,6 +25,8 @@
package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
import java.lang.invoke.MethodType;
import java.util.ArrayList;
import java.util.List;
@ -34,8 +36,6 @@ import jdk.nashorn.internal.ir.Node;
import jdk.nashorn.internal.runtime.ScriptFunction;
import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
/**
* Class that generates function signatures for dynamic calls
*/

View File

@ -36,7 +36,6 @@ import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
import jdk.nashorn.internal.codegen.CompileUnit;
import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.Frame;

View File

@ -28,7 +28,6 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import jdk.nashorn.internal.runtime.GlobalFunctions;
import jdk.nashorn.internal.runtime.Property;
import jdk.nashorn.internal.runtime.PropertyMap;

View File

@ -1,12 +1,10 @@
package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
import jdk.nashorn.internal.codegen.Compiler;
import jdk.nashorn.internal.codegen.FunctionSignature;
import jdk.nashorn.internal.codegen.types.Type;

View File

@ -59,7 +59,6 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.codegen.Namespace;
import jdk.nashorn.internal.ir.AccessNode;
@ -101,8 +100,8 @@ import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.JSErrorType;
import jdk.nashorn.internal.runtime.ParserException;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.ScriptingFunctions;
import jdk.nashorn.internal.runtime.Source;
/**
* Builds the IR.

View File

@ -45,7 +45,6 @@ import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.util.Locale;
import java.util.TimeZone;
import jdk.internal.org.objectweb.asm.ClassReader;
import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
import jdk.nashorn.internal.codegen.ClassEmitter;

View File

@ -31,6 +31,7 @@ import static jdk.nashorn.internal.runtime.linker.Lookup.MH;
import java.lang.invoke.MethodHandle;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.beans.BeansLinker;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
import jdk.internal.dynalink.linker.LinkRequest;
@ -78,14 +79,14 @@ class NashornBottomLinker implements GuardingDynamicLinker {
final String operator = desc.getFirstOperator();
switch (operator) {
case "new":
if(isJavaDynamicMethod(self)) {
if(BeansLinker.isDynamicMethod(self)) {
typeError("method.not.constructor", ScriptRuntime.safeToString(self));
} else {
typeError("not.a.function", ScriptRuntime.safeToString(self));
}
break;
case "call":
if(isJavaDynamicMethod(self)) {
if(BeansLinker.isDynamicMethod(self)) {
typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
} else {
typeError("not.a.function", ScriptRuntime.safeToString(self));
@ -113,16 +114,6 @@ class NashornBottomLinker implements GuardingDynamicLinker {
throw new AssertionError("unknown call type " + desc);
}
/**
* Returns true if the object is a Dynalink dynamic method. Unfortunately, the dynamic method classes are package
* private in Dynalink, so this is the closest we can get to determining it.
* @param obj the object we want to test for being a dynamic method
* @return true if it is a dynamic method, false otherwise.
*/
private static boolean isJavaDynamicMethod(Object obj) {
return obj.getClass().getName().endsWith("DynamicMethod");
}
private static GuardedInvocation getInvocation(final MethodHandle handle, final Object self, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
return Bootstrap.asType(new GuardedInvocation(handle, Guards.getClassGuard(self.getClass())), linkerServices, desc);
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* Expect TypeError on wrong Java method invocations.
*
* @test
* @run
*/
var Exit = java.lang.System.exit;
// Try to invoke it as constructor
try {
new Exit();
fail("Should have thrown TypeError");
} catch (e) {
if (! (e instanceof TypeError)) {
fail("TypeError expected, got " + e);
}
}
// Try to invoke with wrong number of args
try {
Exit(33, 44);
fail("Should have thrown TypeError");
} catch (e) {
if (! (e instanceof TypeError)) {
fail("TypeError expected, got " + e);
}
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* JSObject tests
*
* @test
* @run
*/
var m = new javax.script.ScriptEngineManager();
var e = m.getEngineByName("nashorn");
e.eval("obj = { foo:'hello', 0: 'world', func: function(x) { return x.toUpperCase() } } ");
var obj = e.get("obj");
// try various getters
if (obj.foo != 'hello') {
fail("obj.foo does have expected value");
}
function checkPropGetter(obj, prop, expected) {
if (obj[prop] != expected) {
fail(prop + " does not have value: " + expected);
}
}
checkPropGetter(obj, "foo", "hello");
checkPropGetter(obj, 0, "world");
checkPropGetter(obj, "0", "world");
// try various setters
obj.foo = "HELLO";
if (obj.foo != "HELLO") {
fail("obj.foo set does not work as expected");
}
function checkPropSetter(obj, prop, newValue) {
obj[prop] = newValue;
checkPropGetter(obj, prop, newValue);
}
checkPropSetter(obj, "foo", "NASHORN");
checkPropSetter(obj, 0, "ECMASCRIPT");
checkPropSetter(obj, "0", "CHANGED");
function callFunc(input, expected) {
if (obj.func(input) != expected) {
fail("obj.func(..) does not work as expected");
}
}
callFunc("nashorn", "NASHORN");
callFunc("javascript", "JAVASCRIPT");
callFunc("hello", "HELLO");
var Func = obj.func;
function callWithoutObject(input, expected) {
if (Func(input) != expected) {
fail("obj.func(..) does not work as expected");
}
}
callWithoutObject("nashorn", "NASHORN");
callWithoutObject("javascript", "JAVASCRIPT");
callWithoutObject("hello", "HELLO");