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