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

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

structure typeinfo flags should be inherited.
https://bugs.webkit.org/show_bug.cgi?id=30468

Reviewed by Gavin Barraclough.

Add StructureFlag constant to the various JSC classes and use
it for the TypeInfo construction. This allows us to simply
accumulate flags by basing each classes StructureInfo on its parents.

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