2 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
3 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
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.
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.
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.
22 #ifndef JSGlobalObject_h
23 #define JSGlobalObject_h
26 #include "JSGlobalData.h"
27 #include "JSGlobalThis.h"
28 #include "JSVariableObject.h"
29 #include "JSWeakObjectMapRefInternal.h"
30 #include "NumberPrototype.h"
31 #include "StringPrototype.h"
32 #include "StructureChain.h"
33 #include <wtf/HashSet.h>
34 #include <wtf/OwnPtr.h>
35 #include <wtf/RandomNumber.h>
40 class BooleanPrototype
;
43 class ErrorConstructor
;
44 class FunctionPrototype
;
46 class GlobalCodeBlock
;
47 class LLIntOffsetsExtractor
;
48 class NativeErrorConstructor
;
49 class ProgramCodeBlock
;
50 class RegExpConstructor
;
51 class RegExpPrototype
;
54 struct ActivationStackNode
;
57 typedef Vector
<ExecState
*, 16> ExecStateStack
;
59 struct GlobalObjectMethodTable
{
60 typedef bool (*AllowsAccessFromFunctionPtr
)(const JSGlobalObject
*, ExecState
*);
61 AllowsAccessFromFunctionPtr allowsAccessFrom
;
63 typedef bool (*SupportsProfilingFunctionPtr
)(const JSGlobalObject
*);
64 SupportsProfilingFunctionPtr supportsProfiling
;
66 typedef bool (*SupportsRichSourceInfoFunctionPtr
)(const JSGlobalObject
*);
67 SupportsRichSourceInfoFunctionPtr supportsRichSourceInfo
;
69 typedef bool (*ShouldInterruptScriptFunctionPtr
)(const JSGlobalObject
*);
70 ShouldInterruptScriptFunctionPtr shouldInterruptScript
;
72 typedef bool (*ShouldInterruptScriptBeforeTimeoutPtr
)(const JSGlobalObject
*);
73 ShouldInterruptScriptBeforeTimeoutPtr shouldInterruptScriptBeforeTimeout
;
76 class JSGlobalObject
: public JSVariableObject
{
78 typedef HashSet
<RefPtr
<OpaqueJSWeakObjectMap
> > WeakMapSet
;
80 struct JSGlobalObjectRareData
{
81 JSGlobalObjectRareData()
87 unsigned profileGroup
;
92 size_t m_registerArraySize
;
93 Register m_globalCallFrame
[RegisterFile::CallFrameHeaderSize
];
95 WriteBarrier
<ScopeChainNode
> m_globalScopeChain
;
96 WriteBarrier
<JSObject
> m_methodCallDummy
;
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
;
107 WriteBarrier
<JSFunction
> m_evalFunction
;
108 WriteBarrier
<JSFunction
> m_callFunction
;
109 WriteBarrier
<JSFunction
> m_applyFunction
;
110 WriteBarrier
<GetterSetter
> m_throwTypeErrorGetterSetter
;
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
;
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
;
132 WriteBarrier
<Structure
> m_boundFunctionStructure
;
133 WriteBarrier
<Structure
> m_namedFunctionStructure
;
134 size_t m_functionNameOffset
;
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
;
141 Debugger
* m_debugger
;
143 OwnPtr
<JSGlobalObjectRareData
> m_rareData
;
145 WeakRandom m_weakRandom
;
147 SymbolTable m_symbolTable
;
151 static JS_EXPORTDATA
const GlobalObjectMethodTable s_globalObjectMethodTable
;
152 const GlobalObjectMethodTable
* m_globalObjectMethodTable
;
154 void createRareDataIfNeeded()
158 m_rareData
= adoptPtr(new JSGlobalObjectRareData
);
159 Heap::heap(this)->addFinalizer(this, clearRareData
);
163 typedef JSVariableObject Base
;
165 static JSGlobalObject
* create(JSGlobalData
& globalData
, Structure
* structure
)
167 JSGlobalObject
* globalObject
= new (NotNull
, allocateCell
<JSGlobalObject
>(globalData
.heap
)) JSGlobalObject(globalData
, structure
);
168 globalObject
->finishCreation(globalData
);
172 static JS_EXPORTDATA
const ClassInfo s_info
;
175 explicit JSGlobalObject(JSGlobalData
& globalData
, Structure
* structure
, const GlobalObjectMethodTable
* globalObjectMethodTable
= 0)
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)))
180 , m_evalEnabled(true)
181 , m_globalObjectMethodTable(globalObjectMethodTable
? globalObjectMethodTable
: &s_globalObjectMethodTable
)
185 void finishCreation(JSGlobalData
& globalData
)
187 Base::finishCreation(globalData
);
188 structure()->setGlobalObject(globalData
, this);
192 void finishCreation(JSGlobalData
& globalData
, JSGlobalThis
* thisValue
)
194 Base::finishCreation(globalData
);
195 structure()->setGlobalObject(globalData
, this);
200 JS_EXPORT_PRIVATE
~JSGlobalObject();
201 JS_EXPORT_PRIVATE
static void destroy(JSCell
*);
203 JS_EXPORT_PRIVATE
static void visitChildren(JSCell
*, SlotVisitor
&);
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
&);
210 JS_EXPORT_PRIVATE
static void putDirectVirtual(JSObject
*, ExecState
*, const Identifier
& propertyName
, JSValue
, unsigned attributes
);
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
);
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
);
220 // The following accessors return pristine values, even if a script
221 // replaces the global object's associated property.
223 RegExpConstructor
* regExpConstructor() const { return m_regExpConstructor
.get(); }
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(); }
233 JSFunction
* evalFunction() const { return m_evalFunction
.get(); }
234 JSFunction
* callFunction() const { return m_callFunction
.get(); }
235 JSFunction
* applyFunction() const { return m_applyFunction
.get(); }
236 GetterSetter
* throwTypeErrorGetterSetter(ExecState
* exec
)
238 if (!m_throwTypeErrorGetterSetter
)
239 createThrowTypeError(exec
);
240 return m_throwTypeErrorGetterSetter
.get();
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(); }
252 JSObject
* methodCallDummy() const { return m_methodCallDummy
.get(); }
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(); }
265 Structure
* boundFunctionStructure() const { return m_boundFunctionStructure
.get(); }
266 Structure
* namedFunctionStructure() const { return m_namedFunctionStructure
.get(); }
267 size_t functionNameOffset() const { return m_functionNameOffset
; }
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(); }
274 void setProfileGroup(unsigned value
) { createRareDataIfNeeded(); m_rareData
->profileGroup
= value
; }
275 unsigned profileGroup() const
279 return m_rareData
->profileGroup
;
282 Debugger
* debugger() const { return m_debugger
; }
283 void setDebugger(Debugger
* debugger
) { m_debugger
= debugger
; }
285 const GlobalObjectMethodTable
* globalObjectMethodTable() const { return m_globalObjectMethodTable
; }
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; }
291 ScopeChainNode
* globalScopeChain() { return m_globalScopeChain
.get(); }
293 JS_EXPORT_PRIVATE ExecState
* globalExec();
295 static bool shouldInterruptScriptBeforeTimeout(const JSGlobalObject
*) { return false; }
296 static bool shouldInterruptScript(const JSGlobalObject
*) { return true; }
298 bool isDynamicScope(bool& requiresDynamicChecks
) const;
300 void setEvalEnabled(bool enabled
) { m_evalEnabled
= enabled
; }
301 bool evalEnabled() { return m_evalEnabled
; }
303 void resizeRegisters(size_t newSize
);
305 void resetPrototype(JSGlobalData
&, JSValue prototype
);
307 JSGlobalData
& globalData() const { return *Heap::heap(this)->globalData(); }
309 static Structure
* createStructure(JSGlobalData
& globalData
, JSValue prototype
)
311 return Structure::create(globalData
, 0, prototype
, TypeInfo(GlobalObjectType
, StructureFlags
), &s_info
);
314 void registerWeakMap(OpaqueJSWeakObjectMap
* map
)
316 createRareDataIfNeeded();
317 m_rareData
->weakMaps
.add(map
);
320 void unregisterWeakMap(OpaqueJSWeakObjectMap
* map
)
323 m_rareData
->weakMaps
.remove(map
);
326 double weakRandomNumber() { return m_weakRandom
.get(); }
329 static const unsigned StructureFlags
= OverridesGetOwnPropertySlot
| OverridesVisitChildren
| OverridesGetPropertyNames
| JSVariableObject::StructureFlags
;
331 struct GlobalPropertyInfo
{
332 GlobalPropertyInfo(const Identifier
& i
, JSValue v
, unsigned a
)
339 const Identifier identifier
;
343 JS_EXPORT_PRIVATE
void addStaticGlobals(GlobalPropertyInfo
*, int count
);
346 friend class LLIntOffsetsExtractor
;
348 // FIXME: Fold reset into init.
349 JS_EXPORT_PRIVATE
void init(JSObject
* thisValue
);
350 void reset(JSValue prototype
);
352 void createThrowTypeError(ExecState
*);
354 void setRegisters(WriteBarrier
<Unknown
>* registers
, PassOwnArrayPtr
<WriteBarrier
<Unknown
> > registerArray
, size_t count
);
355 JS_EXPORT_PRIVATE
static void clearRareData(JSCell
*);
358 JSGlobalObject
* asGlobalObject(JSValue
);
360 inline JSGlobalObject
* asGlobalObject(JSValue value
)
362 ASSERT(asObject(value
)->isGlobalObject());
363 return jsCast
<JSGlobalObject
*>(asObject(value
));
366 inline void JSGlobalObject::setRegisters(WriteBarrier
<Unknown
>* registers
, PassOwnArrayPtr
<WriteBarrier
<Unknown
> > registerArray
, size_t count
)
368 JSVariableObject::setRegisters(registers
, registerArray
);
369 m_registerArraySize
= count
;
372 inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState
* exec
, const Identifier
& propertyName
)
375 if (JSVariableObject::getOwnPropertySlot(this, exec
, propertyName
, slot
))
377 bool slotIsWriteable
;
378 return symbolTableGet(propertyName
, slot
, slotIsWriteable
);
381 inline bool JSGlobalObject::symbolTableHasProperty(const Identifier
& propertyName
)
383 SymbolTableEntry entry
= symbolTable().inlineGet(propertyName
.impl());
384 return !entry
.isNull();
387 inline JSValue
Structure::prototypeForLookup(ExecState
* exec
) const
390 return m_prototype
.get();
392 ASSERT(typeInfo().type() == StringType
);
393 return exec
->lexicalGlobalObject()->stringPrototype();
396 inline StructureChain
* Structure::prototypeChain(ExecState
* exec
) const
398 // We cache our prototype chain so our clients can share it.
399 if (!isValid(exec
, m_cachedPrototypeChain
.get())) {
400 JSValue prototype
= prototypeForLookup(exec
);
401 m_cachedPrototypeChain
.set(exec
->globalData(), this, StructureChain::create(exec
->globalData(), prototype
.isNull() ? 0 : asObject(prototype
)->structure()));
403 return m_cachedPrototypeChain
.get();
406 inline bool Structure::isValid(ExecState
* exec
, StructureChain
* cachedPrototypeChain
) const
408 if (!cachedPrototypeChain
)
411 JSValue prototype
= prototypeForLookup(exec
);
412 WriteBarrier
<Structure
>* cachedStructure
= cachedPrototypeChain
->head();
413 while(*cachedStructure
&& !prototype
.isNull()) {
414 if (asObject(prototype
)->structure() != cachedStructure
->get())
417 prototype
= asObject(prototype
)->prototype();
419 return prototype
.isNull() && !*cachedStructure
;
422 inline JSGlobalObject
* ExecState::dynamicGlobalObject()
424 if (this == lexicalGlobalObject()->globalExec())
425 return lexicalGlobalObject();
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
;
433 inline JSObject
* constructEmptyObject(ExecState
* exec
, JSGlobalObject
* globalObject
)
435 return constructEmptyObject(exec
, globalObject
->emptyObjectStructure());
438 inline JSObject
* constructEmptyObject(ExecState
* exec
)
440 return constructEmptyObject(exec
, exec
->lexicalGlobalObject());
443 inline JSArray
* constructEmptyArray(ExecState
* exec
, JSGlobalObject
* globalObject
, unsigned initialLength
= 0)
445 return JSArray::create(exec
->globalData(), globalObject
->arrayStructure(), initialLength
);
448 inline JSArray
* constructEmptyArray(ExecState
* exec
, unsigned initialLength
= 0)
450 return constructEmptyArray(exec
, exec
->lexicalGlobalObject(), initialLength
);
453 inline JSArray
* constructArray(ExecState
* exec
, JSGlobalObject
* globalObject
, const ArgList
& values
)
455 JSGlobalData
& globalData
= exec
->globalData();
456 unsigned length
= values
.size();
457 JSArray
* array
= JSArray::tryCreateUninitialized(globalData
, globalObject
->arrayStructure(), length
);
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.
465 for (unsigned i
= 0; i
< length
; ++i
)
466 array
->initializeIndex(globalData
, i
, values
.at(i
));
467 array
->completeInitialization(length
);
471 inline JSArray
* constructArray(ExecState
* exec
, const ArgList
& values
)
473 return constructArray(exec
, exec
->lexicalGlobalObject(), values
);
476 inline JSArray
* constructArray(ExecState
* exec
, JSGlobalObject
* globalObject
, const JSValue
* values
, unsigned length
)
478 JSGlobalData
& globalData
= exec
->globalData();
479 JSArray
* array
= JSArray::tryCreateUninitialized(globalData
, globalObject
->arrayStructure(), length
);
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.
487 for (unsigned i
= 0; i
< length
; ++i
)
488 array
->initializeIndex(globalData
, i
, values
[i
]);
489 array
->completeInitialization(length
);
493 inline JSArray
* constructArray(ExecState
* exec
, const JSValue
* values
, unsigned length
)
495 return constructArray(exec
, exec
->lexicalGlobalObject(), values
, length
);
498 class DynamicGlobalObjectScope
{
499 WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope
);
501 JS_EXPORT_PRIVATE
DynamicGlobalObjectScope(JSGlobalData
&, JSGlobalObject
*);
503 ~DynamicGlobalObjectScope()
505 m_dynamicGlobalObjectSlot
= m_savedDynamicGlobalObject
;
509 JSGlobalObject
*& m_dynamicGlobalObjectSlot
;
510 JSGlobalObject
* m_savedDynamicGlobalObject
;
513 inline bool JSGlobalObject::isDynamicScope(bool&) const
520 #endif // JSGlobalObject_h