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
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.
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.
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.
27 #include "JSActivation.h"
28 #include "JSFunction.h"
29 #include "JSGlobalObject.h"
30 #include "Interpreter.h"
31 #include "ObjectConstructor.h"
32 #include "PrototypeFunction.h"
36 struct ArgumentsData {
37 WTF_MAKE_NONCOPYABLE(ArgumentsData); WTF_MAKE_FAST_ALLOCATED;
40 WriteBarrier<JSActivation> activation;
42 unsigned numParameters;
43 ptrdiff_t firstParameterIndex;
44 unsigned numArguments;
47 OwnArrayPtr<Register> registerArray;
49 Register* extraArguments;
50 OwnArrayPtr<bool> deletedArguments;
51 Register extraArgumentsFixedBuffer[4];
53 WriteBarrier<JSFunction> callee;
54 bool overrodeLength : 1;
55 bool overrodeCallee : 1;
56 bool overrodeCaller : 1;
57 bool isStrictMode : 1;
61 class Arguments : public JSObject {
63 // Use an enum because otherwise gcc insists on doing a memory
65 enum { MaxArguments = 0x10000 };
67 enum NoParametersType { NoParameters };
69 Arguments(CallFrame*);
70 Arguments(CallFrame*, NoParametersType);
73 static const ClassInfo info;
75 virtual void markChildren(MarkStack&);
77 void fillArgList(ExecState*, MarkedArgumentBuffer&);
79 uint32_t numProvidedArguments(ExecState* exec) const
81 if (UNLIKELY(d->overrodeLength))
82 return get(exec, exec->propertyNames().length).toUInt32(exec);
83 return d->numArguments;
86 void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
88 bool isTornOff() const { return d->registerArray; }
89 void setActivation(JSGlobalData& globalData, JSActivation* activation)
91 d->activation.set(globalData, this, activation);
92 d->registers = &activation->registerAt(0);
95 static PassRefPtr<Structure> createStructure(JSValue prototype)
97 return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
101 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
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, PutPropertySlot&);
111 virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
112 virtual bool deleteProperty(ExecState*, unsigned propertyName);
113 void createStrictModeCallerIfNecessary(ExecState*);
114 void createStrictModeCalleeIfNecessary(ExecState*);
116 virtual const ClassInfo* classInfo() const { return &info; }
118 void init(CallFrame*);
120 OwnPtr<ArgumentsData> d;
123 Arguments* asArguments(JSValue);
125 inline Arguments* asArguments(JSValue value)
127 ASSERT(asObject(value)->inherits(&Arguments::info));
128 return static_cast<Arguments*>(asObject(value));
131 ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
133 function = asFunction(callFrame->callee());
135 int numParameters = function->jsExecutable()->parameterCount();
136 argc = callFrame->argumentCountIncludingThis();
138 if (argc <= numParameters)
139 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
141 argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;
143 argc -= 1; // - 1 to skip "this"
144 firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;
147 inline Arguments::Arguments(CallFrame* callFrame)
148 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
149 , d(adoptPtr(new ArgumentsData))
152 ptrdiff_t firstParameterIndex;
155 getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
157 d->numParameters = callee->jsExecutable()->parameterCount();
158 d->firstParameterIndex = firstParameterIndex;
159 d->numArguments = numArguments;
161 d->registers = callFrame->registers();
163 Register* extraArguments;
164 if (d->numArguments <= d->numParameters)
167 unsigned numExtraArguments = d->numArguments - d->numParameters;
168 if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
169 extraArguments = new Register[numExtraArguments];
171 extraArguments = d->extraArgumentsFixedBuffer;
172 for (unsigned i = 0; i < numExtraArguments; ++i)
173 extraArguments[i] = argv[d->numParameters + i];
176 d->extraArguments = extraArguments;
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();
187 inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
188 : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
189 , d(adoptPtr(new ArgumentsData))
191 ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
193 unsigned numArguments = callFrame->argumentCount();
195 d->numParameters = 0;
196 d->numArguments = numArguments;
198 Register* extraArguments;
199 if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
200 extraArguments = new Register[numArguments];
202 extraArguments = d->extraArgumentsFixedBuffer;
204 Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
205 for (unsigned i = 0; i < numArguments; ++i)
206 extraArguments[i] = argv[i];
208 d->extraArguments = extraArguments;
210 d->callee.set(callFrame->globalData(), this, asFunction(callFrame->callee()));
211 d->overrodeLength = false;
212 d->overrodeCallee = false;
213 d->overrodeCaller = false;
214 d->isStrictMode = callFrame->codeBlock()->isStrictMode();
219 inline void Arguments::copyRegisters()
221 ASSERT(!isTornOff());
223 if (!d->numParameters)
226 int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
227 size_t registerArraySize = d->numParameters;
229 Register* registerArray = new Register[registerArraySize];
230 memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register));
231 d->registerArray.set(registerArray);
232 d->registers = registerArray + registerOffset;
235 // This JSActivation function is defined here so it can get at Arguments::setRegisters.
236 inline void JSActivation::copyRegisters()
238 ASSERT(!d()->registerArray);
240 size_t numParametersMinusThis = d()->functionExecutable->parameterCount();
241 size_t numVars = d()->functionExecutable->capturedVariableCount();
242 size_t numLocals = numVars + numParametersMinusThis;
247 int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
248 size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
250 Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
251 setRegisters(registerArray + registerOffset, registerArray);
256 #endif // Arguments_h