< prev index next >

src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java

Print this page


   1 /*
   2  * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


1231     public final ScriptObject getProto(final int n) {
1232         assert n > 0;
1233         ScriptObject p = getProto();
1234         for (int i = n; --i > 0;) {
1235             p = p.getProto();
1236         }
1237         return p;
1238     }
1239 
1240     /**
1241      * Set the __proto__ of an object.
1242      * @param newProto new __proto__ to set.
1243      */
1244     public final void setProto(final ScriptObject newProto) {
1245         final ScriptObject oldProto = proto;
1246 
1247         if (oldProto != newProto) {
1248             proto = newProto;
1249 
1250             // Let current listeners know that the prototype has changed
1251             getMap().protoChanged(true);
1252             // Replace our current allocator map with one that is associated with the new prototype.
1253             setMap(getMap().changeProto(newProto));
1254         }
1255     }
1256 
1257     /**
1258      * Set the initial __proto__ of this object. This should be used instead of
1259      * {@link #setProto} if it is known that the current property map will not be
1260      * used on a new object with any other parent property map, so we can pass over
1261      * property map invalidation/evolution.
1262      *
1263      * @param initialProto the initial __proto__ to set.
1264      */
1265     public void setInitialProto(final ScriptObject initialProto) {
1266         this.proto = initialProto;
1267     }
1268 
1269     /**
1270      * Invoked from generated bytecode to initialize the prototype of object literals to the global Object prototype.
1271      * @param obj the object literal that needs to have its prototype initialized to the global Object prototype.


2090      * @param returnType     return type for getter
2091      * @param name           name
2092      * @param elementType    index type for getter
2093      * @param desc           call site descriptor
2094      * @return method handle for getter
2095      */
2096     private static MethodHandle findGetIndexMethodHandle(final Class<?> returnType, final String name, final Class<?> elementType, final CallSiteDescriptor desc) {
2097         if (!returnType.isPrimitive()) {
2098             return findOwnMH_V(name, returnType, elementType);
2099         }
2100 
2101         return MH.insertArguments(
2102                 findOwnMH_V(name, returnType, elementType, int.class),
2103                 2,
2104                 NashornCallSiteDescriptor.isOptimistic(desc) ?
2105                         NashornCallSiteDescriptor.getProgramPoint(desc) :
2106                         INVALID_PROGRAM_POINT);
2107     }
2108 
2109     /**
2110      * Get a switch point for a property with the given {@code name} that will be invalidated when
2111      * the property definition is changed in this object's prototype chain. Returns {@code null} if
2112      * the property is defined in this object itself.
2113      *
2114      * @param name the property name
2115      * @param owner the property owner, null if property is not defined
2116      * @return a SwitchPoint or null
2117      */
2118     public final SwitchPoint[] getProtoSwitchPoints(final String name, final ScriptObject owner) {
2119         if (owner == this || getProto() == null) {
2120             return null;
2121         }
2122 
2123         final List<SwitchPoint> switchPoints = new ArrayList<>();




2124         for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
2125             final ScriptObject parent = obj.getProto();
2126             parent.getMap().addListener(name, obj.getMap());
2127             final SwitchPoint sp = parent.getMap().getSharedProtoSwitchPoint();
2128             if (sp != null && !sp.hasBeenInvalidated()) {
2129                 switchPoints.add(sp);





2130             }
2131         }
2132 
2133         switchPoints.add(getMap().getSwitchPoint(name));
2134         return switchPoints.toArray(new SwitchPoint[0]);
2135     }
2136 
2137     // Similar to getProtoSwitchPoints method above, but used for additional prototype switchpoints of
2138     // properties that are known not to exist, e.g. the original property name in a __noSuchProperty__ invocation.
2139     final SwitchPoint getProtoSwitchPoint(final String name) {
2140         if (getProto() == null) {
2141             return null;
2142         }
2143 




2144         for (ScriptObject obj = this; obj.getProto() != null; obj = obj.getProto()) {
2145             final ScriptObject parent = obj.getProto();
2146             parent.getMap().addListener(name, obj.getMap());
2147         }
2148 
2149         return getMap().getSwitchPoint(name);
2150     }
2151 
2152     private void checkSharedProtoMap() {
2153         // Check if our map has an expected shared prototype property map. If it has, make sure that
2154         // the prototype map has not been invalidated, and that it does match the actual map of the prototype.
2155         if (getMap().isInvalidSharedMapFor(getProto())) {
2156             // Change our own map to one that does not assume a shared prototype map.
2157             setMap(getMap().makeUnsharedCopy());
2158         }
2159     }
2160 
2161     /**
2162      * Find the appropriate SET method for an invoke dynamic call.
2163      *
2164      * @param desc    the call site descriptor
2165      * @param request the link request
2166      *
2167      * @return GuardedInvocation to be invoked at call site.
2168      */
2169     protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {


   1 /*
   2  * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


1231     public final ScriptObject getProto(final int n) {
1232         assert n > 0;
1233         ScriptObject p = getProto();
1234         for (int i = n; --i > 0;) {
1235             p = p.getProto();
1236         }
1237         return p;
1238     }
1239 
1240     /**
1241      * Set the __proto__ of an object.
1242      * @param newProto new __proto__ to set.
1243      */
1244     public final void setProto(final ScriptObject newProto) {
1245         final ScriptObject oldProto = proto;
1246 
1247         if (oldProto != newProto) {
1248             proto = newProto;
1249 
1250             // Let current listeners know that the prototype has changed
1251             getMap().protoChanged();
1252             // Replace our current allocator map with one that is associated with the new prototype.
1253             setMap(getMap().changeProto(newProto));
1254         }
1255     }
1256 
1257     /**
1258      * Set the initial __proto__ of this object. This should be used instead of
1259      * {@link #setProto} if it is known that the current property map will not be
1260      * used on a new object with any other parent property map, so we can pass over
1261      * property map invalidation/evolution.
1262      *
1263      * @param initialProto the initial __proto__ to set.
1264      */
1265     public void setInitialProto(final ScriptObject initialProto) {
1266         this.proto = initialProto;
1267     }
1268 
1269     /**
1270      * Invoked from generated bytecode to initialize the prototype of object literals to the global Object prototype.
1271      * @param obj the object literal that needs to have its prototype initialized to the global Object prototype.


2090      * @param returnType     return type for getter
2091      * @param name           name
2092      * @param elementType    index type for getter
2093      * @param desc           call site descriptor
2094      * @return method handle for getter
2095      */
2096     private static MethodHandle findGetIndexMethodHandle(final Class<?> returnType, final String name, final Class<?> elementType, final CallSiteDescriptor desc) {
2097         if (!returnType.isPrimitive()) {
2098             return findOwnMH_V(name, returnType, elementType);
2099         }
2100 
2101         return MH.insertArguments(
2102                 findOwnMH_V(name, returnType, elementType, int.class),
2103                 2,
2104                 NashornCallSiteDescriptor.isOptimistic(desc) ?
2105                         NashornCallSiteDescriptor.getProgramPoint(desc) :
2106                         INVALID_PROGRAM_POINT);
2107     }
2108 
2109     /**
2110      * Get an array of switch points for a property with the given {@code name} that will be
2111      * invalidated when the property definition is changed in this object's prototype chain.
2112      * Returns {@code null} if the property is defined in this object itself.
2113      *
2114      * @param name the property name
2115      * @param owner the property owner, null if property is not defined
2116      * @return an array of SwitchPoints or null
2117      */
2118     public final SwitchPoint[] getProtoSwitchPoints(final String name, final ScriptObject owner) {
2119         if (owner == this || getProto() == null) {
2120             return null;
2121         }
2122 
2123         final Set<SwitchPoint> switchPoints = new HashSet<>();
2124         SwitchPoint switchPoint = getProto().getMap().getSwitchPoint(name);
2125 
2126         if (switchPoint == null) {
2127             switchPoint = new SwitchPoint();
2128             for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
2129                 obj.getProto().getMap().addSwitchPoint(name, switchPoint);
2130             }
2131         }
2132 
2133         switchPoints.add(switchPoint);
2134 
2135         for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
2136             final SwitchPoint sharedProtoSwitchPoint = obj.getProto().getMap().getSharedProtoSwitchPoint();
2137             if (sharedProtoSwitchPoint != null && !sharedProtoSwitchPoint.hasBeenInvalidated()) {
2138                 switchPoints.add(sharedProtoSwitchPoint);
2139             }
2140         }
2141 

