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

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

JavaScriptCore:

2009-06-17 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

<rdar://problem/6974175> ASSERT in JITStubs.cpp at appsaccess.apple.com

Remove PropertySlot::putValue - PropertySlots should only be used for getting,
not putting. Rename JSGlobalObject::getOwnPropertySlot to hasOwnPropertyForWrite,
which is what it really was being used to ask, and remove some other getOwnPropertySlot
& getOwnPropertySlotForWrite methods, which were unused and likely to lead to confusion.

  • runtime/JSGlobalObject.h: (JSC::JSGlobalObject::hasOwnPropertyForWrite):
  • runtime/JSObject.h:
  • runtime/JSStaticScopeObject.cpp:
  • runtime/JSStaticScopeObject.h:
  • runtime/PropertySlot.h:

WebCore:

2009-06-17 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt.

<rdar://problem/6974175> ASSERT in JITStubs.cpp at appsaccess.apple.com

JSDOMWindowCustom was using PropertySlot::putValue, however this interface
appears to be fundaementally incorrect - PropertySlots are only used to get
values, all puts use PutPropertySlot. However PutPropertySlot cannot be
used in the fashion desired here - it only reports the caching type of a
write that has been performed.

(This caused a bug where the put should have triggered a transition, and
failed to do so.)

Removing the faulty case from the optimization leads to a ~0.5% progression
on in-browser SunSpider (presumably the very first case was not being hit
often, and the simplification here is beneficial).

  • bindings/js/JSDOMWindowCustom.cpp: (WebCore::JSDOMWindow::put):
  • Property svn:eol-style set to native
