]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Arguments.h
74bb6ad8eede9223dabc0f10c0fe202d31c61d7b
[apple/javascriptcore.git] / runtime / Arguments.h
1 /*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca)
5 * Copyright (C) 2007 Maks Orlovich
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24 #ifndef Arguments_h
25 #define Arguments_h
26
27 #include "JSActivation.h"
28 #include "JSFunction.h"
29 #include "JSGlobalObject.h"
30 #include "Interpreter.h"
31
32 namespace JSC {
33
34 struct ArgumentsData : Noncopyable {
35 JSActivation* activation;
36
37 unsigned numParameters;
38 ptrdiff_t firstParameterIndex;
39 unsigned numArguments;
40
41 Register* registers;
42 OwnArrayPtr<Register> registerArray;
43
44 Register* extraArguments;
45 OwnArrayPtr<bool> deletedArguments;
46 Register extraArgumentsFixedBuffer[4];
47
48 JSFunction* callee;
49 bool overrodeLength : 1;
50 bool overrodeCallee : 1;
51 };
52
53
54 class Arguments : public JSObject {
55 public:
56 enum NoParametersType { NoParameters };
57
58 Arguments(CallFrame*);
59 Arguments(CallFrame*, NoParametersType);
60 virtual ~Arguments();
61
62 static const ClassInfo info;
63
64 virtual void mark();
65
66 void fillArgList(ExecState*, MarkedArgumentBuffer&);
67
68 uint32_t numProvidedArguments(ExecState* exec) const
69 {
70 if (UNLIKELY(d->overrodeLength))
71 return get(exec, exec->propertyNames().length).toUInt32(exec);
72 return d->numArguments;
73 }
74
75 void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
76 void copyRegisters();
77 bool isTornOff() const { return d->registerArray; }
78 void setActivation(JSActivation* activation)
79 {
80 d->activation = activation;
81 d->registers = &activation->registerAt(0);
82 }
83
84 static PassRefPtr<Structure> createStructure(JSValue prototype)
85 {
86 return Structure::create(prototype, TypeInfo(ObjectType));
87 }
88
89 private:
90 void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
91 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
92 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
93 virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
94 virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&);
95 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
96 virtual bool deleteProperty(ExecState*, unsigned propertyName);
97
98 virtual const ClassInfo* classInfo() const { return &info; }
99
100 void init(CallFrame*);
101
102 OwnPtr<ArgumentsData> d;
103 };
104
105 Arguments* asArguments(JSValue);
106
107 inline Arguments* asArguments(JSValue value)
108 {
109 ASSERT(asObject(value)->inherits(&Arguments::info));
110 return static_cast<Arguments*>(asObject(value));
111 }
112
113 ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
114 {
115 function = callFrame->callee();
116
117 int numParameters = function->body()->parameterCount();
118 argc = callFrame->argumentCount();
119
120 if (argc <= numParameters)
121 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
122 else
123 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;
124
125 argc -= 1; // - 1 to skip "this"
126 firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;
127 }
128
129 inline Arguments::Arguments(CallFrame* callFrame)
130 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
131 , d(new ArgumentsData)
132 {
133 JSFunction* callee;
134 ptrdiff_t firstParameterIndex;
135 Register* argv;
136 int numArguments;
137 getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
138
139 d->numParameters = callee->body()->parameterCount();
140 d->firstParameterIndex = firstParameterIndex;
141 d->numArguments = numArguments;
142
143 d->activation = 0;
144 d->registers = callFrame->registers();
145
146 Register* extraArguments;
147 if (d->numArguments <= d->numParameters)
148 extraArguments = 0;
149 else {
150 unsigned numExtraArguments = d->numArguments - d->numParameters;
151 if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
152 extraArguments = new Register[numExtraArguments];
153 else
154 extraArguments = d->extraArgumentsFixedBuffer;
155 for (unsigned i = 0; i < numExtraArguments; ++i)
156 extraArguments[i] = argv[d->numParameters + i];
157 }
158
159 d->extraArguments = extraArguments;
160
161 d->callee = callee;
162 d->overrodeLength = false;
163 d->overrodeCallee = false;
164 }
165
166 inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
167 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
168 , d(new ArgumentsData)
169 {
170 ASSERT(!callFrame->callee()->body()->parameterCount());
171
172 unsigned numArguments = callFrame->argumentCount() - 1;
173
174 d->numParameters = 0;
175 d->numArguments = numArguments;
176 d->activation = 0;
177
178 Register* extraArguments;
179 if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
180 extraArguments = new Register[numArguments];
181 else
182 extraArguments = d->extraArgumentsFixedBuffer;
183
184 Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
185 for (unsigned i = 0; i < numArguments; ++i)
186 extraArguments[i] = argv[i];
187
188 d->extraArguments = extraArguments;
189
190 d->callee = callFrame->callee();
191 d->overrodeLength = false;
192 d->overrodeCallee = false;
193 }
194
195 inline void Arguments::copyRegisters()
196 {
197 ASSERT(!isTornOff());
198
199 if (!d->numParameters)
200 return;
201
202 int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
203 size_t registerArraySize = d->numParameters;
204
205 Register* registerArray = new Register[registerArraySize];
206 memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register));
207 d->registerArray.set(registerArray);
208 d->registers = registerArray + registerOffset;
209 }
210
211 // This JSActivation function is defined here so it can get at Arguments::setRegisters.
212 inline void JSActivation::copyRegisters(Arguments* arguments)
213 {
214 ASSERT(!d()->registerArray);
215
216 size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
217 size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
218 size_t numLocals = numVars + numParametersMinusThis;
219
220 if (!numLocals)
221 return;
222
223 int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
224 size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
225
226 Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
227 setRegisters(registerArray + registerOffset, registerArray);
228 if (arguments && !arguments->isTornOff())
229 static_cast<Arguments*>(arguments)->setActivation(this);
230 }
231
232 ALWAYS_INLINE Arguments* Register::arguments() const
233 {
234 if (jsValue() == JSValue())
235 return 0;
236 return asArguments(jsValue());
237 }
238
239
240 } // namespace JSC
241
242 #endif // Arguments_h