128 if (sobj.isScope()) {
129 return createGlobalPropertySetter();
130 }
131
132 return createNewPropertySetter(builtinSwitchPoint);
133 }
134
135 private void checkStrictCreateNewVariable() {
136 // In strict mode, assignment can not create a new variable.
137 // See also ECMA Annex C item 4. ReferenceError is thrown.
138 if (NashornCallSiteDescriptor.isScope(desc) && NashornCallSiteDescriptor.isStrict(desc)) {
139 throw referenceError("not.defined", getName());
140 }
141 }
142
143 private SetMethod createExistingPropertySetter() {
144 final Property property = find.getProperty();
145 final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
146 final MethodHandle methodHandle;
147
148 if (NashornCallSiteDescriptor.isDeclaration(desc)) {
149 assert property.needsDeclaration();
150 // This is a LET or CONST being declared. The property is already there but flagged as needing declaration.
151 // We create a new PropertyMap with the flag removed. The map is installed with a fast compare-and-set
152 // method if the pre-callsite map is stable (which should be the case for function scopes except for
153 // non-strict functions containing eval() with var). Otherwise we have to use a slow setter that creates
154 // a new PropertyMap on the fly.
155 final PropertyMap oldMap = getMap();
156 final Property newProperty = property.removeFlags(Property.NEEDS_DECLARATION);
157 final PropertyMap newMap = oldMap.replaceProperty(property, newProperty);
158 final MethodHandle fastSetter = find.replaceProperty(newProperty).getSetter(type, isStrict, request);
159 final MethodHandle slowSetter = MH.insertArguments(ScriptObject.DECLARE_AND_SET, 1, getName()).asType(fastSetter.type());
160
161 // cas map used as guard, if true that means we can do the set fast
162 MethodHandle casMap = MH.insertArguments(ScriptObject.CAS_MAP, 1, oldMap, newMap);
163 casMap = MH.dropArguments(casMap, 1, type);
164 casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class));
165 methodHandle = MH.guardWithTest(casMap, fastSetter, slowSetter);
166 } else {
167 methodHandle = find.getSetter(type, isStrict, request);
168 }
169
|
128 if (sobj.isScope()) {
129 return createGlobalPropertySetter();
130 }
131
132 return createNewPropertySetter(builtinSwitchPoint);
133 }
134
135 private void checkStrictCreateNewVariable() {
136 // In strict mode, assignment can not create a new variable.
137 // See also ECMA Annex C item 4. ReferenceError is thrown.
138 if (NashornCallSiteDescriptor.isScope(desc) && NashornCallSiteDescriptor.isStrict(desc)) {
139 throw referenceError("not.defined", getName());
140 }
141 }
142
143 private SetMethod createExistingPropertySetter() {
144 final Property property = find.getProperty();
145 final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
146 final MethodHandle methodHandle;
147
148 if (NashornCallSiteDescriptor.isDeclaration(desc) && property.needsDeclaration()) {
149 // This is a LET or CONST being declared. The property is already there but flagged as needing declaration.
150 // We create a new PropertyMap with the flag removed. The map is installed with a fast compare-and-set
151 // method if the pre-callsite map is stable (which should be the case for function scopes except for
152 // non-strict functions containing eval() with var). Otherwise we have to use a slow setter that creates
153 // a new PropertyMap on the fly.
154 final PropertyMap oldMap = getMap();
155 final Property newProperty = property.removeFlags(Property.NEEDS_DECLARATION);
156 final PropertyMap newMap = oldMap.replaceProperty(property, newProperty);
157 final MethodHandle fastSetter = find.replaceProperty(newProperty).getSetter(type, isStrict, request);
158 final MethodHandle slowSetter = MH.insertArguments(ScriptObject.DECLARE_AND_SET, 1, getName()).asType(fastSetter.type());
159
160 // cas map used as guard, if true that means we can do the set fast
161 MethodHandle casMap = MH.insertArguments(ScriptObject.CAS_MAP, 1, oldMap, newMap);
162 casMap = MH.dropArguments(casMap, 1, type);
163 casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class));
164 methodHandle = MH.guardWithTest(casMap, fastSetter, slowSetter);
165 } else {
166 methodHandle = find.getSetter(type, isStrict, request);
167 }
168
|