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 // Use an enum because otherwise gcc insists on doing a memory
60 enum { MaxArguments
= 0x10000 };
62 enum NoParametersType
{ NoParameters
};
64 Arguments(CallFrame
*);
65 Arguments(CallFrame
*, NoParametersType
);
68 static const ClassInfo info
;
70 virtual void markChildren(MarkStack
&);
72 void fillArgList(ExecState
*, MarkedArgumentBuffer
&);
74 uint32_t numProvidedArguments(ExecState
* exec
) const
76 if (UNLIKELY(d
->overrodeLength
))
77 return get(exec
, exec
->propertyNames().length
).toUInt32(exec
);
78 return d
->numArguments
;
81 void copyToRegisters(ExecState
* exec
, Register
* buffer
, uint32_t maxSize
);
83 bool isTornOff() const { return d
->registerArray
; }
84 void setActivation(JSActivation
* activation
)
86 d
->activation
= activation
;
87 d
->registers
= &activation
->registerAt(0);
90 static PassRefPtr
<Structure
> createStructure(JSValue prototype
)
92 return Structure::create(prototype
, TypeInfo(ObjectType
, StructureFlags
), AnonymousSlotCount
);
96 static const unsigned StructureFlags
= OverridesGetOwnPropertySlot
| OverridesMarkChildren
| OverridesGetPropertyNames
| JSObject::StructureFlags
;
99 void getArgumentsData(CallFrame
*, JSFunction
*&, ptrdiff_t& firstParameterIndex
, Register
*& argv
, int& argc
);
100 virtual bool getOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
101 virtual bool getOwnPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&);
102 virtual bool getOwnPropertyDescriptor(ExecState
*, const Identifier
&, PropertyDescriptor
&);
103 virtual void getOwnPropertyNames(ExecState
*, PropertyNameArray
&, EnumerationMode mode
= ExcludeDontEnumProperties
);
104 virtual void put(ExecState
*, const Identifier
& propertyName
, JSValue
, PutPropertySlot
&);
105 virtual void put(ExecState
*, unsigned propertyName
, JSValue
, PutPropertySlot
&);
106 virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
);
107 virtual bool deleteProperty(ExecState
*, unsigned propertyName
);
109 virtual const ClassInfo
* classInfo() const { return &info
; }
111 void init(CallFrame
*);
113 OwnPtr
<ArgumentsData
> d
;
116 Arguments
* asArguments(JSValue
);
118 inline Arguments
* asArguments(JSValue value
)
120 ASSERT(asObject(value
)->inherits(&Arguments::info
));
121 return static_cast<Arguments
*>(asObject(value
));
124 ALWAYS_INLINE
void Arguments::getArgumentsData(CallFrame
* callFrame
, JSFunction
*& function
, ptrdiff_t& firstParameterIndex
, Register
*& argv
, int& argc
)
126 function
= callFrame
->callee();
128 int numParameters
= function
->jsExecutable()->parameterCount();
129 argc
= callFrame
->argumentCount();
131 if (argc
<= numParameters
)
132 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
;
134 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
- argc
;
136 argc
-= 1; // - 1 to skip "this"
137 firstParameterIndex
= -RegisterFile::CallFrameHeaderSize
- numParameters
;
140 inline Arguments::Arguments(CallFrame
* callFrame
)
141 : JSObject(callFrame
->lexicalGlobalObject()->argumentsStructure())
142 , d(new ArgumentsData
)
145 ptrdiff_t firstParameterIndex
;
148 getArgumentsData(callFrame
, callee
, firstParameterIndex
, argv
, numArguments
);
150 d
->numParameters
= callee
->jsExecutable()->parameterCount();
151 d
->firstParameterIndex
= firstParameterIndex
;
152 d
->numArguments
= numArguments
;
155 d
->registers
= callFrame
->registers();
157 Register
* extraArguments
;
158 if (d
->numArguments
<= d
->numParameters
)
161 unsigned numExtraArguments
= d
->numArguments
- d
->numParameters
;
162 if (numExtraArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(Register
))
163 extraArguments
= new Register
[numExtraArguments
];
165 extraArguments
= d
->extraArgumentsFixedBuffer
;
166 for (unsigned i
= 0; i
< numExtraArguments
; ++i
)
167 extraArguments
[i
] = argv
[d
->numParameters
+ i
];
170 d
->extraArguments
= extraArguments
;
173 d
->overrodeLength
= false;
174 d
->overrodeCallee
= false;
177 inline Arguments::Arguments(CallFrame
* callFrame
, NoParametersType
)
178 : JSObject(callFrame
->lexicalGlobalObject()->argumentsStructure())
179 , d(new ArgumentsData
)
181 ASSERT(!callFrame
->callee()->jsExecutable()->parameterCount());
183 unsigned numArguments
= callFrame
->argumentCount() - 1;
185 d
->numParameters
= 0;
186 d
->numArguments
= numArguments
;
189 Register
* extraArguments
;
190 if (numArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(Register
))
191 extraArguments
= new Register
[numArguments
];
193 extraArguments
= d
->extraArgumentsFixedBuffer
;
195 Register
* argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numArguments
- 1;
196 for (unsigned i
= 0; i
< numArguments
; ++i
)
197 extraArguments
[i
] = argv
[i
];
199 d
->extraArguments
= extraArguments
;
201 d
->callee
= callFrame
->callee();
202 d
->overrodeLength
= false;
203 d
->overrodeCallee
= false;
206 inline void Arguments::copyRegisters()
208 ASSERT(!isTornOff());
210 if (!d
->numParameters
)
213 int registerOffset
= d
->numParameters
+ RegisterFile::CallFrameHeaderSize
;
214 size_t registerArraySize
= d
->numParameters
;
216 Register
* registerArray
= new Register
[registerArraySize
];
217 memcpy(registerArray
, d
->registers
- registerOffset
, registerArraySize
* sizeof(Register
));
218 d
->registerArray
.set(registerArray
);
219 d
->registers
= registerArray
+ registerOffset
;
222 // This JSActivation function is defined here so it can get at Arguments::setRegisters.
223 inline void JSActivation::copyRegisters(Arguments
* arguments
)
225 ASSERT(!d()->registerArray
);
227 size_t numParametersMinusThis
= d()->functionExecutable
->generatedBytecode().m_numParameters
- 1;
228 size_t numVars
= d()->functionExecutable
->generatedBytecode().m_numVars
;
229 size_t numLocals
= numVars
+ numParametersMinusThis
;
234 int registerOffset
= numParametersMinusThis
+ RegisterFile::CallFrameHeaderSize
;
235 size_t registerArraySize
= numLocals
+ RegisterFile::CallFrameHeaderSize
;
237 Register
* registerArray
= copyRegisterArray(d()->registers
- registerOffset
, registerArraySize
);
238 setRegisters(registerArray
+ registerOffset
, registerArray
);
239 if (arguments
&& !arguments
->isTornOff())
240 static_cast<Arguments
*>(arguments
)->setActivation(this);
243 ALWAYS_INLINE Arguments
* Register::arguments() const
245 if (jsValue() == JSValue())
247 return asArguments(jsValue());
253 #endif // Arguments_h