source: webkit/trunk/JavaScriptCore/runtime/Arguments.h@ 43121

Last change on this file since 43121 was 43037, checked in by [email protected], 16 years ago

Clean up ArgList to be a trivial type

Reviewed by Gavin Barraclough

Separate out old ArgList logic to handle buffering and marking arguments
into a distinct MarkedArgumentBuffer type. ArgList becomes a trivial
struct of a pointer and length.

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