49 import java.util.Arrays;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.HashSet;
53 import java.util.Iterator;
54 import java.util.LinkedHashSet;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.Set;
58
59 import jdk.internal.dynalink.CallSiteDescriptor;
60 import jdk.internal.dynalink.linker.GuardedInvocation;
61 import jdk.internal.dynalink.linker.LinkRequest;
62 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
63 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
64 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
65 import jdk.nashorn.internal.lookup.Lookup;
66 import jdk.nashorn.internal.lookup.MethodHandleFactory;
67 import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
68 import jdk.nashorn.internal.objects.DataPropertyDescriptor;
69 import jdk.nashorn.internal.runtime.arrays.ArrayData;
70 import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
71 import jdk.nashorn.internal.runtime.linker.Bootstrap;
72 import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
73 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
74 import jdk.nashorn.internal.runtime.linker.NashornGuards;
75
76 /**
77 * Base class for generic JavaScript objects.
78 * <p>
79 * Notes:
80 * <ul>
81 * <li>The map is used to identify properties in the object.</li>
82 * <li>If the map is modified then it must be cloned and replaced. This notifies
83 * any code that made assumptions about the object that things have changed.
84 * Ex. CallSites that have been validated must check to see if the map has
85 * changed (or a map from a different object type) and hence relink the method
86 * to call.</li>
87 * <li>Modifications of the map include adding/deleting attributes or changing a
88 * function field value.</li>
114 /** Spill growth rate - by how many elements does {@link ScriptObject#spill} when full */
115 public static final int SPILL_RATE = 8;
116
117 /** Map to property information and accessor functions. Ordered by insertion. */
118 private PropertyMap map;
119
120 /** objects proto. */
121 private ScriptObject proto;
122
123 /** Object flags. */
124 private int flags;
125
126 /** Area for properties added to object after instantiation, see {@link AccessorProperty} */
127 public Object[] spill;
128
129 /** Indexed array data. */
130 private ArrayData arrayData;
131
132 static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class);
133 static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class);
134 static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class);
135
136 static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
137 static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
138 static final MethodHandle SETSPILLWITHNEW = findOwnMH("setSpillWithNew", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
139 static final MethodHandle SETSPILLWITHGROW = findOwnMH("setSpillWithGrow", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, int.class, Object.class, Object.class);
140
141 private static final MethodHandle TRUNCATINGFILTER = findOwnMH("truncatingFilter", Object[].class, int.class, Object[].class);
142 private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
143
144 private static final ArrayList<MethodHandle> protoFilters = new ArrayList<>();
145
146 /** Method handle for getting a function argument at a given index. Used from MapCreator */
147 public static final Call GET_ARGUMENT = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArgument", Object.class, int.class);
148
149 /** Method handle for setting a function argument at a given index. Used from MapCreator */
150 public static final Call SET_ARGUMENT = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setArgument", void.class, int.class, Object.class);
151
152 /** Method handle for getting the proto of a ScriptObject */
153 public static final Call GET_PROTO = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
154
155 /** Method handle for setting the proto of a ScriptObject */
156 public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class);
157
158 /** Method handle for setting the proto of a ScriptObject after checking argument */
159 public static final Call SET_PROTO_CHECK = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class);
1723 filter = addProtoFilter(GETPROTO, depth - 1);
1724 protoFilters.add(null);
1725 protoFilters.set(listIndex, filter);
1726 }
1727
1728 return MH.filterArguments(methodHandle, 0, filter.asType(filter.type().changeReturnType(methodHandle.type().parameterType(0))));
1729 }
1730
1731 /**
1732 * Find the appropriate GET method for an invoke dynamic call.
1733 *
1734 * @param desc the call site descriptor
1735 * @param request the link request
1736 * @param operator operator for get: getProp, getMethod, getElem etc
1737 *
1738 * @return GuardedInvocation to be invoked at call site.
1739 */
1740 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
1741 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
1742 if (request.isCallSiteUnstable() || hasWithScope()) {
1743 return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator));
1744 }
1745
1746 final FindProperty find = findProperty(name, true);
1747 MethodHandle methodHandle;
1748
1749 if (find == null) {
1750 if (PROTO_PROPERTY_NAME.equals(name)) {
1751 return new GuardedInvocation(GETPROTO, NashornGuards.getScriptObjectGuard());
1752 }
1753
1754 if ("getProp".equals(operator)) {
1755 return noSuchProperty(desc, request);
1756 } else if ("getMethod".equals(operator)) {
1757 return noSuchMethod(desc, request);
1758 } else if ("getElem".equals(operator)) {
1759 return createEmptyGetter(desc, name);
1760 }
1761 throw new AssertionError(); // never invoked with any other operation
1762 }
1763
1764 final Class<?> returnType = desc.getMethodType().returnType();
1765 final Property property = find.getProperty();
1766 methodHandle = find.getGetter(returnType);
1767
1768 final boolean noGuard = ObjectClassGenerator.OBJECT_FIELDS_ONLY && NashornCallSiteDescriptor.isFastScope(desc) && !property.canChangeType();
1769 // getMap() is fine as we have the prototype switchpoint depending on where the property was found
1770 final MethodHandle guard = noGuard ? null : NashornGuards.getMapGuard(getMap());
1771 final ScriptObject owner = find.getOwner();
1772
1773 if (methodHandle != null) {
1774 assert methodHandle.type().returnType().equals(returnType);
1775 if (find.isSelf()) {
1776 return new GuardedInvocation(methodHandle, guard);
1777 }
1778
1779 if (!property.hasGetterFunction(owner)) {
1780 // If not a scope bind to actual prototype as changing prototype will change the property map.
1781 // For scopes we install a filter that replaces the self object with the prototype owning the property.
1782 methodHandle = isScope() ?
1783 addProtoFilter(methodHandle, find.getProtoChainLength()) :
1784 bindTo(methodHandle, owner);
1785 }
1786 return new GuardedInvocation(methodHandle, noGuard ? null : getProtoSwitchPoint(name, owner), guard);
1787 }
1788
1789 assert !NashornCallSiteDescriptor.isFastScope(desc);
1790 return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard);
1791 }
1792
1793 private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
1794 final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
1795 final MethodHandle guard = getScriptObjectGuard(desc.getMethodType());
1796 return new GuardedInvocation(invoker, guard);
1797 }
1798
1799 @SuppressWarnings("unused")
1800 private Object megamorphicGet(final String key, final boolean isMethod) {
1801 final FindProperty find = findProperty(key, true);
1802
1803 if (find != null) {
1804 return getObjectValue(find);
1805 }
1806
1807 return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key);
1808 }
1809
1810 /**
1811 * Find the appropriate GETINDEX method for an invoke dynamic call.
1812 *
1813 * @param desc the call site descriptor
1814 * @param request the link request
1815 *
1816 * @return GuardedInvocation to be invoked at call site.
1817 */
1818 protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
1819 return findGetIndexMethod(desc.getMethodType());
1820 }
1821
1822 /**
1823 * Find the appropriate GETINDEX method for an invoke dynamic call.
1824 *
1825 * @param callType the call site method type
1979 @SuppressWarnings("unused")
1980 private static void setSpillWithGrow(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final int newLength, final Object self, final Object value) {
1981 final ScriptObject obj = (ScriptObject)self;
1982 final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
1983
1984 if (!obj.isExtensible()) {
1985 if (isStrict) {
1986 throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
1987 }
1988 } else if (obj.compareAndSetMap(oldMap, newMap)) {
1989 final int oldLength = obj.spill.length;
1990 final Object[] newSpill = new Object[newLength];
1991 System.arraycopy(obj.spill, 0, newSpill, 0, oldLength);
1992 obj.spill = newSpill;
1993 obj.spill[index] = value;
1994 } else {
1995 obj.set(desc.getNameToken(2), value, isStrict);
1996 }
1997 }
1998
1999 private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
2000 final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
2001 final GuardedInvocation inv = findSetIndexMethod(type, NashornCallSiteDescriptor.isStrict(desc));
2002 return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
2003 }
2004
2005 private static GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc) { // array, index, value
2006 return findSetIndexMethod(desc.getMethodType(), NashornCallSiteDescriptor.isStrict(desc));
2007 }
2008
2009 /**
2010 * Find the appropriate SETINDEX method for an invoke dynamic call.
2011 *
2012 * @param callType the method type at the call site
2013 * @param isStrict are we in strict mode?
2014 *
2015 * @return GuardedInvocation to be invoked at call site.
2016 */
2017 private static GuardedInvocation findSetIndexMethod(final MethodType callType, final boolean isStrict) {
2018 assert callType.parameterCount() == 3;
2806 // Setting a property should not modify the property in prototype unless this is a scope object.
2807 f = null;
2808 }
2809
2810 if (f != null) {
2811 if (!f.getProperty().isWritable()) {
2812 if (strict) {
2813 throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
2814 }
2815
2816 return;
2817 }
2818
2819 f.setObjectValue(value, strict);
2820
2821 } else if (!isExtensible()) {
2822 if (strict) {
2823 throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
2824 }
2825 } else {
2826 spill(key, value);
2827 }
2828 }
2829
2830 private void spill(final String key, final Object value) {
2831 addSpillProperty(key, 0).setObjectValue(this, this, value, false);
2832 }
2833
2834
2835 @Override
2836 public void set(final Object key, final int value, final boolean strict) {
2837 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2838 final int index = getArrayIndex(primitiveKey);
2839
2840 if (isValidArrayIndex(index)) {
2841 if (getArray().has(index)) {
2842 setArray(getArray().set(index, value, strict));
2843 } else {
2844 doesNotHave(index, value, strict);
2845 }
2846
|
49 import java.util.Arrays;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.HashSet;
53 import java.util.Iterator;
54 import java.util.LinkedHashSet;
55 import java.util.List;
56 import java.util.Map;
57 import java.util.Set;
58
59 import jdk.internal.dynalink.CallSiteDescriptor;
60 import jdk.internal.dynalink.linker.GuardedInvocation;
61 import jdk.internal.dynalink.linker.LinkRequest;
62 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
63 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
64 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
65 import jdk.nashorn.internal.lookup.Lookup;
66 import jdk.nashorn.internal.lookup.MethodHandleFactory;
67 import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
68 import jdk.nashorn.internal.objects.DataPropertyDescriptor;
69 import jdk.nashorn.internal.objects.Global;
70 import jdk.nashorn.internal.runtime.arrays.ArrayData;
71 import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
72 import jdk.nashorn.internal.runtime.linker.Bootstrap;
73 import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
74 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
75 import jdk.nashorn.internal.runtime.linker.NashornGuards;
76
77 /**
78 * Base class for generic JavaScript objects.
79 * <p>
80 * Notes:
81 * <ul>
82 * <li>The map is used to identify properties in the object.</li>
83 * <li>If the map is modified then it must be cloned and replaced. This notifies
84 * any code that made assumptions about the object that things have changed.
85 * Ex. CallSites that have been validated must check to see if the map has
86 * changed (or a map from a different object type) and hence relink the method
87 * to call.</li>
88 * <li>Modifications of the map include adding/deleting attributes or changing a
89 * function field value.</li>
115 /** Spill growth rate - by how many elements does {@link ScriptObject#spill} when full */
116 public static final int SPILL_RATE = 8;
117
118 /** Map to property information and accessor functions. Ordered by insertion. */
119 private PropertyMap map;
120
121 /** objects proto. */
122 private ScriptObject proto;
123
124 /** Object flags. */
125 private int flags;
126
127 /** Area for properties added to object after instantiation, see {@link AccessorProperty} */
128 public Object[] spill;
129
130 /** Indexed array data. */
131 private ArrayData arrayData;
132
133 static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class);
134 static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class);
135 static final MethodHandle MEGAMORPHIC_GET = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class, boolean.class);
136
137 static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
138 static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
139 static final MethodHandle SETSPILLWITHNEW = findOwnMH("setSpillWithNew", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
140 static final MethodHandle SETSPILLWITHGROW = findOwnMH("setSpillWithGrow", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, int.class, Object.class, Object.class);
141 static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
142
143 private static final MethodHandle TRUNCATINGFILTER = findOwnMH("truncatingFilter", Object[].class, int.class, Object[].class);
144 private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
145
146 private static final ArrayList<MethodHandle> protoFilters = new ArrayList<>();
147
148 /** Method handle for getting a function argument at a given index. Used from MapCreator */
149 public static final Call GET_ARGUMENT = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArgument", Object.class, int.class);
150
151 /** Method handle for setting a function argument at a given index. Used from MapCreator */
152 public static final Call SET_ARGUMENT = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setArgument", void.class, int.class, Object.class);
153
154 /** Method handle for getting the proto of a ScriptObject */
155 public static final Call GET_PROTO = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
156
157 /** Method handle for setting the proto of a ScriptObject */
158 public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class);
159
160 /** Method handle for setting the proto of a ScriptObject after checking argument */
161 public static final Call SET_PROTO_CHECK = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class);
1725 filter = addProtoFilter(GETPROTO, depth - 1);
1726 protoFilters.add(null);
1727 protoFilters.set(listIndex, filter);
1728 }
1729
1730 return MH.filterArguments(methodHandle, 0, filter.asType(filter.type().changeReturnType(methodHandle.type().parameterType(0))));
1731 }
1732
1733 /**
1734 * Find the appropriate GET method for an invoke dynamic call.
1735 *
1736 * @param desc the call site descriptor
1737 * @param request the link request
1738 * @param operator operator for get: getProp, getMethod, getElem etc
1739 *
1740 * @return GuardedInvocation to be invoked at call site.
1741 */
1742 protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
1743 final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
1744 if (request.isCallSiteUnstable() || hasWithScope()) {
1745 return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator), isScope() && NashornCallSiteDescriptor.isScope(desc));
1746 }
1747
1748 final FindProperty find = findProperty(name, true);
1749 MethodHandle methodHandle;
1750
1751 if (find == null) {
1752 if (PROTO_PROPERTY_NAME.equals(name)) {
1753 return new GuardedInvocation(GETPROTO, NashornGuards.getScriptObjectGuard());
1754 }
1755
1756 if ("getProp".equals(operator)) {
1757 return noSuchProperty(desc, request);
1758 } else if ("getMethod".equals(operator)) {
1759 return noSuchMethod(desc, request);
1760 } else if ("getElem".equals(operator)) {
1761 return createEmptyGetter(desc, name);
1762 }
1763 throw new AssertionError(); // never invoked with any other operation
1764 }
1765
1766 final Class<?> returnType = desc.getMethodType().returnType();
1767 final Property property = find.getProperty();
1768 methodHandle = find.getGetter(returnType);
1769
1770 // Get the appropriate guard for this callsite and property.
1771 final MethodHandle guard = NashornGuards.getGuard(this, property, desc);
1772 final ScriptObject owner = find.getOwner();
1773
1774 if (methodHandle != null) {
1775 assert methodHandle.type().returnType().equals(returnType);
1776 if (find.isSelf()) {
1777 return new GuardedInvocation(methodHandle, guard);
1778 }
1779
1780 if (!property.hasGetterFunction(owner)) {
1781 // Add a filter that replaces the self object with the prototype owning the property.
1782 methodHandle = addProtoFilter(methodHandle, find.getProtoChainLength());
1783 }
1784 return new GuardedInvocation(methodHandle, guard == null ? null : getProtoSwitchPoint(name, owner), guard);
1785 }
1786
1787 assert !NashornCallSiteDescriptor.isFastScope(desc);
1788 return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard);
1789 }
1790
1791 private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name,
1792 final boolean isMethod, final boolean isScope) {
1793 final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod, isScope);
1794 final MethodHandle guard = getScriptObjectGuard(desc.getMethodType());
1795 return new GuardedInvocation(invoker, guard);
1796 }
1797
1798 @SuppressWarnings("unused")
1799 private Object megamorphicGet(final String key, final boolean isMethod, final boolean isScope) {
1800 final FindProperty find = findProperty(key, true);
1801
1802 if (find != null) {
1803 return getObjectValue(find);
1804 }
1805 if (isScope) {
1806 throw referenceError("not.defined", key);
1807 }
1808
1809 return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key);
1810 }
1811
1812 /**
1813 * Find the appropriate GETINDEX method for an invoke dynamic call.
1814 *
1815 * @param desc the call site descriptor
1816 * @param request the link request
1817 *
1818 * @return GuardedInvocation to be invoked at call site.
1819 */
1820 protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
1821 return findGetIndexMethod(desc.getMethodType());
1822 }
1823
1824 /**
1825 * Find the appropriate GETINDEX method for an invoke dynamic call.
1826 *
1827 * @param callType the call site method type
1981 @SuppressWarnings("unused")
1982 private static void setSpillWithGrow(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final int newLength, final Object self, final Object value) {
1983 final ScriptObject obj = (ScriptObject)self;
1984 final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
1985
1986 if (!obj.isExtensible()) {
1987 if (isStrict) {
1988 throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
1989 }
1990 } else if (obj.compareAndSetMap(oldMap, newMap)) {
1991 final int oldLength = obj.spill.length;
1992 final Object[] newSpill = new Object[newLength];
1993 System.arraycopy(obj.spill, 0, newSpill, 0, oldLength);
1994 obj.spill = newSpill;
1995 obj.spill[index] = value;
1996 } else {
1997 obj.set(desc.getNameToken(2), value, isStrict);
1998 }
1999 }
2000
2001 @SuppressWarnings("unused")
2002 private static Object globalFilter(final Object object) {
2003 ScriptObject sobj = (ScriptObject) object;
2004 while (sobj != null && !(sobj instanceof Global)) {
2005 sobj = sobj.getProto();
2006 }
2007 return sobj;
2008 }
2009
2010 private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
2011 final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
2012 final GuardedInvocation inv = findSetIndexMethod(type, NashornCallSiteDescriptor.isStrict(desc));
2013 return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
2014 }
2015
2016 private static GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc) { // array, index, value
2017 return findSetIndexMethod(desc.getMethodType(), NashornCallSiteDescriptor.isStrict(desc));
2018 }
2019
2020 /**
2021 * Find the appropriate SETINDEX method for an invoke dynamic call.
2022 *
2023 * @param callType the method type at the call site
2024 * @param isStrict are we in strict mode?
2025 *
2026 * @return GuardedInvocation to be invoked at call site.
2027 */
2028 private static GuardedInvocation findSetIndexMethod(final MethodType callType, final boolean isStrict) {
2029 assert callType.parameterCount() == 3;
2817 // Setting a property should not modify the property in prototype unless this is a scope object.
2818 f = null;
2819 }
2820
2821 if (f != null) {
2822 if (!f.getProperty().isWritable()) {
2823 if (strict) {
2824 throw typeError("property.not.writable", key, ScriptRuntime.safeToString(this));
2825 }
2826
2827 return;
2828 }
2829
2830 f.setObjectValue(value, strict);
2831
2832 } else if (!isExtensible()) {
2833 if (strict) {
2834 throw typeError("object.non.extensible", key, ScriptRuntime.safeToString(this));
2835 }
2836 } else {
2837 ScriptObject sobj = this;
2838 // undefined scope properties are set in the global object.
2839 if (isScope()) {
2840 while (sobj != null && !(sobj instanceof Global)) {
2841 sobj = sobj.getProto();
2842 }
2843 assert sobj != null : "no parent global object in scope";
2844 }
2845 sobj.spill(key, value);
2846 }
2847 }
2848
2849 private void spill(final String key, final Object value) {
2850 addSpillProperty(key, 0).setObjectValue(this, this, value, false);
2851 }
2852
2853
2854 @Override
2855 public void set(final Object key, final int value, final boolean strict) {
2856 final Object primitiveKey = JSType.toPrimitive(key, String.class);
2857 final int index = getArrayIndex(primitiveKey);
2858
2859 if (isValidArrayIndex(index)) {
2860 if (getArray().has(index)) {
2861 setArray(getArray().set(index, value, strict));
2862 } else {
2863 doesNotHave(index, value, strict);
2864 }
2865
|