< prev index next >

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

Print this page




  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
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.runtime;
  27 
  28 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
  31 import static jdk.nashorn.internal.lookup.Lookup.MH;
  32 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
  33 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  34 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE;
  35 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
  36 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
  37 import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
  38 import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
  39 import static jdk.nashorn.internal.runtime.PropertyDescriptor.GET;
  40 import static jdk.nashorn.internal.runtime.PropertyDescriptor.SET;
  41 import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
  42 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
  43 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  44 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
  45 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
  46 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
  47 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
  48 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isScopeFlag;
  49 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isStrictFlag;
  50 import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
  51 
  52 import java.lang.invoke.MethodHandle;
  53 import java.lang.invoke.MethodHandles;
  54 import java.lang.invoke.MethodType;
  55 import java.lang.invoke.SwitchPoint;
  56 import java.lang.reflect.Array;


 171     public static final Call SET_ARGUMENT       = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setArgument", void.class, int.class, Object.class);
 172 
 173     /** Method handle for getting the proto of a ScriptObject */
 174     public static final Call GET_PROTO          = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
 175 
 176     /** Method handle for getting the proto of a ScriptObject */
 177     public static final Call GET_PROTO_DEPTH    = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class, int.class);
 178 
 179     /** Method handle for setting the proto of a ScriptObject */
 180     public static final Call SET_GLOBAL_OBJECT_PROTO = staticCallNoLookup(ScriptObject.class, "setGlobalObjectProto", void.class, ScriptObject.class);
 181 
 182     /** Method handle for setting the proto of a ScriptObject after checking argument */
 183     public static final Call SET_PROTO_FROM_LITERAL    = virtualCallNoLookup(ScriptObject.class, "setProtoFromLiteral", void.class, Object.class);
 184 
 185     /** Method handle for setting the user accessors of a ScriptObject */
 186     //TODO fastpath this
 187     public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
 188 
 189     static final MethodHandle[] SET_SLOW = new MethodHandle[] {
 190         findOwnMH_V("set", void.class, Object.class, int.class, int.class),
 191         findOwnMH_V("set", void.class, Object.class, long.class, int.class),
 192         findOwnMH_V("set", void.class, Object.class, double.class, int.class),
 193         findOwnMH_V("set", void.class, Object.class, Object.class, int.class)
 194     };
 195 
 196     /** Method handle to reset the map of this ScriptObject */
 197     public static final Call SET_MAP = virtualCallNoLookup(ScriptObject.class, "setMap", void.class, PropertyMap.class);
 198 
 199     static final MethodHandle CAS_MAP           = findOwnMH_V("compareAndSetMap", boolean.class, PropertyMap.class, PropertyMap.class);
 200     static final MethodHandle EXTENSION_CHECK   = findOwnMH_V("extensionCheck", boolean.class, boolean.class, String.class);
 201     static final MethodHandle ENSURE_SPILL_SIZE = findOwnMH_V("ensureSpillSize", Object.class, int.class);
 202 
 203     /**
 204      * Constructor
 205      */
 206     public ScriptObject() {
 207         this(null);
 208     }
 209 
 210     /**
 211     * Constructor


1070         } else {
1071             addOwnProperty(newUserAccessors(key, oldProperty != null ? oldProperty.getFlags() : 0, getter, setter));
1072         }
1073     }
1074 
1075     private static int getIntValue(final FindProperty find, final int programPoint) {
1076         final MethodHandle getter = find.getGetter(int.class, programPoint, null);
1077         if (getter != null) {
1078             try {
1079                 return (int)getter.invokeExact((Object)find.getGetterReceiver());
1080             } catch (final Error|RuntimeException e) {
1081                 throw e;
1082             } catch (final Throwable e) {
1083                 throw new RuntimeException(e);
1084             }
1085         }
1086 
1087         return UNDEFINED_INT;
1088     }
1089 
1090     private static long getLongValue(final FindProperty find, final int programPoint) {
1091         final MethodHandle getter = find.getGetter(long.class, programPoint, null);
1092         if (getter != null) {
1093             try {
1094                 return (long)getter.invokeExact((Object)find.getGetterReceiver());
1095             } catch (final Error|RuntimeException e) {
1096                 throw e;
1097             } catch (final Throwable e) {
1098                 throw new RuntimeException(e);
1099             }
1100         }
1101 
1102         return UNDEFINED_LONG;
1103     }
1104 
1105     private static double getDoubleValue(final FindProperty find, final int programPoint) {
1106         final MethodHandle getter = find.getGetter(double.class, programPoint, null);
1107         if (getter != null) {
1108             try {
1109                 return (double)getter.invokeExact((Object)find.getGetterReceiver());
1110             } catch (final Error|RuntimeException e) {
1111                 throw e;
1112             } catch (final Throwable e) {
1113                 throw new RuntimeException(e);
1114             }
1115         }
1116 
1117         return UNDEFINED_DOUBLE;
1118     }
1119 
1120     /**
1121      * Return methodHandle of value function for call.
1122      *
1123      * @param find      data from find property.
1124      * @param type      method type of function.


2787         if (array.has(index)) {
2788             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2789         }
2790 
2791         return getInt(index, JSType.toPropertyKey(primitiveKey), programPoint);
2792     }
2793 
2794     @Override
2795     public int getInt(final double key, final int programPoint) {
2796         final int       index = getArrayIndex(key);
2797         final ArrayData array = getArray();
2798 
2799         if (array.has(index)) {
2800             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2801         }
2802 
2803         return getInt(index, JSType.toString(key), programPoint);
2804     }
2805 
2806     @Override
2807     public int getInt(final long key, final int programPoint) {
2808         final int       index = getArrayIndex(key);
2809         final ArrayData array = getArray();
2810 
2811         if (array.has(index)) {
2812             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2813         }
2814 
2815         return getInt(index, JSType.toString(key), programPoint);
2816     }
2817 
2818     @Override
2819     public int getInt(final int key, final int programPoint) {
2820         final int       index = getArrayIndex(key);
2821         final ArrayData array = getArray();
2822 
2823         if (array.has(index)) {
2824             return isValid(programPoint) ? array.getIntOptimistic(key, programPoint) : array.getInt(key);
2825         }
2826 
2827         return getInt(index, JSType.toString(key), programPoint);
2828     }
2829 
2830     private long getLong(final int index, final Object key, final int programPoint) {
2831         if (isValidArrayIndex(index)) {
2832             for (ScriptObject object = this; ; ) {
2833                 if (object.getMap().containsArrayKeys()) {
2834                     final FindProperty find = object.findProperty(key, false, this);
2835                     if (find != null) {
2836                         return getLongValue(find, programPoint);
2837                     }
2838                 }
2839 
2840                 if ((object = object.getProto()) == null) {
2841                     break;
2842                 }
2843 
2844                 final ArrayData array = object.getArray();
2845 
2846                 if (array.has(index)) {
2847                     return isValid(programPoint) ?
2848                         array.getLongOptimistic(index, programPoint) :
2849                         array.getLong(index);
2850                 }
2851             }
2852         } else {
2853             final FindProperty find = findProperty(key, true);
2854 
2855             if (find != null) {
2856                 return getLongValue(find, programPoint);
2857             }
2858         }
2859 
2860         return JSType.toLong(invokeNoSuchProperty(key, false, programPoint));
2861     }
2862 
2863     @Override
2864     public long getLong(final Object key, final int programPoint) {
2865         final Object    primitiveKey = JSType.toPrimitive(key, String.class);
2866         final int       index        = getArrayIndex(primitiveKey);
2867         final ArrayData array        = getArray();
2868 
2869         if (array.has(index)) {
2870             return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
2871         }
2872 
2873         return getLong(index, JSType.toPropertyKey(primitiveKey), programPoint);
2874     }
2875 
2876     @Override
2877     public long getLong(final double key, final int programPoint) {
2878         final int       index = getArrayIndex(key);
2879         final ArrayData array = getArray();
2880 
2881         if (array.has(index)) {
2882             return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
2883         }
2884 
2885         return getLong(index, JSType.toString(key), programPoint);
2886     }
2887 
2888     @Override
2889     public long getLong(final long key, final int programPoint) {
2890         final int       index = getArrayIndex(key);
2891         final ArrayData array = getArray();
2892 
2893         if (array.has(index)) {
2894             return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
2895         }
2896 
2897         return getLong(index, JSType.toString(key), programPoint);
2898     }
2899 
2900     @Override
2901     public long getLong(final int key, final int programPoint) {
2902         final int       index = getArrayIndex(key);
2903         final ArrayData array = getArray();
2904 
2905         if (array.has(index)) {
2906             return isValid(programPoint) ? array.getLongOptimistic(key, programPoint) : array.getLong(key);
2907         }
2908 
2909         return getLong(index, JSType.toString(key), programPoint);
2910     }
2911 
2912     private double getDouble(final int index, final Object key, final int programPoint) {
2913         if (isValidArrayIndex(index)) {
2914             for (ScriptObject object = this; ; ) {
2915                 if (object.getMap().containsArrayKeys()) {
2916                     final FindProperty find = object.findProperty(key, false, this);
2917                     if (find != null) {
2918                         return getDoubleValue(find, programPoint);
2919                     }
2920                 }
2921 
2922                 if ((object = object.getProto()) == null) {
2923                     break;
2924                 }
2925 
2926                 final ArrayData array = object.getArray();
2927 
2928                 if (array.has(index)) {
2929                     return isValid(programPoint) ?
2930                         array.getDoubleOptimistic(index, programPoint) :
2931                         array.getDouble(index);


2951         if (array.has(index)) {
2952             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2953         }
2954 
2955         return getDouble(index, JSType.toPropertyKey(primitiveKey), programPoint);
2956     }
2957 
2958     @Override
2959     public double getDouble(final double key, final int programPoint) {
2960         final int       index = getArrayIndex(key);
2961         final ArrayData array = getArray();
2962 
2963         if (array.has(index)) {
2964             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2965         }
2966 
2967         return getDouble(index, JSType.toString(key), programPoint);
2968     }
2969 
2970     @Override
2971     public double getDouble(final long key, final int programPoint) {
2972         final int       index = getArrayIndex(key);
2973         final ArrayData array = getArray();
2974 
2975         if (array.has(index)) {
2976             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2977         }
2978 
2979         return getDouble(index, JSType.toString(key), programPoint);
2980     }
2981 
2982     @Override
2983     public double getDouble(final int key, final int programPoint) {
2984         final int       index = getArrayIndex(key);
2985         final ArrayData array = getArray();
2986 
2987         if (array.has(index)) {
2988             return isValid(programPoint) ? array.getDoubleOptimistic(key, programPoint) : array.getDouble(key);
2989         }
2990 
2991         return getDouble(index, JSType.toString(key), programPoint);
2992     }
2993 
2994     private Object get(final int index, final Object key) {
2995         if (isValidArrayIndex(index)) {
2996             for (ScriptObject object = this; ; ) {
2997                 if (object.getMap().containsArrayKeys()) {
2998                     final FindProperty find = object.findProperty(key, false, this);
2999 
3000                     if (find != null) {
3001                         return find.getObjectValue();
3002                     }


3032         if (array.has(index)) {
3033             return array.getObject(index);
3034         }
3035 
3036         return get(index, JSType.toPropertyKey(primitiveKey));
3037     }
3038 
3039     @Override
3040     public Object get(final double key) {
3041         final int index = getArrayIndex(key);
3042         final ArrayData array = getArray();
3043 
3044         if (array.has(index)) {
3045             return array.getObject(index);
3046         }
3047 
3048         return get(index, JSType.toString(key));
3049     }
3050 
3051     @Override
3052     public Object get(final long key) {
3053         final int index = getArrayIndex(key);
3054         final ArrayData array = getArray();
3055 
3056         if (array.has(index)) {
3057             return array.getObject(index);
3058         }
3059 
3060         return get(index, JSType.toString(key));
3061     }
3062 
3063     @Override
3064     public Object get(final int key) {
3065         final int index = getArrayIndex(key);
3066         final ArrayData array = getArray();
3067 
3068         if (array.has(index)) {
3069             return array.getObject(index);
3070         }
3071 
3072         return get(index, JSType.toString(key));
3073     }
3074 
3075     private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final int callSiteFlags) {
3076         if (getMap().containsArrayKeys()) {
3077             final String       key  = JSType.toString(longIndex);
3078             final FindProperty find = findProperty(key, true);
3079             if (find != null) {
3080                 setObject(find, callSiteFlags, key, value);
3081                 return true;
3082             }
3083         }


3126             if (!isExtensible()) {
3127                 if (isStrictFlag(callSiteFlags)) {
3128                     throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
3129                 }
3130                 return true;
3131             }
3132             setArray(getArray().ensure(longIndex));
3133         }
3134         return false;
3135     }
3136 
3137     private void doesNotHave(final int index, final int value, final int callSiteFlags) {
3138         final long oldLength = getArray().length();
3139         final long longIndex = ArrayIndex.toLongIndex(index);
3140         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3141             final boolean strict = isStrictFlag(callSiteFlags);
3142             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3143         }
3144     }
3145 
3146     private void doesNotHave(final int index, final long value, final int callSiteFlags) {
3147         final long oldLength = getArray().length();
3148         final long longIndex = ArrayIndex.toLongIndex(index);
3149         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3150             final boolean strict = isStrictFlag(callSiteFlags);
3151             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3152         }
3153     }
3154 
3155     private void doesNotHave(final int index, final double value, final int callSiteFlags) {
3156         final long oldLength = getArray().length();
3157         final long longIndex = ArrayIndex.toLongIndex(index);
3158         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3159             final boolean strict = isStrictFlag(callSiteFlags);
3160             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3161         }
3162     }
3163 
3164     private void doesNotHave(final int index, final Object value, final int callSiteFlags) {
3165         final long oldLength = getArray().length();
3166         final long longIndex = ArrayIndex.toLongIndex(index);
3167         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3168             final boolean strict = isStrictFlag(callSiteFlags);
3169             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3170         }
3171     }
3172 
3173     /**
3174      * This is the most generic of all Object setters. Most of the others use this in some form.


3241     public void set(final Object key, final int value, final int callSiteFlags) {
3242         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3243         final int    index        = getArrayIndex(primitiveKey);
3244 
3245         if (isValidArrayIndex(index)) {
3246             final ArrayData data = getArray();
3247             if (data.has(index)) {
3248                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3249             } else {
3250                 doesNotHave(index, value, callSiteFlags);
3251             }
3252 
3253             return;
3254         }
3255 
3256         final Object propName = JSType.toPropertyKey(primitiveKey);
3257         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3258     }
3259 
3260     @Override
3261     public void set(final Object key, final long value, final int callSiteFlags) {
3262         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3263         final int    index        = getArrayIndex(primitiveKey);
3264 
3265         if (isValidArrayIndex(index)) {
3266             final ArrayData data = getArray();
3267             if (data.has(index)) {
3268                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3269             } else {
3270                 doesNotHave(index, value, callSiteFlags);
3271             }
3272 
3273             return;
3274         }
3275 
3276         final Object propName = JSType.toPropertyKey(primitiveKey);
3277         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3278     }
3279 
3280     @Override
3281     public void set(final Object key, final double value, final int callSiteFlags) {
3282         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3283         final int    index        = getArrayIndex(primitiveKey);
3284 
3285         if (isValidArrayIndex(index)) {
3286             final ArrayData data = getArray();
3287             if (data.has(index)) {
3288                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3289             } else {
3290                 doesNotHave(index, value, callSiteFlags);
3291             }
3292 
3293             return;
3294         }
3295 
3296         final Object propName = JSType.toPropertyKey(primitiveKey);
3297         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3298     }
3299 
3300     @Override


3320     @Override
3321     public void set(final double key, final int value, final int callSiteFlags) {
3322         final int index = getArrayIndex(key);
3323 
3324         if (isValidArrayIndex(index)) {
3325             final ArrayData data = getArray();
3326             if (data.has(index)) {
3327                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3328             } else {
3329                 doesNotHave(index, value, callSiteFlags);
3330             }
3331 
3332             return;
3333         }
3334 
3335         final String propName = JSType.toString(key);
3336         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3337     }
3338 
3339     @Override
3340     public void set(final double key, final long value, final int callSiteFlags) {
3341         final int index = getArrayIndex(key);
3342 
3343         if (isValidArrayIndex(index)) {
3344             final ArrayData data = getArray();
3345             if (data.has(index)) {
3346                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3347             } else {
3348                 doesNotHave(index, value, callSiteFlags);
3349             }
3350 
3351             return;
3352         }
3353 
3354         final String propName = JSType.toString(key);
3355         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3356     }
3357 
3358     @Override
3359     public void set(final double key, final double value, final int callSiteFlags) {
3360         final int index = getArrayIndex(key);
3361 
3362         if (isValidArrayIndex(index)) {
3363             final ArrayData data = getArray();
3364             if (data.has(index)) {
3365                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3366             } else {
3367                 doesNotHave(index, value, callSiteFlags);
3368             }
3369 
3370             return;
3371         }
3372 
3373         final String propName = JSType.toString(key);
3374         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3375     }
3376 
3377     @Override
3378     public void set(final double key, final Object value, final int callSiteFlags) {
3379         final int index = getArrayIndex(key);
3380 
3381         if (isValidArrayIndex(index)) {
3382             final ArrayData data = getArray();
3383             if (data.has(index)) {
3384                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3385             } else {
3386                 doesNotHave(index, value, callSiteFlags);
3387             }
3388 
3389             return;
3390         }
3391 
3392         final String propName = JSType.toString(key);
3393         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3394     }
3395 
3396     @Override
3397     public void set(final long key, final int value, final int callSiteFlags) {
3398         final int index = getArrayIndex(key);
3399 
3400         if (isValidArrayIndex(index)) {
3401             final ArrayData data = getArray();
3402             if (data.has(index)) {
3403                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3404             } else {
3405                 doesNotHave(index, value, callSiteFlags);
3406             }
3407 
3408             return;
3409         }
3410 
3411         final String propName = JSType.toString(key);
3412         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3413     }
3414 
3415     @Override
3416     public void set(final long key, final long value, final int callSiteFlags) {
3417         final int index = getArrayIndex(key);
3418 
3419         if (isValidArrayIndex(index)) {
3420             final ArrayData data = getArray();
3421             if (data.has(index)) {
3422                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3423             } else {
3424                 doesNotHave(index, value, callSiteFlags);
3425             }
3426 
3427             return;
3428         }
3429 
3430         final String propName = JSType.toString(key);
3431         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3432     }
3433 
3434     @Override
3435     public void set(final long key, final double value, final int callSiteFlags) {
3436         final int index = getArrayIndex(key);
3437 
3438         if (isValidArrayIndex(index)) {
3439             final ArrayData data = getArray();
3440             if (data.has(index)) {
3441                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3442             } else {
3443                 doesNotHave(index, value, callSiteFlags);
3444             }
3445 
3446             return;
3447         }
3448 
3449         final String propName = JSType.toString(key);
3450         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3451     }
3452 
3453     @Override
3454     public void set(final long key, final Object value, final int callSiteFlags) {
3455         final int index = getArrayIndex(key);
3456 
3457         if (isValidArrayIndex(index)) {
3458             final ArrayData data = getArray();
3459             if (data.has(index)) {
3460                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3461             } else {
3462                 doesNotHave(index, value, callSiteFlags);
3463             }
3464 
3465             return;
3466         }
3467 
3468         final String propName = JSType.toString(key);
3469         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3470     }
3471 
3472     @Override
3473     public void set(final int key, final int value, final int callSiteFlags) {
3474         final int index = getArrayIndex(key);
3475         if (isValidArrayIndex(index)) {
3476             if (getArray().has(index)) {
3477                 final ArrayData data = getArray();
3478                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3479             } else {
3480                 doesNotHave(index, value, callSiteFlags);
3481             }
3482             return;
3483         }
3484 
3485         final String propName = JSType.toString(key);
3486         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3487     }
3488 
3489     @Override
3490     public void set(final int key, final long value, final int callSiteFlags) {
3491         final int index = getArrayIndex(key);
3492 
3493         if (isValidArrayIndex(index)) {
3494             final ArrayData data = getArray();
3495             if (data.has(index)) {
3496                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3497             } else {
3498                 doesNotHave(index, value, callSiteFlags);
3499             }
3500 
3501             return;
3502         }
3503 
3504         final String propName = JSType.toString(key);
3505         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3506     }
3507 
3508     @Override
3509     public void set(final int key, final double value, final int callSiteFlags) {
3510         final int index = getArrayIndex(key);
3511 
3512         if (isValidArrayIndex(index)) {
3513             final ArrayData data = getArray();
3514             if (data.has(index)) {
3515                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3516             } else {
3517                 doesNotHave(index, value, callSiteFlags);
3518             }
3519 
3520             return;
3521         }
3522 
3523         final String propName = JSType.toString(key);
3524         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3525     }
3526 
3527     @Override
3528     public void set(final int key, final Object value, final int callSiteFlags) {


3540         }
3541 
3542         final String propName = JSType.toString(key);
3543         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3544     }
3545 
3546     @Override
3547     public boolean has(final Object key) {
3548         final Object primitiveKey = JSType.toPrimitive(key);
3549         final int    index        = getArrayIndex(primitiveKey);
3550         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toPropertyKey(primitiveKey), true);
3551     }
3552 
3553     @Override
3554     public boolean has(final double key) {
3555         final int index = getArrayIndex(key);
3556         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3557     }
3558 
3559     @Override
3560     public boolean has(final long key) {
3561         final int index = getArrayIndex(key);
3562         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3563     }
3564 
3565     @Override
3566     public boolean has(final int key) {
3567         final int index = getArrayIndex(key);
3568         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3569     }
3570 
3571     private boolean hasArrayProperty(final int index) {
3572         boolean hasArrayKeys = false;
3573 
3574         for (ScriptObject self = this; self != null; self = self.getProto()) {
3575             if (self.getArray().has(index)) {
3576                 return true;
3577             }
3578             hasArrayKeys = hasArrayKeys || self.getMap().containsArrayKeys();
3579         }
3580 
3581         return hasArrayKeys && hasProperty(ArrayIndex.toKey(index), true);
3582     }
3583 
3584     @Override
3585     public boolean hasOwnProperty(final Object key) {
3586         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3587         final int    index        = getArrayIndex(primitiveKey);
3588         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toPropertyKey(primitiveKey), false);
3589     }
3590 
3591     @Override
3592     public boolean hasOwnProperty(final int key) {
3593         final int index = getArrayIndex(key);
3594         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3595     }
3596 
3597     @Override
3598     public boolean hasOwnProperty(final long key) {
3599         final int index = getArrayIndex(key);
3600         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3601     }
3602 
3603     @Override
3604     public boolean hasOwnProperty(final double key) {
3605         final int index = getArrayIndex(key);
3606         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3607     }
3608 
3609     private boolean hasOwnArrayProperty(final int index) {
3610         return getArray().has(index) || getMap().containsArrayKeys() && hasProperty(ArrayIndex.toKey(index), false);
3611     }
3612 
3613     @Override
3614     public boolean delete(final int key, final boolean strict) {
3615         final int index = getArrayIndex(key);
3616         final ArrayData array = getArray();
3617 
3618         if (array.has(index)) {
3619             if (array.canDelete(index, strict)) {
3620                 setArray(array.delete(index));
3621                 return true;
3622             }
3623             return false;
3624         }
3625         return deleteObject(JSType.toObject(key), strict);
3626     }
3627 
3628     @Override
3629     public boolean delete(final long key, final boolean strict) {
3630         final int index = getArrayIndex(key);
3631         final ArrayData array = getArray();
3632 
3633         if (array.has(index)) {
3634             if (array.canDelete(index, strict)) {
3635                 setArray(array.delete(index));
3636                 return true;
3637             }
3638             return false;
3639         }
3640 
3641         return deleteObject(JSType.toObject(key), strict);
3642     }
3643 
3644     @Override
3645     public boolean delete(final double key, final boolean strict) {
3646         final int index = getArrayIndex(key);
3647         final ArrayData array = getArray();
3648 
3649         if (array.has(index)) {
3650             if (array.canDelete(index, strict)) {
3651                 setArray(array.delete(index));
3652                 return true;
3653             }
3654             return false;
3655         }
3656 
3657         return deleteObject(JSType.toObject(key), strict);
3658     }
3659 
3660     @Override




  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
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.runtime;
  27 
  28 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
  29 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
  30 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
  31 import static jdk.nashorn.internal.lookup.Lookup.MH;
  32 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
  33 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
  34 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE;
  35 import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;

  36 import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
  37 import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
  38 import static jdk.nashorn.internal.runtime.PropertyDescriptor.GET;
  39 import static jdk.nashorn.internal.runtime.PropertyDescriptor.SET;
  40 import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
  41 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
  42 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
  43 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
  44 import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
  45 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
  46 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
  47 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isScopeFlag;
  48 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.isStrictFlag;
  49 import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
  50 
  51 import java.lang.invoke.MethodHandle;
  52 import java.lang.invoke.MethodHandles;
  53 import java.lang.invoke.MethodType;
  54 import java.lang.invoke.SwitchPoint;
  55 import java.lang.reflect.Array;


 170     public static final Call SET_ARGUMENT       = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setArgument", void.class, int.class, Object.class);
 171 
 172     /** Method handle for getting the proto of a ScriptObject */
 173     public static final Call GET_PROTO          = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
 174 
 175     /** Method handle for getting the proto of a ScriptObject */
 176     public static final Call GET_PROTO_DEPTH    = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class, int.class);
 177 
 178     /** Method handle for setting the proto of a ScriptObject */
 179     public static final Call SET_GLOBAL_OBJECT_PROTO = staticCallNoLookup(ScriptObject.class, "setGlobalObjectProto", void.class, ScriptObject.class);
 180 
 181     /** Method handle for setting the proto of a ScriptObject after checking argument */
 182     public static final Call SET_PROTO_FROM_LITERAL    = virtualCallNoLookup(ScriptObject.class, "setProtoFromLiteral", void.class, Object.class);
 183 
 184     /** Method handle for setting the user accessors of a ScriptObject */
 185     //TODO fastpath this
 186     public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
 187 
 188     static final MethodHandle[] SET_SLOW = new MethodHandle[] {
 189         findOwnMH_V("set", void.class, Object.class, int.class, int.class),

 190         findOwnMH_V("set", void.class, Object.class, double.class, int.class),
 191         findOwnMH_V("set", void.class, Object.class, Object.class, int.class)
 192     };
 193 
 194     /** Method handle to reset the map of this ScriptObject */
 195     public static final Call SET_MAP = virtualCallNoLookup(ScriptObject.class, "setMap", void.class, PropertyMap.class);
 196 
 197     static final MethodHandle CAS_MAP           = findOwnMH_V("compareAndSetMap", boolean.class, PropertyMap.class, PropertyMap.class);
 198     static final MethodHandle EXTENSION_CHECK   = findOwnMH_V("extensionCheck", boolean.class, boolean.class, String.class);
 199     static final MethodHandle ENSURE_SPILL_SIZE = findOwnMH_V("ensureSpillSize", Object.class, int.class);
 200 
 201     /**
 202      * Constructor
 203      */
 204     public ScriptObject() {
 205         this(null);
 206     }
 207 
 208     /**
 209     * Constructor


1068         } else {
1069             addOwnProperty(newUserAccessors(key, oldProperty != null ? oldProperty.getFlags() : 0, getter, setter));
1070         }
1071     }
1072 
1073     private static int getIntValue(final FindProperty find, final int programPoint) {
1074         final MethodHandle getter = find.getGetter(int.class, programPoint, null);
1075         if (getter != null) {
1076             try {
1077                 return (int)getter.invokeExact((Object)find.getGetterReceiver());
1078             } catch (final Error|RuntimeException e) {
1079                 throw e;
1080             } catch (final Throwable e) {
1081                 throw new RuntimeException(e);
1082             }
1083         }
1084 
1085         return UNDEFINED_INT;
1086     }
1087 















1088     private static double getDoubleValue(final FindProperty find, final int programPoint) {
1089         final MethodHandle getter = find.getGetter(double.class, programPoint, null);
1090         if (getter != null) {
1091             try {
1092                 return (double)getter.invokeExact((Object)find.getGetterReceiver());
1093             } catch (final Error|RuntimeException e) {
1094                 throw e;
1095             } catch (final Throwable e) {
1096                 throw new RuntimeException(e);
1097             }
1098         }
1099 
1100         return UNDEFINED_DOUBLE;
1101     }
1102 
1103     /**
1104      * Return methodHandle of value function for call.
1105      *
1106      * @param find      data from find property.
1107      * @param type      method type of function.


2770         if (array.has(index)) {
2771             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2772         }
2773 
2774         return getInt(index, JSType.toPropertyKey(primitiveKey), programPoint);
2775     }
2776 
2777     @Override
2778     public int getInt(final double key, final int programPoint) {
2779         final int       index = getArrayIndex(key);
2780         final ArrayData array = getArray();
2781 
2782         if (array.has(index)) {
2783             return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
2784         }
2785 
2786         return getInt(index, JSType.toString(key), programPoint);
2787     }
2788 
2789     @Override












2790     public int getInt(final int key, final int programPoint) {
2791         final int       index = getArrayIndex(key);
2792         final ArrayData array = getArray();
2793 
2794         if (array.has(index)) {
2795             return isValid(programPoint) ? array.getIntOptimistic(key, programPoint) : array.getInt(key);
2796         }
2797 
2798         return getInt(index, JSType.toString(key), programPoint);
2799     }
2800 


















































































2801     private double getDouble(final int index, final Object key, final int programPoint) {
2802         if (isValidArrayIndex(index)) {
2803             for (ScriptObject object = this; ; ) {
2804                 if (object.getMap().containsArrayKeys()) {
2805                     final FindProperty find = object.findProperty(key, false, this);
2806                     if (find != null) {
2807                         return getDoubleValue(find, programPoint);
2808                     }
2809                 }
2810 
2811                 if ((object = object.getProto()) == null) {
2812                     break;
2813                 }
2814 
2815                 final ArrayData array = object.getArray();
2816 
2817                 if (array.has(index)) {
2818                     return isValid(programPoint) ?
2819                         array.getDoubleOptimistic(index, programPoint) :
2820                         array.getDouble(index);


2840         if (array.has(index)) {
2841             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2842         }
2843 
2844         return getDouble(index, JSType.toPropertyKey(primitiveKey), programPoint);
2845     }
2846 
2847     @Override
2848     public double getDouble(final double key, final int programPoint) {
2849         final int       index = getArrayIndex(key);
2850         final ArrayData array = getArray();
2851 
2852         if (array.has(index)) {
2853             return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
2854         }
2855 
2856         return getDouble(index, JSType.toString(key), programPoint);
2857     }
2858 
2859     @Override












2860     public double getDouble(final int key, final int programPoint) {
2861         final int       index = getArrayIndex(key);
2862         final ArrayData array = getArray();
2863 
2864         if (array.has(index)) {
2865             return isValid(programPoint) ? array.getDoubleOptimistic(key, programPoint) : array.getDouble(key);
2866         }
2867 
2868         return getDouble(index, JSType.toString(key), programPoint);
2869     }
2870 
2871     private Object get(final int index, final Object key) {
2872         if (isValidArrayIndex(index)) {
2873             for (ScriptObject object = this; ; ) {
2874                 if (object.getMap().containsArrayKeys()) {
2875                     final FindProperty find = object.findProperty(key, false, this);
2876 
2877                     if (find != null) {
2878                         return find.getObjectValue();
2879                     }


2909         if (array.has(index)) {
2910             return array.getObject(index);
2911         }
2912 
2913         return get(index, JSType.toPropertyKey(primitiveKey));
2914     }
2915 
2916     @Override
2917     public Object get(final double key) {
2918         final int index = getArrayIndex(key);
2919         final ArrayData array = getArray();
2920 
2921         if (array.has(index)) {
2922             return array.getObject(index);
2923         }
2924 
2925         return get(index, JSType.toString(key));
2926     }
2927 
2928     @Override












2929     public Object get(final int key) {
2930         final int index = getArrayIndex(key);
2931         final ArrayData array = getArray();
2932 
2933         if (array.has(index)) {
2934             return array.getObject(index);
2935         }
2936 
2937         return get(index, JSType.toString(key));
2938     }
2939 
2940     private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final int callSiteFlags) {
2941         if (getMap().containsArrayKeys()) {
2942             final String       key  = JSType.toString(longIndex);
2943             final FindProperty find = findProperty(key, true);
2944             if (find != null) {
2945                 setObject(find, callSiteFlags, key, value);
2946                 return true;
2947             }
2948         }


2991             if (!isExtensible()) {
2992                 if (isStrictFlag(callSiteFlags)) {
2993                     throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
2994                 }
2995                 return true;
2996             }
2997             setArray(getArray().ensure(longIndex));
2998         }
2999         return false;
3000     }
3001 
3002     private void doesNotHave(final int index, final int value, final int callSiteFlags) {
3003         final long oldLength = getArray().length();
3004         final long longIndex = ArrayIndex.toLongIndex(index);
3005         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3006             final boolean strict = isStrictFlag(callSiteFlags);
3007             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3008         }
3009     }
3010 









3011     private void doesNotHave(final int index, final double value, final int callSiteFlags) {
3012         final long oldLength = getArray().length();
3013         final long longIndex = ArrayIndex.toLongIndex(index);
3014         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3015             final boolean strict = isStrictFlag(callSiteFlags);
3016             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3017         }
3018     }
3019 
3020     private void doesNotHave(final int index, final Object value, final int callSiteFlags) {
3021         final long oldLength = getArray().length();
3022         final long longIndex = ArrayIndex.toLongIndex(index);
3023         if (!doesNotHaveCheckArrayKeys(longIndex, value, callSiteFlags) && !doesNotHaveEnsureLength(longIndex, oldLength, callSiteFlags)) {
3024             final boolean strict = isStrictFlag(callSiteFlags);
3025             setArray(getArray().set(index, value, strict).safeDelete(oldLength, longIndex - 1, strict));
3026         }
3027     }
3028 
3029     /**
3030      * This is the most generic of all Object setters. Most of the others use this in some form.


3097     public void set(final Object key, final int value, final int callSiteFlags) {
3098         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3099         final int    index        = getArrayIndex(primitiveKey);
3100 
3101         if (isValidArrayIndex(index)) {
3102             final ArrayData data = getArray();
3103             if (data.has(index)) {
3104                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3105             } else {
3106                 doesNotHave(index, value, callSiteFlags);
3107             }
3108 
3109             return;
3110         }
3111 
3112         final Object propName = JSType.toPropertyKey(primitiveKey);
3113         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3114     }
3115 
3116     @Override




















3117     public void set(final Object key, final double value, final int callSiteFlags) {
3118         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3119         final int    index        = getArrayIndex(primitiveKey);
3120 
3121         if (isValidArrayIndex(index)) {
3122             final ArrayData data = getArray();
3123             if (data.has(index)) {
3124                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3125             } else {
3126                 doesNotHave(index, value, callSiteFlags);
3127             }
3128 
3129             return;
3130         }
3131 
3132         final Object propName = JSType.toPropertyKey(primitiveKey);
3133         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3134     }
3135 
3136     @Override


3156     @Override
3157     public void set(final double key, final int value, final int callSiteFlags) {
3158         final int index = getArrayIndex(key);
3159 
3160         if (isValidArrayIndex(index)) {
3161             final ArrayData data = getArray();
3162             if (data.has(index)) {
3163                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3164             } else {
3165                 doesNotHave(index, value, callSiteFlags);
3166             }
3167 
3168             return;
3169         }
3170 
3171         final String propName = JSType.toString(key);
3172         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3173     }
3174 
3175     @Override



















3176     public void set(final double key, final double value, final int callSiteFlags) {
3177         final int index = getArrayIndex(key);
3178 
3179         if (isValidArrayIndex(index)) {
3180             final ArrayData data = getArray();
3181             if (data.has(index)) {
3182                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3183             } else {
3184                 doesNotHave(index, value, callSiteFlags);
3185             }
3186 
3187             return;
3188         }
3189 
3190         final String propName = JSType.toString(key);
3191         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3192     }
3193 
3194     @Override
3195     public void set(final double key, final Object value, final int callSiteFlags) {
3196         final int index = getArrayIndex(key);
3197 
3198         if (isValidArrayIndex(index)) {
3199             final ArrayData data = getArray();
3200             if (data.has(index)) {
3201                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3202             } else {
3203                 doesNotHave(index, value, callSiteFlags);
3204             }
3205 
3206             return;
3207         }
3208 
3209         final String propName = JSType.toString(key);
3210         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3211     }
3212 
3213     @Override












































































3214     public void set(final int key, final int value, final int callSiteFlags) {
3215         final int index = getArrayIndex(key);
3216         if (isValidArrayIndex(index)) {
3217             if (getArray().has(index)) {
3218                 final ArrayData data = getArray();
3219                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3220             } else {
3221                 doesNotHave(index, value, callSiteFlags);
3222             }
3223             return;
3224         }
3225 
3226         final String propName = JSType.toString(key);
3227         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3228     }
3229 
3230     @Override



















3231     public void set(final int key, final double value, final int callSiteFlags) {
3232         final int index = getArrayIndex(key);
3233 
3234         if (isValidArrayIndex(index)) {
3235             final ArrayData data = getArray();
3236             if (data.has(index)) {
3237                 setArray(data.set(index, value, isStrictFlag(callSiteFlags)));
3238             } else {
3239                 doesNotHave(index, value, callSiteFlags);
3240             }
3241 
3242             return;
3243         }
3244 
3245         final String propName = JSType.toString(key);
3246         setObject(findProperty(propName, true), callSiteFlags, propName, JSType.toObject(value));
3247     }
3248 
3249     @Override
3250     public void set(final int key, final Object value, final int callSiteFlags) {


3262         }
3263 
3264         final String propName = JSType.toString(key);
3265         setObject(findProperty(propName, true), callSiteFlags, propName, value);
3266     }
3267 
3268     @Override
3269     public boolean has(final Object key) {
3270         final Object primitiveKey = JSType.toPrimitive(key);
3271         final int    index        = getArrayIndex(primitiveKey);
3272         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toPropertyKey(primitiveKey), true);
3273     }
3274 
3275     @Override
3276     public boolean has(final double key) {
3277         final int index = getArrayIndex(key);
3278         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3279     }
3280 
3281     @Override






3282     public boolean has(final int key) {
3283         final int index = getArrayIndex(key);
3284         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(key), true);
3285     }
3286 
3287     private boolean hasArrayProperty(final int index) {
3288         boolean hasArrayKeys = false;
3289 
3290         for (ScriptObject self = this; self != null; self = self.getProto()) {
3291             if (self.getArray().has(index)) {
3292                 return true;
3293             }
3294             hasArrayKeys = hasArrayKeys || self.getMap().containsArrayKeys();
3295         }
3296 
3297         return hasArrayKeys && hasProperty(ArrayIndex.toKey(index), true);
3298     }
3299 
3300     @Override
3301     public boolean hasOwnProperty(final Object key) {
3302         final Object primitiveKey = JSType.toPrimitive(key, String.class);
3303         final int    index        = getArrayIndex(primitiveKey);
3304         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toPropertyKey(primitiveKey), false);
3305     }
3306 
3307     @Override
3308     public boolean hasOwnProperty(final int key) {
3309         final int index = getArrayIndex(key);
3310         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3311     }
3312 
3313     @Override






3314     public boolean hasOwnProperty(final double key) {
3315         final int index = getArrayIndex(key);
3316         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(key), false);
3317     }
3318 
3319     private boolean hasOwnArrayProperty(final int index) {
3320         return getArray().has(index) || getMap().containsArrayKeys() && hasProperty(ArrayIndex.toKey(index), false);
3321     }
3322 
3323     @Override
3324     public boolean delete(final int key, final boolean strict) {
3325         final int index = getArrayIndex(key);
3326         final ArrayData array = getArray();
3327 
3328         if (array.has(index)) {
3329             if (array.canDelete(index, strict)) {
3330                 setArray(array.delete(index));
3331                 return true;
3332             }
3333             return false;
3334         }
















3335         return deleteObject(JSType.toObject(key), strict);
3336     }
3337 
3338     @Override
3339     public boolean delete(final double key, final boolean strict) {
3340         final int index = getArrayIndex(key);
3341         final ArrayData array = getArray();
3342 
3343         if (array.has(index)) {
3344             if (array.canDelete(index, strict)) {
3345                 setArray(array.delete(index));
3346                 return true;
3347             }
3348             return false;
3349         }
3350 
3351         return deleteObject(JSType.toObject(key), strict);
3352     }
3353 
3354     @Override


< prev index next >