initial import
[vuplus_webkit] / Source / JavaScriptCore / 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 "JSActivation.h"
28 #include "JSFunction.h"
29 #include "JSGlobalObject.h"
30 #include "Interpreter.h"
31 #include "ObjectConstructor.h"
32
33 namespace JSC {
34
35     struct ArgumentsData {
36         WTF_MAKE_NONCOPYABLE(ArgumentsData); WTF_MAKE_FAST_ALLOCATED;
37     public:
38         ArgumentsData() { }
39         WriteBarrier<JSActivation> activation;
40
41         unsigned numParameters;
42         ptrdiff_t firstParameterIndex;
43         unsigned numArguments;
44
45         WriteBarrier<Unknown>* registers;
46         OwnArrayPtr<WriteBarrier<Unknown> > registerArray;
47
48         WriteBarrier<Unknown>* extraArguments;
49         OwnArrayPtr<bool> deletedArguments;
50         WriteBarrier<Unknown> extraArgumentsFixedBuffer[4];
51
52         WriteBarrier<JSFunction> callee;
53         bool overrodeLength : 1;
54         bool overrodeCallee : 1;
55         bool overrodeCaller : 1;
56         bool isStrictMode : 1;
57     };
58
59
60     class Arguments : public JSNonFinalObject {
61     public:
62         typedef JSNonFinalObject Base;
63
64         static Arguments* create(JSGlobalData& globalData, CallFrame* callFrame)
65         {
66             Arguments* arguments = new (allocateCell<Arguments>(globalData.heap)) Arguments(callFrame);
67             arguments->finishCreation(callFrame);
68             return arguments;
69         }
70         
71         static Arguments* createNoParameters(JSGlobalData& globalData, CallFrame* callFrame)
72         {
73             Arguments* arguments = new (allocateCell<Arguments>(globalData.heap)) Arguments(callFrame, NoParameters);
74             arguments->finishCreation(callFrame, NoParameters);
75             return arguments;
76         }
77
78         // Use an enum because otherwise gcc insists on doing a memory
79         // read.
80         enum { MaxArguments = 0x10000 };
81
82     private:
83         enum NoParametersType { NoParameters };
84         
85         Arguments(CallFrame*);
86         Arguments(CallFrame*, NoParametersType);
87
88     public:
89         virtual ~Arguments();
90
91         static const ClassInfo s_info;
92
93         virtual void visitChildren(SlotVisitor&);
94
95         void fillArgList(ExecState*, MarkedArgumentBuffer&);
96
97         uint32_t numProvidedArguments(ExecState* exec) const 
98         {
99             if (UNLIKELY(d->overrodeLength))
100                 return get(exec, exec->propertyNames().length).toUInt32(exec);
101             return d->numArguments; 
102         }
103         
104         void copyToRegisters(ExecState* exec, Register* buffer, uint32_t maxSize);
105         void copyRegisters(JSGlobalData&);
106         bool isTornOff() const { return d->registerArray; }
107         void setActivation(JSGlobalData& globalData, JSActivation* activation)
108         {
109             ASSERT(!d->registerArray);
110             d->activation.set(globalData, this, activation);
111             d->registers = &activation->registerAt(0);
112         }
113
114         static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype) 
115         { 
116             return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); 
117         }
118
119     protected:
120         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSObject::StructureFlags;
121
122         void finishCreation(CallFrame*);
123         void finishCreation(CallFrame*, NoParametersType);
124
125     private:
126         void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc);
127         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
128         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
129         virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
130         virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties);
131         virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
132         virtual void put(ExecState*, unsigned propertyName, JSValue);
133         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
134         virtual bool deleteProperty(ExecState*, unsigned propertyName);
135         void createStrictModeCallerIfNecessary(ExecState*);
136         void createStrictModeCalleeIfNecessary(ExecState*);
137
138         void init(CallFrame*);
139
140         OwnPtr<ArgumentsData> d;
141     };
142
143     Arguments* asArguments(JSValue);
144
145     inline Arguments* asArguments(JSValue value)
146     {
147         ASSERT(asObject(value)->inherits(&Arguments::s_info));
148         return static_cast<Arguments*>(asObject(value));
149     }
150
151     ALWAYS_INLINE void Arguments::getArgumentsData(CallFrame* callFrame, JSFunction*& function, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc)
152     {
153         function = asFunction(callFrame->callee());
154
155         int numParameters = function->jsExecutable()->parameterCount();
156         argc = callFrame->argumentCountIncludingThis();
157
158         if (argc <= numParameters)
159             argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters;
160         else
161             argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numParameters - argc;
162
163         argc -= 1; // - 1 to skip "this"
164         firstParameterIndex = -RegisterFile::CallFrameHeaderSize - numParameters;
165     }
166
167     inline Arguments::Arguments(CallFrame* callFrame)
168         : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
169         , d(adoptPtr(new ArgumentsData))
170     {
171     }
172
173     inline Arguments::Arguments(CallFrame* callFrame, NoParametersType)
174         : JSNonFinalObject(callFrame->globalData(), callFrame->lexicalGlobalObject()->argumentsStructure())
175         , d(adoptPtr(new ArgumentsData))
176     {
177     }
178     
179     inline void Arguments::finishCreation(CallFrame* callFrame)
180     {
181         Base::finishCreation(callFrame->globalData());
182         ASSERT(inherits(&s_info));
183
184         JSFunction* callee;
185         ptrdiff_t firstParameterIndex;
186         Register* argv;
187         int numArguments;
188         getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
189
190         d->numParameters = callee->jsExecutable()->parameterCount();
191         d->firstParameterIndex = firstParameterIndex;
192         d->numArguments = numArguments;
193
194         d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers());
195
196         WriteBarrier<Unknown>* extraArguments;
197         if (d->numArguments <= d->numParameters)
198             extraArguments = 0;
199         else {
200             unsigned numExtraArguments = d->numArguments - d->numParameters;
201             if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(WriteBarrier<Unknown>))
202                 extraArguments = new WriteBarrier<Unknown>[numExtraArguments];
203             else
204                 extraArguments = d->extraArgumentsFixedBuffer;
205             for (unsigned i = 0; i < numExtraArguments; ++i)
206                 extraArguments[i].set(callFrame->globalData(), this, argv[d->numParameters + i].jsValue());
207         }
208
209         d->extraArguments = extraArguments;
210
211         d->callee.set(callFrame->globalData(), this, callee);
212         d->overrodeLength = false;
213         d->overrodeCallee = false;
214         d->overrodeCaller = false;
215         d->isStrictMode = callFrame->codeBlock()->isStrictMode();
216         if (d->isStrictMode)
217             copyRegisters(callFrame->globalData());
218     }
219
220     inline void Arguments::finishCreation(CallFrame* callFrame, NoParametersType)
221     {
222         Base::finishCreation(callFrame->globalData());
223         ASSERT(inherits(&s_info));
224         ASSERT(!asFunction(callFrame->callee())->jsExecutable()->parameterCount());
225
226         unsigned numArguments = callFrame->argumentCount();
227
228         d->numParameters = 0;
229         d->numArguments = numArguments;
230
231         WriteBarrier<Unknown>* extraArguments;
232         if (numArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
233             extraArguments = new WriteBarrier<Unknown>[numArguments];
234         else
235             extraArguments = d->extraArgumentsFixedBuffer;
236
237         Register* argv = callFrame->registers() - RegisterFile::CallFrameHeaderSize - numArguments - 1;
238         for (unsigned i = 0; i < numArguments; ++i)
239             extraArguments[i].set(callFrame->globalData(), this, argv[i].jsValue());
240
241         d->extraArguments = extraArguments;
242
243         d->callee.set(callFrame->globalData(), this, asFunction(callFrame->callee()));
244         d->overrodeLength = false;
245         d->overrodeCallee = false;
246         d->overrodeCaller = false;
247         d->isStrictMode = callFrame->codeBlock()->isStrictMode();
248         if (d->isStrictMode)
249             copyRegisters(callFrame->globalData());
250     }
251
252     inline void Arguments::copyRegisters(JSGlobalData& globalData)
253     {
254         ASSERT(!isTornOff());
255
256         if (!d->numParameters)
257             return;
258
259         int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
260         size_t registerArraySize = d->numParameters;
261
262         OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]);
263         for (size_t i = 0; i < registerArraySize; i++)
264             registerArray[i].set(globalData, this, d->registers[i - registerOffset].get());
265         d->registers = registerArray.get() + registerOffset;
266         d->registerArray = registerArray.release();
267     }
268
269     // This JSActivation function is defined here so it can get at Arguments::setRegisters.
270     inline void JSActivation::copyRegisters(JSGlobalData& globalData)
271     {
272         ASSERT(!m_registerArray);
273
274         size_t numLocals = m_numCapturedVars + m_numParametersMinusThis;
275
276         if (!numLocals)
277             return;
278
279         int registerOffset = m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
280         size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
281
282         OwnArrayPtr<WriteBarrier<Unknown> > registerArray = copyRegisterArray(globalData, m_registers - registerOffset, registerArraySize, m_numParametersMinusThis + 1);
283         WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset;
284         setRegisters(registers, registerArray.release());
285     }
286
287 } // namespace JSC
288
289 #endif // Arguments_h