]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Arguments.h
JavaScriptCore-903.5.tar.gz
[apple/javascriptcore.git] / runtime / Arguments.h
1 /*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2006, 2007, 2008, 2009 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 #include "ObjectConstructor.h"
32
33 namespace JSC {
34
35 struct ArgumentsData {
36 WTF_MAKE_NONCOPYABLE(ArgumentsData); WTF_MAKE_FAST_ALLOCATED;
37 public:
38 ArgumentsData() { }
39 WriteBarrier<JSActivation> activation;
40
41 unsigned numParameters;
42 ptrdiff_t firstParameterIndex;
43 unsigned numArguments;
44
45 WriteBarrier<Unknown>* registers;
46 OwnArrayPtr<WriteBarrier<Unknown> > registerArray;
47
48 WriteBarrier<Unknown>* extraArguments;
49 OwnArrayPtr<bool> deletedArguments;
50 WriteBarrier<Unknown> extraArgumentsFixedBuffer[4];
51
52 WriteBarrier<JSFunction> callee;
53 bool overrodeLength : 1;
54 bool overrodeCallee : 1;
55 bool overrodeCaller : 1;
56 bool isStrictMode : 1;
57 };
58
59
60 class Arguments : public JSNonFinalObject {
61 public:
62 // Use an enum because otherwise gcc insists on doing a memory
63 // read.
64 enum { MaxArguments = 0x10000 };
65
66 enum NoParametersType { NoParameters };
67
68 Arguments(CallFrame*);
69 Arguments(CallFrame*, NoParametersType);
70 virtual ~Arguments();
71
72 static const ClassInfo s_info;
73
74 virtual void visitChildren(SlotVisitor&);
75
76 void fillArgList(ExecState*, MarkedArgumentBuffer&);
77
78 uint32_t numProvidedArguments(ExecState* exec) const
79 {
80 if (UNLIKELY(d->overrodeLength))
81 return get(exec, exec->propertyNames().length).toUInt32(exec);
82 return d->numArguments;
83 }
84
85 void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
86 void copyRegisters(JSGlobalData&);
87 bool isTornOff() const { return d->registerArray; }
88 void setActivation(JSGlobalData& globalData, JSActivation* activation)
89 {
90 ASSERT(!d->registerArray);
91 d->activation.set(globalData, this, activation);
92 d->registers = &activation->registerAt(0);
93 }
94
95 static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
96 {
97 return Structure::create(globalData, prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount, &s_info);
98 }
99
100 protected:
101 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
102
103 private:
104 void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
105 virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
106 virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
107 virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
108 virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
109 virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
110 virtual void put(ExecState*, unsigned propertyName, JSValue);
111 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
112 virtual bool deleteProperty(ExecState*, unsigned propertyName);
113 void createStrictModeCallerIfNecessary(ExecState*);
114 void createStrictModeCalleeIfNecessary(ExecState*);
115
116 void init(CallFrame*);
117
118 OwnPtr<ArgumentsData> d;
119 };
120
121 Arguments* asArguments(JSValue);
122
123 inline Arguments* asArguments(JSValue value)
124 {
125 ASSERT(asObject(value)->inherits(&Arguments::s_info));
126 return static_cast<Arguments*>(asObject(value));
127 }
128
129 ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
130 {
131 function = asFunction(callFrame->callee());
132
133 int numParameters = function->jsExecutable()->parameterCount();
134 argc = callFrame->argumentCountIncludingThis();
135
136 if (argc <= numParameters)
137 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
138 else
139 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;
140
141 argc -= 1; // - 1 to skip "this"
142 firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;
143 }
144
145 inline Arguments::Arguments(CallFrame* callFrame)
146 : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
147 , d(adoptPtr(new ArgumentsData))
148 {
149 ASSERT(inherits(&s_info));
150
151 JSFunction* callee;
152 ptrdiff_t firstParameterIndex;
153 Register* argv;
154 int numArguments;
155 getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
156
157 d->numParameters = callee->jsExecutable()->parameterCount();
158 d->firstParameterIndex = firstParameterIndex;
159 d->numArguments = numArguments;
160
161 d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers());
162
163 WriteBarrier<Unknown>* extraArguments;
164 if (d->numArguments <= d->numParameters)
165 extraArguments = 0;
166 else {
167 unsigned numExtraArguments = d->numArguments - d->numParameters;
168 if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(WriteBarrier<Unknown>))
169 extraArguments = new WriteBarrier<Unknown>[numExtraArguments];
170 else
171 extraArguments = d->extraArgumentsFixedBuffer;
172 for (unsigned i = 0; i < numExtraArguments; ++i)
173 extraArguments[i].set(callFrame->globalData(), this, argv[d->numParameters + i].jsValue());
174 }
175
176 d->extraArguments = extraArguments;
177
178 d->callee.set(callFrame->globalData(), this, callee);
179 d->overrodeLength = false;
180 d->overrodeCallee = false;
181 d->overrodeCaller = false;
182 d->isStrictMode = callFrame->codeBlock()->isStrictMode();
183 if (d->isStrictMode)
184 copyRegisters(callFrame->globalData());
185 }
186
187 inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
188 : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
189 , d(adoptPtr(new ArgumentsData))
190 {
191 ASSERT(inherits(&s_info));
192 ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
193
194 unsigned numArguments = callFrame->argumentCount();
195
196 d->numParameters = 0;
197 d->numArguments = numArguments;
198
199 WriteBarrier<Unknown>* extraArguments;
200 if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
201 extraArguments = new WriteBarrier<Unknown>[numArguments];
202 else
203 extraArguments = d->extraArgumentsFixedBuffer;
204
205 Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
206 for (unsigned i = 0; i < numArguments; ++i)
207 extraArguments[i].set(callFrame->globalData(), this, argv[i].jsValue());
208
209 d->extraArguments = extraArguments;
210
211 d->callee.set(callFrame->globalData(), this, asFunction(callFrame->callee()));
212 d->overrodeLength = false;
213 d->overrodeCallee = false;
214 d->overrodeCaller = false;
215 d->isStrictMode = callFrame->codeBlock()->isStrictMode();
216 if (d->isStrictMode)
217 copyRegisters(callFrame->globalData());
218 }
219
220 inline void Arguments::copyRegisters(JSGlobalData& globalData)
221 {
222 ASSERT(!isTornOff());
223
224 if (!d->numParameters)
225 return;
226
227 int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
228 size_t registerArraySize = d->numParameters;
229
230 OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
231 for (size_t i = 0; i < registerArraySize; i++)
232 registerArray[i].set(globalData, this, d->registers[i - registerOffset].get());
233 d->registers = registerArray.get() + registerOffset;
234 d->registerArray = registerArray.release();
235 }
236
237 // This JSActivation function is defined here so it can get at Arguments::setRegisters.
238 inline void JSActivation::copyRegisters(JSGlobalData& globalData)
239 {
240 ASSERT(!m_registerArray);
241
242 size_t numLocals = m_numCapturedVars + m_numParametersMinusThis;
243
244 if (!numLocals)
245 return;
246
247 int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
248 size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
249
250 OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize, m_numParametersMinusThis + 1);
251 WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
252 setRegisters(registers, registerArray.release());
253 }
254
255 } // namespace JSC
256
257 #endif // Arguments_h