< prev index next >

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

Print this page




  92  * <li>If the map is modified then it must be cloned and replaced.  This notifies
  93  *     any code that made assumptions about the object that things have changed.
  94  *     Ex. CallSites that have been validated must check to see if the map has
  95  *     changed (or a map from a different object type) and hence relink the method
  96  *     to call.</li>
  97  * <li>Modifications of the map include adding/deleting attributes or changing a
  98  *     function field value.</li>
  99  * </ul>
 100  */
 101 
 102 public abstract class ScriptObject implements PropertyAccess, Cloneable {
 103     /** __proto__ special property name inside object literals. ES6 draft. */
 104     public static final String PROTO_PROPERTY_NAME   = "__proto__";
 105 
 106     /** Search fall back routine name for "no such method" */
 107     public static final String NO_SUCH_METHOD_NAME   = "__noSuchMethod__";
 108 
 109     /** Search fall back routine name for "no such property" */
 110     public static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
 111 
 112     /** Per ScriptObject flag - is this a scope object? */
 113     public static final int IS_SCOPE       = 1 << 0;
 114 
 115     /** Per ScriptObject flag - is this an array object? */
 116     public static final int IS_ARRAY       = 1 << 1;
 117 
 118     /** Per ScriptObject flag - is this an arguments object? */
 119     public static final int IS_ARGUMENTS   = 1 << 2;
 120 
 121     /** Is length property not-writable? */
 122     public static final int IS_LENGTH_NOT_WRITABLE = 1 << 3;
 123 
 124     /** Is this a builtin object? */
 125     public static final int IS_BUILTIN = 1 << 4;
 126 
 127     /**
 128      * Spill growth rate - by how many elements does {@link ScriptObject#primitiveSpill} and
 129      * {@link ScriptObject#objectSpill} when full
 130      */
 131     public static final int SPILL_RATE = 8;
 132 
 133     /** Map to property information and accessor functions. Ordered by insertion. */
 134     private PropertyMap map;
 135 
 136     /** objects proto. */
 137     private ScriptObject proto;
 138 
 139     /** Object flags. */
 140     private int flags;
 141 
 142     /** Area for primitive properties added to object after instantiation, see {@link AccessorProperty} */
 143     protected long[]   primitiveSpill;
 144 
 145     /** Area for reference properties added to object after instantiation, see {@link AccessorProperty} */


1613         while (true) {
1614             final PropertyMap newMap = getMap().freeze();
1615 
1616             if (!compareAndSetMap(oldMap, newMap)) {
1617                 oldMap = getMap();
1618             } else {
1619                 setArray(ArrayData.freeze(getArray()));
1620                 return this;
1621             }
1622         }
1623     }
1624 
1625     /**
1626      * Check whether this ScriptObject is frozen
1627      * @return true if frozen
1628      */
1629     public boolean isFrozen() {
1630         return getMap().isFrozen();
1631     }
1632 
1633 
1634     /**
1635      * Flag this ScriptObject as scope
1636      */
1637     public final void setIsScope() {
1638         if (Context.DEBUG) {
1639             scopeCount++;
1640         }
1641         flags |= IS_SCOPE;
1642     }
1643 
1644     /**
1645      * Check whether this ScriptObject is scope
1646      * @return true if scope
1647      */
1648     public final boolean isScope() {
1649         return (flags & IS_SCOPE) != 0;
1650     }
1651 
1652     /**
1653      * Tag this script object as built in
1654      */
1655     public final void setIsBuiltin() {
1656         flags |= IS_BUILTIN;
1657     }
1658 
1659     /**
1660      * Check if this script object is built in
1661      * @return true if build in
1662      */
1663     public final boolean isBuiltin() {
1664         return (flags & IS_BUILTIN) != 0;
1665     }
1666 
1667     /**
1668      * Clears the properties from a ScriptObject
1669      * (java.util.Map-like method to help ScriptObjectMirror implementation)


1904      */
1905     protected GuardedInvocation findCallMethodMethod(final CallSiteDescriptor desc, final LinkRequest request) {
1906         // R(P0, P1, ...)
1907         final MethodType callType = desc.getMethodType();
1908         // use type Object(P0) for the getter
1909         final CallSiteDescriptor getterType = desc.changeMethodType(MethodType.methodType(Object.class, callType.parameterType(0)));
1910         final GuardedInvocation getter = findGetMethod(getterType, request, "getMethod");
1911 
1912         // Object(P0) => Object(P0, P1, ...)
1913         final MethodHandle argDroppingGetter = MH.dropArguments(getter.getInvocation(), 1, callType.parameterList().subList(1, callType.parameterCount()));
1914         // R(Object, P0, P1, ...)
1915         final MethodHandle invoker = Bootstrap.createDynamicInvoker("dyn:call", callType.insertParameterTypes(0, argDroppingGetter.type().returnType()));
1916         // Fold Object(P0, P1, ...) into R(Object, P0, P1, ...) => R(P0, P1, ...)
1917         return getter.replaceMethods(MH.foldArguments(invoker, argDroppingGetter), getter.getGuard());
1918     }
1919 
1920     /**
1921      * Test whether this object contains in its prototype chain or is itself a with-object.
1922      * @return true if a with-object was found
1923      */
1924     final boolean hasWithScope() {
1925         if (isScope()) {
1926             for (ScriptObject obj = this; obj != null; obj = obj.getProto()) {
1927                 if (obj instanceof WithObject) {
1928                     return true;
1929                 }
1930             }
1931         }
1932         return false;
1933     }
1934 
1935     /**
1936      * Add a filter to the first argument of {@code methodHandle} that calls its {@link #getProto()} method
1937      * {@code depth} times.
1938      * @param methodHandle a method handle
1939      * @param depth        distance to target prototype
1940      * @return the filtered method handle
1941      */
1942     static MethodHandle addProtoFilter(final MethodHandle methodHandle, final int depth) {
1943         if (depth == 0) {
1944             return methodHandle;
1945         }
1946         final int listIndex = depth - 1; // We don't need 0-deep walker
1947         MethodHandle filter = listIndex < PROTO_FILTERS.size() ? PROTO_FILTERS.get(listIndex) : null;
1948 
1949         if (filter == null) {
1950             filter = addProtoFilter(GETPROTO, depth - 1);
1951             PROTO_FILTERS.add(null);


3800         if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
3801             final ScriptObject proto = getProto((ScriptObject)self, depth);
3802             if (proto == null) {
3803                 return false;
3804             }
3805             try {
3806                 return getter.invokeExact((Object)proto) == func;
3807             } catch (final RuntimeException | Error e) {
3808                 throw e;
3809             } catch (final Throwable t) {
3810                 throw new RuntimeException(t);
3811             }
3812         }
3813 
3814         return false;
3815     }
3816 
3817     /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created */
3818     private static int count;
3819 
3820     /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created that are scope */
3821     private static int scopeCount;
3822 
3823     /**
3824      * Get number of {@code ScriptObject} instances created. If not running in debug
3825      * mode this is always 0
3826      *
3827      * @return number of ScriptObjects created
3828      */
3829     public static int getCount() {
3830         return count;
3831     }
3832 
3833     /**
3834      * Get number of scope {@code ScriptObject} instances created. If not running in debug
3835      * mode this is always 0
3836      *
3837      * @return number of scope ScriptObjects created
3838      */
3839     public static int getScopeCount() {
3840         return scopeCount;
3841     }
3842 
3843 }


  92  * <li>If the map is modified then it must be cloned and replaced.  This notifies
  93  *     any code that made assumptions about the object that things have changed.
  94  *     Ex. CallSites that have been validated must check to see if the map has
  95  *     changed (or a map from a different object type) and hence relink the method
  96  *     to call.</li>
  97  * <li>Modifications of the map include adding/deleting attributes or changing a
  98  *     function field value.</li>
  99  * </ul>
 100  */
 101 
 102 public abstract class ScriptObject implements PropertyAccess, Cloneable {
 103     /** __proto__ special property name inside object literals. ES6 draft. */
 104     public static final String PROTO_PROPERTY_NAME   = "__proto__";
 105 
 106     /** Search fall back routine name for "no such method" */
 107     public static final String NO_SUCH_METHOD_NAME   = "__noSuchMethod__";
 108 
 109     /** Search fall back routine name for "no such property" */
 110     public static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
 111 



 112     /** Per ScriptObject flag - is this an array object? */
 113     public static final int IS_ARRAY               = 1 << 0;
 114 
 115     /** Per ScriptObject flag - is this an arguments object? */
 116     public static final int IS_ARGUMENTS           = 1 << 1;
 117 
 118     /** Is length property not-writable? */
 119     public static final int IS_LENGTH_NOT_WRITABLE = 1 << 2;
 120 
 121     /** Is this a builtin object? */
 122     public static final int IS_BUILTIN             = 1 << 3;
 123 
 124     /**
 125      * Spill growth rate - by how many elements does {@link ScriptObject#primitiveSpill} and
 126      * {@link ScriptObject#objectSpill} when full
 127      */
 128     public static final int SPILL_RATE = 8;
 129 
 130     /** Map to property information and accessor functions. Ordered by insertion. */
 131     private PropertyMap map;
 132 
 133     /** objects proto. */
 134     private ScriptObject proto;
 135 
 136     /** Object flags. */
 137     private int flags;
 138 
 139     /** Area for primitive properties added to object after instantiation, see {@link AccessorProperty} */
 140     protected long[]   primitiveSpill;
 141 
 142     /** Area for reference properties added to object after instantiation, see {@link AccessorProperty} */


1610         while (true) {
1611             final PropertyMap newMap = getMap().freeze();
1612 
1613             if (!compareAndSetMap(oldMap, newMap)) {
1614                 oldMap = getMap();
1615             } else {
1616                 setArray(ArrayData.freeze(getArray()));
1617                 return this;
1618             }
1619         }
1620     }
1621 
1622     /**
1623      * Check whether this ScriptObject is frozen
1624      * @return true if frozen
1625      */
1626     public boolean isFrozen() {
1627         return getMap().isFrozen();
1628     }
1629 











