tizen beta release
[framework/web/webkit-efl.git] / Source / JavaScriptCore / runtime / JSActivation.cpp
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 #include "config.h"
30 #include "JSActivation.h"
31
32 #include "Arguments.h"
33 #include "Interpreter.h"
34 #include "JSFunction.h"
35
36 namespace JSC {
37
38 ASSERT_CLASS_FITS_IN_CELL(JSActivation);
39
40 const ClassInfo JSActivation::s_info = { "JSActivation", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSActivation) };
41
42 JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExecutable)
43     : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers())
44     , m_numParametersMinusThis(static_cast<int>(functionExecutable->parameterCount()))
45     , m_numCapturedVars(functionExecutable->capturedVariableCount())
46     , m_requiresDynamicChecks(functionExecutable->usesEval())
47     , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister())
48 {
49 }
50
51 void JSActivation::finishCreation(CallFrame* callFrame)
52 {
53     Base::finishCreation(callFrame->globalData());
54     ASSERT(inherits(&s_info));
55
56     // We have to manually ref and deref the symbol table as JSVariableObject
57     // doesn't know about SharedSymbolTable
58     static_cast<SharedSymbolTable*>(m_symbolTable)->ref();
59     callFrame->globalData().heap.addFinalizer(this, &finalize);
60 }
61
62 void JSActivation::finalize(JSCell* cell)
63 {
64     static_cast<SharedSymbolTable*>(jsCast<JSActivation*>(cell)->m_symbolTable)->deref();
65 }
66
67 void JSActivation::visitChildren(JSCell* cell, SlotVisitor& visitor)
68 {
69     JSActivation* thisObject = jsCast<JSActivation*>(cell);
70     ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info);
71     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
72     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
73     Base::visitChildren(thisObject, visitor);
74
75     // No need to mark our registers if they're still in the RegisterFile.
76     WriteBarrier<Unknown>* registerArray = thisObject->m_registerArray.get();
77     if (!registerArray)
78         return;
79
80     visitor.appendValues(registerArray, thisObject->m_numParametersMinusThis);
81
82     // Skip the call frame, which sits between the parameters and vars.
83     visitor.appendValues(registerArray + thisObject->m_numParametersMinusThis + RegisterFile::CallFrameHeaderSize, thisObject->m_numCapturedVars);
84 }
85
86 inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
87 {
88     SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
89     if (entry.isNull())
90         return false;
91     if (entry.getIndex() >= m_numCapturedVars)
92         return false;
93
94     slot.setValue(registerAt(entry.getIndex()).get());
95     return true;
96 }
97
98 inline bool JSActivation::symbolTablePut(JSGlobalData& globalData, const Identifier& propertyName, JSValue value)
99 {
100     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
101     
102     SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
103     if (entry.isNull())
104         return false;
105     if (entry.isReadOnly())
106         return true;
107     if (entry.getIndex() >= m_numCapturedVars)
108         return false;
109
110     registerAt(entry.getIndex()).set(globalData, this, value);
111     return true;
112 }
113
114 void JSActivation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
115 {
116     JSActivation* thisObject = jsCast<JSActivation*>(object);
117     SymbolTable::const_iterator end = thisObject->symbolTable().end();
118     for (SymbolTable::const_iterator it = thisObject->symbolTable().begin(); it != end; ++it) {
119         if (it->second.getAttributes() & DontEnum && mode != IncludeDontEnumProperties)
120             continue;
121         if (it->second.getIndex() >= thisObject->m_numCapturedVars)
122             continue;
123         propertyNames.add(Identifier(exec, it->first.get()));
124     }
125     // Skip the JSVariableObject implementation of getOwnPropertyNames
126     JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
127 }
128
129 inline bool JSActivation::symbolTablePutWithAttributes(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes)
130 {
131     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(this));
132     
133     SymbolTable::iterator iter = symbolTable().find(propertyName.impl());
134     if (iter == symbolTable().end())
135         return false;
136     SymbolTableEntry& entry = iter->second;
137     ASSERT(!entry.isNull());
138     if (entry.getIndex() >= m_numCapturedVars)
139         return false;
140
141     entry.setAttributes(attributes);
142     registerAt(entry.getIndex()).set(globalData, this, value);
143     return true;
144 }
145
146 bool JSActivation::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
147 {
148     JSActivation* thisObject = jsCast<JSActivation*>(cell);
149     if (propertyName == exec->propertyNames().arguments) {
150         slot.setCustom(thisObject, thisObject->getArgumentsGetter());
151         return true;
152     }
153
154     if (thisObject->symbolTableGet(propertyName, slot))
155         return true;
156
157     if (WriteBarrierBase<Unknown>* location = thisObject->getDirectLocation(exec->globalData(), propertyName)) {
158         slot.setValue(location->get());
159         return true;
160     }
161
162     // We don't call through to JSObject because there's no way to give an 
163     // activation object getter properties or a prototype.
164     ASSERT(!thisObject->hasGetterSetterProperties());
165     ASSERT(thisObject->prototype().isNull());
166     return false;
167 }
168
169 void JSActivation::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot)
170 {
171     JSActivation* thisObject = jsCast<JSActivation*>(cell);
172     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
173
174     if (thisObject->symbolTablePut(exec->globalData(), propertyName, value))
175         return;
176
177     // We don't call through to JSObject because __proto__ and getter/setter 
178     // properties are non-standard extensions that other implementations do not
179     // expose in the activation object.
180     ASSERT(!thisObject->hasGetterSetterProperties());
181     thisObject->putDirect(exec->globalData(), propertyName, value, 0, true, slot);
182 }
183
184 // FIXME: Make this function honor ReadOnly (const) and DontEnum
185 void JSActivation::putWithAttributes(JSObject* object, ExecState* exec, const Identifier& propertyName, JSValue value, unsigned attributes)
186 {
187     JSActivation* thisObject = jsCast<JSActivation*>(object);
188     ASSERT(!Heap::heap(value) || Heap::heap(value) == Heap::heap(thisObject));
189
190     if (thisObject->symbolTablePutWithAttributes(exec->globalData(), propertyName, value, attributes))
191         return;
192
193     // We don't call through to JSObject because __proto__ and getter/setter 
194     // properties are non-standard extensions that other implementations do not
195     // expose in the activation object.
196     ASSERT(!thisObject->hasGetterSetterProperties());
197     JSObject::putWithAttributes(thisObject, exec, propertyName, value, attributes);
198 }
199
200 bool JSActivation::deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName)
201 {
202     if (propertyName == exec->propertyNames().arguments)
203         return false;
204
205     return Base::deleteProperty(cell, exec, propertyName);
206 }
207
208 JSObject* JSActivation::toThisObject(JSCell*, ExecState* exec)
209 {
210     return exec->globalThisValue();
211 }
212
213 JSValue JSActivation::argumentsGetter(ExecState*, JSValue slotBase, const Identifier&)
214 {
215     JSActivation* activation = asActivation(slotBase);
216     CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(activation->m_registers));
217     int argumentsRegister = activation->m_argumentsRegister;
218     if (JSValue arguments = callFrame->uncheckedR(argumentsRegister).jsValue())
219         return arguments;
220     int realArgumentsRegister = unmodifiedArgumentsRegister(argumentsRegister);
221
222     JSValue arguments = JSValue(Arguments::create(callFrame->globalData(), callFrame));
223     callFrame->uncheckedR(argumentsRegister) = arguments;
224     callFrame->uncheckedR(realArgumentsRegister) = arguments;
225     
226     ASSERT(callFrame->uncheckedR(realArgumentsRegister).jsValue().inherits(&Arguments::s_info));
227     return callFrame->uncheckedR(realArgumentsRegister).jsValue();
228 }
229
230 // These two functions serve the purpose of isolating the common case from a
231 // PIC branch.
232
233 PropertySlot::GetValueFunc JSActivation::getArgumentsGetter()
234 {
235     return argumentsGetter;
236 }
237
238 } // namespace JSC