• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
3  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
5  *  Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
6  *  Copyright (C) 2007 Maks Orlovich
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Library General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Library General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Library General Public License
19  *  along with this library; see the file COPYING.LIB.  If not, write to
20  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  *  Boston, MA 02110-1301, USA.
22  *
23  */
24 
25 #include "config.h"
26 #include "Arguments.h"
27 
28 #include "JSActivation.h"
29 #include "JSFunction.h"
30 #include "JSGlobalObject.h"
31 
32 using namespace std;
33 
34 namespace JSC {
35 
36 ASSERT_CLASS_FITS_IN_CELL(Arguments);
37 
38 const ClassInfo Arguments::info = { "Arguments", 0, 0, 0 };
39 
~Arguments()40 Arguments::~Arguments()
41 {
42     if (d->extraArguments != d->extraArgumentsFixedBuffer)
43         delete [] d->extraArguments;
44 }
45 
markChildren(MarkStack & markStack)46 void Arguments::markChildren(MarkStack& markStack)
47 {
48     JSObject::markChildren(markStack);
49 
50     if (d->registerArray)
51         markStack.appendValues(reinterpret_cast<JSValue*>(d->registerArray.get()), d->numParameters);
52 
53     if (d->extraArguments) {
54         unsigned numExtraArguments = d->numArguments - d->numParameters;
55         markStack.appendValues(reinterpret_cast<JSValue*>(d->extraArguments), numExtraArguments);
56     }
57 
58     markStack.append(d->callee);
59 
60     if (d->activation)
61         markStack.append(d->activation);
62 }
63 
copyToRegisters(ExecState * exec,Register * buffer,uint32_t maxSize)64 void Arguments::copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize)
65 {
66     if (UNLIKELY(d->overrodeLength)) {
67         unsigned length = min(get(exec, exec->propertyNames().length).toUInt32(exec), maxSize);
68         for (unsigned i = 0; i < length; i++)
69             buffer[i] = get(exec, i);
70         return;
71     }
72 
73     if (LIKELY(!d->deletedArguments)) {
74         unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
75         unsigned i = 0;
76         for (; i < parametersLength; ++i)
77             buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
78         for (; i < d->numArguments; ++i)
79             buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
80         return;
81     }
82 
83     unsigned parametersLength = min(min(d->numParameters, d->numArguments), maxSize);
84     unsigned i = 0;
85     for (; i < parametersLength; ++i) {
86         if (!d->deletedArguments[i])
87             buffer[i] = d->registers[d->firstParameterIndex + i].jsValue();
88         else
89             buffer[i] = get(exec, i);
90     }
91     for (; i < d->numArguments; ++i) {
92         if (!d->deletedArguments[i])
93             buffer[i] = d->extraArguments[i - d->numParameters].jsValue();
94         else
95             buffer[i] = get(exec, i);
96     }
97 }
98 
fillArgList(ExecState * exec,MarkedArgumentBuffer & args)99 void Arguments::fillArgList(ExecState* exec, MarkedArgumentBuffer& args)
100 {
101     if (UNLIKELY(d->overrodeLength)) {
102         unsigned length = get(exec, exec->propertyNames().length).toUInt32(exec);
103         for (unsigned i = 0; i < length; i++)
104             args.append(get(exec, i));
105         return;
106     }
107 
108     if (LIKELY(!d->deletedArguments)) {
109         if (LIKELY(!d->numParameters)) {
110             args.initialize(d->extraArguments, d->numArguments);
111             return;
112         }
113 
114         if (d->numParameters == d->numArguments) {
115             args.initialize(&d->registers[d->firstParameterIndex], d->numArguments);
116             return;
117         }
118 
119         unsigned parametersLength = min(d->numParameters, d->numArguments);
120         unsigned i = 0;
121         for (; i < parametersLength; ++i)
122             args.append(d->registers[d->firstParameterIndex + i].jsValue());
123         for (; i < d->numArguments; ++i)
124             args.append(d->extraArguments[i - d->numParameters].jsValue());
125         return;
126     }
127 
128     unsigned parametersLength = min(d->numParameters, d->numArguments);
129     unsigned i = 0;
130     for (; i < parametersLength; ++i) {
131         if (!d->deletedArguments[i])
132             args.append(d->registers[d->firstParameterIndex + i].jsValue());
133         else
134             args.append(get(exec, i));
135     }
136     for (; i < d->numArguments; ++i) {
137         if (!d->deletedArguments[i])
138             args.append(d->extraArguments[i - d->numParameters].jsValue());
139         else
140             args.append(get(exec, i));
141     }
142 }
143 
getOwnPropertySlot(ExecState * exec,unsigned i,PropertySlot & slot)144 bool Arguments::getOwnPropertySlot(ExecState* exec, unsigned i, PropertySlot& slot)
145 {
146     if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
147         if (i < d->numParameters) {
148             slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
149         } else
150             slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
151         return true;
152     }
153 
154     return JSObject::getOwnPropertySlot(exec, Identifier(exec, UString::from(i)), slot);
155 }
156 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)157 bool Arguments::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
158 {
159     bool isArrayIndex;
160     unsigned i = propertyName.toArrayIndex(&isArrayIndex);
161     if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
162         if (i < d->numParameters) {
163             slot.setRegisterSlot(&d->registers[d->firstParameterIndex + i]);
164         } else
165             slot.setValue(d->extraArguments[i - d->numParameters].jsValue());
166         return true;
167     }
168 
169     if (propertyName == exec->propertyNames().length && LIKELY(!d->overrodeLength)) {
170         slot.setValue(jsNumber(exec, d->numArguments));
171         return true;
172     }
173 
174     if (propertyName == exec->propertyNames().callee && LIKELY(!d->overrodeCallee)) {
175         slot.setValue(d->callee);
176         return true;
177     }
178 
179     return JSObject::getOwnPropertySlot(exec, propertyName, slot);
180 }
181 
put(ExecState * exec,unsigned i,JSValue value,PutPropertySlot & slot)182 void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot)
183 {
184     if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
185         if (i < d->numParameters)
186             d->registers[d->firstParameterIndex + i] = JSValue(value);
187         else
188             d->extraArguments[i - d->numParameters] = JSValue(value);
189         return;
190     }
191 
192     JSObject::put(exec, Identifier(exec, UString::from(i)), value, slot);
193 }
194 
put(ExecState * exec,const Identifier & propertyName,JSValue value,PutPropertySlot & slot)195 void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
196 {
197     bool isArrayIndex;
198     unsigned i = propertyName.toArrayIndex(&isArrayIndex);
199     if (isArrayIndex && i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) {
200         if (i < d->numParameters)
201             d->registers[d->firstParameterIndex + i] = JSValue(value);
202         else
203             d->extraArguments[i - d->numParameters] = JSValue(value);
204         return;
205     }
206 
207     if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
208         d->overrodeLength = true;
209         putDirect(propertyName, value, DontEnum);
210         return;
211     }
212 
213     if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
214         d->overrodeCallee = true;
215         putDirect(propertyName, value, DontEnum);
216         return;
217     }
218 
219     JSObject::put(exec, propertyName, value, slot);
220 }
221 
deleteProperty(ExecState * exec,unsigned i)222 bool Arguments::deleteProperty(ExecState* exec, unsigned i)
223 {
224     if (i < d->numArguments) {
225         if (!d->deletedArguments) {
226             d->deletedArguments.set(new bool[d->numArguments]);
227             memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
228         }
229         if (!d->deletedArguments[i]) {
230             d->deletedArguments[i] = true;
231             return true;
232         }
233     }
234 
235     return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)));
236 }
237 
deleteProperty(ExecState * exec,const Identifier & propertyName)238 bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName)
239 {
240     bool isArrayIndex;
241     unsigned i = propertyName.toArrayIndex(&isArrayIndex);
242     if (isArrayIndex && i < d->numArguments) {
243         if (!d->deletedArguments) {
244             d->deletedArguments.set(new bool[d->numArguments]);
245             memset(d->deletedArguments.get(), 0, sizeof(bool) * d->numArguments);
246         }
247         if (!d->deletedArguments[i]) {
248             d->deletedArguments[i] = true;
249             return true;
250         }
251     }
252 
253     if (propertyName == exec->propertyNames().length && !d->overrodeLength) {
254         d->overrodeLength = true;
255         return true;
256     }
257 
258     if (propertyName == exec->propertyNames().callee && !d->overrodeCallee) {
259         d->overrodeCallee = true;
260         return true;
261     }
262 
263     return JSObject::deleteProperty(exec, propertyName);
264 }
265 
266 } // namespace JSC
267