2  *  Copyright (C) 2007 Eric Seidel <eric@webkit.org> 
   3  *  Copyright (C) 2007, 2008 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 
  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> 
  36     class BooleanPrototype
; 
  39     class ErrorConstructor
; 
  40     class FunctionPrototype
; 
  41     class GlobalEvalFunction
; 
  42     class NativeErrorConstructor
; 
  43     class ProgramCodeBlock
; 
  44     class PrototypeFunction
; 
  45     class RegExpConstructor
; 
  46     class RegExpPrototype
; 
  49     struct ActivationStackNode
; 
  52     typedef Vector
<ExecState
*, 16> ExecStateStack
; 
  54     class JSGlobalObject 
: public JSVariableObject 
{ 
  56         using JSVariableObject::JSVariableObjectData
; 
  58         struct JSGlobalObjectData 
: public JSVariableObjectData 
{ 
  60                 : JSVariableObjectData(&symbolTable
, 0) 
  61                 , registerArraySize(0) 
  62                 , globalScopeChain(NoScopeChain()) 
  63                 , regExpConstructor(0) 
  65                 , evalErrorConstructor(0) 
  66                 , rangeErrorConstructor(0) 
  67                 , referenceErrorConstructor(0) 
  68                 , syntaxErrorConstructor(0) 
  69                 , typeErrorConstructor(0) 
  70                 , URIErrorConstructor(0) 
  75                 , functionPrototype(0) 
  86             virtual ~JSGlobalObjectData() 
  90             size_t registerArraySize
; 
  97             ScopeChain globalScopeChain
; 
  98             Register globalCallFrame
[RegisterFile::CallFrameHeaderSize
]; 
 102             RegExpConstructor
* regExpConstructor
; 
 103             ErrorConstructor
* errorConstructor
; 
 104             NativeErrorConstructor
* evalErrorConstructor
; 
 105             NativeErrorConstructor
* rangeErrorConstructor
; 
 106             NativeErrorConstructor
* referenceErrorConstructor
; 
 107             NativeErrorConstructor
* syntaxErrorConstructor
; 
 108             NativeErrorConstructor
* typeErrorConstructor
; 
 109             NativeErrorConstructor
* URIErrorConstructor
; 
 111             GlobalEvalFunction
* evalFunction
; 
 112             NativeFunctionWrapper
* callFunction
; 
 113             NativeFunctionWrapper
* applyFunction
; 
 115             ObjectPrototype
* objectPrototype
; 
 116             FunctionPrototype
* functionPrototype
; 
 117             ArrayPrototype
* arrayPrototype
; 
 118             BooleanPrototype
* booleanPrototype
; 
 119             StringPrototype
* stringPrototype
; 
 120             NumberPrototype
* numberPrototype
; 
 121             DatePrototype
* datePrototype
; 
 122             RegExpPrototype
* regExpPrototype
; 
 124             JSObject
* methodCallDummy
; 
 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
; 
 142             SymbolTable symbolTable
; 
 143             unsigned profileGroup
; 
 145             RefPtr
<JSGlobalData
> globalData
; 
 147             HashSet
<ProgramCodeBlock
*> codeBlocks
; 
 151         void* operator new(size_t, JSGlobalData
*); 
 153         explicit JSGlobalObject() 
 154             : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData
) 
 160         JSGlobalObject(PassRefPtr
<Structure
> structure
, JSGlobalObjectData
* data
, JSObject
* thisValue
) 
 161             : JSVariableObject(structure
, data
) 
 167         virtual ~JSGlobalObject(); 
 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
); 
 176         virtual void defineGetter(ExecState
*, const Identifier
& propertyName
, JSObject
* getterFunc
); 
 177         virtual void defineSetter(ExecState
*, const Identifier
& propertyName
, JSObject
* setterFunc
); 
 179         // Linked list of all global objects that use the same JSGlobalData. 
 180         JSGlobalObject
*& head() { return d()->globalData
->head
; } 
 181         JSGlobalObject
* next() { return d()->next
; } 
 183         // The following accessors return pristine values, even if a script  
 184         // replaces the global object's associated property. 
 186         RegExpConstructor
* regExpConstructor() const { return d()->regExpConstructor
; } 
 188         ErrorConstructor
* errorConstructor() const { return d()->errorConstructor
; } 
 189         NativeErrorConstructor
* evalErrorConstructor() const { return d()->evalErrorConstructor
; } 
 190         NativeErrorConstructor
* rangeErrorConstructor() const { return d()->rangeErrorConstructor
; } 
 191         NativeErrorConstructor
* referenceErrorConstructor() const { return d()->referenceErrorConstructor
; } 
 192         NativeErrorConstructor
* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor
; } 
 193         NativeErrorConstructor
* typeErrorConstructor() const { return d()->typeErrorConstructor
; } 
 194         NativeErrorConstructor
* URIErrorConstructor() const { return d()->URIErrorConstructor
; } 
 196         GlobalEvalFunction
