]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/GenericArgumentsInlines.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / GenericArgumentsInlines.h
CommitLineData
ed1e77d3
A
1/*
2 * Copyright (C) 2015 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef GenericArgumentsInlines_h
27#define GenericArgumentsInlines_h
28
29#include "GenericArguments.h"
30#include "JSCInlines.h"
31
32namespace JSC {
33
34template<typename Type>
35bool GenericArguments<Type>::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName ident, PropertySlot& slot)
36{
37 Type* thisObject = jsCast<Type*>(object);
38 VM& vm = exec->vm();
39
40 if (!thisObject->overrodeThings()) {
41 if (ident == vm.propertyNames->length) {
42 slot.setValue(thisObject, DontEnum, jsNumber(thisObject->internalLength()));
43 return true;
44 }
45 if (ident == vm.propertyNames->callee) {
46 slot.setValue(thisObject, DontEnum, thisObject->callee().get());
47 return true;
48 }
49 if (ident == vm.propertyNames->iteratorSymbol) {
50 slot.setValue(thisObject, DontEnum, thisObject->globalObject()->arrayProtoValuesFunction());
51 return true;
52 }
53 }
54
55 Optional<uint32_t> index = parseIndex(ident);
56 if (index && thisObject->canAccessIndexQuickly(index.value())) {
57 slot.setValue(thisObject, None, thisObject->getIndexQuickly(index.value()));
58 return true;
59 }
60
61 return Base::getOwnPropertySlot(thisObject, exec, ident, slot);
62}
63
64template<typename Type>
65bool GenericArguments<Type>::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
66{
67 Type* thisObject = jsCast<Type*>(object);
68
69 if (thisObject->canAccessIndexQuickly(index)) {
70 slot.setValue(thisObject, None, thisObject->getIndexQuickly(index));
71 return true;
72 }
73
74 return Base::getOwnPropertySlotByIndex(object, exec, index, slot);
75}
76
77template<typename Type>
78void GenericArguments<Type>::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)
79{
80 Type* thisObject = jsCast<Type*>(object);
81
82 for (unsigned i = 0; i < thisObject->internalLength(); ++i) {
83 if (!thisObject->canAccessIndexQuickly(i))
84 continue;
85 array.add(Identifier::from(exec, i));
86 }
87 if (mode.includeDontEnumProperties() && !thisObject->overrodeThings()) {
88 array.add(exec->propertyNames().length);
89 array.add(exec->propertyNames().callee);
90 if (mode.includeSymbolProperties())
91 array.add(exec->propertyNames().iteratorSymbol);
92 }
93 Base::getOwnPropertyNames(thisObject, exec, array, mode);
94}
95
96template<typename Type>
97void GenericArguments<Type>::put(JSCell* cell, ExecState* exec, PropertyName ident, JSValue value, PutPropertySlot& slot)
98{
99 Type* thisObject = jsCast<Type*>(cell);
100 VM& vm = exec->vm();
101
102 if (!thisObject->overrodeThings()
103 && (ident == vm.propertyNames->length
104 || ident == vm.propertyNames->callee
105 || ident == vm.propertyNames->iteratorSymbol)) {
106 thisObject->overrideThings(vm);
107 PutPropertySlot dummy = slot; // This put is not cacheable, so we shadow the slot that was given to us.
108 Base::put(thisObject, exec, ident, value, dummy);
109 return;
110 }
111
112 Optional<uint32_t> index = parseIndex(ident);
113 if (index && thisObject->canAccessIndexQuickly(index.value())) {
114 thisObject->setIndexQuickly(vm, index.value(), value);
115 return;
116 }
117
118 Base::put(thisObject, exec, ident, value, slot);
119}
120
121template<typename Type>
122void GenericArguments<Type>::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow)
123{
124 Type* thisObject = jsCast<Type*>(cell);
125 VM& vm = exec->vm();
126
127 if (thisObject->canAccessIndexQuickly(index)) {
128 thisObject->setIndexQuickly(vm, index, value);
129 return;
130 }
131
132 return Base::putByIndex(cell, exec, index, value, shouldThrow);
133}
134
135template<typename Type>
136bool GenericArguments<Type>::deleteProperty(JSCell* cell, ExecState* exec, PropertyName ident)
137{
138 Type* thisObject = jsCast<Type*>(cell);
139 VM& vm = exec->vm();
140
141 if (!thisObject->overrodeThings()
142 && (ident == vm.propertyNames->length
143 || ident == vm.propertyNames->callee
144 || ident == vm.propertyNames->iteratorSymbol))
145 thisObject->overrideThings(vm);
146
147 Optional<uint32_t> index = parseIndex(ident);
148 if (index && thisObject->canAccessIndexQuickly(index.value())) {
149 thisObject->overrideArgument(vm, index.value());
150 return true;
151 }
152
153 return Base::deleteProperty(thisObject, exec, ident);
154}
155
156template<typename Type>
157bool GenericArguments<Type>::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned index)
158{
159 Type* thisObject = jsCast<Type*>(cell);
160 VM& vm = exec->vm();
161
162 if (thisObject->canAccessIndexQuickly(index)) {
163 thisObject->overrideArgument(vm, index);
164 return true;
165 }
166
167 return Base::deletePropertyByIndex(cell, exec, index);
168}
169
170template<typename Type>
171bool GenericArguments<Type>::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName ident, const PropertyDescriptor& descriptor, bool shouldThrow)
172{
173 Type* thisObject = jsCast<Type*>(object);
174 VM& vm = exec->vm();
175
176 if (ident == vm.propertyNames->length
177 || ident == vm.propertyNames->callee
178 || ident == vm.propertyNames->iteratorSymbol)
179 thisObject->overrideThingsIfNecessary(vm);
180 else {
181 Optional<uint32_t> optionalIndex = parseIndex(ident);
182 if (optionalIndex && thisObject->canAccessIndexQuickly(optionalIndex.value())) {
183 uint32_t index = optionalIndex.value();
184 if (!descriptor.isAccessorDescriptor()) {
185 // If the property is not deleted and we are using a non-accessor descriptor, then
186 // make sure that the aliased argument sees the value.
187 if (descriptor.value())
188 thisObject->setIndexQuickly(vm, index, descriptor.value());
189
190 // If the property is not deleted and we are using a non-accessor, writable
191 // descriptor, then we are done. The argument continues to be aliased. Note that we
192 // ignore the request to change enumerability. We appear to have always done so, in
193 // cases where the argument was still aliased.
194 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=141952
195 if (descriptor.writable())
196 return true;
197 }
198
199 // If the property is a non-deleted argument, then move it into the base object and
200 // then delete it.
201 JSValue value = thisObject->getIndexQuickly(index);
202 ASSERT(value);
203 object->putDirectMayBeIndex(exec, ident, value);
204 thisObject->overrideArgument(vm, index);
205 }
206 }
207
208 // Now just let the normal object machinery do its thing.
209 return Base::defineOwnProperty(object, exec, ident, descriptor, shouldThrow);
210}
211
212template<typename Type>
213void GenericArguments<Type>::copyToArguments(ExecState* exec, VirtualRegister firstElementDest, unsigned offset, unsigned length)
214{
215 Type* thisObject = static_cast<Type*>(this);
216 for (unsigned i = 0; i < length; ++i) {
217 if (thisObject->canAccessIndexQuickly(i + offset))
218 exec->r(firstElementDest + i) = thisObject->getIndexQuickly(i + offset);
219 else {
220 exec->r(firstElementDest + i) = get(exec, i + offset);
221 if (UNLIKELY(exec->vm().exception()))
222 return;
223 }
224 }
225}
226
227} // namespace JSC
228
229#endif // GenericArgumentsInlines_h
230