src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
changeset 48354 c96d4c720995
parent 47216 71c04702a3d5
equal deleted inserted replaced
48353:315c690bb90b 48354:c96d4c720995
    37 import java.util.function.Supplier;
    37 import java.util.function.Supplier;
    38 import jdk.dynalink.CallSiteDescriptor;
    38 import jdk.dynalink.CallSiteDescriptor;
    39 import jdk.dynalink.NamedOperation;
    39 import jdk.dynalink.NamedOperation;
    40 import jdk.dynalink.Operation;
    40 import jdk.dynalink.Operation;
    41 import jdk.dynalink.beans.BeansLinker;
    41 import jdk.dynalink.beans.BeansLinker;
       
    42 import jdk.dynalink.beans.StaticClass;
    42 import jdk.dynalink.linker.GuardedInvocation;
    43 import jdk.dynalink.linker.GuardedInvocation;
    43 import jdk.dynalink.linker.GuardingDynamicLinker;
    44 import jdk.dynalink.linker.GuardingDynamicLinker;
    44 import jdk.dynalink.linker.GuardingTypeConverterFactory;
    45 import jdk.dynalink.linker.GuardingTypeConverterFactory;
    45 import jdk.dynalink.linker.LinkRequest;
    46 import jdk.dynalink.linker.LinkRequest;
    46 import jdk.dynalink.linker.LinkerServices;
    47 import jdk.dynalink.linker.LinkerServices;
       
    48 import jdk.dynalink.linker.support.Guards;
    47 import jdk.dynalink.linker.support.Lookup;
    49 import jdk.dynalink.linker.support.Lookup;
    48 import jdk.nashorn.internal.codegen.types.Type;
    50 import jdk.nashorn.internal.codegen.types.Type;
    49 import jdk.nashorn.internal.runtime.ECMAException;
    51 import jdk.nashorn.internal.runtime.ECMAException;
    50 import jdk.nashorn.internal.runtime.JSType;
    52 import jdk.nashorn.internal.runtime.JSType;
    51 import jdk.nashorn.internal.runtime.ScriptRuntime;
    53 import jdk.nashorn.internal.runtime.ScriptRuntime;
    84             MH.asType(EMPTY_ELEM_GETTER, EMPTY_ELEM_GETTER.type().changeReturnType(void.class));
    86             MH.asType(EMPTY_ELEM_GETTER, EMPTY_ELEM_GETTER.type().changeReturnType(void.class));
    85     private static final MethodHandle EMPTY_ELEM_SETTER =
    87     private static final MethodHandle EMPTY_ELEM_SETTER =
    86             MH.dropArguments(EMPTY_PROP_SETTER, 0, Object.class);
    88             MH.dropArguments(EMPTY_PROP_SETTER, 0, Object.class);
    87 
    89 
    88     private static final MethodHandle THROW_STRICT_PROPERTY_SETTER;
    90     private static final MethodHandle THROW_STRICT_PROPERTY_SETTER;
       
    91     private static final MethodHandle THROW_STRICT_PROPERTY_REMOVER;
    89     private static final MethodHandle THROW_OPTIMISTIC_UNDEFINED;
    92     private static final MethodHandle THROW_OPTIMISTIC_UNDEFINED;
       
    93     private static final MethodHandle MISSING_PROPERTY_REMOVER;
    90 
    94 
    91     static {
    95     static {
    92         final Lookup lookup = new Lookup(MethodHandles.lookup());
    96         final Lookup lookup = new Lookup(MethodHandles.lookup());
    93         THROW_STRICT_PROPERTY_SETTER = lookup.findOwnStatic("throwStrictPropertySetter", void.class, Object.class, Object.class);
    97         THROW_STRICT_PROPERTY_SETTER = lookup.findOwnStatic("throwStrictPropertySetter", void.class, Object.class, Object.class);
       
    98         THROW_STRICT_PROPERTY_REMOVER = lookup.findOwnStatic("throwStrictPropertyRemover", boolean.class, Object.class, Object.class);
    94         THROW_OPTIMISTIC_UNDEFINED = lookup.findOwnStatic("throwOptimisticUndefined", Object.class, int.class);
    99         THROW_OPTIMISTIC_UNDEFINED = lookup.findOwnStatic("throwOptimisticUndefined", Object.class, int.class);
       
   100         MISSING_PROPERTY_REMOVER = lookup.findOwnStatic("missingPropertyRemover", boolean.class, Object.class, Object.class);
    95     }
   101     }
    96 
   102 
    97     private static GuardedInvocation linkBean(final LinkRequest linkRequest) throws Exception {
   103     private static GuardedInvocation linkBean(final LinkRequest linkRequest) throws Exception {
    98         final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
   104         final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
    99         final Object self = linkRequest.getReceiver();
   105         final Object self = linkRequest.getReceiver();
   122     }
   128     }
   123 
   129 
   124     static MethodHandle linkMissingBeanMember(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
   130     static MethodHandle linkMissingBeanMember(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
   125         final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
   131         final CallSiteDescriptor desc = linkRequest.getCallSiteDescriptor();
   126         final String operand = NashornCallSiteDescriptor.getOperand(desc);
   132         final String operand = NashornCallSiteDescriptor.getOperand(desc);
       
   133         final boolean strict = NashornCallSiteDescriptor.isStrict(desc);
   127         switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
   134         switch (NashornCallSiteDescriptor.getStandardOperation(desc)) {
   128         case GET:
   135         case GET:
   129             if (NashornCallSiteDescriptor.isOptimistic(desc)) {
   136             if (NashornCallSiteDescriptor.isOptimistic(desc)) {
   130                 return adaptThrower(MethodHandles.insertArguments(THROW_OPTIMISTIC_UNDEFINED, 0, NashornCallSiteDescriptor.getProgramPoint(desc)), desc);
   137                 return adaptThrower(MethodHandles.insertArguments(THROW_OPTIMISTIC_UNDEFINED, 0, NashornCallSiteDescriptor.getProgramPoint(desc)), desc);
   131             } else if (operand != null) {
   138             } else if (operand != null) {
   132                 return getInvocation(EMPTY_PROP_GETTER, linkerServices, desc);
   139                 return getInvocation(EMPTY_PROP_GETTER, linkerServices, desc);
   133             }
   140             }
   134             return getInvocation(EMPTY_ELEM_GETTER, linkerServices, desc);
   141             return getInvocation(EMPTY_ELEM_GETTER, linkerServices, desc);
   135         case SET:
   142         case SET:
   136             final boolean strict = NashornCallSiteDescriptor.isStrict(desc);
       
   137             if (strict) {
   143             if (strict) {
   138                 return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_SETTER, operand), desc);
   144                 return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_SETTER, operand), desc);
   139             } else if (operand != null) {
   145             } else if (operand != null) {
   140                 return getInvocation(EMPTY_PROP_SETTER, linkerServices, desc);
   146                 return getInvocation(EMPTY_PROP_SETTER, linkerServices, desc);
   141             }
   147             }
   142             return getInvocation(EMPTY_ELEM_SETTER, linkerServices, desc);
   148             return getInvocation(EMPTY_ELEM_SETTER, linkerServices, desc);
       
   149         case REMOVE:
       
   150             if (strict) {
       
   151                 return adaptThrower(bindOperand(THROW_STRICT_PROPERTY_REMOVER, operand), desc);
       
   152             }
       
   153             return getInvocation(bindOperand(MISSING_PROPERTY_REMOVER, operand), linkerServices, desc);
   143         default:
   154         default:
   144             throw new AssertionError("unknown call type " + desc);
   155             throw new AssertionError("unknown call type " + desc);
   145         }
   156         }
   146     }
   157     }
   147 
   158 
   158     }
   169     }
   159 
   170 
   160     @SuppressWarnings("unused")
   171     @SuppressWarnings("unused")
   161     private static void throwStrictPropertySetter(final Object self, final Object name) {
   172     private static void throwStrictPropertySetter(final Object self, final Object name) {
   162         throw createTypeError(self, name, "cant.set.property");
   173         throw createTypeError(self, name, "cant.set.property");
       
   174     }
       
   175 
       
   176     @SuppressWarnings("unused")
       
   177     private static boolean throwStrictPropertyRemover(final Object self, final Object name) {
       
   178         if (isNonConfigurableProperty(self, name)) {
       
   179             throw createTypeError(self, name, "cant.delete.property");
       
   180         }
       
   181         return true;
       
   182     }
       
   183 
       
   184     @SuppressWarnings("unused")
       
   185     private static boolean missingPropertyRemover(final Object self, final Object name) {
       
   186         return !isNonConfigurableProperty(self, name);
       
   187     }
       
   188 
       
   189     // Corresponds to ECMAScript 5.1 8.12.7 [[Delete]] point 3 check for "isConfigurable" (but negated)
       
   190     private static boolean isNonConfigurableProperty(final Object self, final Object name) {
       
   191         if (self instanceof StaticClass) {
       
   192             final Class<?> clazz = ((StaticClass)self).getRepresentedClass();
       
   193             return BeansLinker.getReadableStaticPropertyNames(clazz).contains(name) ||
       
   194                    BeansLinker.getWritableStaticPropertyNames(clazz).contains(name) ||
       
   195                    BeansLinker.getStaticMethodNames(clazz).contains(name);
       
   196         }
       
   197         final Class<?> clazz = self.getClass();
       
   198         return BeansLinker.getReadableInstancePropertyNames(clazz).contains(name) ||
       
   199             BeansLinker.getWritableInstancePropertyNames(clazz).contains(name) ||
       
   200             BeansLinker.getInstanceMethodNames(clazz).contains(name);
   163     }
   201     }
   164 
   202 
   165     private static ECMAException createTypeError(final Object self, final Object name, final String msg) {
   203     private static ECMAException createTypeError(final Object self, final Object name, final String msg) {
   166         return typeError(msg, String.valueOf(name), ScriptRuntime.safeToString(self));
   204         return typeError(msg, String.valueOf(name), ScriptRuntime.safeToString(self));
   167     }
   205     }
   213             throw typeError("not.a.function", "null");
   251             throw typeError("not.a.function", "null");
   214         case GET:
   252         case GET:
   215             throw typeError(NashornCallSiteDescriptor.isMethodFirstOperation(desc) ? "no.such.function" : "cant.get.property", getArgument(linkRequest), "null");
   253             throw typeError(NashornCallSiteDescriptor.isMethodFirstOperation(desc) ? "no.such.function" : "cant.get.property", getArgument(linkRequest), "null");
   216         case SET:
   254         case SET:
   217             throw typeError("cant.set.property", getArgument(linkRequest), "null");
   255             throw typeError("cant.set.property", getArgument(linkRequest), "null");
       
   256         case REMOVE:
       
   257             throw typeError("cant.delete.property", getArgument(linkRequest), "null");
   218         default:
   258         default:
   219             throw new AssertionError("unknown call type " + desc);
   259             throw new AssertionError("unknown call type " + desc);
   220         }
   260         }
   221     }
   261     }
   222 
   262