Wed, 26 Jun 2013 15:40:52 +0200
8019157: Avoid calling ScriptObject.setProto() if possible
Reviewed-by: jlaskey, sundar
1 /*
2 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package jdk.nashorn.internal.objects;
28 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
29 import static jdk.nashorn.internal.lookup.Lookup.MH;
31 import java.lang.invoke.MethodHandle;
32 import java.lang.invoke.MethodHandles;
33 import java.util.Arrays;
34 import jdk.nashorn.internal.runtime.Property;
35 import jdk.nashorn.internal.runtime.PropertyMap;
36 import jdk.nashorn.internal.runtime.ScriptFunction;
37 import jdk.nashorn.internal.runtime.ScriptObject;
38 import jdk.nashorn.internal.runtime.arrays.ArrayData;
39 import jdk.nashorn.internal.lookup.Lookup;
40 import jdk.nashorn.internal.lookup.MethodHandleFactory;
42 /**
43 * ECMA 10.6 Arguments Object.
44 *
45 * Arguments object for strict mode functions.
46 */
47 public final class NativeStrictArguments extends ScriptObject {
49 private static final MethodHandle G$LENGTH = findOwnMH("G$length", Object.class, Object.class);
51 private static final MethodHandle S$LENGTH = findOwnMH("S$length", void.class, Object.class, Object.class);
53 // property map for strict mode arguments object
54 private static final PropertyMap map$;
56 static {
57 PropertyMap map = PropertyMap.newMap(NativeStrictArguments.class);
58 map = Lookup.newProperty(map, "length", Property.NOT_ENUMERABLE, G$LENGTH, S$LENGTH);
59 // In strict mode, the caller and callee properties should throw TypeError
60 // Need to add properties directly to map since slots are assigned speculatively by newUserAccessors.
61 final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
62 map = map.addProperty(map.newUserAccessors("caller", flags));
63 map = map.addProperty(map.newUserAccessors("callee", flags));
64 map$ = map;
65 }
67 private Object length;
68 private final Object[] namedArgs;
70 NativeStrictArguments(final ScriptObject proto, final Object[] values, final int numParams) {
71 super(proto, map$);
72 setIsArguments();
74 final ScriptFunction func = ScriptFunctionImpl.getTypeErrorThrower();
75 // We have to fill user accessor functions late as these are stored
76 // in this object rather than in the PropertyMap of this object.
77 setUserAccessors("caller", func, func);
78 setUserAccessors("callee", func, func);
80 setArray(ArrayData.allocate(values));
81 this.length = values.length;
83 // extend/truncate named arg array as needed and copy values
84 this.namedArgs = new Object[numParams];
85 if (numParams > values.length) {
86 Arrays.fill(namedArgs, UNDEFINED);
87 }
88 System.arraycopy(values, 0, namedArgs, 0, Math.min(namedArgs.length, values.length));
89 }
91 @Override
92 public String getClassName() {
93 return "Arguments";
94 }
96 /**
97 * getArgument is used for named argument access.
98 */
99 @Override
100 public Object getArgument(final int key) {
101 return (key >=0 && key < namedArgs.length) ? namedArgs[key] : UNDEFINED;
102 }
104 /**
105 * setArgument is used for named argument set.
106 */
107 @Override
108 public void setArgument(final int key, final Object value) {
109 if (key >= 0 && key < namedArgs.length) {
110 namedArgs[key] = value;
111 }
112 }
114 /**
115 * Length getter
116 * @param self self reference
117 * @return length property value
118 */
119 public static Object G$length(final Object self) {
120 if (self instanceof NativeStrictArguments) {
121 return ((NativeStrictArguments)self).getArgumentsLength();
122 }
123 return 0;
124 }
126 /**
127 * Length setter
128 * @param self self reference
129 * @param value value for length property
130 */
131 public static void S$length(final Object self, final Object value) {
132 if (self instanceof NativeStrictArguments) {
133 ((NativeStrictArguments)self).setArgumentsLength(value);
134 }
135 }
137 private Object getArgumentsLength() {
138 return length;
139 }
141 private void setArgumentsLength(final Object length) {
142 this.length = length;
143 }
145 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
146 try {
147 return MethodHandles.lookup().findStatic(NativeStrictArguments.class, name, MH.type(rtype, types));
148 } catch (final NoSuchMethodException | IllegalAccessException e) {
149 throw new MethodHandleFactory.LookupException(e);
150 }
151 }
152 }