• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
3  *  Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
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 
25 #include "JSGlobalData.h"
26 #include "JSVariableObject.h"
27 #include "NumberPrototype.h"
28 #include "StringPrototype.h"
29 #include <wtf/HashSet.h>
30 #include <wtf/OwnPtr.h>
31 
32 namespace JSC {
33 
34     class ArrayPrototype;
35     class BooleanPrototype;
36     class DatePrototype;
37     class Debugger;
38     class ErrorConstructor;
39     class FunctionPrototype;
40     class GlobalEvalFunction;
41     class NativeErrorConstructor;
42     class ProgramCodeBlock;
43     class RegExpConstructor;
44     class RegExpPrototype;
45     class RegisterFile;
46 
47     struct ActivationStackNode;
48     struct HashTable;
49 
50     typedef Vector<ExecState*, 16> ExecStateStack;
51 
52     class JSGlobalObject : public JSVariableObject {
53     protected:
54         using JSVariableObject::JSVariableObjectData;
55 
56         struct JSGlobalObjectData : public JSVariableObjectData {
JSGlobalObjectDataJSGlobalObjectData57             JSGlobalObjectData()
58                 : JSVariableObjectData(&symbolTable, 0)
59                 , registerArraySize(0)
60                 , globalScopeChain(NoScopeChain())
61                 , regExpConstructor(0)
62                 , errorConstructor(0)
63                 , evalErrorConstructor(0)
64                 , rangeErrorConstructor(0)
65                 , referenceErrorConstructor(0)
66                 , syntaxErrorConstructor(0)
67                 , typeErrorConstructor(0)
68                 , URIErrorConstructor(0)
69                 , evalFunction(0)
70                 , objectPrototype(0)
71                 , functionPrototype(0)
72                 , arrayPrototype(0)
73                 , booleanPrototype(0)
74                 , stringPrototype(0)
75                 , numberPrototype(0)
76                 , datePrototype(0)
77                 , regExpPrototype(0)
78             {
79             }
80 
~JSGlobalObjectDataJSGlobalObjectData81             virtual ~JSGlobalObjectData()
82             {
83             }
84 
85             size_t registerArraySize;
86 
87             JSGlobalObject* next;
88             JSGlobalObject* prev;
89 
90             Debugger* debugger;
91 
92             ScopeChain globalScopeChain;
93             Register globalCallFrame[RegisterFile::CallFrameHeaderSize];
94 
95             int recursion;
96 
97             RegExpConstructor* regExpConstructor;
98             ErrorConstructor* errorConstructor;
99             NativeErrorConstructor* evalErrorConstructor;
100             NativeErrorConstructor* rangeErrorConstructor;
101             NativeErrorConstructor* referenceErrorConstructor;
102             NativeErrorConstructor* syntaxErrorConstructor;
103             NativeErrorConstructor* typeErrorConstructor;
104             NativeErrorConstructor* URIErrorConstructor;
105 
106             GlobalEvalFunction* evalFunction;
107 
108             ObjectPrototype* objectPrototype;
109             FunctionPrototype* functionPrototype;
110             ArrayPrototype* arrayPrototype;
111             BooleanPrototype* booleanPrototype;
112             StringPrototype* stringPrototype;
113             NumberPrototype* numberPrototype;
114             DatePrototype* datePrototype;
115             RegExpPrototype* regExpPrototype;
116 
117             RefPtr<Structure> argumentsStructure;
118             RefPtr<Structure> arrayStructure;
119             RefPtr<Structure> booleanObjectStructure;
120             RefPtr<Structure> callbackConstructorStructure;
121             RefPtr<Structure> callbackFunctionStructure;
122             RefPtr<Structure> callbackObjectStructure;
123             RefPtr<Structure> dateStructure;
124             RefPtr<Structure> emptyObjectStructure;
125             RefPtr<Structure> errorStructure;
126             RefPtr<Structure> functionStructure;
127             RefPtr<Structure> numberObjectStructure;
128             RefPtr<Structure> prototypeFunctionStructure;
129             RefPtr<Structure> regExpMatchesArrayStructure;
130             RefPtr<Structure> regExpStructure;
131             RefPtr<Structure> stringObjectStructure;
132 
133             SymbolTable symbolTable;
134             unsigned profileGroup;
135 
136             RefPtr<JSGlobalData> globalData;
137 
138             HashSet<ProgramCodeBlock*> codeBlocks;
139         };
140 
141     public:
142         void* operator new(size_t, JSGlobalData*);
143 
JSGlobalObject()144         explicit JSGlobalObject()
145             : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData)
146         {
147             init(this);
148         }
149 
150     protected:
JSGlobalObject(PassRefPtr<Structure> structure,JSGlobalObjectData * data,JSObject * thisValue)151         JSGlobalObject(PassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
152             : JSVariableObject(structure, data)
153         {
154             init(thisValue);
155         }
156 
157     public:
158         virtual ~JSGlobalObject();
159 
160         virtual void mark();
161 
162         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
163         virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
164         virtual void put(ExecState*, const Identifier&, JSValuePtr, PutPropertySlot&);
165         virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValuePtr value, unsigned attributes);
166 
167         virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
168         virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
169 
170         // Linked list of all global objects that use the same JSGlobalData.
head()171         JSGlobalObject*& head() { return d()->globalData->head; }
next()172         JSGlobalObject* next() { return d()->next; }
173 
174         // The following accessors return pristine values, even if a script
175         // replaces the global object's associated property.
176 
regExpConstructor()177         RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor; }
178 
errorConstructor()179         ErrorConstructor* errorConstructor() const { return d()->errorConstructor; }
evalErrorConstructor()180         NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor; }
rangeErrorConstructor()181         NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor; }
referenceErrorConstructor()182         NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor; }
syntaxErrorConstructor()183         NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor; }
typeErrorConstructor()184         NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor; }
URIErrorConstructor()185         NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor; }
186 
evalFunction()187         GlobalEvalFunction* evalFunction() const { return d()->evalFunction; }
188 
objectPrototype()189         ObjectPrototype* objectPrototype() const { return d()->objectPrototype; }
functionPrototype()190         FunctionPrototype* functionPrototype() const { return d()->functionPrototype; }
arrayPrototype()191         ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype; }
booleanPrototype()192         BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype; }
stringPrototype()193         StringPrototype* stringPrototype() const { return d()->stringPrototype; }
numberPrototype()194         NumberPrototype* numberPrototype() const { return d()->numberPrototype; }
datePrototype()195         DatePrototype* datePrototype() const { return d()->datePrototype; }
regExpPrototype()196         RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; }
197 
argumentsStructure()198         Structure* argumentsStructure() const { return d()->argumentsStructure.get(); }
arrayStructure()199         Structure* arrayStructure() const { return d()->arrayStructure.get(); }
booleanObjectStructure()200         Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); }
callbackConstructorStructure()201         Structure* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); }
callbackFunctionStructure()202         Structure* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); }
callbackObjectStructure()203         Structure* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); }
dateStructure()204         Structure* dateStructure() const { return d()->dateStructure.get(); }
emptyObjectStructure()205         Structure* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); }
errorStructure()206         Structure* errorStructure() const { return d()->errorStructure.get(); }
functionStructure()207         Structure* functionStructure() const { return d()->functionStructure.get(); }
numberObjectStructure()208         Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); }
prototypeFunctionStructure()209         Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); }
regExpMatchesArrayStructure()210         Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); }
regExpStructure()211         Structure* regExpStructure() const { return d()->regExpStructure.get(); }
stringObjectStructure()212         Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); }
213 
setProfileGroup(unsigned value)214         void setProfileGroup(unsigned value) { d()->profileGroup = value; }
profileGroup()215         unsigned profileGroup() const { return d()->profileGroup; }
216 
217         void setTimeoutTime(unsigned timeoutTime);
218         void startTimeoutCheck();
219         void stopTimeoutCheck();
220 
debugger()221         Debugger* debugger() const { return d()->debugger; }
setDebugger(Debugger * debugger)222         void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
223 
supportsProfiling()224         virtual bool supportsProfiling() const { return false; }
225 
recursion()226         int recursion() { return d()->recursion; }
incRecursion()227         void incRecursion() { ++d()->recursion; }
decRecursion()228         void decRecursion() { --d()->recursion; }
229 
globalScopeChain()230         ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
231 
isGlobalObject()232         virtual bool isGlobalObject() const { return true; }
233 
234         virtual ExecState* globalExec();
235 
shouldInterruptScript()236         virtual bool shouldInterruptScript() const { return true; }
237 
allowsAccessFrom(const JSGlobalObject *)238         virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; }
239 
240         virtual bool isDynamicScope() const;
241 
codeBlocks()242         HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
243 
244         void copyGlobalsFrom(RegisterFile&);
245         void copyGlobalsTo(RegisterFile&);
246 
247         void resetPrototype(JSValuePtr prototype);
248 
globalData()249         JSGlobalData* globalData() { return d()->globalData.get(); }
d()250         JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
251 
createStructure(JSValuePtr prototype)252         static PassRefPtr<Structure> createStructure(JSValuePtr prototype)
253         {
254             return Structure::create(prototype, TypeInfo(ObjectType));
255         }
256 
257     protected:
258         struct GlobalPropertyInfo {
GlobalPropertyInfoGlobalPropertyInfo259             GlobalPropertyInfo(const Identifier& i, JSValuePtr v, unsigned a)
260                 : identifier(i)
261                 , value(v)
262                 , attributes(a)
263             {
264             }
265 
266             const Identifier identifier;
267             JSValuePtr value;
268             unsigned attributes;
269         };
270         void addStaticGlobals(GlobalPropertyInfo*, int count);
271 
272     private:
273         // FIXME: Fold reset into init.
274         void init(JSObject* thisValue);
275         void reset(JSValuePtr prototype);
276 
277         void setRegisters(Register* registers, Register* registerArray, size_t count);
278 
279         void* operator new(size_t); // can only be allocated with JSGlobalData
280     };
281 
282     JSGlobalObject* asGlobalObject(JSValuePtr);
283 
asGlobalObject(JSValuePtr value)284     inline JSGlobalObject* asGlobalObject(JSValuePtr value)
285     {
286         ASSERT(asObject(value)->isGlobalObject());
287         return static_cast<JSGlobalObject*>(asObject(value));
288     }
289 
setRegisters(Register * registers,Register * registerArray,size_t count)290     inline void JSGlobalObject::setRegisters(Register* registers, Register* registerArray, size_t count)
291     {
292         JSVariableObject::setRegisters(registers, registerArray);
293         d()->registerArraySize = count;
294     }
295 
addStaticGlobals(GlobalPropertyInfo * globals,int count)296     inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
297     {
298         size_t oldSize = d()->registerArraySize;
299         size_t newSize = oldSize + count;
300         Register* registerArray = new Register[newSize];
301         if (d()->registerArray)
302             memcpy(registerArray + count, d()->registerArray.get(), oldSize * sizeof(Register));
303         setRegisters(registerArray + newSize, registerArray, newSize);
304 
305         for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
306             GlobalPropertyInfo& global = globals[i];
307             ASSERT(global.attributes & DontDelete);
308             SymbolTableEntry newEntry(index, global.attributes);
309             symbolTable().add(global.identifier.ustring().rep(), newEntry);
310             registerAt(index) = global.value;
311         }
312     }
313 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot)314     inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
315     {
316         if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
317             return true;
318         return symbolTableGet(propertyName, slot);
319     }
320 
getOwnPropertySlot(ExecState * exec,const Identifier & propertyName,PropertySlot & slot,bool & slotIsWriteable)321     inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
322     {
323         if (JSVariableObject::getOwnPropertySlotForWrite(exec, propertyName, slot, slotIsWriteable))
324             return true;
325         return symbolTableGet(propertyName, slot, slotIsWriteable);
326     }
327 
globalObject()328     inline JSGlobalObject* ScopeChainNode::globalObject() const
329     {
330         const ScopeChainNode* n = this;
331         while (n->next)
332             n = n->next;
333         return asGlobalObject(n->object);
334     }
335 
prototypeForLookup(ExecState * exec)336     inline JSValuePtr Structure::prototypeForLookup(ExecState* exec)
337     {
338         if (typeInfo().type() == ObjectType)
339             return m_prototype;
340 
341         if (typeInfo().type() == StringType)
342             return exec->lexicalGlobalObject()->stringPrototype();
343 
344         ASSERT(typeInfo().type() == NumberType);
345         return exec->lexicalGlobalObject()->numberPrototype();
346     }
347 
dynamicGlobalObject()348     inline JSGlobalObject* ExecState::dynamicGlobalObject()
349     {
350         if (this == lexicalGlobalObject()->globalExec())
351             return lexicalGlobalObject();
352 
353         // For any ExecState that's not a globalExec, the
354         // dynamic global object must be set since code is running
355         ASSERT(globalData().dynamicGlobalObject);
356         return globalData().dynamicGlobalObject;
357     }
358 
359     class DynamicGlobalObjectScope : Noncopyable {
360     public:
DynamicGlobalObjectScope(CallFrame * callFrame,JSGlobalObject * dynamicGlobalObject)361         DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
362             : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
363             , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
364         {
365             m_dynamicGlobalObjectSlot = dynamicGlobalObject;
366         }
367 
~DynamicGlobalObjectScope()368         ~DynamicGlobalObjectScope()
369         {
370             m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject;
371         }
372 
373     private:
374         JSGlobalObject*& m_dynamicGlobalObjectSlot;
375         JSGlobalObject* m_savedDynamicGlobalObject;
376     };
377 
378 } // namespace JSC
379 
380 #endif // JSGlobalObject_h
381