tizen beta release
[framework/web/webkit-efl.git] / Source / JavaScriptCore / runtime / JSGlobalObject.h
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 "JSArray.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>
36
37 namespace JSC {
38
39     class ArrayPrototype;
40     class BooleanPrototype;
41     class DatePrototype;
42     class Debugger;
43     class ErrorConstructor;
44     class FunctionPrototype;
45     class GetterSetter;
46     class GlobalCodeBlock;
47     class NativeErrorConstructor;
48     class ProgramCodeBlock;
49     class RegExpConstructor;
50     class RegExpPrototype;
51     class RegisterFile;
52
53     struct ActivationStackNode;
54     struct HashTable;
55
56     typedef Vector<ExecState*, 16> ExecStateStack;
57     
58     struct GlobalObjectMethodTable {
59         typedef bool (*SupportsProfilingFunctionPtr)(const JSGlobalObject*); 
60         SupportsProfilingFunctionPtr supportsProfiling;
61
62         typedef bool (*SupportsRichSourceInfoFunctionPtr)(const JSGlobalObject*);
63         SupportsRichSourceInfoFunctionPtr supportsRichSourceInfo;
64
65         typedef bool (*ShouldInterruptScriptFunctionPtr)(const JSGlobalObject*);
66         ShouldInterruptScriptFunctionPtr shouldInterruptScript;
67     };
68
69     class JSGlobalObject : public JSVariableObject {
70     private:
71         typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
72
73         struct JSGlobalObjectRareData {
74             JSGlobalObjectRareData()
75                 : profileGroup(0)
76             {
77             }
78
79             WeakMapSet weakMaps;
80             unsigned profileGroup;
81         };
82
83     protected:
84
85         RefPtr<JSGlobalData> m_globalData;
86
87         size_t m_registerArraySize;
88         Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize];
89
90         WriteBarrier<ScopeChainNode> m_globalScopeChain;
91         WriteBarrier<JSObject> m_methodCallDummy;
92
93         WriteBarrier<RegExpConstructor> m_regExpConstructor;
94         WriteBarrier<ErrorConstructor> m_errorConstructor;
95         WriteBarrier<NativeErrorConstructor> m_evalErrorConstructor;
96         WriteBarrier<NativeErrorConstructor> m_rangeErrorConstructor;
97         WriteBarrier<NativeErrorConstructor> m_referenceErrorConstructor;
98         WriteBarrier<NativeErrorConstructor> m_syntaxErrorConstructor;
99         WriteBarrier<NativeErrorConstructor> m_typeErrorConstructor;
100         WriteBarrier<NativeErrorConstructor> m_URIErrorConstructor;
101
102         WriteBarrier<JSFunction> m_evalFunction;
103         WriteBarrier<JSFunction> m_callFunction;
104         WriteBarrier<JSFunction> m_applyFunction;
105         WriteBarrier<GetterSetter> m_throwTypeErrorGetterSetter;
106
107         WriteBarrier<ObjectPrototype> m_objectPrototype;
108         WriteBarrier<FunctionPrototype> m_functionPrototype;
109         WriteBarrier<ArrayPrototype> m_arrayPrototype;
110         WriteBarrier<BooleanPrototype> m_booleanPrototype;
111         WriteBarrier<StringPrototype> m_stringPrototype;
112         WriteBarrier<NumberPrototype> m_numberPrototype;
113         WriteBarrier<DatePrototype> m_datePrototype;
114         WriteBarrier<RegExpPrototype> m_regExpPrototype;
115
116         WriteBarrier<Structure> m_argumentsStructure;
117         WriteBarrier<Structure> m_arrayStructure;
118         WriteBarrier<Structure> m_booleanObjectStructure;
119         WriteBarrier<Structure> m_callbackConstructorStructure;
120         WriteBarrier<Structure> m_callbackFunctionStructure;
121         WriteBarrier<Structure> m_callbackObjectStructure;
122         WriteBarrier<Structure> m_dateStructure;
123         WriteBarrier<Structure> m_emptyObjectStructure;
124         WriteBarrier<Structure> m_nullPrototypeObjectStructure;
125         WriteBarrier<Structure> m_errorStructure;
126         WriteBarrier<Structure> m_functionStructure;
127         WriteBarrier<Structure> m_boundFunctionStructure;
128         WriteBarrier<Structure> m_namedFunctionStructure;
129         size_t m_functionNameOffset;
130         WriteBarrier<Structure> m_numberObjectStructure;
131         WriteBarrier<Structure> m_regExpMatchesArrayStructure;
132         WriteBarrier<Structure> m_regExpStructure;
133         WriteBarrier<Structure> m_stringObjectStructure;
134         WriteBarrier<Structure> m_internalFunctionStructure;
135         WriteBarrier<Structure> m_strictModeTypeErrorFunctionStructure;
136
137         Debugger* m_debugger;
138
139         OwnPtr<JSGlobalObjectRareData> m_rareData;
140
141         WeakRandom m_weakRandom;
142
143         SymbolTable m_symbolTable;
144
145         bool m_evalEnabled;
146
147         static JS_EXPORTDATA const GlobalObjectMethodTable s_globalObjectMethodTable;
148         const GlobalObjectMethodTable* m_globalObjectMethodTable;
149
150         void createRareDataIfNeeded()
151         {
152             if (m_rareData)
153                 return;
154             m_rareData = adoptPtr(new JSGlobalObjectRareData);
155             Heap::heap(this)->addFinalizer(this, clearRareData);
156         }
157         
158     public:
159         typedef JSVariableObject Base;
160
161         static JSGlobalObject* create(JSGlobalData& globalData, Structure* structure)
162         {
163             JSGlobalObject* globalObject = new (allocateCell<JSGlobalObject>(globalData.heap)) JSGlobalObject(globalData, structure);
164             globalObject->finishCreation(globalData);
165             return globalObject;
166         }
167
168         static JS_EXPORTDATA const ClassInfo s_info;
169
170     protected:
171         explicit JSGlobalObject(JSGlobalData& globalData, Structure* structure, const GlobalObjectMethodTable* globalObjectMethodTable = 0)
172             : JSVariableObject(globalData, structure, &m_symbolTable, 0)
173             , m_registerArraySize(0)
174             , m_globalScopeChain()
175             , m_weakRandom(static_cast<unsigned>(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0)))
176             , m_evalEnabled(true)
177             , m_globalObjectMethodTable(globalObjectMethodTable ? globalObjectMethodTable : &s_globalObjectMethodTable)
178         {
179         }
180
181         void finishCreation(JSGlobalData& globalData)
182         {
183             Base::finishCreation(globalData);
184             structure()->setGlobalObject(globalData, this);
185             init(this);
186         }
187
188         void finishCreation(JSGlobalData& globalData, JSGlobalThis* thisValue)
189         {
190             Base::finishCreation(globalData);
191             structure()->setGlobalObject(globalData, this);
192             init(thisValue);
193         }
194
195     public:
196         virtual ~JSGlobalObject();
197
198         static void visitChildren(JSCell*, SlotVisitor&);
199
200         static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&);
201         static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&);
202         bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
203         static void put(JSCell*, ExecState*, const Identifier&, JSValue, PutPropertySlot&);
204
205         static void putWithAttributes(JSObject*, ExecState*, const Identifier& propertyName, JSValue, unsigned attributes);
206
207         static void defineGetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
208         static void defineSetter(JSObject*, ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
209
210         // We use this in the code generator as we perform symbol table
211         // lookups prior to initializing the properties
212         bool symbolTableHasProperty(const Identifier& propertyName);
213
214         // The following accessors return pristine values, even if a script 
215         // replaces the global object's associated property.
216
217         RegExpConstructor* regExpConstructor() const { return m_regExpConstructor.get(); }
218
219         ErrorConstructor* errorConstructor() const { return m_errorConstructor.get(); }
220         NativeErrorConstructor* evalErrorConstructor() const { return m_evalErrorConstructor.get(); }
221         NativeErrorConstructor* rangeErrorConstructor() const { return m_rangeErrorConstructor.get(); }
222         NativeErrorConstructor* referenceErrorConstructor() const { return m_referenceErrorConstructor.get(); }
223         NativeErrorConstructor* syntaxErrorConstructor() const { return m_syntaxErrorConstructor.get(); }
224         NativeErrorConstructor* typeErrorConstructor() const { return m_typeErrorConstructor.get(); }
225         NativeErrorConstructor* URIErrorConstructor() const { return m_URIErrorConstructor.get(); }
226
227         JSFunction* evalFunction() const { return m_evalFunction.get(); }
228         JSFunction* callFunction() const { return m_callFunction.get(); }
229         JSFunction* applyFunction() const { return m_applyFunction.get(); }
230         GetterSetter* throwTypeErrorGetterSetter(ExecState* exec)
231         {
232             if (!m_throwTypeErrorGetterSetter)
233                 createThrowTypeError(exec);
234             return m_throwTypeErrorGetterSetter.get();
235         }
236
237         ObjectPrototype* objectPrototype() const { return m_objectPrototype.get(); }
238         FunctionPrototype* functionPrototype() const { return m_functionPrototype.get(); }
239         ArrayPrototype* arrayPrototype() const { return m_arrayPrototype.get(); }
240         BooleanPrototype* booleanPrototype() const { return m_booleanPrototype.get(); }
241         StringPrototype* stringPrototype() const { return m_stringPrototype.get(); }
242         NumberPrototype* numberPrototype() const { return m_numberPrototype.get(); }
243         DatePrototype* datePrototype() const { return m_datePrototype.get(); }
244         RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); }
245
246         JSObject* methodCallDummy() const { return m_methodCallDummy.get(); }
247
248         Structure* argumentsStructure() const { return m_argumentsStructure.get(); }
249         Structure* arrayStructure() const { return m_arrayStructure.get(); }
250         Structure* booleanObjectStructure() const { return m_booleanObjectStructure.get(); }
251         Structure* callbackConstructorStructure() const { return m_callbackConstructorStructure.get(); }
252         Structure* callbackFunctionStructure() const { return m_callbackFunctionStructure.get(); }
253         Structure* callbackObjectStructure() const { return m_callbackObjectStructure.get(); }
254         Structure* dateStructure() const { return m_dateStructure.get(); }
255         Structure* emptyObjectStructure() const { return m_emptyObjectStructure.get(); }
256         Structure* nullPrototypeObjectStructure() const { return m_nullPrototypeObjectStructure.get(); }
257         Structure* errorStructure() const { return m_errorStructure.get(); }
258         Structure* functionStructure() const { return m_functionStructure.get(); }
259         Structure* boundFunctionStructure() const { return m_boundFunctionStructure.get(); }
260         Structure* namedFunctionStructure() const { return m_namedFunctionStructure.get(); }
261         size_t functionNameOffset() const { return m_functionNameOffset; }
262         Structure* numberObjectStructure() const { return m_numberObjectStructure.get(); }
263         Structure* internalFunctionStructure() const { return m_internalFunctionStructure.get(); }
264         Structure* strictModeTypeErrorFunctionStructure() const { return m_strictModeTypeErrorFunctionStructure.get(); }
265         Structure* regExpMatchesArrayStructure() const { return m_regExpMatchesArrayStructure.get(); }
266         Structure* regExpStructure() const { return m_regExpStructure.get(); }
267         Structure* stringObjectStructure() const { return m_stringObjectStructure.get(); }
268
269         void setProfileGroup(unsigned value) { createRareDataIfNeeded(); m_rareData->profileGroup = value; }
270         unsigned profileGroup() const
271         { 
272             if (!m_rareData)
273                 return 0;
274             return m_rareData->profileGroup;
275         }
276
277         Debugger* debugger() const { return m_debugger; }
278         void setDebugger(Debugger* debugger) { m_debugger = debugger; }
279
280         const GlobalObjectMethodTable* globalObjectMethodTable() const { return m_globalObjectMethodTable; }
281
282         static bool supportsProfiling(const JSGlobalObject*) { return false; }
283         static bool supportsRichSourceInfo(const JSGlobalObject*) { return true; }
284
285         ScopeChainNode* globalScopeChain() { return m_globalScopeChain.get(); }
286
287         ExecState* globalExec();
288
289         static bool shouldInterruptScript(const JSGlobalObject*) { return true; }
290
291         bool isDynamicScope(bool& requiresDynamicChecks) const;
292
293         void setEvalEnabled(bool enabled) { m_evalEnabled = enabled; }
294         bool evalEnabled() { return m_evalEnabled; }
295
296         void resizeRegisters(size_t newSize);
297
298         void resetPrototype(JSGlobalData&, JSValue prototype);
299
300         JSGlobalData& globalData() const { return *m_globalData.get(); }
301
302         static Structure* createStructure(JSGlobalData& globalData, JSValue prototype)
303         {
304             return Structure::create(globalData, 0, prototype, TypeInfo(GlobalObjectType, StructureFlags), &s_info);
305         }
306
307         void registerWeakMap(OpaqueJSWeakObjectMap* map)
308         {
309             createRareDataIfNeeded();
310             m_rareData->weakMaps.add(map);
311         }
312
313         void unregisterWeakMap(OpaqueJSWeakObjectMap* map)
314         {
315             if (m_rareData)
316                 m_rareData->weakMaps.remove(map);
317         }
318
319         double weakRandomNumber() { return m_weakRandom.get(); }
320     protected:
321
322         static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
323
324         struct GlobalPropertyInfo {
325             GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
326                 : identifier(i)
327                 , value(v)
328                 , attributes(a)
329             {
330             }
331
332             const Identifier identifier;
333             JSValue value;
334             unsigned attributes;
335         };
336         void addStaticGlobals(GlobalPropertyInfo*, int count);
337
338     private:
339         // FIXME: Fold reset into init.
340         void init(JSObject* thisValue);
341         void reset(JSValue prototype);
342
343         void createThrowTypeError(ExecState*);
344
345         void setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count);
346         static void clearRareData(JSCell*);
347     };
348
349     JSGlobalObject* asGlobalObject(JSValue);
350
351     inline JSGlobalObject* asGlobalObject(JSValue value)
352     {
353         ASSERT(asObject(value)->isGlobalObject());
354         return static_cast<JSGlobalObject*>(asObject(value));
355     }
356
357     inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count)
358     {
359         JSVariableObject::setRegisters(registers, registerArray);
360         m_registerArraySize = count;
361     }
362
363     inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
364     {
365         PropertySlot slot;
366         if (JSVariableObject::getOwnPropertySlot(this, exec, propertyName, slot))
367             return true;
368         bool slotIsWriteable;
369         return symbolTableGet(propertyName, slot, slotIsWriteable);
370     }
371
372     inline bool JSGlobalObject::symbolTableHasProperty(const Identifier& propertyName)
373     {
374         SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl());
375         return !entry.isNull();
376     }
377
378     inline JSValue Structure::prototypeForLookup(ExecState* exec) const
379     {
380         if (isObject())
381             return m_prototype.get();
382
383         ASSERT(typeInfo().type() == StringType);
384         return exec->lexicalGlobalObject()->stringPrototype();
385     }
386
387     inline StructureChain* Structure::prototypeChain(ExecState* exec) const
388     {
389         // We cache our prototype chain so our clients can share it.
390         if (!isValid(exec, m_cachedPrototypeChain.get())) {
391             JSValue prototype = prototypeForLookup(exec);
392             m_cachedPrototypeChain.set(exec->globalData(), this, StructureChain::create(exec->globalData(), prototype.isNull() ? 0 : asObject(prototype)->structure()));
393         }
394         return m_cachedPrototypeChain.get();
395     }
396
397     inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
398     {
399         if (!cachedPrototypeChain)
400             return false;
401
402         JSValue prototype = prototypeForLookup(exec);
403         WriteBarrier<Structure>* cachedStructure = cachedPrototypeChain->head();
404         while(*cachedStructure && !prototype.isNull()) {
405             if (asObject(prototype)->structure() != cachedStructure->get())
406                 return false;
407             ++cachedStructure;
408             prototype = asObject(prototype)->prototype();
409         }
410         return prototype.isNull() && !*cachedStructure;
411     }
412
413     inline JSGlobalObject* ExecState::dynamicGlobalObject()
414     {
415         if (this == lexicalGlobalObject()->globalExec())
416             return lexicalGlobalObject();
417
418         // For any ExecState that's not a globalExec, the 
419         // dynamic global object must be set since code is running
420         ASSERT(globalData().dynamicGlobalObject);
421         return globalData().dynamicGlobalObject;
422     }
423
424     inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject)
425     {
426         return constructEmptyObject(exec, globalObject->emptyObjectStructure());
427     }
428
429     inline JSObject* constructEmptyObject(ExecState* exec)
430     {
431         return constructEmptyObject(exec, exec->lexicalGlobalObject());
432     }
433
434     inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject)
435     {
436         return JSArray::create(exec->globalData(), globalObject->arrayStructure());
437     }
438     
439     inline JSArray* constructEmptyArray(ExecState* exec)
440     {
441         return constructEmptyArray(exec, exec->lexicalGlobalObject());
442     }
443
444     inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject, unsigned initialLength)
445     {
446         return JSArray::create(exec->globalData(), globalObject->arrayStructure(), initialLength, CreateInitialized);
447     }
448
449     inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
450     {
451         return constructEmptyArray(exec, exec->lexicalGlobalObject(), initialLength);
452     }
453
454     inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, JSValue singleItemValue)
455     {
456         MarkedArgumentBuffer values;
457         values.append(singleItemValue);
458         return JSArray::create(exec->globalData(), globalObject->arrayStructure(), values);
459     }
460
461     inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
462     {
463         return constructArray(exec, exec->lexicalGlobalObject(), singleItemValue);
464     }
465
466     inline JSArray* constructArray(ExecState* exec, JSGlobalObject* globalObject, const ArgList& values)
467     {
468         return JSArray::create(exec->globalData(), globalObject->arrayStructure(), values);
469     }
470
471     inline JSArray* constructArray(ExecState* exec, const ArgList& values)
472     {
473         return constructArray(exec, exec->lexicalGlobalObject(), values);
474     }
475
476     inline JSArray* constructArray(ExecState* exec, const JSValue* values, size_t length)
477     {
478         return JSArray::create(exec->globalData(), exec->lexicalGlobalObject()->arrayStructure(), values, length);
479     }
480
481     class DynamicGlobalObjectScope {
482         WTF_MAKE_NONCOPYABLE(DynamicGlobalObjectScope);
483     public:
484         DynamicGlobalObjectScope(JSGlobalData&, JSGlobalObject*);
485
486         ~DynamicGlobalObjectScope()
487         {
488             m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject;
489         }
490
491     private:
492         JSGlobalObject*& m_dynamicGlobalObjectSlot;
493         JSGlobalObject* m_savedDynamicGlobalObject;
494     };
495
496     inline bool JSGlobalObject::isDynamicScope(bool&) const
497     {
498         return true;
499     }
500
501 } // namespace JSC
502
503 #endif // JSGlobalObject_h