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