]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Arguments.h
ebea6ad1556364cf5b46cb48261eaf5480b7a01a
[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*, ArgList&);
67
68 void copyRegisters();
69 bool isTornOff() const { return d->registerArray; }
70 void setActivation(JSActivation* activation)
71 {
72 d->activation = activation;
73 d->registers = &activation->registerAt(0);
74 }
75
76 static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
77 {
78 return Structure::create(prototype, TypeInfo(ObjectType));
79 }
80
81 private:
82 void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
83 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
84 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
85 virtual void put(ExecState*, const Identifier& propertyName, JSValuePtr, PutPropertySlot&);
86 virtual void put(ExecState*, unsigned propertyName, JSValuePtr, PutPropertySlot&);
87 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
88 virtual bool deleteProperty(ExecState*, unsigned propertyName);
89
90 virtual const ClassInfo* classInfo() const { return &info; }
91
92 void init(CallFrame*);
93
94 OwnPtr<ArgumentsData> d;
95 };
96
97 Arguments* asArguments(JSValuePtr);
98
99 inline Arguments* asArguments(JSValuePtr value)
100 {
101 ASSERT(asObject(value)->inherits(&Arguments::info));
102 return static_cast<Arguments*>(asObject(value));
103 }
104
105 ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
106 {
107 function = callFrame->callee();
108
109 CodeBlock* codeBlock = &function->body()->generatedBytecode();
110 int numParameters = codeBlock->m_numParameters;
111 argc = callFrame->argumentCount();
112
113 if (argc <= numParameters)
114 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
115 else
116 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc + 1; // + 1 to skip "this"
117
118 argc -= 1; // - 1 to skip "this"
119 firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters + 1; // + 1 to skip "this"
120 }
121
122 inline Arguments::Arguments(CallFrame* callFrame)
123 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
124 , d(new ArgumentsData)
125 {
126 JSFunction* callee;
127 ptrdiff_t firstParameterIndex;
128 Register* argv;
129 int numArguments;
130 getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
131
132 d->numParameters = callee->body()->parameterCount();
133 d->firstParameterIndex = firstParameterIndex;
134 d->numArguments = numArguments;
135
136 d->activation = 0;
137 d->registers = callFrame->registers();
138
139 Register* extraArguments;
140 if (d->numArguments <= d->numParameters)
141 extraArguments = 0;
142 else {
143 unsigned numExtraArguments = d->numArguments - d->numParameters;
144 if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
145 extraArguments = new Register[numExtraArguments];
146 else
147 extraArguments = d->extraArgumentsFixedBuffer;
148 for (unsigned i = 0; i < numExtraArguments; ++i)
149 extraArguments[i] = argv[d->numParameters + i];
150 }
151
152 d->extraArguments = extraArguments;
153
154 d->callee = callee;
155 d->overrodeLength = false;
156 d->overrodeCallee = false;
157 }
158
159 inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
160 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
161 , d(new ArgumentsData)
162 {
163 ASSERT(!callFrame->callee()->body()->parameterCount());
164
165 unsigned numArguments = callFrame->argumentCount() - 1;
166
167 d->numParameters = 0;
168 d->numArguments = numArguments;
169 d->activation = 0;
170
171 Register* extraArguments;
172 if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
173 extraArguments = new Register[numArguments];
174 else
175 extraArguments = d->extraArgumentsFixedBuffer;
176
177 Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
178 for (unsigned i = 0; i < numArguments; ++i)
179 extraArguments[i] = argv[i];
180
181 d->extraArguments = extraArguments;
182
183 d->callee = callFrame->callee();
184 d->overrodeLength = false;
185 d->overrodeCallee = false;
186 }
187
188 inline void Arguments::copyRegisters()
189 {
190 ASSERT(!isTornOff());
191
192 if (!d->numParameters)
193 return;
194
195 int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
196 size_t registerArraySize = d->numParameters;
197
198 Register* registerArray = new Register[registerArraySize];
199 memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register));
200 d->registerArray.set(registerArray);
201 d->registers = registerArray + registerOffset;
202 }
203
204 // This JSActivation function is defined here so it can get at Arguments::setRegisters.
205 inline void JSActivation::copyRegisters(Arguments* arguments)
206 {
207 ASSERT(!d()->registerArray);
208
209 size_t numParametersMinusThis = d()->functionBody->generatedBytecode().m_numParameters - 1;
210 size_t numVars = d()->functionBody->generatedBytecode().m_numVars;
211 size_t numLocals = numVars + numParametersMinusThis;
212
213 if (!numLocals)
214 return;
215
216 int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
217 size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
218
219 Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
220 setRegisters(registerArray + registerOffset, registerArray);
221 if (arguments && !arguments->isTornOff())
222 static_cast<Arguments*>(arguments)->setActivation(this);
223 }
224
225 } // namespace JSC
226
227 #endif // Arguments_h