2142         return switchPoints.toArray(new SwitchPoint[0]);
2143     }
2144 
2145     // Similar to getProtoSwitchPoints method above, but used for additional prototype switchpoints of
2146     // properties that are known not to exist, e.g. the original property name in a __noSuchProperty__ invocation.
2147     final SwitchPoint getProtoSwitchPoint(final String name) {
2148         if (getProto() == null) {
2149             return null;
2150         }
2151 
2152         SwitchPoint switchPoint = getProto().getMap().getSwitchPoint(name);
2153 
2154         if (switchPoint == null) {
2155             switchPoint = new SwitchPoint();
2156             for (ScriptObject obj = this; obj.getProto() != null; obj = obj.getProto()) {
2157                 obj.getProto().getMap().addSwitchPoint(name, switchPoint);
2158             }
2159         }
2160 
2161         return switchPoint;
2162     }
2163 
2164     private void checkSharedProtoMap() {
2165         // Check if our map has an expected shared prototype property map. If it has, make sure that
2166         // the prototype map has not been invalidated, and that it does match the actual map of the prototype.
2167         if (getMap().isInvalidSharedMapFor(getProto())) {
2168             // Change our own map to one that does not assume a shared prototype map.
2169             setMap(getMap().makeUnsharedCopy());
2170         }
2171     }
2172 
2173     /**
2174      * Find the appropriate SET method for an invoke dynamic call.
2175      *
2176      * @param desc    the call site descriptor
2177      * @param request the link request
2178      *
2179      * @return GuardedInvocation to be invoked at call site.
2180      */
2181     protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {


< prev index next >