dd9718dff117d38ca781b2e29411d26b15315f8d
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSActivation.h
1 /*
2  * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28  
29 #ifndef JSActivation_h
30 #define JSActivation_h
31
32 #include "CodeBlock.h"
33 #include "CopiedSpaceInlines.h"
34 #include "JSVariableObject.h"
35 #include "Nodes.h"
36 #include "SymbolTable.h"
37
38 namespace JSC {
39
40     class Register;
41     
42     class JSActivation : public JSVariableObject {
43     private:
44         JSActivation(VM& vm, CallFrame*, SharedSymbolTable*);
45     
46     public:
47         typedef JSVariableObject Base;
48
49         static JSActivation* create(VM& vm, CallFrame* callFrame, CodeBlock* codeBlock)
50         {
51             SharedSymbolTable* symbolTable = codeBlock->symbolTable();
52             JSActivation* activation = new (
53                 NotNull,
54                 allocateCell<JSActivation>(
55                     vm.heap,
56                     allocationSize(symbolTable)
57                 )
58             ) JSActivation(vm, callFrame, symbolTable);
59             activation->finishCreation(vm);
60             return activation;
61         }
62
63         static void visitChildren(JSCell*, SlotVisitor&);
64
65         static bool getOwnPropertySlot(JSObject*, ExecState*, PropertyName, PropertySlot&);
66         static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
67         JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, PropertyName, PropertyDescriptor&);
68
69         static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
70
71         static void putDirectVirtual(JSObject*, ExecState*, PropertyName, JSValue, unsigned attributes);
72         static bool deleteProperty(JSCell*, ExecState*, PropertyName);
73
74         static JSValue toThis(JSCell*, ExecState*, ECMAMode);
75
76         void tearOff(VM&);
77         
78         static const ClassInfo s_info;
79
80         static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue proto) { return Structure::create(vm, globalObject, proto, TypeInfo(ActivationObjectType, StructureFlags), &s_info); }
81
82         WriteBarrierBase<Unknown>& registerAt(int) const;
83         bool isValidIndex(int) const;
84         bool isValid(const SymbolTableEntry&) const;
85         bool isTornOff();
86         int registersOffset();
87         static int registersOffset(SharedSymbolTable*);
88
89     protected:
90         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags;
91
92     private:
93         bool symbolTableGet(PropertyName, PropertySlot&);
94         bool symbolTableGet(PropertyName, PropertyDescriptor&);
95         bool symbolTableGet(PropertyName, PropertySlot&, bool& slotIsWriteable);
96         bool symbolTablePut(ExecState*, PropertyName, JSValue, bool shouldThrow);
97         bool symbolTablePutWithAttributes(VM&, PropertyName, JSValue, unsigned attributes);
98
99         static JSValue argumentsGetter(ExecState*, JSValue, PropertyName);
100         NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter();
101
102         static size_t allocationSize(SharedSymbolTable*);
103         static size_t storageOffset();
104
105         WriteBarrier<Unknown>* storage(); // captureCount() number of registers.
106     };
107
108     extern int activationCount;
109     extern int allTheThingsCount;
110
111     inline JSActivation::JSActivation(VM& vm, CallFrame* callFrame, SharedSymbolTable* symbolTable)
112         : Base(
113             vm,
114             callFrame->lexicalGlobalObject()->activationStructure(),
115             callFrame->registers(),
116             callFrame->scope(),
117             symbolTable
118         )
119     {
120         WriteBarrier<Unknown>* storage = this->storage();
121         size_t captureCount = symbolTable->captureCount();
122         for (size_t i = 0; i < captureCount; ++i)
123             new(&storage[i]) WriteBarrier<Unknown>;
124     }
125
126     JSActivation* asActivation(JSValue);
127
128     inline JSActivation* asActivation(JSValue value)
129     {
130         ASSERT(asObject(value)->inherits(&JSActivation::s_info));
131         return jsCast<JSActivation*>(asObject(value));
132     }
133     
134     ALWAYS_INLINE JSActivation* Register::activation() const
135     {
136         return asActivation(jsValue());
137     }
138
139     inline int JSActivation::registersOffset(SharedSymbolTable* symbolTable)
140     {
141         return storageOffset() - (symbolTable->captureStart() * sizeof(WriteBarrier<Unknown>));
142     }
143
144     inline void JSActivation::tearOff(VM& vm)
145     {
146         ASSERT(!isTornOff());
147
148         WriteBarrierBase<Unknown>* dst = reinterpret_cast_ptr<WriteBarrierBase<Unknown>*>(
149             reinterpret_cast<char*>(this) + registersOffset(symbolTable()));
150         WriteBarrierBase<Unknown>* src = m_registers;
151
152         int captureEnd = symbolTable()->captureEnd();
153         for (int i = symbolTable()->captureStart(); i < captureEnd; ++i)
154             dst[i].set(vm, this, src[i].get());
155
156         m_registers = dst;
157         ASSERT(isTornOff());
158     }
159
160     inline bool JSActivation::isTornOff()
161     {
162         return m_registers == reinterpret_cast_ptr<WriteBarrierBase<Unknown>*>(
163             reinterpret_cast<char*>(this) + registersOffset(symbolTable()));
164     }
165
166     inline size_t JSActivation::storageOffset()
167     {
168         return WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSActivation));
169     }
170
171     inline WriteBarrier<Unknown>* JSActivation::storage()
172     {
173         return reinterpret_cast_ptr<WriteBarrier<Unknown>*>(
174             reinterpret_cast<char*>(this) + storageOffset());
175     }
176
177     inline size_t JSActivation::allocationSize(SharedSymbolTable* symbolTable)
178     {
179         size_t objectSizeInBytes = WTF::roundUpToMultipleOf<sizeof(WriteBarrier<Unknown>)>(sizeof(JSActivation));
180         size_t storageSizeInBytes = symbolTable->captureCount() * sizeof(WriteBarrier<Unknown>);
181         return objectSizeInBytes + storageSizeInBytes;
182     }
183
184     inline bool JSActivation::isValidIndex(int index) const
185     {
186         if (index < symbolTable()->captureStart())
187             return false;
188         if (index >= symbolTable()->captureEnd())
189             return false;
190         return true;
191     }
192
193     inline bool JSActivation::isValid(const SymbolTableEntry& entry) const
194     {
195         return isValidIndex(entry.getIndex());
196     }
197
198     inline WriteBarrierBase<Unknown>& JSActivation::registerAt(int index) const
199     {
200         ASSERT(isValidIndex(index));
201         return Base::registerAt(index);
202     }
203
204 } // namespace JSC
205
206 #endif // JSActivation_h