]>
Commit | Line | Data |
---|---|---|
9dae56ea A |
1 | /* |
2 | * Copyright (C) 2007 Eric Seidel <eric@webkit.org> | |
f9bf01c6 | 3 | * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. |
9dae56ea A |
4 | * |
5 | * This library is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU Library General Public | |
7 | * License as published by the Free Software Foundation; either | |
8 | * version 2 of the License, or (at your option) any later version. | |
9 | * | |
10 | * This library is distributed in the hope that it will be useful, | |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | * Library General Public License for more details. | |
14 | * | |
15 | * You should have received a copy of the GNU Library General Public License | |
16 | * along with this library; see the file COPYING.LIB. If not, write to | |
17 | * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | |
18 | * Boston, MA 02110-1301, USA. | |
19 | * | |
20 | */ | |
21 | ||
22 | #ifndef JSGlobalObject_h | |
23 | #define JSGlobalObject_h | |
24 | ||
f9bf01c6 | 25 | #include "JSArray.h" |
9dae56ea | 26 | #include "JSGlobalData.h" |
6fe7ccc8 | 27 | #include "JSGlobalThis.h" |
9dae56ea | 28 | #include "JSVariableObject.h" |
4e4e5a6f | 29 | #include "JSWeakObjectMapRefInternal.h" |
9dae56ea A |
30 | #include "NumberPrototype.h" |
31 | #include "StringPrototype.h" | |
14957cd0 | 32 | #include "StructureChain.h" |
9dae56ea A |
33 | #include <wtf/HashSet.h> |
34 | #include <wtf/OwnPtr.h> | |
4e4e5a6f | 35 | #include <wtf/RandomNumber.h> |
9dae56ea A |
36 | |
37 | namespace JSC { | |
38 | ||
39 | class ArrayPrototype; | |
40 | class BooleanPrototype; | |
41 | class DatePrototype; | |
42 | class Debugger; | |
43 | class ErrorConstructor; | |
44 | class FunctionPrototype; | |
6fe7ccc8 | 45 | class GetterSetter; |
f9bf01c6 | 46 | class GlobalCodeBlock; |
6fe7ccc8 | 47 | class LLIntOffsetsExtractor; |
9dae56ea A |
48 | class NativeErrorConstructor; |
49 | class ProgramCodeBlock; | |
50 | class RegExpConstructor; | |
51 | class RegExpPrototype; | |
52 | class RegisterFile; | |
53 | ||
54 | struct ActivationStackNode; | |
55 | struct HashTable; | |
56 | ||
57 | typedef Vector<ExecState*, 16> ExecStateStack; | |
f9bf01c6 | 58 | |
6fe7ccc8 A |
59 | struct GlobalObjectMethodTable { |
60 | typedef bool (*AllowsAccessFromFunctionPtr)(const JSGlobalObject*, ExecState*); | |
61 | AllowsAccessFromFunctionPtr allowsAccessFrom; | |
62 | ||
63 | typedef bool (*SupportsProfilingFunctionPtr)(const JSGlobalObject*); | |
64 | SupportsProfilingFunctionPtr supportsProfiling; | |
65 | ||
66 | typedef bool (*SupportsRichSourceInfoFunctionPtr)(const JSGlobalObject*); | |
67 | SupportsRichSourceInfoFunctionPtr supportsRichSourceInfo; | |
68 | ||
69 | typedef bool (*ShouldInterruptScriptFunctionPtr)(const JSGlobalObject*); | |
70 | ShouldInterruptScriptFunctionPtr shouldInterruptScript; | |
71 | ||
72 | typedef bool (*ShouldInterruptScriptBeforeTimeoutPtr)(const JSGlobalObject*); | |
73 | ShouldInterruptScriptBeforeTimeoutPtr shouldInterruptScriptBeforeTimeout; | |
74 | }; | |
75 | ||
9dae56ea | 76 | class JSGlobalObject : public JSVariableObject { |
6fe7ccc8 | 77 | private: |
4e4e5a6f | 78 | typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet; |
9dae56ea | 79 | |
6fe7ccc8 A |
80 | struct JSGlobalObjectRareData { |
81 | JSGlobalObjectRareData() | |
82 | : profileGroup(0) | |
83 | { | |
84 | } | |
85 | ||
86 | WeakMapSet weakMaps; | |
87 | unsigned profileGroup; | |
88 | }; | |
89 | ||
90 | protected: | |
14957cd0 A |
91 | |
92 | size_t m_registerArraySize; | |
93 | Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize]; | |
94 | ||
95 | WriteBarrier<ScopeChainNode> m_globalScopeChain; | |
96 | WriteBarrier<JSObject> m_methodCallDummy; | |
97 | ||
98 | WriteBarrier<RegExpConstructor> m_regExpConstructor; | |
99 | WriteBarrier<ErrorConstructor> m_errorConstructor; | |
100 | WriteBarrier<NativeErrorConstructor> m_evalErrorConstructor; | |
101 | WriteBarrier<NativeErrorConstructor> m_rangeErrorConstructor; | |
102 | WriteBarrier<NativeErrorConstructor> m_referenceErrorConstructor; | |
103 | WriteBarrier<NativeErrorConstructor> m_syntaxErrorConstructor; | |
104 | WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor; | |
105 | WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor; | |
106 | ||
107 | WriteBarrier<JSFunction> m_evalFunction; | |
108 | WriteBarrier<JSFunction> m_callFunction; | |
109 | WriteBarrier<JSFunction> m_applyFunction; | |
6fe7ccc8 | 110 | WriteBarrier<GetterSetter> m_throwTypeErrorGetterSetter; |
14957cd0 A |
111 | |
112 | WriteBarrier<ObjectPrototype> m_objectPrototype; | |
113 | WriteBarrier<FunctionPrototype> m_functionPrototype; | |
114 | WriteBarrier<ArrayPrototype> m_arrayPrototype; | |
115 | WriteBarrier<BooleanPrototype> m_booleanPrototype; | |
116 | WriteBarrier<StringPrototype> m_stringPrototype; | |
117 | WriteBarrier<NumberPrototype> m_numberPrototype; | |
118 | WriteBarrier<DatePrototype> m_datePrototype; | |
119 | WriteBarrier<RegExpPrototype> m_regExpPrototype; | |
120 | ||
121 | WriteBarrier<Structure> m_argumentsStructure; | |
122 | WriteBarrier<Structure> m_arrayStructure; | |
123 | WriteBarrier<Structure> m_booleanObjectStructure; | |
124 | WriteBarrier<Structure> m_callbackConstructorStructure; | |
125 | WriteBarrier<Structure> m_callbackFunctionStructure; | |
126 | WriteBarrier<Structure> m_callbackObjectStructure; | |
127 | WriteBarrier<Structure> m_dateStructure; | |
128 | WriteBarrier<Structure> m_emptyObjectStructure; | |
129 | WriteBarrier<Structure> m_nullPrototypeObjectStructure; | |
130 | WriteBarrier<Structure> m_errorStructure; | |
131 | WriteBarrier<Structure> m_functionStructure; | |
6fe7ccc8 A |
132 | WriteBarrier<Structure> m_boundFunctionStructure; |
133 | WriteBarrier<Structure> m_namedFunctionStructure; | |
134 | size_t m_functionNameOffset; | |
14957cd0 A |
135 | WriteBarrier<Structure> m_numberObjectStructure; |
136 | WriteBarrier<Structure> m_regExpMatchesArrayStructure; | |
137 | WriteBarrier<Structure> m_regExpStructure; | |
138 | WriteBarrier<Structure> m_stringObjectStructure; | |
139 | WriteBarrier<Structure> m_internalFunctionStructure; | |
140 | ||
14957cd0 A |
141 | Debugger* m_debugger; |
142 | ||
6fe7ccc8 | 143 | OwnPtr<JSGlobalObjectRareData> m_rareData; |
14957cd0 A |
144 | |
145 | WeakRandom m_weakRandom; | |
146 | ||
147 | SymbolTable m_symbolTable; | |
148 | ||
6fe7ccc8 A |
149 | bool m_evalEnabled; |
150 | ||
151 | static JS_EXPORTDATA const GlobalObjectMethodTable s_globalObjectMethodTable; | |
152 | const GlobalObjectMethodTable* m_globalObjectMethodTable; | |
9dae56ea | 153 | |
6fe7ccc8 A |
154 | void createRareDataIfNeeded() |
155 | { | |
156 | if (m_rareData) | |
157 | return; | |
158 | m_rareData = adoptPtr(new JSGlobalObjectRareData); | |
159 | Heap::heap(this)->addFinalizer(this, clearRareData); | |
160 | } | |
161 | ||
9dae56ea | 162 | public: |
6fe7ccc8 | 163 | typedef JSVariableObject Base; |
9dae56ea | 164 | |
6fe7ccc8 | 165 | static JSGlobalObject* create(JSGlobalData& globalData, Structure* structure) |
9dae56ea | 166 | { |
6fe7ccc8 A |
167 | JSGlobalObject* globalObject = new (NotNull, allocateCell<JSGlobalObject>(globalData.heap)) JSGlobalObject(globalData, structure); |
168 | globalObject->finishCreation(globalData); | |
169 | return globalObject; | |
9dae56ea A |
170 | } |
171 | ||
14957cd0 A |
172 | static JS_EXPORTDATA const ClassInfo s_info; |
173 | ||
9dae56ea | 174 | protected: |
6fe7ccc8 | 175 | explicit JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable = 0) |
14957cd0 A |
176 | : JSVariableObject(globalData, structure, &m_symbolTable, 0) |
177 | , m_registerArraySize(0) | |
178 | , m_globalScopeChain() | |
179 | , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0))) | |
6fe7ccc8 A |
180 | , m_evalEnabled(true) |
181 | , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable) | |
182 | { | |
183 | } | |
184 | ||
185 | void finishCreation(JSGlobalData& globalData) | |
186 | { | |
187 | Base::finishCreation(globalData); | |
188 | structure()->setGlobalObject(globalData, this); | |
189 | init(this); | |
190 | } | |
191 | ||
192 | void finishCreation(JSGlobalData& globalData, JSGlobalThis* thisValue) | |
9dae56ea | 193 | { |
6fe7ccc8 A |
194 | Base::finishCreation(globalData); |
195 | structure()->setGlobalObject(globalData, this); | |
9dae56ea A |
196 | init(thisValue); |
197 | } | |
198 | ||
199 | public: | |
6fe7ccc8 A |
200 | JS_EXPORT_PRIVATE ~JSGlobalObject(); |
201 | JS_EXPORT_PRIVATE static void destroy(JSCell*); | |
202 | ||
203 | JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); | |
9dae56ea | 204 | |
6fe7ccc8 A |
205 | JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); |
206 | JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); | |
207 | bool hasOwnPropertyForWrite(ExecState*, const Identifier&); | |
208 | JS_EXPORT_PRIVATE static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&); | |
9dae56ea | 209 | |
6fe7ccc8 | 210 | JS_EXPORT_PRIVATE static void putDirectVirtual(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); |
9dae56ea | 211 | |
6fe7ccc8 A |
212 | JS_EXPORT_PRIVATE static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes); |
213 | JS_EXPORT_PRIVATE static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes); | |
214 | JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); | |
9dae56ea | 215 | |
14957cd0 A |
216 | // We use this in the code generator as we perform symbol table |
217 | // lookups prior to initializing the properties | |
218 | bool symbolTableHasProperty(const Identifier& propertyName); | |
9dae56ea A |
219 | |
220 | // The following accessors return pristine values, even if a script | |
221 | // replaces the global object's associated property. | |
222 | ||
14957cd0 A |
223 | RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); } |
224 | ||
225 | ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); } | |
226 | NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); } | |
227 | NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); } | |
228 | NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); } | |
229 | NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); } | |
230 | NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); } | |
231 | NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); } | |
232 | ||
233 | JSFunction* evalFunction() const { return m_evalFunction.get(); } | |
234 | JSFunction* callFunction() const { return m_callFunction.get(); } | |
235 | JSFunction* applyFunction() const { return m_applyFunction.get(); } | |
6fe7ccc8 A |
236 | GetterSetter* throwTypeErrorGetterSetter(ExecState* exec) |
237 | { | |
238 | if (!m_throwTypeErrorGetterSetter) | |
239 | createThrowTypeError(exec); | |
240 | return m_throwTypeErrorGetterSetter.get(); | |
241 | } | |
14957cd0 A |
242 | |
243 | ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); } | |
244 | FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); } | |
245 | ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); } | |
246 | BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); } | |
247 | StringPrototype* stringPrototype() const { return m_stringPrototype.get(); } | |
248 | NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); } | |
249 | DatePrototype* datePrototype() const { return m_datePrototype.get(); } | |
250 | RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); } | |
251 | ||
252 | JSObject* methodCallDummy() const { return m_methodCallDummy.get(); } | |
253 | ||
254 | Structure* argumentsStructure() const { return m_argumentsStructure.get(); } | |
255 | Structure* arrayStructure() const { return m_arrayStructure.get(); } | |
256 | Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); } | |
257 | Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); } | |
258 | Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); } | |
259 | Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); } | |
260 | Structure* dateStructure() const { return m_dateStructure.get(); } | |
261 | Structure* emptyObjectStructure() const { return m_emptyObjectStructure.get(); } | |
262 | Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); } | |
263 | Structure* errorStructure() const { return m_errorStructure.get(); } | |
264 | Structure* functionStructure() const { return m_functionStructure.get(); } | |
6fe7ccc8 A |
265 | Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(); } |
266 | Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(); } | |
267 | size_t functionNameOffset() const { return m_functionNameOffset; } | |
14957cd0 A |
268 | Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); } |
269 | Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); } | |
270 | Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); } | |
271 | Structure* regExpStructure() const { return m_regExpStructure.get(); } | |
272 | Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); } | |
273 | ||
6fe7ccc8 A |
274 | void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; } |
275 | unsigned profileGroup() const | |
276 | { | |
277 | if (!m_rareData) | |
278 | return 0; | |
279 | return m_rareData->profileGroup; | |
280 | } | |
14957cd0 A |
281 | |
282 | Debugger* debugger() const { return m_debugger; } | |
283 | void setDebugger(Debugger* debugger) { m_debugger = debugger; } | |
284 | ||
6fe7ccc8 | 285 | const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; } |
14957cd0 | 286 | |
6fe7ccc8 A |
287 | static bool allowsAccessFrom(const JSGlobalObject*, ExecState*) { return true; } |
288 | static bool supportsProfiling(const JSGlobalObject*) { return false; } | |
289 | static bool supportsRichSourceInfo(const JSGlobalObject*) { return true; } | |
9dae56ea | 290 | |
6fe7ccc8 | 291 | ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); } |
9dae56ea | 292 | |
6fe7ccc8 | 293 | JS_EXPORT_PRIVATE ExecState* globalExec(); |
9dae56ea | 294 | |
6fe7ccc8 A |
295 | static bool shouldInterruptScriptBeforeTimeout(const JSGlobalObject*) { return false; } |
296 | static bool shouldInterruptScript(const JSGlobalObject*) { return true; } | |
9dae56ea | 297 | |
6fe7ccc8 | 298 | bool isDynamicScope(bool& requiresDynamicChecks) const; |
9dae56ea | 299 | |
6fe7ccc8 A |
300 | void setEvalEnabled(bool enabled) { m_evalEnabled = enabled; } |
301 | bool evalEnabled() { return m_evalEnabled; } | |
9dae56ea | 302 | |
6fe7ccc8 | 303 | void resizeRegisters(size_t newSize); |
14957cd0 A |
304 | |
305 | void resetPrototype(JSGlobalData&, JSValue prototype); | |
9dae56ea | 306 | |
6fe7ccc8 | 307 | JSGlobalData& globalData() const { return *Heap::heap(this)->globalData(); } |
9dae56ea | 308 | |
14957cd0 | 309 | static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) |
9dae56ea | 310 | { |
6fe7ccc8 | 311 | return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info); |
9dae56ea A |
312 | } |
313 | ||
4e4e5a6f A |
314 | void registerWeakMap(OpaqueJSWeakObjectMap* map) |
315 | { | |
6fe7ccc8 A |
316 | createRareDataIfNeeded(); |
317 | m_rareData->weakMaps.add(map); | |
4e4e5a6f A |
318 | } |
319 | ||
6fe7ccc8 | 320 | void unregisterWeakMap(OpaqueJSWeakObjectMap* map) |
4e4e5a6f | 321 | { |
6fe7ccc8 A |
322 | if (m_rareData) |
323 | m_rareData->weakMaps.remove(map); | |
4e4e5a6f A |
324 | } |
325 | ||
14957cd0 | 326 | double weakRandomNumber() { return m_weakRandom.get(); } |
9dae56ea | 327 | protected: |
f9bf01c6 | 328 | |
14957cd0 | 329 | static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; |
f9bf01c6 | 330 | |
9dae56ea | 331 | struct GlobalPropertyInfo { |
ba379fdc | 332 | GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a) |
9dae56ea A |
333 | : identifier(i) |
334 | , value(v) | |
335 | , attributes(a) | |
336 | { | |
337 | } | |
338 | ||
339 | const Identifier identifier; | |
ba379fdc | 340 | JSValue value; |
9dae56ea A |
341 | unsigned attributes; |
342 | }; | |
6fe7ccc8 | 343 | JS_EXPORT_PRIVATE void addStaticGlobals(GlobalPropertyInfo*, int count); |
9dae56ea A |
344 | |
345 | private: | |
6fe7ccc8 A |
346 | friend class LLIntOffsetsExtractor; |
347 | ||
9dae56ea | 348 | // FIXME: Fold reset into init. |
6fe7ccc8 | 349 | JS_EXPORT_PRIVATE void init(JSObject* thisValue); |
ba379fdc | 350 | void reset(JSValue prototype); |
9dae56ea | 351 | |
6fe7ccc8 | 352 | void createThrowTypeError(ExecState*); |
9dae56ea | 353 | |
6fe7ccc8 A |
354 | void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count); |
355 | JS_EXPORT_PRIVATE static void clearRareData(JSCell*); | |
9dae56ea A |
356 | }; |
357 | ||
ba379fdc | 358 | JSGlobalObject* asGlobalObject(JSValue); |
9dae56ea | 359 | |
ba379fdc | 360 | inline JSGlobalObject* asGlobalObject(JSValue value) |
9dae56ea A |
361 | { |
362 | ASSERT(asObject(value)->isGlobalObject()); | |
6fe7ccc8 | 363 | return jsCast<JSGlobalObject*>(asObject(value)); |
9dae56ea A |
364 | } |
365 | ||
14957cd0 | 366 | inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count) |
9dae56ea A |
367 | { |
368 | JSVariableObject::setRegisters(registers, registerArray); | |
14957cd0 | 369 | m_registerArraySize = count; |
f9bf01c6 A |
370 | } |
371 | ||
ba379fdc | 372 | inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName) |
9dae56ea | 373 | { |
ba379fdc | 374 | PropertySlot slot; |
6fe7ccc8 | 375 | if (JSVariableObject::getOwnPropertySlot(this, exec, propertyName, slot)) |
9dae56ea | 376 | return true; |
ba379fdc | 377 | bool slotIsWriteable; |
9dae56ea A |
378 | return symbolTableGet(propertyName, slot, slotIsWriteable); |
379 | } | |
380 | ||
14957cd0 A |
381 | inline bool JSGlobalObject::symbolTableHasProperty(const Identifier& propertyName) |
382 | { | |
383 | SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); | |
384 | return !entry.isNull(); | |
385 | } | |
386 | ||
ba379fdc | 387 | inline JSValue Structure::prototypeForLookup(ExecState* exec) const |
9dae56ea | 388 | { |
6fe7ccc8 | 389 | if (isObject()) |
14957cd0 | 390 | return m_prototype.get(); |
9dae56ea | 391 | |
ba379fdc A |
392 | ASSERT(typeInfo().type() == StringType); |
393 | return exec->lexicalGlobalObject()->stringPrototype(); | |
9dae56ea A |
394 | } |
395 | ||
396 | inline StructureChain* Structure::prototypeChain(ExecState* exec) const | |
397 | { | |
398 | // We cache our prototype chain so our clients can share it. | |
399 | if (!isValid(exec, m_cachedPrototypeChain.get())) { | |
ba379fdc | 400 | JSValue prototype = prototypeForLookup(exec); |
14957cd0 | 401 | m_cachedPrototypeChain.set(exec->globalData(), this, StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure())); |
9dae56ea A |
402 | } |
403 | return m_cachedPrototypeChain.get(); | |
404 | } | |
405 | ||
406 | inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const | |
407 | { | |
408 | if (!cachedPrototypeChain) | |
409 | return false; | |
410 | ||
ba379fdc | 411 | JSValue prototype = prototypeForLookup(exec); |
14957cd0 | 412 | WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head(); |
9dae56ea | 413 | while(*cachedStructure && !prototype.isNull()) { |
14957cd0 | 414 | if (asObject(prototype)->structure() != cachedStructure->get()) |
9dae56ea A |
415 | return false; |
416 | ++cachedStructure; | |
417 | prototype = asObject(prototype)->prototype(); | |
418 | } | |
419 | return prototype.isNull() && !*cachedStructure; | |
420 | } | |
421 | ||
422 | inline JSGlobalObject* ExecState::dynamicGlobalObject() | |
423 | { | |
424 | if (this == lexicalGlobalObject()->globalExec()) | |
425 | return lexicalGlobalObject(); | |
426 | ||
427 | // For any ExecState that's not a globalExec, the | |
428 | // dynamic global object must be set since code is running | |
429 | ASSERT(globalData().dynamicGlobalObject); | |
430 | return globalData().dynamicGlobalObject; | |
431 | } | |
432 | ||
14957cd0 | 433 | inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject) |
f9bf01c6 | 434 | { |
14957cd0 | 435 | return constructEmptyObject(exec, globalObject->emptyObjectStructure()); |
f9bf01c6 | 436 | } |
14957cd0 A |
437 | |
438 | inline JSObject* constructEmptyObject(ExecState* exec) | |
f9bf01c6 | 439 | { |
14957cd0 | 440 | return constructEmptyObject(exec, exec->lexicalGlobalObject()); |
f9bf01c6 A |
441 | } |
442 | ||
6fe7ccc8 | 443 | inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject, unsigned initialLength = 0) |
f9bf01c6 | 444 | { |
6fe7ccc8 | 445 | return JSArray::create(exec->globalData(), globalObject->arrayStructure(), initialLength); |
f9bf01c6 A |
446 | } |
447 | ||
6fe7ccc8 | 448 | inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength = 0) |
f9bf01c6 | 449 | { |
14957cd0 | 450 | return constructEmptyArray(exec, exec->lexicalGlobalObject(), initialLength); |
f9bf01c6 A |
451 | } |
452 | ||
6fe7ccc8 | 453 | inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const ArgList& values) |
f9bf01c6 | 454 | { |
6fe7ccc8 A |
455 | JSGlobalData& globalData = exec->globalData(); |
456 | unsigned length = values.size(); | |
457 | JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length); | |
458 | ||
459 | // FIXME: we should probably throw an out of memory error here, but | |
460 | // when making this change we should check that all clients of this | |
461 | // function will correctly handle an exception being thrown from here. | |
462 | if (!array) | |
463 | CRASH(); | |
464 | ||
465 | for (unsigned i = 0; i < length; ++i) | |
466 | array->initializeIndex(globalData, i, values.at(i)); | |
467 | array->completeInitialization(length); | |
468 | return array; | |
14957cd0 A |
469 | } |
470 | ||
6fe7ccc8 | 471 | inline JSArray* constructArray(ExecState* exec, const ArgList& values) |
14957cd0 | 472 | { |
6fe7ccc8 | 473 | return constructArray(exec, exec->lexicalGlobalObject(), values); |
14957cd0 A |
474 | } |
475 | ||
6fe7ccc8 | 476 | inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const JSValue* values, unsigned length) |
14957cd0 | 477 | { |
6fe7ccc8 A |
478 | JSGlobalData& globalData = exec->globalData(); |
479 | JSArray* array = JSArray::tryCreateUninitialized(globalData, globalObject->arrayStructure(), length); | |
480 | ||
481 | // FIXME: we should probably throw an out of memory error here, but | |
482 | // when making this change we should check that all clients of this | |
483 | // function will correctly handle an exception being thrown from here. | |
484 | if (!array) | |
485 | CRASH(); | |
486 | ||
487 | for (unsigned i = 0; i < length; ++i) | |
488 | array->initializeIndex(globalData, i, values[i]); | |
489 | array->completeInitialization(length); | |
490 | return array; | |
f9bf01c6 A |
491 | } |
492 | ||
6fe7ccc8 | 493 | inline JSArray* constructArray(ExecState* exec, const JSValue* values, unsigned length) |
f9bf01c6 | 494 | { |
6fe7ccc8 | 495 | return constructArray(exec, exec->lexicalGlobalObject(), values, length); |
f9bf01c6 A |
496 | } |
497 | ||
14957cd0 A |
498 | class DynamicGlobalObjectScope { |
499 | WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope); | |
9dae56ea | 500 | public: |
6fe7ccc8 | 501 | JS_EXPORT_PRIVATE DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*); |
9dae56ea A |
502 | |
503 | ~DynamicGlobalObjectScope() | |
504 | { | |
505 | m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject; | |
506 | } | |
507 | ||
508 | private: | |
509 | JSGlobalObject*& m_dynamicGlobalObjectSlot; | |
510 | JSGlobalObject* m_savedDynamicGlobalObject; | |
511 | }; | |
512 | ||
6fe7ccc8 A |
513 | inline bool JSGlobalObject::isDynamicScope(bool&) const |
514 | { | |
515 | return true; | |
516 | } | |
517 | ||
9dae56ea A |
518 | } // namespace JSC |
519 | ||
520 | #endif // JSGlobalObject_h |