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