* evalFunction() const { return d()->evalFunction
; } 
 198         ObjectPrototype
* objectPrototype() const { return d()->objectPrototype
; } 
 199         FunctionPrototype
* functionPrototype() const { return d()->functionPrototype
; } 
 200         ArrayPrototype
* arrayPrototype() const { return d()->arrayPrototype
; } 
 201         BooleanPrototype
* booleanPrototype() const { return d()->booleanPrototype
; } 
 202         StringPrototype
* stringPrototype() const { return d()->stringPrototype
; } 
 203         NumberPrototype
* numberPrototype() const { return d()->numberPrototype
; } 
 204         DatePrototype
* datePrototype() const { return d()->datePrototype
; } 
 205         RegExpPrototype
* regExpPrototype() const { return d()->regExpPrototype
; } 
 207         JSObject
* methodCallDummy() const { return d()->methodCallDummy
; } 
 209         Structure
* argumentsStructure() const { return d()->argumentsStructure
.get(); } 
 210         Structure
* arrayStructure() const { return d()->arrayStructure
.get(); } 
 211         Structure
* booleanObjectStructure() const { return d()->booleanObjectStructure
.get(); } 
 212         Structure
* callbackConstructorStructure() const { return d()->callbackConstructorStructure
.get(); } 
 213         Structure
* callbackFunctionStructure() const { return d()->callbackFunctionStructure
.get(); } 
 214         Structure
* callbackObjectStructure() const { return d()->callbackObjectStructure
.get(); } 
 215         Structure
* dateStructure() const { return d()->dateStructure
.get(); } 
 216         Structure
* emptyObjectStructure() const { return d()->emptyObjectStructure
.get(); } 
 217         Structure
* errorStructure() const { return d()->errorStructure
.get(); } 
 218         Structure
* functionStructure() const { return d()->functionStructure
.get(); } 
 219         Structure
* numberObjectStructure() const { return d()->numberObjectStructure
.get(); } 
 220         Structure
* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure
.get(); } 
 221         Structure
* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure
.get(); } 
 222         Structure
* regExpStructure() const { return d()->regExpStructure
.get(); } 
 223         Structure
* stringObjectStructure() const { return d()->stringObjectStructure
.get(); } 
 225         void setProfileGroup(unsigned value
) { d()->profileGroup 
= value
; } 
 226         unsigned profileGroup() const { return d()->profileGroup
; } 
 228         Debugger
* debugger() const { return d()->debugger
; } 
 229         void setDebugger(Debugger
* debugger
) { d()->debugger 
= debugger
; } 
 231         virtual bool supportsProfiling() const { return false; } 
 233         int recursion() { return d()->recursion
; } 
 234         void incRecursion() { ++d()->recursion
; } 
 235         void decRecursion() { --d()->recursion
; } 
 237         ScopeChain
& globalScopeChain() { return d()->globalScopeChain
; } 
 239         virtual bool isGlobalObject() const { return true; } 
 241         virtual ExecState
* globalExec(); 
 243         virtual bool shouldInterruptScriptBeforeTimeout() const { return false; } 
 244         virtual bool shouldInterruptScript() const { return true; } 
 246         virtual bool allowsAccessFrom(const JSGlobalObject
*) const { return true; } 
 248         virtual bool isDynamicScope() const; 
 250         HashSet
<ProgramCodeBlock
*>& codeBlocks() { return d()->codeBlocks
; } 
 252         void copyGlobalsFrom(RegisterFile
&); 
 253         void copyGlobalsTo(RegisterFile
&); 
 255         void resetPrototype(JSValue prototype
); 
 257         JSGlobalData
* globalData() { return d()->globalData
.get(); } 
 258         JSGlobalObjectData
* d() const { return static_cast<JSGlobalObjectData
*>(JSVariableObject::d
); } 
 260         static PassRefPtr
<Structure
> createStructure(JSValue prototype
) 
 262             return Structure::create(prototype
, TypeInfo(ObjectType
)); 
 266         struct GlobalPropertyInfo 
{ 
 267             GlobalPropertyInfo(const Identifier
& i
, JSValue v
, unsigned a
) 
 274             const Identifier identifier
; 
 278         void addStaticGlobals(GlobalPropertyInfo
*, int count
); 
 281         // FIXME: Fold reset into init. 
 282         void init(JSObject
* thisValue
); 
 283         void reset(JSValue prototype
); 
 285         void setRegisters(Register
* registers
, Register
* registerArray
, size_t count
); 
 287         void* operator new(size_t); // can only be allocated with JSGlobalData 
 290     JSGlobalObject
* asGlobalObject(JSValue
); 
 292     inline JSGlobalObject
* asGlobalObject(JSValue value
) 
 294         ASSERT(asObject(value
)->isGlobalObject()); 
 295         return static_cast<JSGlobalObject
*>(asObject(value
)); 
 298     inline void JSGlobalObject::setRegisters(Register
* registers
, Register
* registerArray
, size_t count
) 
 300         JSVariableObject::setRegisters(registers
, registerArray
); 
 301         d()->registerArraySize 
= count
; 
 304     inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo
* globals
, int count
) 
 306         size_t oldSize 