1630     /**
1631      * Check whether this ScriptObject is scope
1632      * @return true if scope
1633      */
1634     public boolean isScope() {
1635         return false;
1636     }
1637 
1638     /**
1639      * Tag this script object as built in
1640      */
1641     public final void setIsBuiltin() {
1642         flags |= IS_BUILTIN;
1643     }
1644 
1645     /**
1646      * Check if this script object is built in
1647      * @return true if build in
1648      */
1649     public final boolean isBuiltin() {
1650         return (flags & IS_BUILTIN) != 0;
1651     }
1652 
1653     /**
1654      * Clears the properties from a ScriptObject
1655      * (java.util.Map-like method to help ScriptObjectMirror implementation)


1890      */
1891     protected GuardedInvocation findCallMethodMethod(final CallSiteDescriptor desc, final LinkRequest request) {
1892         // R(P0, P1, ...)
1893         final MethodType callType = desc.getMethodType();
1894         // use type Object(P0) for the getter
1895         final CallSiteDescriptor getterType = desc.changeMethodType(MethodType.methodType(Object.class, callType.parameterType(0)));
1896         final GuardedInvocation getter = findGetMethod(getterType, request, "getMethod");
1897 
1898         // Object(P0) => Object(P0, P1, ...)
1899         final MethodHandle argDroppingGetter = MH.dropArguments(getter.getInvocation(), 1, callType.parameterList().subList(1, callType.parameterCount()));
1900         // R(Object, P0, P1, ...)
1901         final MethodHandle invoker = Bootstrap.createDynamicInvoker("dyn:call", callType.insertParameterTypes(0, argDroppingGetter.type().returnType()));
1902         // Fold Object(P0, P1, ...) into R(Object, P0, P1, ...) => R(P0, P1, ...)
1903         return getter.replaceMethods(MH.foldArguments(invoker, argDroppingGetter), getter.getGuard());
1904     }
1905 
1906     /**
1907      * Test whether this object contains in its prototype chain or is itself a with-object.
1908      * @return true if a with-object was found
1909      */
1910     boolean hasWithScope() {







1911         return false;
1912     }
1913 
1914     /**
1915      * Add a filter to the first argument of {@code methodHandle} that calls its {@link #getProto()} method
1916      * {@code depth} times.
1917      * @param methodHandle a method handle
1918      * @param depth        distance to target prototype
1919      * @return the filtered method handle
1920      */
1921     static MethodHandle addProtoFilter(final MethodHandle methodHandle, final int depth) {
1922         if (depth == 0) {
1923             return methodHandle;
1924         }
1925         final int listIndex = depth - 1; // We don't need 0-deep walker
1926         MethodHandle filter = listIndex < PROTO_FILTERS.size() ? PROTO_FILTERS.get(listIndex) : null;
1927 
1928         if (filter == null) {
1929             filter = addProtoFilter(GETPROTO, depth - 1);
1930             PROTO_FILTERS.add(null);


3779         if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
3780             final ScriptObject proto = getProto((ScriptObject)self, depth);
3781             if (proto == null) {
3782                 return false;
3783             }
3784             try {
3785                 return getter.invokeExact((Object)proto) == func;
3786             } catch (final RuntimeException | Error e) {
3787                 throw e;
3788             } catch (final Throwable t) {
3789                 throw new RuntimeException(t);
3790             }
3791         }
3792 
3793         return false;
3794     }
3795 
3796     /** This is updated only in debug mode - counts number of {@code ScriptObject} instances created */
3797     private static int count;
3798 



3799     /**
3800      * Get number of {@code ScriptObject} instances created. If not running in debug
3801      * mode this is always 0
3802      *
3803      * @return number of ScriptObjects created
3804      */
3805     public static int getCount() {
3806         return count;
3807     }











3808 }
< prev index next >