2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2006, 2007, 2008 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"
34 struct ArgumentsData
: Noncopyable
{
35 JSActivation
* activation
;
37 unsigned numParameters
;
38 ptrdiff_t firstParameterIndex
;
39 unsigned numArguments
;
42 OwnArrayPtr
<Register
> registerArray
;
44 Register
* extraArguments
;
45 OwnArrayPtr
<bool> deletedArguments
;
46 Register extraArgumentsFixedBuffer
[4];
49 bool overrodeLength
: 1;
50 bool overrodeCallee
: 1;
54 class Arguments
: public JSObject
{
56 enum NoParametersType
{ NoParameters
};
58 Arguments(CallFrame
*);
59 Arguments(CallFrame
*, NoParametersType
);
62 static const ClassInfo info
;
66 void fillArgList(ExecState
*, MarkedArgumentBuffer
&);
68 uint32_t numProvidedArguments(ExecState
* exec
) const
70 if (UNLIKELY(d
->overrodeLength
))
71 return get(exec
, exec
->propertyNames().length
).toUInt32(exec
);
72 return d
->numArguments
;
75 void copyToRegisters(ExecState
* exec
, Register
* buffer
, uint32_t maxSize
);
77 bool isTornOff() const { return d
->registerArray
; }
78 void setActivation(JSActivation
* activation
)
80 d
->activation
= activation
;
81 d
->registers
= &activation
->registerAt(0);
84 static PassRefPtr
<Structure
> createStructure(JSValue prototype
)
86 return Structure::create(prototype
, TypeInfo(ObjectType
));
90 void getArgumentsData(CallFrame
*, JSFunction
*&, ptrdiff_t& firstParameterIndex
, Register
*& argv
, int& argc
);
91 virtual bool getOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
92 virtual bool getOwnPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&);
93 virtual void put(ExecState
*, const Identifier
& propertyName
, JSValue
, PutPropertySlot
&);
94 virtual void put(ExecState
*, unsigned propertyName
, JSValue
, PutPropertySlot
&);
95 virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
);
96 virtual bool deleteProperty(ExecState
*, unsigned propertyName
);
98 virtual const ClassInfo
* classInfo() const { return &info
; }
100 void init(CallFrame
*);
102 OwnPtr
<ArgumentsData
> d
;
105 Arguments
* asArguments(JSValue
);
107 inline Arguments
* asArguments(JSValue value
)
109 ASSERT(asObject(value
)->inherits(&Arguments::info
));
110 return static_cast<Arguments
*>(asObject(value
));
113 ALWAYS_INLINE
void Arguments::getArgumentsData(CallFrame
* callFrame
, JSFunction
*& function
, ptrdiff_t& firstParameterIndex
, Register
*& argv
, int& argc
)
115 function
= callFrame
->callee();
117 int numParameters
= function
->body()->parameterCount();
118 argc
= callFrame
->argumentCount();
120 if (argc
<= numParameters
)
121 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
;
123 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
- argc
;
125 argc
-= 1; // - 1 to skip "this"
126 firstParameterIndex
= -RegisterFile::CallFrameHeaderSize
- numParameters
;
129 inline Arguments::Arguments(CallFrame
* callFrame
)
130 : JSObject(callFrame
->lexicalGlobalObject()->argumentsStructure())
131 , d(new ArgumentsData
)
134 ptrdiff_t firstParameterIndex
;
137 getArgumentsData(callFrame
, callee
, firstParameterIndex
, argv
, numArguments
);
139 d
->numParameters
= callee
->body()->parameterCount();
140 d
->firstParameterIndex
= firstParameterIndex
;
141 d
->numArguments
= numArguments
;
144 d
->registers
= callFrame
->registers();
146 Register
* extraArguments
;
147 if (d
->numArguments
<= d
->numParameters
)
150 unsigned numExtraArguments
= d
->numArguments
- d
->numParameters
;
151 if (numExtraArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(Register
))
152 extraArguments
= new Register
[numExtraArguments
];
154 extraArguments
= d
->extraArgumentsFixedBuffer
;
155 for (unsigned i
= 0; i
< numExtraArguments
; ++i
)
156 extraArguments
[i
] = argv
[d
->numParameters
+ i
];
159 d
->extraArguments
= extraArguments
;
162 d
->overrodeLength
= false;
163 d
->overrodeCallee
= false;
166 inline Arguments::Arguments(CallFrame
* callFrame
, NoParametersType
)
167 : JSObject(callFrame
->lexicalGlobalObject()->argumentsStructure())
168 , d(new ArgumentsData
)
170 ASSERT(!callFrame
->callee()->body()->parameterCount());
172 unsigned numArguments
= callFrame
->argumentCount() - 1;
174 d
->numParameters
= 0;
175 d
->numArguments
= numArguments
;
178 Register
* extraArguments
;
179 if (numArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(Register
))
180 extraArguments
= new Register
[numArguments
];
182 extraArguments
= d
->extraArgumentsFixedBuffer
;
184 Register
* argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numArguments
- 1;
185 for (unsigned i
= 0; i
< numArguments
; ++i
)
186 extraArguments
[i
] = argv
[i
];
188 d
->extraArguments
= extraArguments
;
190 d
->callee
= callFrame
->callee();
191 d
->overrodeLength
= false;
192 d
->overrodeCallee
= false;
195 inline void Arguments::copyRegisters()
197 ASSERT(!isTornOff());
199 if (!d
->numParameters
)
202 int registerOffset
= d
->numParameters
+ RegisterFile::CallFrameHeaderSize
;
203 size_t registerArraySize
= d
->numParameters
;
205 Register
* registerArray
= new Register
[registerArraySize
];
206 memcpy(registerArray
, d
->registers
- registerOffset
, registerArraySize
* sizeof(Register
));
207 d
->registerArray
.set(registerArray
);
208 d
->registers
= registerArray
+ registerOffset
;
211 // This JSActivation function is defined here so it can get at Arguments::setRegisters.
212 inline void JSActivation::copyRegisters(Arguments
* arguments
)
214 ASSERT(!d()->registerArray
);
216 size_t numParametersMinusThis
= d()->functionBody
->generatedBytecode().m_numParameters
- 1;
217 size_t numVars
= d()->functionBody
->generatedBytecode().m_numVars
;
218 size_t numLocals
= numVars
+ numParametersMinusThis
;
223 int registerOffset
= numParametersMinusThis
+ RegisterFile::CallFrameHeaderSize
;
224 size_t registerArraySize
= numLocals
+ RegisterFile::CallFrameHeaderSize
;
226 Register
* registerArray
= copyRegisterArray(d()->registers
- registerOffset
, registerArraySize
);
227 setRegisters(registerArray
+ registerOffset
, registerArray
);
228 if (arguments
&& !arguments
->isTornOff())
229 static_cast<Arguments
*>(arguments
)->setActivation(this);
232 ALWAYS_INLINE Arguments
* Register::arguments() const
234 if (jsValue() == JSValue())
236 return asArguments(jsValue());
242 #endif // Arguments_h