]> git.saurik.com Git - apple/javascriptcore.git/blob - runtime/Arguments.h
JavaScriptCore-1218.34.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 "CodeOrigin.h"
28 #include "JSActivation.h"
29 #include "JSDestructibleObject.h"
30 #include "JSFunction.h"
31 #include "JSGlobalObject.h"
32 #include "Interpreter.h"
33 #include "ObjectConstructor.h"
34
35 namespace JSC {
36
37 class Arguments : public JSDestructibleObject {
38 friend class JIT;
39 friend class DFG::SpeculativeJIT;
40 public:
41 typedef JSDestructibleObject Base;
42
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 }
56
57 enum { MaxArguments = 0x10000 };
58
59 private:
60 enum NoParametersType { NoParameters };
61
62 Arguments(CallFrame*);
63 Arguments(CallFrame*, NoParametersType);
64
65 void tearOffForInlineCallFrame(VM& vm, Register*, InlineCallFrame*);
66
67 public:
68 static const ClassInfo s_info;
69
70 static void visitChildren(JSCell*, SlotVisitor&);
71
72 void fillArgList(ExecState*, MarkedArgumentBuffer&);
73
74 uint32_t length(ExecState* exec) const
75 {
76 if (UNLIKELY(m_overrodeLength))
77 return get(exec, exec->propertyNames().length).toUInt32(exec);
78 return m_numArguments;
79 }
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);
90 }
91
92 protected:
93 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
94
95 void finishCreation(CallFrame*);
96 void finishCreation(CallFrame*, InlineCallFrame*);
97
98 private:
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
142 Arguments* asArguments(JSValue);
143
144 inline Arguments* asArguments(JSValue value)
145 {
146 ASSERT(asObject(value)->inherits(&Arguments::s_info));
147 return static_cast<Arguments*>(asObject(value));
148 }
149
150 inline Arguments::Arguments(CallFrame* callFrame)
151 : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure())
152 {
153 }
154
155 inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
156 : JSDestructibleObject(callFrame->vm(), callFrame->lexicalGlobalObject()->argumentsStructure())
157 {
158 }
159
160 inline 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);
168 }
169 }
170
171 inline 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
180 inline 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
188 inline JSValue Arguments::tryGetArgument(size_t argument)
189 {
190 if (!isArgument(argument))
191 return JSValue();
192 return this->argument(argument).get();
193 }
194
195 inline 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
206 inline 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
215 inline 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
228 inline 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];
249 }
250
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
257 inline 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 }
277
278 } // namespace JSC
279
280 #endif // Arguments_h