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) {
|