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"
35 struct ArgumentsData
{
36 WTF_MAKE_NONCOPYABLE(ArgumentsData
); WTF_MAKE_FAST_ALLOCATED
;
39 WriteBarrier
<JSActivation
> activation
;
41 unsigned numParameters
;
42 ptrdiff_t firstParameterIndex
;
43 unsigned numArguments
;
45 WriteBarrier
<Unknown
>* registers
;
46 OwnArrayPtr
<WriteBarrier
<Unknown
> > registerArray
;
48 WriteBarrier
<Unknown
>* extraArguments
;
49 OwnArrayPtr
<bool> deletedArguments
;
50 WriteBarrier
<Unknown
> extraArgumentsFixedBuffer
[4];
52 WriteBarrier
<JSFunction
> callee
;
53 bool overrodeLength
: 1;
54 bool overrodeCallee
: 1;
55 bool overrodeCaller
: 1;
56 bool isStrictMode
: 1;
60 class Arguments
: public JSNonFinalObject
{
62 // Use an enum because otherwise gcc insists on doing a memory
64 enum { MaxArguments
= 0x10000 };
66 enum NoParametersType
{ NoParameters
};
68 Arguments(CallFrame
*);
69 Arguments(CallFrame
*, NoParametersType
);
72 static const ClassInfo s_info
;
74 virtual void visitChildren(SlotVisitor
&);
76 void fillArgList(ExecState
*, MarkedArgumentBuffer
&);
78 uint32_t numProvidedArguments(ExecState
* exec
) const
80 if (UNLIKELY(d
->overrodeLength
))
81 return get(exec
, exec
->propertyNames().length
).toUInt32(exec
);
82 return d
->numArguments
;
85 void copyToRegisters(ExecState
* exec
, Register
* buffer
, uint32_t maxSize
);
86 void copyRegisters(JSGlobalData
&);
87 bool isTornOff() const { return d
->registerArray
; }
88 void setActivation(JSGlobalData
& globalData
, JSActivation
* activation
)
90 ASSERT(!d
->registerArray
);
91 d
->activation
.set(globalData
, this, activation
);
92 d
->registers
= &activation
->registerAt(0);
95 static Structure
* createStructure(JSGlobalData
& globalData
, JSValue prototype
)
97 return Structure::create(globalData
, prototype
, TypeInfo(ObjectType
, StructureFlags
), AnonymousSlotCount
, &s_info
);
101 static const unsigned StructureFlags
= OverridesGetOwnPropertySlot
| OverridesVisitChildren
| 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
);
111 virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
);
112 virtual bool deleteProperty(ExecState
*, unsigned propertyName
);
113 void createStrictModeCallerIfNecessary(ExecState
*);
114 void createStrictModeCalleeIfNecessary(ExecState
*);
116 void init(CallFrame
*);
118 OwnPtr
<ArgumentsData
> d
;
121 Arguments
* asArguments(JSValue
);
123 inline Arguments
* asArguments(JSValue value
)
125 ASSERT(asObject(value
)->inherits(&Arguments::s_info
));
126 return static_cast<Arguments
*>(asObject(value
));
129 ALWAYS_INLINE
void Arguments::getArgumentsData(CallFrame
* callFrame
, JSFunction
*& function
, ptrdiff_t& firstParameterIndex
, Register
*& argv
, int& argc
)
131 function
= asFunction(callFrame
->callee());
133 int numParameters
= function
->jsExecutable()->parameterCount();
134 argc
= callFrame
->argumentCountIncludingThis();
136 if (argc
<= numParameters
)
137 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
;
139 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
- argc
;
141 argc
-= 1; // - 1 to skip "this"
142 firstParameterIndex
= -RegisterFile::CallFrameHeaderSize
- numParameters
;
145 inline Arguments::Arguments(CallFrame
* callFrame
)
146 : JSNonFinalObject(callFrame
->globalData(), callFrame
->lexicalGlobalObject()->argumentsStructure())
147 , d(adoptPtr(new ArgumentsData
))
149 ASSERT(inherits(&s_info
));
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
= reinterpret_cast<WriteBarrier
<Unknown
>*>(callFrame
->registers());
163 WriteBarrier
<Unknown
>* extraArguments
;
164 if (d
->numArguments
<= d
->numParameters
)
167 unsigned numExtraArguments
= d
->numArguments
- d
->numParameters
;
168 if (numExtraArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(WriteBarrier
<Unknown
>))
169 extraArguments
= new WriteBarrier
<Unknown
>[numExtraArguments
];
171 extraArguments
= d
->extraArgumentsFixedBuffer
;
172 for (unsigned i
= 0; i
< numExtraArguments
; ++i
)
173 extraArguments
[i
].set(callFrame
->globalData(), this, argv
[d
->numParameters
+ i
].jsValue());
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();
184 copyRegisters(callFrame
->globalData());
187 inline Arguments::Arguments(CallFrame
* callFrame
, NoParametersType
)
188 : JSNonFinalObject(callFrame
->globalData(), callFrame
->lexicalGlobalObject()->argumentsStructure())
189 , d(adoptPtr(new ArgumentsData
))
191 ASSERT(inherits(&s_info
));
192 ASSERT(!asFunction(callFrame
->callee())->jsExecutable()->parameterCount());
194 unsigned numArguments
= callFrame
->argumentCount();
196 d
->numParameters
= 0;
197 d
->numArguments
= numArguments
;
199 WriteBarrier
<Unknown
>* extraArguments
;
200 if (numArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(Register
))
201 extraArguments
= new WriteBarrier
<Unknown
>[numArguments
];
203 extraArguments
= d
->extraArgumentsFixedBuffer
;
205 Register
* argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numArguments
- 1;
206 for (unsigned i
= 0; i
< numArguments
; ++i
)
207 extraArguments
[i
].set(callFrame
->globalData(), this, argv
[i
].jsValue());
209 d
->extraArguments
= extraArguments
;
211 d
->callee
.set(callFrame
->globalData(), this, asFunction(callFrame
->callee()));
212 d
->overrodeLength
= false;
213 d
->overrodeCallee
= false;
214 d
->overrodeCaller
= false;
215 d
->isStrictMode
= callFrame
->codeBlock()->isStrictMode();
217 copyRegisters(callFrame
->globalData());
220 inline void Arguments::copyRegisters(JSGlobalData
& globalData
)
222 ASSERT(!isTornOff());
224 if (!d
->numParameters
)
227 int registerOffset
= d
->numParameters
+ RegisterFile::CallFrameHeaderSize
;
228 size_t registerArraySize
= d
->numParameters
;
230 OwnArrayPtr
<WriteBarrier
<Unknown
> > registerArray
= adoptArrayPtr(new WriteBarrier
<Unknown
>[registerArraySize
]);
231 for (size_t i
= 0; i
< registerArraySize
; i
++)
232 registerArray
[i
].set(globalData
, this, d
->registers
[i
- registerOffset
].get());
233 d
->registers
= registerArray
.get() + registerOffset
;
234 d
->registerArray
= registerArray
.release();
237 // This JSActivation function is defined here so it can get at Arguments::setRegisters.
238 inline void JSActivation::copyRegisters(JSGlobalData
& globalData
)
240 ASSERT(!m_registerArray
);
242 size_t numLocals
= m_numCapturedVars
+ m_numParametersMinusThis
;
247 int registerOffset
= m_numParametersMinusThis
+ RegisterFile::CallFrameHeaderSize
;
248 size_t registerArraySize
= numLocals
+ RegisterFile::CallFrameHeaderSize
;
250 OwnArrayPtr
<WriteBarrier
<Unknown
> > registerArray
= copyRegisterArray(globalData
, m_registers
- registerOffset
, registerArraySize
, m_numParametersMinusThis
+ 1);
251 WriteBarrier
<Unknown
>* registers
= registerArray
.get() + registerOffset
;
252 setRegisters(registers
, registerArray
.release());
257 #endif // Arguments_h