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
: Noncopyable
{
37 JSActivation
* activation
;
39 unsigned numParameters
;
40 ptrdiff_t firstParameterIndex
;
41 unsigned numArguments
;
44 OwnArrayPtr
<Register
> registerArray
;
46 Register
* extraArguments
;
47 OwnArrayPtr
<bool> deletedArguments
;
48 Register extraArgumentsFixedBuffer
[4];
51 bool overrodeLength
: 1;
52 bool overrodeCallee
: 1;
56 class Arguments
: public JSObject
{
58 enum NoParametersType
{ NoParameters
};
60 Arguments(CallFrame
*);
61 Arguments(CallFrame
*, NoParametersType
);
64 static const ClassInfo info
;
66 virtual void markChildren(MarkStack
&);
68 void fillArgList(ExecState
*, MarkedArgumentBuffer
&);
70 uint32_t numProvidedArguments(ExecState
* exec
) const
72 if (UNLIKELY(d
->overrodeLength
))
73 return get(exec
, exec
->propertyNames().length
).toUInt32(exec
);
74 return d
->numArguments
;
77 void copyToRegisters(ExecState
* exec
, Register
* buffer
, uint32_t maxSize
);
79 bool isTornOff() const { return d
->registerArray
; }
80 void setActivation(JSActivation
* activation
)
82 d
->activation
= activation
;
83 d
->registers
= &activation
->registerAt(0);
86 static PassRefPtr
<Structure
> createStructure(JSValue prototype
)
88 return Structure::create(prototype
, TypeInfo(ObjectType
, StructureFlags
), AnonymousSlotCount
);
92 static const unsigned StructureFlags
= OverridesGetOwnPropertySlot
| OverridesMarkChildren
| OverridesGetPropertyNames
| JSObject::StructureFlags
;
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 getOwnPropertyNames(ExecState
*, PropertyNameArray
&, EnumerationMode mode
= ExcludeDontEnumProperties
);
100 virtual void put(ExecState
*, const Identifier
& propertyName
, JSValue
, PutPropertySlot
&);
101 virtual void put(ExecState
*, unsigned propertyName
, JSValue
, PutPropertySlot
&);
102 virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
);
103 virtual bool deleteProperty(ExecState
*, unsigned propertyName
);
105 virtual const ClassInfo
* classInfo() const { return &info
; }
107 void init(CallFrame
*);
109 OwnPtr
<ArgumentsData
> d
;
112 Arguments
* asArguments(JSValue
);
114 inline Arguments
* asArguments(JSValue value
)
116 ASSERT(asObject(value
)->inherits(&Arguments::info
));
117 return static_cast<Arguments
*>(asObject(value
));
120 ALWAYS_INLINE
void Arguments::getArgumentsData(CallFrame
* callFrame
, JSFunction
*& function
, ptrdiff_t& firstParameterIndex
, Register
*& argv
, int& argc
)
122 function
= callFrame
->callee();
124 int numParameters
= function
->jsExecutable()->parameterCount();
125 argc
= callFrame
->argumentCount();
127 if (argc
<= numParameters
)
128 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
;
130 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
- argc
;
132 argc
-= 1; // - 1 to skip "this"
133 firstParameterIndex
= -RegisterFile::CallFrameHeaderSize
- numParameters
;
136 inline Arguments::Arguments(CallFrame
* callFrame
)
137 : JSObject(callFrame
->lexicalGlobalObject()->argumentsStructure())
138 , d(new ArgumentsData
)
141 ptrdiff_t firstParameterIndex
;
144 getArgumentsData(callFrame
, callee
, firstParameterIndex
, argv
, numArguments
);
146 d
->numParameters
= callee
->jsExecutable()->parameterCount();
147 d
->firstParameterIndex
= firstParameterIndex
;
148 d
->numArguments
= numArguments
;
151 d
->registers
= callFrame
->registers();
153 Register
* extraArguments
;
154 if (d
->numArguments
<= d
->numParameters
)
157 unsigned numExtraArguments
= d
->numArguments
- d
->numParameters
;
158 if (numExtraArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(Register
))
159 extraArguments
= new Register
[numExtraArguments
];
161 extraArguments
= d
->extraArgumentsFixedBuffer
;
162 for (unsigned i
= 0; i
< numExtraArguments
; ++i
)
163 extraArguments
[i
] = argv
[d
->numParameters
+ i
];
166 d
->extraArguments
= extraArguments
;
169 d
->overrodeLength
= false;
170 d
->overrodeCallee
= false;
173 inline Arguments::Arguments(CallFrame
* callFrame
, NoParametersType
)
174 : JSObject(callFrame
->lexicalGlobalObject()->argumentsStructure())
175 , d(new ArgumentsData
)
177 ASSERT(!callFrame
->callee()->jsExecutable()->parameterCount());
179 unsigned numArguments
= callFrame
->argumentCount() - 1;
181 d
->numParameters
= 0;
182 d
->numArguments
= numArguments
;
185 Register
* extraArguments
;
186 if (numArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(Register
))
187 extraArguments
= new Register
[numArguments
];
189 extraArguments
= d
->extraArgumentsFixedBuffer
;
191 Register
* argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numArguments
- 1;
192 for (unsigned i
= 0; i
< numArguments
; ++i
)
193 extraArguments
[i
] = argv
[i
];
195 d
->extraArguments
= extraArguments
;
197 d
->callee
= callFrame
->callee();
198 d
->overrodeLength
= false;
199 d
->overrodeCallee
= false;
202 inline void Arguments::copyRegisters()
204 ASSERT(!isTornOff());
206 if (!d
->numParameters
)
209 int registerOffset
= d
->numParameters
+ RegisterFile::CallFrameHeaderSize
;
210 size_t registerArraySize
= d
->numParameters
;
212 Register
* registerArray
= new Register
[registerArraySize
];
213 memcpy(registerArray
, d
->registers
- registerOffset
, registerArraySize
* sizeof(Register
));
214 d
->registerArray
.set(registerArray
);
215 d
->registers
= registerArray
+ registerOffset
;
218 // This JSActivation function is defined here so it can get at Arguments::setRegisters.
219 inline void JSActivation::copyRegisters(Arguments
* arguments
)
221 ASSERT(!d()->registerArray
);
223 size_t numParametersMinusThis
= d()->functionExecutable
->generatedBytecode().m_numParameters
- 1;
224 size_t numVars
= d()->functionExecutable
->generatedBytecode().m_numVars
;
225 size_t numLocals
= numVars
+ numParametersMinusThis
;
230 int registerOffset
= numParametersMinusThis
+ RegisterFile::CallFrameHeaderSize
;
231 size_t registerArraySize
= numLocals
+ RegisterFile::CallFrameHeaderSize
;
233 Register
* registerArray
= copyRegisterArray(d()->registers
- registerOffset
, registerArraySize
);
234 setRegisters(registerArray
+ registerOffset
, registerArray
);
235 if (arguments
&& !arguments
->isTornOff())
236 static_cast<Arguments
*>(arguments
)->setActivation(this);
239 ALWAYS_INLINE Arguments
* Register::arguments() const
241 if (jsValue() == JSValue())
243 return asArguments(jsValue());
249 #endif // Arguments_h