File size: 16.1 KB
Line 
1/*
2 * Copyright (C) 2007 Eric Seidel <[email protected]>
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 "NativeFunctionWrapper.h"
28#include "NumberPrototype.h"
29#include "StringPrototype.h"
30#include <wtf/HashSet.h>
31#include <wtf/OwnPtr.h>
32
33namespace JSC {
34
35 class ArrayPrototype;
36 class BooleanPrototype;
37 class DatePrototype;
38 class Debugger;
39 class ErrorConstructor;
40 class FunctionPrototype;
41 class GlobalEvalFunction;
42 class NativeErrorConstructor;
43 class ProgramCodeBlock;
44 class PrototypeFunction;
45 class RegExpConstructor;
46 class RegExpPrototype;
47 class RegisterFile;
48
49 struct ActivationStackNode;
50 struct HashTable;
51
52 typedef Vector<ExecState*, 16> ExecStateStack;
53
54 class JSGlobalObject : public JSVariableObject {
55 protected:
56 using JSVariableObject::JSVariableObjectData;
57
58 struct JSGlobalObjectData : public JSVariableObjectData {
59 JSGlobalObjectData()
60 : JSVariableObjectData(&symbolTable, 0)
61 , registerArraySize(0)
62 , globalScopeChain(NoScopeChain())
63 , regExpConstructor(0)
64 , errorConstructor(0)
65 , evalErrorConstructor(0)
66 , rangeErrorConstructor(0)
67 , referenceErrorConstructor(0)
68 , syntaxErrorConstructor(0)
69 , typeErrorConstructor(0)
70 , URIErrorConstructor(0)
71 , evalFunction(0)
72 , callFunction(0)
73 , applyFunction(0)
74 , objectPrototype(0)
75 , functionPrototype(0)
76 , arrayPrototype(0)
77 , booleanPrototype(0)
78 , stringPrototype(0)
79 , numberPrototype(0)
80 , datePrototype(0)
81 , regExpPrototype(0)
82 , methodCallDummy(0)
83 {
84 }
85
86 virtual ~JSGlobalObjectData()
87 {
88 }
89
90 size_t registerArraySize;
91
92 JSGlobalObject* next;
93 JSGlobalObject* prev;
94
95 Debugger* debugger;
96
97 ScopeChain globalScopeChain;
98 Register globalCallFrame[RegisterFile::CallFrameHeaderSize];
99
100 int recursion;
101
102 RegExpConstructor* regExpConstructor;
103 ErrorConstructor* errorConstructor;
104 NativeErrorConstructor* evalErrorConstructor;
105 NativeErrorConstructor* rangeErrorConstructor;
106 NativeErrorConstructor* referenceErrorConstructor;
107 NativeErrorConstructor* syntaxErrorConstructor;
108 NativeErrorConstructor* typeErrorConstructor;
109 NativeErrorConstructor* URIErrorConstructor;
110
111 GlobalEvalFunction* evalFunction;
112 NativeFunctionWrapper* callFunction;
113 NativeFunctionWrapper* applyFunction;
114
115 ObjectPrototype* objectPrototype;
116 FunctionPrototype* functionPrototype;
117 ArrayPrototype* arrayPrototype;
118 BooleanPrototype* booleanPrototype;
119 StringPrototype* stringPrototype;
120 NumberPrototype* numberPrototype;
121 DatePrototype* datePrototype;
122 RegExpPrototype* regExpPrototype;
123
124 JSObject* methodCallDummy;
125
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;
141
142 SymbolTable symbolTable;
143 unsigned profileGroup;
144
145 RefPtr<JSGlobalData> globalData;
146
147 HashSet<ProgramCodeBlock*> codeBlocks;
148 };
149
150 public:
151 void* operator new(size_t, JSGlobalData*);
152
153 explicit JSGlobalObject()
154 : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData)
155 {
156 init(this);
157 }
158
159 protected:
160 JSGlobalObject(PassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue)
161 : JSVariableObject(structure, data)
162 {
163 init(thisValue);
164 }
165
166 public:
167 virtual ~JSGlobalObject();
168
169 virtual void mark();
170
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);
175
176 virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
177 virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
178
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; }
182
183 // The following accessors return pristine values, even if a script
184 // replaces the global object's associated property.
185
186 RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor; }
187
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; }
195
196 GlobalEvalFunction* evalFunction() const { return d()->evalFunction; }
197
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; }
206
207 JSObject* methodCallDummy() const { return d()->methodCallDummy; }
208
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(); }
224
225 void setProfileGroup(unsigned value) { d()->profileGroup = value; }
226 unsigned profileGroup() const { return d()->profileGroup; }
227
228 Debugger* debugger() const { return d()->debugger; }
229 void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
230
231 virtual bool supportsProfiling() const { return false; }
232
233 int recursion() { return d()->recursion; }
234 void incRecursion() { ++d()->recursion; }
235 void decRecursion() { --d()->recursion; }
236
237 ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
238
239 virtual bool isGlobalObject() const { return true; }
240
241 virtual ExecState* globalExec();
242
243 virtual bool shouldInterruptScript() const { return true; }
244
245 virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; }
246
247 virtual bool isDynamicScope() const;
248
249 HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
250
251 void copyGlobalsFrom(RegisterFile&);
252 void copyGlobalsTo(RegisterFile&);
253
254 void resetPrototype(JSValue prototype);
255
256 JSGlobalData* globalData() { return d()->globalData.get(); }
257 JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
258
259 static PassRefPtr<Structure> createStructure(JSValue prototype)
260 {
261 return Structure::create(prototype, TypeInfo(ObjectType));
262 }
263
264 protected:
265 struct GlobalPropertyInfo {
266 GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a)
267 : identifier(i)
268 , value(v)
269 , attributes(a)
270 {
271 }
272
273 const Identifier identifier;
274 JSValue value;
275 unsigned attributes;
276 };
277 void addStaticGlobals(GlobalPropertyInfo*, int count);
278
279 private:
280 // FIXME: Fold reset into init.
281 void init(JSObject* thisValue);
282 void reset(JSValue prototype);
283
284 void setRegisters(Register* registers, Register* registerArray, size_t count);
285
286 void* operator new(size_t); // can only be allocated with JSGlobalData
287 };
288
289 JSGlobalObject* asGlobalObject(JSValue);
290
291 inline JSGlobalObject* asGlobalObject(JSValue value)
292 {
293 ASSERT(asObject(value)->isGlobalObject());
294 return static_cast<JSGlobalObject*>(asObject(value));
295 }
296
297 inline void JSGlobalObject::setRegisters(Register* registers, Register* registerArray, size_t count)
298 {
299 JSVariableObject::setRegisters(registers, registerArray);
300 d()->registerArraySize = count;
301 }
302
303 inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
304 {
305 size_t oldSize = d()->registerArraySize;
306 size_t newSize = oldSize + count;
307 Register* registerArray = new Register[newSize];
308 if (d()->registerArray)
309 memcpy(registerArray + count, d()->registerArray.get(), oldSize * sizeof(Register));
310 setRegisters(registerArray + newSize, registerArray, newSize);
311
312 for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
313 GlobalPropertyInfo& global = globals[i];
314 ASSERT(global.attributes & DontDelete);
315 SymbolTableEntry newEntry(index, global.attributes);
316 symbolTable().add(global.identifier.ustring().rep(), newEntry);
317 registerAt(index) = global.value;
318 }
319 }
320
321 inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
322 {
323 if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
324 return true;
325 return symbolTableGet(propertyName, slot);
326 }
327
328 inline bool JSGlobalObject::hasOwnPropertyForWrite(ExecState* exec, const Identifier& propertyName)
329 {
330 PropertySlot slot;
331 if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
332 return true;
333 bool slotIsWriteable;
334 return symbolTableGet(propertyName, slot, slotIsWriteable);
335 }
336
337 inline JSGlobalObject* ScopeChainNode::globalObject() const
338 {
339 const ScopeChainNode* n = this;
340 while (n->next)
341 n = n->next;
342 return asGlobalObject(n->object);
343 }
344
345 inline JSValue Structure::prototypeForLookup(ExecState* exec) const
346 {
347 if (typeInfo().type() == ObjectType)
348 return m_prototype;
349
350 if (typeInfo().type() == StringType)
351 return exec->lexicalGlobalObject()->stringPrototype();
352
353 ASSERT(typeInfo().type() == NumberType);
354 return exec->lexicalGlobalObject()->numberPrototype();
355 }
356
357 inline StructureChain* Structure::prototypeChain(ExecState* exec) const
358 {
359 // We cache our prototype chain so our clients can share it.
360 if (!isValid(exec, m_cachedPrototypeChain.get())) {
361 JSValue prototype = prototypeForLookup(exec);
362 m_cachedPrototypeChain = StructureChain::create(prototype.isNull() ? 0 : asObject(prototype)->structure());
363 }
364 return m_cachedPrototypeChain.get();
365 }
366
367 inline bool Structure::isValid(ExecState* exec, StructureChain* cachedPrototypeChain) const
368 {
369 if (!cachedPrototypeChain)
370 return false;
371
372 JSValue prototype = prototypeForLookup(exec);
373 RefPtr<Structure>* cachedStructure = cachedPrototypeChain->head();
374 while(*cachedStructure && !prototype.isNull()) {
375 if (asObject(prototype)->structure() != *cachedStructure)
376 return false;
377 ++cachedStructure;
378 prototype = asObject(prototype)->prototype();
379 }
380 return prototype.isNull() && !*cachedStructure;
381 }
382
383 inline JSGlobalObject* ExecState::dynamicGlobalObject()
384 {
385 if (this == lexicalGlobalObject()->globalExec())
386 return lexicalGlobalObject();
387
388 // For any ExecState that's not a globalExec, the
389 // dynamic global object must be set since code is running
390 ASSERT(globalData().dynamicGlobalObject);
391 return globalData().dynamicGlobalObject;
392 }
393
394 class DynamicGlobalObjectScope : Noncopyable {
395 public:
396 DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject)
397 : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject)
398 , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot)
399 {
400 m_dynamicGlobalObjectSlot = dynamicGlobalObject;
401 }
402
403 ~DynamicGlobalObjectScope()
404 {
405 m_dynamicGlobalObjectSlot = m_savedDynamicGlobalObject;
406 }
407
408 private:
409 JSGlobalObject*& m_dynamicGlobalObjectSlot;
410 JSGlobalObject* m_savedDynamicGlobalObject;
411 };
412
413} // namespace JSC
414
415#endif // JSGlobalObject_h
Note: See TracBrowser for help on using the repository browser.