source: webkit/trunk/JavaScriptCore/runtime/JSGlobalObject.h@ 58224

Last change on this file since 58224 was 57120, checked in by [email protected], 15 years ago

2010-04-05 Oliver Hunt <[email protected]>

Reviewed by Gavin Barraclough.

Support weak maps in JSC
https://bugs.webkit.org/show_bug.cgi?id=37132

Expose an API to allow creation of a map for storing
weak JS references.

  • API/JSWeakObjectMapRefInternal.h: Added. (OpaqueJSWeakObjectMap::create): (OpaqueJSWeakObjectMap::map): (OpaqueJSWeakObjectMap::~OpaqueJSWeakObjectMap): (OpaqueJSWeakObjectMap::OpaqueJSWeakObjectMap):
  • API/JSWeakObjectMapRefPrivate.cpp: Added.
  • API/JSWeakObjectMapRefPrivate.h: Added.
  • JavaScriptCore.exp:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • runtime/JSGlobalObject.h: (JSC::JSGlobalObject::registerWeakMap): (JSC::JSGlobalObject::deregisterWeakMap):
  • Property svn:eol-style set to native
File size: 19.1 KB
Line 
1/*
2 * Copyright (C) 2007 Eric Seidel <[email protected]>
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 "JSVariableObject.h"
28#include "JSWeakObjectMapRefInternal.h"
29#include "NativeFunctionWrapper.h"
30#include "NumberPrototype.h"
31#include "StringPrototype.h"
32#include <wtf/HashSet.h>
33#include <wtf/OwnPtr.h>
34
35namespace JSC {
36
37 class ArrayPrototype;
38 class BooleanPrototype;
39 class DatePrototype;
40 class Debugger;
41 class ErrorConstructor;
42 class FunctionPrototype;
43 class GlobalCodeBlock;
44 class GlobalEvalFunction;
45 class NativeErrorConstructor;
46 class ProgramCodeBlock;
47 class PrototypeFunction;
48 class RegExpConstructor;
49 class RegExpPrototype;
50 class RegisterFile;
51
52 struct ActivationStackNode;
53 struct HashTable;
54
55 typedef Vector<ExecState*, 16> ExecStateStack;
56
57 class JSGlobalObject : public JSVariableObject {
58 protected:
59 using JSVariableObject::JSVariableObjectData;
60 typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet;
61
62 struct JSGlobalObjectData : public JSVariableObjectData {
63 // We use an explicit destructor function pointer instead of a
64 // virtual destructor because we want to avoid adding a vtable
65 // pointer to this struct. Adding a vtable pointer would force the
66 // compiler to emit costly pointer fixup code when casting from
67 // JSVariableObjectData* to JSGlobalObjectData*.
68 typedef void (*Destructor)(void*);
69
70 JSGlobalObjectData(Destructor destructor)
71 : JSVariableObjectData(&symbolTable, 0)
72 , destructor(destructor)
73 , registerArraySize(0)
74 , globalScopeChain(NoScopeChain())
75 , regExpConstructor(0)
76 , errorConstructor(0)
77 , evalErrorConstructor(0)
78 , rangeErrorConstructor(0)
79 , referenceErrorConstructor(0)
80 , syntaxErrorConstructor(0)
81 , typeErrorConstructor(0)
82 , URIErrorConstructor(0)
83 , evalFunction(0)
84 , callFunction(0)
85 , applyFunction(0)
86 , objectPrototype(0)
87 , functionPrototype(0)
88 , arrayPrototype(0)
89 , booleanPrototype(0)
90 , stringPrototype(0)
91 , numberPrototype(0)
92 , datePrototype(0)
93 , regExpPrototype(0)
94 , methodCallDummy(0)
95 {
96 }
97
98 Destructor destructor;
99
100 size_t registerArraySize;
101
102 JSGlobalObject* next;
103 JSGlobalObject* prev;
104
105 Debugger* debugger;
106
107 ScopeChain globalScopeChain;
108 Register globalCallFrame[RegisterFile::CallFrameHeaderSize];
109
110 int recursion;
111
112 RegExpConstructor* regExpConstructor;
113 ErrorConstructor* errorConstructor;
114 NativeErrorConstructor* evalErrorConstructor;
115 NativeErrorConstructor* rangeErrorConstructor;
116 NativeErrorConstructor* referenceErrorConstructor;
117 NativeErrorConstructor* syntaxErrorConstructor;
118 NativeErrorConstructor* typeErrorConstructor;
119 NativeErrorConstructor* URIErrorConstructor;
120
121 GlobalEvalFunction* evalFunction;
122 NativeFunctionWrapper* callFunction;
123 NativeFunctionWrapper* applyFunction;
124
125 ObjectPrototype* objectPrototype;
126 FunctionPrototype* functionPrototype;
127 ArrayPrototype* arrayPrototype;
128 BooleanPrototype* booleanPrototype;
129 StringPrototype* stringPrototype;
130 NumberPrototype* numberPrototype;
131 DatePrototype* datePrototype;
132 RegExpPrototype* regExpPrototype;
133
134 JSObject* methodCallDummy;
135
136 RefPtr<Structure> argumentsStructure;
137 RefPtr<Structure> arrayStructure;
138 RefPtr<Structure> booleanObjectStructure;
139 RefPtr<Structure> callbackConstructorStructure;
140 RefPtr<Structure> callbackFunctionStructure;
141 RefPtr<Structure> callbackObjectStructure;
142 RefPtr<Structure> dateStructure;
143 RefPtr<Structure> emptyObjectStructure;
144 RefPtr<Structure> errorStructure;
145 RefPtr<Structure> functionStructure;
146 RefPtr<Structure> numberObjectStructure;
147 RefPtr<Structure> prototypeFunctionStructure;
148 RefPtr<Structure> regExpMatchesArrayStructure;
149 RefPtr<Structure> regExpStructure;
150 RefPtr<Structure> stringObjectStructure;
151
152 SymbolTable symbolTable;
153 unsigned profileGroup;
154
155 RefPtr<JSGlobalData> globalData;
156
157 HashSet<GlobalCodeBlock*> codeBlocks;
158 WeakMapSet weakMaps;
159 };
160
161 public:
162 void* operator new(size_t, JSGlobalData*);
163
164 explicit JSGlobalObject()
165 : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData))
166 {
167 init(this);
168 }
169
170 protected:
171 JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
172 : JSVariableObject(structure, data)
173 {
174 init(thisValue);
175 }
176
177 public:
178 virtual ~JSGlobalObject();
179
180 virtual void markChildren(MarkStack&);
181
182 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
183 virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&);
184 virtual bool hasOwnPropertyForWrite(ExecState*, const Identifier&);
185 virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&);
186 virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue value, unsigned attributes);
187
188 virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc, unsigned attributes);
189 virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc, unsigned attributes);
190
191 // Linked list of all global objects that use the same JSGlobalData.
192 JSGlobalObject*& head() { return d()->globalData->head; }
193 JSGlobalObject* next() { return d()->next; }
194
195 // The following accessors return pristine values, even if a script
196 // replaces the global object's associated property.
197
198 RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor; }
199
200 ErrorConstructor* errorConstructor() const { return d()->errorConstructor; }
201 NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor; }
202 NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor; }
203 NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor; }
204 NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor; }
205 NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor; }
206 NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor; }
207
208 GlobalEvalFunction* evalFunction() const { return d()->evalFunction; }
209
210 ObjectPrototype* objectPrototype() const { return d()->objectPrototype; }
211 FunctionPrototype* functionPrototype() const { return d()->functionPrototype; }
212 ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype; }
213 BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype; }
214 StringPrototype* stringPrototype() const { return d()->stringPrototype; }
215 NumberPrototype* numberPrototype() const { return d()->numberPrototype; }
216 DatePrototype* datePrototype() const { return d()->datePrototype; }
217 RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; }
218
219 JSObject* methodCallDummy() const { return d()->methodCallDummy; }
220
221 Structure* argumentsStructure() const { return d()->argumentsStructure.get(); }
222 Structure* arrayStructure() const { return d()->arrayStructure.get(); }
223 Structure* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); }
224 Structure* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); }
225 Structure* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); }
226 Structure* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); }
227 Structure* dateStructure() const { return d()->dateStructure.get(); }
228 Structure* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); }
229 Structure* errorStructure() const { return d()->errorStructure.get(); }
230 Structure* functionStructure() const { return d()->functionStructure.get(); }
231 Structure* numberObjectStructure() const { return d()->numberObjectStructure.get(); }
232 Structure* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); }
233 Structure* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); }
234 Structure* regExpStructure() const { return d()->regExpStructure.get(); }
235 Structure* stringObjectStructure() const { return d()->stringObjectStructure.get(); }
236
237 void setProfileGroup(unsigned value) { d()->profileGroup = value; }
238 unsigned profileGroup() const { return d()->profileGroup; }
239
240 Debugger* debugger() const { return d()->debugger; }
241 void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
242
243 virtual bool supportsProfiling() const { return false; }
244
245 int recursion() { return d()->recursion; }
246 void incRecursion() { ++d()->recursion; }
247 void decRecursion() { --d()->recursion; }
248
249 ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
250
251 virtual bool isGlobalObject() const { return true; }
252
253 virtual ExecState* globalExec();
254
255 virtual bool shouldInterruptScript() const { return true; }
256
257 virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; }
258
259 virtual bool isDynamicScope() const;
260
261 HashSet<GlobalCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
262
263 void copyGlobalsFrom(RegisterFile&);
264 void copyGlobalsTo(RegisterFile&);
265
266 void resetPrototype(JSValue prototype);
267
268 JSGlobalData* globalData() { return d()->globalData.get(); }
269 JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
270
271 static PassRefPtr<Structure> createStructure(JSValue prototype)
272 {
273 return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount);
274 }
275
276 void registerWeakMap(OpaqueJSWeakObjectMap* map)
277 {
278 d()->weakMaps.add(map);
279 }
280
281 void deregisterWeakMap(OpaqueJSWeakObjectMap* map)
282 {
283 d()->weakMaps.remove(map);
284 }
285
286 protected:
287
288 static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags;
289
290 struct GlobalPropertyInfo {
291 GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
292 : identifier(i)
293 , value(v)
294 , attributes(a)
295 {
296 }
297
298 const Identifier identifier;
299 JSValue value;
300 unsigned attributes;
301 };
302 void addStaticGlobals(GlobalPropertyInfo*, int count);
303
304 private:
305 static void destroyJSGlobalObjectData(void*);
306
307 // FIXME: Fold reset into init.
308 void init(JSObject* thisValue);
309 void reset(JSValue prototype);
310
311 void setRegisters(Register* registers, Register* registerArray, size_t count);
312
313 void* operator new(size_t); // can only be allocated with JSGlobalData
314 };
315
316 JSGlobalObject* asGlobalObject(JSValue);
317
318 inline JSGlobalObject* asGlobalObject(JSValue value)
319 {
320 ASSERT(asObject(value)->isGlobalObject());
321 return static_cast<JSGlobalObject*>(asObject(value));
322 }
323
324 inline void JSGlobalObject::setRegisters(Register* registers, Register* registerArray, size_t count)
325 {
326 JSVariableObject::setRegisters(registers, registerArray);
327 d()->registerArraySize = count;
328 }
329
330 inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
331 {
332 size_t oldSize = d()->registerArraySize;
333 size_t newSize = oldSize + count;
334 Register* registerArray = new Register[newSize];
335 if (d()->registerArray)
336 memcpy(registerArray + count, d()->registerArray.get(), oldSize * sizeof(Register));
337 setRegisters(registerArray + newSize, registerArray, newSize);
338
339 for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
340 GlobalPropertyInfo& global = globals[i];
341 ASSERT(global.attributes & DontDelete);
342 SymbolTableEntry newEntry(index, global.attributes);
343 symbolTable().add(global.identifier.ustring().rep(), newEntry);
344 registerAt(index) = global.value;
345 }
346 }
347
348 inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
349 {
350 if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
351 return true;
352 return symbolTableGet(propertyName, slot);
353 }
354
355 inline bool JSGlobalObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor)
356 {
357 if (symbolTableGet(propertyName, descriptor))
358 return true;
359 return JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor);
360 }
361
362 inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
363 {
364 PropertySlot slot;
365 if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
366 return true;
367 bool slotIsWriteable;
368 return symbolTableGet(propertyName, slot, slotIsWriteable);
369 }
370
371 inline JSValue Structure::prototypeForLookup(ExecState* exec) const
372 {
373 if (typeInfo().type() == ObjectType)
374 return m_prototype;
375
376#if USE(JSVALUE32)
377 if (typeInfo().type() == StringType)
378 return exec->lexicalGlobalObject()->stringPrototype();
379
380 ASSERT(typeInfo().type() == NumberType);
381 return exec->lexicalGlobalObject()->numberPrototype();
382#else
383 ASSERT(typeInfo().type() == StringType);
384 return exec->lexicalGlobalObject()->stringPrototype();
385#endif
386 }
387
388 inline StructureChain* Structure::prototypeChain(ExecState* exec) const
389 {
390 // We cache our prototype chain so our clients can share it.
391 if (!isValid(exec, m_cachedPrototypeChain.get())) {
392 JSValue prototype = prototypeForLookup(exec);
393 m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure());
394 }
395 return m_cachedPrototypeChain.get();
396 }
397
398 inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
399 {
400 if (!cachedPrototypeChain)
401 return false;
402
403 JSValue prototype = prototypeForLookup(exec);
404 RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head();
405 while(*cachedStructure && !prototype.isNull()) {
406 if (asObject(prototype)->structure() != *cachedStructure)
407 return false;
408 ++cachedStructure;
409 prototype = asObject(prototype)->prototype();
410 }
411 return prototype.isNull() && !*cachedStructure;
412 }
413
414 inline JSGlobalObject* ExecState::dynamicGlobalObject()
415 {
416 if (this == lexicalGlobalObject()->globalExec())
417 return lexicalGlobalObject();
418
419 // For any ExecState that's not a globalExec, the
420 // dynamic global object must be set since code is running
421 ASSERT(globalData().dynamicGlobalObject);
422 return globalData().dynamicGlobalObject;
423 }
424
425 inline JSObject* constructEmptyObject(ExecState* exec)
426 {
427 return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure());
428 }
429
430 inline JSObject* constructEmptyObject(ExecState* exec, JSGlobalObject* globalObject)
431 {
432 return new (exec) JSObject(globalObject->emptyObjectStructure());
433 }
434
435 inline JSArray* constructEmptyArray(ExecState* exec)
436 {
437 return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure());
438 }
439
440 inline JSArray* constructEmptyArray(ExecState* exec, JSGlobalObject* globalObject)
441 {
442 return new (exec) JSArray(globalObject->arrayStructure());
443 }
444
445 inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength)
446 {
447 return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength);
448 }
449
450 inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue)
451 {
452 MarkedArgumentBuffer values;
453 values.append(singleItemValue);
454 return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
455 }
456
457 inline JSArray* constructArray(ExecState* exec, const ArgList& values)
458 {
459 return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values);
460 }
461
462 class DynamicGlobalObjectScope : public Noncopyable {
463 public:
464 DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
465 : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
466 , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
467 {
468 if (!m_dynamicGlobalObjectSlot) {
469 m_dynamicGlobalObjectSlot = dynamicGlobalObject;
470
471 // Reset the date cache between JS invocations to force the VM
472 // to observe time zone changes.
473 callFrame->globalData().resetDateCache();
474 }
475 }
476
477 ~DynamicGlobalObjectScope()
478 {
479 m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject;
480 }
481
482 private:
483 JSGlobalObject*& m_dynamicGlobalObjectSlot;
484 JSGlobalObject* m_savedDynamicGlobalObject;
485 };
486
487} // namespace JSC
488
489#endif // JSGlobalObject_h
Note: See TracBrowser for help on using the repository browser.