]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/Arguments.h
JavaScriptCore-1218.35.tar.gz
[apple/javascriptcore.git] / runtime / Arguments.h
CommitLineData
9dae56ea
A
1/*
2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
f9bf01c6 3 * Copyright (C) 2003, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
9dae56ea
A
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
6fe7ccc8 27#include "CodeOrigin.h"
9dae56ea 28#include "JSActivation.h"
93a37866 29#include "JSDestructibleObject.h"
9dae56ea
A
30#include "JSFunction.h"
31#include "JSGlobalObject.h"
32#include "Interpreter.h"
f9bf01c6 33#include "ObjectConstructor.h"
9dae56ea
A
34
35namespace JSC {
36
93a37866
A
37class Arguments : public JSDestructibleObject {
38 friend class JIT;
39 friend class DFG::SpeculativeJIT;
40public:
41 typedef JSDestructibleObject Base;
9dae56ea 42
93a37866
A
43 static Arguments* create(VM& vm, CallFrame* callFrame)
44 {
45 Arguments* arguments = new (NotNull, allocateCell<Arguments>(vm.heap)) Arguments(callFrame);
46 arguments->finishCreation(callFrame);
47 return arguments;
48 }
49
50 static Arguments* create(VM& vm, CallFrame* callFrame, InlineCallFrame* inlineCallFrame)
51 {
52 Arguments* arguments = new (NotNull, allocateCell<Arguments>(vm.heap)) Arguments(callFrame);
53 arguments->finishCreation(callFrame, inlineCallFrame);
54 return arguments;
55 }
6fe7ccc8 56
93a37866 57 enum { MaxArguments = 0x10000 };
fb8617cd 58
93a37866
A
59private:
60 enum NoParametersType { NoParameters };
61
62 Arguments(CallFrame*);
63 Arguments(CallFrame*, NoParametersType);
6fe7ccc8 64
93a37866 65 void tearOffForInlineCallFrame(VM& vm, Register*, InlineCallFrame*);
9dae56ea 66
93a37866
A
67public:
68 static const ClassInfo s_info;
9dae56ea 69
93a37866 70 static void visitChildren(JSCell*, SlotVisitor&);
9dae56ea 71
93a37866 72 void fillArgList(ExecState*, MarkedArgumentBuffer&);
9dae56ea 73
93a37866 74 uint32_t length(ExecState* exec) const
9dae56ea 75 {
93a37866
A
76 if (UNLIKELY(m_overrodeLength))
77 return get(exec, exec->propertyNames().length).toUInt32(exec);
78 return m_numArguments;
9dae56ea 79 }
93a37866
A
80
81 void copyToArguments(ExecState*, CallFrame*, uint32_t length);
82 void tearOff(CallFrame*);
83 void tearOff(CallFrame*, InlineCallFrame*);
84 bool isTornOff() const { return m_registerArray; }
85 void didTearOffActivation(ExecState*, JSActivation*);
86
87 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
88 {
89 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info);
9dae56ea 90 }
93a37866
A
91
92protected:
93 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
94
95 void finishCreation(CallFrame*);
96 void finishCreation(CallFrame*, InlineCallFrame*);
97
98private:
99 static void destroy(JSCell*);
100 static bool getOwnPropertySlot(JSCell*, ExecState*, PropertyName, PropertySlot&);
101 static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&);
102 static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
103 static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
104 static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
105 static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
106 static bool deleteProperty(JSCell*, ExecState*, PropertyName);
107 static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
108 static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, PropertyDescriptor&, bool shouldThrow);
109 void createStrictModeCallerIfNecessary(ExecState*);
110 void createStrictModeCalleeIfNecessary(ExecState*);
111
112 bool isArgument(size_t);
113 bool trySetArgument(VM&, size_t argument, JSValue);
114 JSValue tryGetArgument(size_t argument);
115 bool isDeletedArgument(size_t);
116 bool tryDeleteArgument(size_t);
117 WriteBarrierBase<Unknown>& argument(size_t);
118 void allocateSlowArguments();
119
120 void init(CallFrame*);
121
122 WriteBarrier<JSActivation> m_activation;
123
124 unsigned m_numArguments;
125
126 // We make these full byte booleans to make them easy to test from the JIT,
127 // and because even if they were single-bit booleans we still wouldn't save
128 // any space.
129 bool m_overrodeLength;
130 bool m_overrodeCallee;
131 bool m_overrodeCaller;
132 bool m_isStrictMode;
133
134 WriteBarrierBase<Unknown>* m_registers;
135 OwnArrayPtr<WriteBarrier<Unknown> > m_registerArray;
136
137 OwnArrayPtr<SlowArgument> m_slowArguments;
138
139 WriteBarrier<JSFunction> m_callee;
140};
141
142Arguments* asArguments(JSValue);
143
144inline Arguments* asArguments(JSValue value)
145{
146 ASSERT(asObject(value)->inherits(&Arguments::s_info));
147 return static_cast<Arguments*>(asObject(value));
148}
149
150inline Arguments::Arguments(CallFrame* callFrame)
151 : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure())
152{
153}
154
155inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
156 : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure())
157{
158}
159
160inline void Arguments::allocateSlowArguments()
161{
162 if (m_slowArguments)
163 return;
164 m_slowArguments = adoptArrayPtr(new SlowArgument[m_numArguments]);
165 for (size_t i = 0; i < m_numArguments; ++i) {
166 ASSERT(m_slowArguments[i].status == SlowArgument::Normal);
167 m_slowArguments[i].index = CallFrame::argumentOffset(i);
9dae56ea 168 }
93a37866
A
169}
170
171inline bool Arguments::tryDeleteArgument(size_t argument)
172{
173 if (!isArgument(argument))
174 return false;
175 allocateSlowArguments();
176 m_slowArguments[argument].status = SlowArgument::Deleted;
177 return true;
178}
179
180inline bool Arguments::trySetArgument(VM& vm, size_t argument, JSValue value)
181{
182 if (!isArgument(argument))
183 return false;
184 this->argument(argument).set(vm, this, value);
185 return true;
186}
187
188inline JSValue Arguments::tryGetArgument(size_t argument)
189{
190 if (!isArgument(argument))
191 return JSValue();
192 return this->argument(argument).get();
193}
194
195inline bool Arguments::isDeletedArgument(size_t argument)
196{
197 if (argument >= m_numArguments)
198 return false;
199 if (!m_slowArguments)
200 return false;
201 if (m_slowArguments[argument].status != SlowArgument::Deleted)
202 return false;
203 return true;
204}
205
206inline bool Arguments::isArgument(size_t argument)
207{
208 if (argument >= m_numArguments)
209 return false;
210 if (m_slowArguments && m_slowArguments[argument].status == SlowArgument::Deleted)
211 return false;
212 return true;
213}
214
215inline WriteBarrierBase<Unknown>& Arguments::argument(size_t argument)
216{
217 ASSERT(isArgument(argument));
218 if (!m_slowArguments)
219 return m_registers[CallFrame::argumentOffset(argument)];
220
221 int index = m_slowArguments[argument].index;
222 if (!m_activation || m_slowArguments[argument].status != SlowArgument::Captured)
223 return m_registers[index];
224
225 return m_activation->registerAt(index);
226}
227
228inline void Arguments::finishCreation(CallFrame* callFrame)
229{
230 Base::finishCreation(callFrame->vm());
231 ASSERT(inherits(&s_info));
232
233 JSFunction* callee = jsCast<JSFunction*>(callFrame->callee());
234 m_numArguments = callFrame->argumentCount();
235 m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers());
236 m_callee.set(callFrame->vm(), this, callee);
237 m_overrodeLength = false;
238 m_overrodeCallee = false;
239 m_overrodeCaller = false;
240 m_isStrictMode = callFrame->codeBlock()->isStrictMode();
241
242 SharedSymbolTable* symbolTable = callFrame->codeBlock()->symbolTable();
243 const SlowArgument* slowArguments = symbolTable->slowArguments();
244 if (slowArguments) {
245 allocateSlowArguments();
246 size_t count = std::min<unsigned>(m_numArguments, symbolTable->parameterCount());
247 for (size_t i = 0; i < count; ++i)
248 m_slowArguments[i] = slowArguments[i];
9dae56ea
A
249 }
250
93a37866
A
251 // The bytecode generator omits op_tear_off_activation in cases of no
252 // declared parameters, so we need to tear off immediately.
253 if (m_isStrictMode || !callee->jsExecutable()->parameterCount())
254 tearOff(callFrame);
255}
256
257inline void Arguments::finishCreation(CallFrame* callFrame, InlineCallFrame* inlineCallFrame)
258{
259 Base::finishCreation(callFrame->vm());
260 ASSERT(inherits(&s_info));
261
262 JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame);
263 m_numArguments = inlineCallFrame->arguments.size() - 1;
264 m_registers = reinterpret_cast<WriteBarrierBase<Unknown>*>(callFrame->registers()) + inlineCallFrame->stackOffset;
265 m_callee.set(callFrame->vm(), this, callee);
266 m_overrodeLength = false;
267 m_overrodeCallee = false;
268 m_overrodeCaller = false;
269 m_isStrictMode = jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->isStrictMode();
270 ASSERT(!jsCast<FunctionExecutable*>(inlineCallFrame->executable.get())->symbolTable(inlineCallFrame->isCall ? CodeForCall : CodeForConstruct)->slowArguments());
271
272 // The bytecode generator omits op_tear_off_activation in cases of no
273 // declared parameters, so we need to tear off immediately.
274 if (m_isStrictMode || !callee->jsExecutable()->parameterCount())
275 tearOff(callFrame, inlineCallFrame);
276}
ba379fdc 277
9dae56ea
A
278} // namespace JSC
279
280#endif // Arguments_h