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
*, ArgList
&);
69 bool isTornOff() const { return d
->registerArray
; }
70 void setActivation(JSActivation
* activation
)
72 d
->activation
= activation
;
73 d
->registers
= &activation
->registerAt(0);
76 static PassRefPtr
<Structure
> createStructure(JSValuePtr prototype
)
78 return Structure::create(prototype
, TypeInfo(ObjectType
));
82 void getArgumentsData(CallFrame
*, JSFunction
*&, ptrdiff_t& firstParameterIndex
, Register
*& argv
, int& argc
);
83 virtual bool getOwnPropertySlot(ExecState
*, const Identifier
& propertyName
, PropertySlot
&);
84 virtual bool getOwnPropertySlot(ExecState
*, unsigned propertyName
, PropertySlot
&);
85 virtual void put(ExecState
*, const Identifier
& propertyName
, JSValuePtr
, PutPropertySlot
&);
86 virtual void put(ExecState
*, unsigned propertyName
, JSValuePtr
, PutPropertySlot
&);
87 virtual bool deleteProperty(ExecState
*, const Identifier
& propertyName
);
88 virtual bool deleteProperty(ExecState
*, unsigned propertyName
);
90 virtual const ClassInfo
* classInfo() const { return &info
; }
92 void init(CallFrame
*);
94 OwnPtr
<ArgumentsData
> d
;
97 Arguments
* asArguments(JSValuePtr
);
99 inline Arguments
* asArguments(JSValuePtr value
)
101 ASSERT(asObject(value
)->inherits(&Arguments::info
));
102 return static_cast<Arguments
*>(asObject(value
));
105 ALWAYS_INLINE
void Arguments::getArgumentsData(CallFrame
* callFrame
, JSFunction
*& function
, ptrdiff_t& firstParameterIndex
, Register
*& argv
, int& argc
)
107 function
= callFrame
->callee();
109 CodeBlock
* codeBlock
= &function
->body()->generatedBytecode();
110 int numParameters
= codeBlock
->m_numParameters
;
111 argc
= callFrame
->argumentCount();
113 if (argc
<= numParameters
)
114 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
+ 1; // + 1 to skip "this"
116 argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numParameters
- argc
+ 1; // + 1 to skip "this"
118 argc
-= 1; // - 1 to skip "this"
119 firstParameterIndex
= -RegisterFile::CallFrameHeaderSize
- numParameters
+ 1; // + 1 to skip "this"
122 inline Arguments::Arguments(CallFrame
* callFrame
)
123 : JSObject(callFrame
->lexicalGlobalObject()->argumentsStructure())
124 , d(new ArgumentsData
)
127 ptrdiff_t firstParameterIndex
;
130 getArgumentsData(callFrame
, callee
, firstParameterIndex
, argv
, numArguments
);
132 d
->numParameters
= callee
->body()->parameterCount();
133 d
->firstParameterIndex
= firstParameterIndex
;
134 d
->numArguments
= numArguments
;
137 d
->registers
= callFrame
->registers();
139 Register
* extraArguments
;
140 if (d
->numArguments
<= d
->numParameters
)
143 unsigned numExtraArguments
= d
->numArguments
- d
->numParameters
;
144 if (numExtraArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(Register
))
145 extraArguments
= new Register
[numExtraArguments
];
147 extraArguments
= d
->extraArgumentsFixedBuffer
;
148 for (unsigned i
= 0; i
< numExtraArguments
; ++i
)
149 extraArguments
[i
] = argv
[d
->numParameters
+ i
];
152 d
->extraArguments
= extraArguments
;
155 d
->overrodeLength
= false;
156 d
->overrodeCallee
= false;
159 inline Arguments::Arguments(CallFrame
* callFrame
, NoParametersType
)
160 : JSObject(callFrame
->lexicalGlobalObject()->argumentsStructure())
161 , d(new ArgumentsData
)
163 ASSERT(!callFrame
->callee()->body()->parameterCount());
165 unsigned numArguments
= callFrame
->argumentCount() - 1;
167 d
->numParameters
= 0;
168 d
->numArguments
= numArguments
;
171 Register
* extraArguments
;
172 if (numArguments
> sizeof(d
->extraArgumentsFixedBuffer
) / sizeof(Register
))
173 extraArguments
= new Register
[numArguments
];
175 extraArguments
= d
->extraArgumentsFixedBuffer
;
177 Register
* argv
= callFrame
->registers() - RegisterFile::CallFrameHeaderSize
- numArguments
- 1;
178 for (unsigned i
= 0; i
< numArguments
; ++i
)
179 extraArguments
[i
] = argv
[i
];
181 d
->extraArguments
= extraArguments
;
183 d
->callee
= callFrame
->callee();
184 d
->overrodeLength
= false;
185 d
->overrodeCallee
= false;
188 inline void Arguments::copyRegisters()
190 ASSERT(!isTornOff());
192 if (!d
->numParameters
)
195 int registerOffset
= d
->numParameters
+ RegisterFile::CallFrameHeaderSize
;
196 size_t registerArraySize
= d
->numParameters
;
198 Register
* registerArray
= new Register
[registerArraySize
];
199 memcpy(registerArray
, d
->registers
- registerOffset
, registerArraySize
* sizeof(Register
));
200 d
->registerArray
.set(registerArray
);
201 d
->registers
= registerArray
+ registerOffset
;
204 // This JSActivation function is defined here so it can get at Arguments::setRegisters.
205 inline void JSActivation::copyRegisters(Arguments
* arguments
)
207 ASSERT(!d()->registerArray
);
209 size_t numParametersMinusThis
= d()->functionBody
->generatedBytecode().m_numParameters
- 1;
210 size_t numVars
= d()->functionBody
->generatedBytecode().m_numVars
;
211 size_t numLocals
= numVars
+ numParametersMinusThis
;
216 int registerOffset
= numParametersMinusThis
+ RegisterFile::CallFrameHeaderSize
;
217 size_t registerArraySize
= numLocals
+ RegisterFile::CallFrameHeaderSize
;
219 Register
* registerArray
= copyRegisterArray(d()->registers
- registerOffset
, registerArraySize
);
220 setRegisters(registerArray
+ registerOffset
, registerArray
);
221 if (arguments
&& !arguments
->isTornOff())
222 static_cast<Arguments
*>(arguments
)->setActivation(this);
227 #endif // Arguments_h