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

Last change on this file since 52956 was 50705, checked in by [email protected], 16 years ago

Added a tiny cache for Date parsing.

Reviewed by Sam "Home Wrecker" Weinig.

SunSpider says 1.2% faster.

  • runtime/DateConversion.cpp:

(JSC::parseDate): Try to reuse the last parsed Date, if present.

  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::resetDateCache):

  • runtime/JSGlobalData.h: Added storage for last parsed Date. Refactored

this code to make resetting the date cache easier.

  • runtime/JSGlobalObject.h:

(JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Updated for
refactoring.

  • wtf/DateMath.cpp:

(JSC::parseDateFromNullTerminatedCharacters):

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