= d()->registerArraySize
; 
 307         size_t newSize 
= oldSize 
+ count
; 
 308         Register
* registerArray 
= new Register
[newSize
]; 
 309         if (d()->registerArray
) 
 310             memcpy(registerArray 
+ count
, d()->registerArray
.get(), oldSize 
* sizeof(Register
)); 
 311         setRegisters(registerArray 
+ newSize
, registerArray
, newSize
); 
 313         for (int i 
= 0, index 
= -static_cast<int>(oldSize
) - 1; i 
< count
; ++i
, --index
) { 
 314             GlobalPropertyInfo
& global 
= globals
[i
]; 
 315             ASSERT(global
.attributes 
& DontDelete
); 
 316             SymbolTableEntry 
newEntry(index
, global
.attributes
); 
 317             symbolTable().add(global
.identifier
.ustring().rep(), newEntry
); 
 318             registerAt(index
) = global
.value
; 
 322     inline bool JSGlobalObject::getOwnPropertySlot(ExecState
* exec
, const Identifier
& propertyName
, PropertySlot
& slot
) 
 324         if (JSVariableObject::getOwnPropertySlot(exec
, propertyName
, slot
)) 
 326         return symbolTableGet(propertyName
, slot
); 
 329     inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState
* exec
, const Identifier
& propertyName
) 
 332         if (JSVariableObject::getOwnPropertySlot(exec
, propertyName
, slot
)) 
 334         bool slotIsWriteable
; 
 335         return symbolTableGet(propertyName
, slot
, slotIsWriteable
); 
 338     inline JSGlobalObject
* ScopeChainNode::globalObject() const 
 340         const ScopeChainNode
* n 
= this; 
 343         return asGlobalObject(n
->object
); 
 346     inline JSValue 
Structure::prototypeForLookup(ExecState
* exec
) const 
 348         if (typeInfo().type() == ObjectType
) 
 352         if (typeInfo().type() == StringType
) 
 353             return exec
->lexicalGlobalObject()->stringPrototype(); 
 355         ASSERT(typeInfo().type() == NumberType
); 
 356         return exec
->lexicalGlobalObject()->numberPrototype(); 
 358         ASSERT(typeInfo().type() == StringType
); 
 359         return exec
->lexicalGlobalObject()->stringPrototype(); 
 363     inline StructureChain
* Structure::prototypeChain(ExecState
* exec
) const 
 365         // We cache our prototype chain so our clients can share it. 
 366         if (!isValid(exec
, m_cachedPrototypeChain
.get())) { 
 367             JSValue prototype 
= prototypeForLookup(exec
); 
 368             m_cachedPrototypeChain 
= StructureChain::create(prototype
.isNull() ? 0 : asObject(prototype
)->structure()); 
 370         return m_cachedPrototypeChain
.get(); 
 373     inline bool Structure::isValid(ExecState
* exec
, StructureChain
* cachedPrototypeChain
) const 
 375         if (!cachedPrototypeChain
) 
 378         JSValue prototype 
= prototypeForLookup(exec
); 
 379         RefPtr
<Structure
>* cachedStructure 
= cachedPrototypeChain
->head(); 
 380         while(*cachedStructure 
&& !prototype
.isNull()) { 
 381             if (asObject(prototype
)->structure() != *cachedStructure
) 
 384             prototype 
= asObject(prototype
)->prototype(); 
 386         return prototype
.isNull() && !*cachedStructure
; 
 389     inline JSGlobalObject
* ExecState::dynamicGlobalObject() 
 391         if (this == lexicalGlobalObject()->globalExec()) 
 392             return lexicalGlobalObject(); 
 394         // For any ExecState that's not a globalExec, the  
 395         // dynamic global object must be set since code is running 
 396         ASSERT(globalData().dynamicGlobalObject
); 
 397         return globalData().dynamicGlobalObject
; 
 400     class DynamicGlobalObjectScope 
: Noncopyable 
{ 
 402         DynamicGlobalObjectScope(CallFrame
* callFrame
, JSGlobalObject
* dynamicGlobalObject
)  
 403             : m_dynamicGlobalObjectSlot(callFrame
->globalData().dynamicGlobalObject
) 
 404             , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot
) 
 406             m_dynamicGlobalObjectSlot 
= dynamicGlobalObject
; 
 409         ~DynamicGlobalObjectScope() 
 411             m_dynamicGlobalObjectSlot 
= m_savedDynamicGlobalObject
; 
 415         JSGlobalObject
*& m_dynamicGlobalObjectSlot
; 
 416         JSGlobalObject
* m_savedDynamicGlobalObject
; 
 421 #endif // JSGlobalObject_h