2008-10-09 Cameron Zwarich <zwarich@apple.com>
[WebKit-https.git] / JavaScriptCore / kjs / Arguments.h
1 /*
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
6  *
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.
11  *
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.
16  *
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.
21  *
22  */
23
24 #ifndef Arguments_h
25 #define Arguments_h
26
27 #include "JSActivation.h"
28 #include "JSFunction.h"
29 #include "JSGlobalObject.h"
30 #include "Machine.h"
31
32 namespace JSC {
33
34     struct ArgumentsData : Noncopyable {
35         JSActivation* activation;
36
37         unsigned numParameters;
38         ptrdiff_t firstParameterIndex;
39         unsigned numArguments;
40
41         Register* registers;
42         OwnArrayPtr<Register> registerArray;
43
44         Register* extraArguments;
45         OwnArrayPtr<bool> deletedArguments;
46         Register extraArgumentsFixedBuffer[4];
47
48         JSFunction* callee;
49         bool overrodeLength : 1;
50         bool overrodeCallee : 1;
51     };
52
53
54     class Arguments : public JSObject {
55     public:
56         Arguments(CallFrame*);
57         virtual ~Arguments();
58
59         static const ClassInfo info;
60
61         virtual void mark();
62
63         void fillArgList(ExecState*, ArgList&);
64
65         void copyRegisters();
66         bool isTornOff() const { return d->registerArray; }
67         void setActivation(JSActivation* activation)
68         {
69             d->activation = activation;
70             d->registers = &activation->registerAt(0);
71         }
72
73     private:
74         virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&);
75         virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&);
76         virtual void put(ExecState*, const Identifier& propertyName, JSValue*, PutPropertySlot&);
77         virtual void put(ExecState*, unsigned propertyName, JSValue*, PutPropertySlot&);
78         virtual bool deleteProperty(ExecState*, const Identifier& propertyName);
79         virtual bool deleteProperty(ExecState*, unsigned propertyName);
80
81         virtual const ClassInfo* classInfo() const { return &info; }
82
83         void init(CallFrame*);
84
85         OwnPtr<ArgumentsData> d;
86     };
87
88     inline Arguments::Arguments(CallFrame* callFrame)
89         : JSObject(callFrame->lexicalGlobalObject()->argumentsStructure())
90         , d(new ArgumentsData)
91     {
92         JSFunction* callee;
93         ptrdiff_t firstParameterIndex;
94         Register* argv;
95         int numArguments;
96         callFrame->machine()->getArgumentsData(callFrame, callee, firstParameterIndex, argv, numArguments);
97
98         d->numParameters = callee->m_body->parameterCount();
99         d->firstParameterIndex = firstParameterIndex;
100         d->numArguments = numArguments;
101
102         d->activation = 0;
103         d->registers = callFrame->registers();
104
105         Register* extraArguments;
106         if (d->numArguments <= d->numParameters)
107             extraArguments = 0;
108         else {
109             unsigned numExtraArguments = d->numArguments - d->numParameters;
110             if (numExtraArguments > sizeof(d->extraArgumentsFixedBuffer) / sizeof(Register))
111                 extraArguments = new Register[numExtraArguments];
112             else
113                 extraArguments = d->extraArgumentsFixedBuffer;
114             for (unsigned i = 0; i < numExtraArguments; ++i)
115                 extraArguments[i] = argv[d->numParameters + i];
116         }
117
118         d->extraArguments = extraArguments;
119
120         d->callee = callee;
121         d->overrodeLength = false;
122         d->overrodeCallee = false;
123     }
124
125     inline void Arguments::copyRegisters()
126     {
127         ASSERT(!isTornOff());
128
129         if (!d->numParameters)
130             return;
131
132         int registerOffset = d->numParameters + RegisterFile::CallFrameHeaderSize;
133         size_t registerArraySize = d->numParameters;
134
135         Register* registerArray = new Register[registerArraySize];
136         memcpy(registerArray, d->registers - registerOffset, registerArraySize * sizeof(Register));
137         d->registerArray.set(registerArray);
138         d->registers = registerArray + registerOffset;
139     }
140
141     // This JSActivation function is defined here so it can get at Arguments::setRegisters.
142     inline void JSActivation::copyRegisters(Arguments* arguments)
143     {
144         ASSERT(!d()->registerArray);
145
146         size_t numParametersMinusThis = d()->functionBody->generatedByteCode().numParameters - 1;
147         size_t numVars = d()->functionBody->generatedByteCode().numVars;
148         size_t numLocals = numVars + numParametersMinusThis;
149
150         if (!numLocals)
151             return;
152
153         int registerOffset = numParametersMinusThis + RegisterFile::CallFrameHeaderSize;
154         size_t registerArraySize = numLocals + RegisterFile::CallFrameHeaderSize;
155
156         Register* registerArray = copyRegisterArray(d()->registers - registerOffset, registerArraySize);
157         setRegisters(registerArray + registerOffset, registerArray);
158         if (arguments && !arguments->isTornOff())
159             static_cast<Arguments*>(arguments)->setActivation(this);
160     }
161
162 } // namespace JSC
163
164 #endif // Arguments_h