source: webkit/trunk/JavaScriptCore/kjs/JSGlobalObject.h@ 37086

Last change on this file since 37086 was 37086, checked in by [email protected], 17 years ago

JavaScriptCore:

2008-09-29 Geoffrey Garen <[email protected]>

Reviewed by Cameron Zwarich.


Store the callee ScopeChain, not the caller ScopeChain, in the call frame
header. Nix the "scopeChain" local variable and ExecState::m_scopeChain, and
access the callee ScopeChain through the call frame header instead.

Profit: call + return are simpler, because they don't have to update the
"scopeChain" local variable, or ExecState::m_scopeChain.


Because CTI keeps "r" in a register, reading the callee ScopeChain relative
to "r" can be very fast, in any cases we care to optimize.

0% speedup on empty function call benchmark. (5.5% speedup in bytecode.)
0% speedup on SunSpider. (7.5% speedup on controlflow-recursive.)
2% speedup on SunSpider --v8.
2% speedup on v8 benchmark.

  • VM/CTI.cpp: Changed scope chain access to read the scope chain from the call frame header. Sped up op_ret by changing it not to fuss with the "scopeChain" local variable or ExecState::m_scopeChain.
  • VM/CTI.h: Updated CTI trampolines not to take a ScopeChainNode* argument, since that's stored in the call frame header now.
  • VM/Machine.cpp: Access "scopeChain" and "codeBlock" through new helper functions that read from the call frame header. Updated functions operating on ExecState::m_callFrame to account for / take advantage of the fact that Exec:m_callFrame is now never NULL.


Fixed a bug in op_construct, where it would use the caller's default
object prototype, rather than the callee's, when constructing a new object.

  • VM/Machine.h: Made some helper functions available. Removed ScopeChainNode* arguments to a lot of functions, since the ScopeChainNode* is now stored in the call frame header.
  • VM/RegisterFile.h: Renamed "CallerScopeChain" to "ScopeChain", since that's what it is now.
  • kjs/DebuggerCallFrame.cpp: Updated for change to ExecState signature.
  • kjs/ExecState.cpp:
  • kjs/ExecState.h: Nixed ExecState::m_callFrame, along with the unused isGlobalObject function.
  • kjs/JSGlobalObject.cpp:
  • kjs/JSGlobalObject.h: Gave the global object a fake call frame in which to store the global scope chain, since our code now assumes that it can always read the scope chain out of the ExecState's call frame.

JavaScriptGlue:

2008-09-29 Geoffrey Garen <[email protected]>

Not reviewed.


Forwarding headers to fix the build.

  • ForwardingHeaders/kjs/CTI.h: Copied from ForwardingHeaders/kjs/ExecState.h.
  • ForwardingHeaders/kjs/ustring.h: Copied from ForwardingHeaders/kjs/ExecState.h.
  • ForwardingHeaders/masm: Added.
  • ForwardingHeaders/masm/X86Assembler.h: Added.
  • ForwardingHeaders/profiler: Added.
  • ForwardingHeaders/profiler/Profiler.h: Added.

LayoutTests:

2008-09-29 Geoffrey Garen <[email protected]>

Reviewed by Cameron Zwarich.


Test case for which prototype is used when calling "new" across windows.

  • fast/js/construct-global-object-expected.txt: Added.
  • fast/js/construct-global-object.html: Added.
  • Property svn:eol-style set to native
File size: 14.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 "NumberPrototype.h"
28#include "StringPrototype.h"
29#include <wtf/HashSet.h>
30#include <wtf/OwnPtr.h>
31
32namespace 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 {
57 JSGlobalObjectData(JSGlobalObject* globalObject, JSObject* thisValue)
58 : JSVariableObjectData(&symbolTable, 0)
59 , registerArraySize(0)
60 , globalScopeChain(globalObject, thisValue)
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 Machine::initializeCallFrame(globalCallFrame + RegisterFile::CallFrameHeaderSize, 0, 0, globalScopeChain.node(), 0, 0, 0, 0);
80 }
81
82 virtual ~JSGlobalObjectData()
83 {
84 }
85
86 size_t registerArraySize;
87
88 JSGlobalObject* next;
89 JSGlobalObject* prev;
90
91 Debugger* debugger;
92
93 ScopeChain globalScopeChain;
94 Register globalCallFrame[RegisterFile::CallFrameHeaderSize];
95 OwnPtr<ExecState> globalExec;
96
97 int recursion;
98
99 RegExpConstructor* regExpConstructor;
100 ErrorConstructor* errorConstructor;
101 NativeErrorConstructor* evalErrorConstructor;
102 NativeErrorConstructor* rangeErrorConstructor;
103 NativeErrorConstructor* referenceErrorConstructor;
104 NativeErrorConstructor* syntaxErrorConstructor;
105 NativeErrorConstructor* typeErrorConstructor;
106 NativeErrorConstructor* URIErrorConstructor;
107
108 GlobalEvalFunction* evalFunction;
109
110 ObjectPrototype* objectPrototype;
111 FunctionPrototype* functionPrototype;
112 ArrayPrototype* arrayPrototype;
113 BooleanPrototype* booleanPrototype;
114 StringPrototype* stringPrototype;
115 NumberPrototype* numberPrototype;
116 DatePrototype* datePrototype;
117 RegExpPrototype* regExpPrototype;
118
119 RefPtr<StructureID> argumentsStructure;
120 RefPtr<StructureID> arrayStructure;
121 RefPtr<StructureID> booleanObjectStructure;
122 RefPtr<StructureID> callbackConstructorStructure;
123 RefPtr<StructureID> callbackFunctionStructure;
124 RefPtr<StructureID> callbackObjectStructure;
125 RefPtr<StructureID> dateStructure;
126 RefPtr<StructureID> emptyObjectStructure;
127 RefPtr<StructureID> errorStructure;
128 RefPtr<StructureID> functionStructure;
129 RefPtr<StructureID> numberObjectStructure;
130 RefPtr<StructureID> prototypeFunctionStructure;
131 RefPtr<StructureID> regExpMatchesArrayStructure;
132 RefPtr<StructureID> regExpStructure;
133 RefPtr<StructureID> stringObjectStructure;
134
135 SymbolTable symbolTable;
136 unsigned profileGroup;
137
138 RefPtr<JSGlobalData> globalData;
139
140 HashSet<ProgramCodeBlock*> codeBlocks;
141
142 OwnPtr<HashSet<JSObject*> > arrayVisitedElements; // Global data shared by array prototype functions.
143 };
144
145 public:
146 void* operator new(size_t, JSGlobalData*);
147
148 JSGlobalObject(JSGlobalData* globalData)
149 : JSVariableObject(globalData->nullProtoStructureID, new JSGlobalObjectData(this, this))
150 {
151 init(this);
152 }
153
154 protected:
155 JSGlobalObject(PassRefPtr<StructureID> structure, JSGlobalObjectData* data, JSObject* globalThisValue)
156 : JSVariableObject(structure, data)
157 {
158 init(globalThisValue);
159 }
160
161 public:
162 virtual ~JSGlobalObject();
163
164 virtual void mark();
165
166 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&);
167 virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&, bool& slotIsWriteable);
168 virtual void put(ExecState*, const Identifier&, JSValue*, PutPropertySlot&);
169 virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue* value, unsigned attributes);
170
171 virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunc);
172 virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunc);
173
174 // Linked list of all global objects that use the same JSGlobalData.
175 JSGlobalObject*& head() { return d()->globalData->head; }
176 JSGlobalObject* next() { return d()->next; }
177
178 // The following accessors return pristine values, even if a script
179 // replaces the global object's associated property.
180
181 RegExpConstructor* regExpConstructor() const { return d()->regExpConstructor; }
182
183 ErrorConstructor* errorConstructor() const { return d()->errorConstructor; }
184 NativeErrorConstructor* evalErrorConstructor() const { return d()->evalErrorConstructor; }
185 NativeErrorConstructor* rangeErrorConstructor() const { return d()->rangeErrorConstructor; }
186 NativeErrorConstructor* referenceErrorConstructor() const { return d()->referenceErrorConstructor; }
187 NativeErrorConstructor* syntaxErrorConstructor() const { return d()->syntaxErrorConstructor; }
188 NativeErrorConstructor* typeErrorConstructor() const { return d()->typeErrorConstructor; }
189 NativeErrorConstructor* URIErrorConstructor() const { return d()->URIErrorConstructor; }
190
191 GlobalEvalFunction* evalFunction() const { return d()->evalFunction; }
192
193 ObjectPrototype* objectPrototype() const { return d()->objectPrototype; }
194 FunctionPrototype* functionPrototype() const { return d()->functionPrototype; }
195 ArrayPrototype* arrayPrototype() const { return d()->arrayPrototype; }
196 BooleanPrototype* booleanPrototype() const { return d()->booleanPrototype; }
197 StringPrototype* stringPrototype() const { return d()->stringPrototype; }
198 NumberPrototype* numberPrototype() const { return d()->numberPrototype; }
199 DatePrototype* datePrototype() const { return d()->datePrototype; }
200 RegExpPrototype* regExpPrototype() const { return d()->regExpPrototype; }
201
202 StructureID* argumentsStructure() const { return d()->argumentsStructure.get(); }
203 StructureID* arrayStructure() const { return d()->arrayStructure.get(); }
204 StructureID* booleanObjectStructure() const { return d()->booleanObjectStructure.get(); }
205 StructureID* callbackConstructorStructure() const { return d()->callbackConstructorStructure.get(); }
206 StructureID* callbackFunctionStructure() const { return d()->callbackFunctionStructure.get(); }
207 StructureID* callbackObjectStructure() const { return d()->callbackObjectStructure.get(); }
208 StructureID* dateStructure() const { return d()->dateStructure.get(); }
209 StructureID* emptyObjectStructure() const { return d()->emptyObjectStructure.get(); }
210 StructureID* errorStructure() const { return d()->errorStructure.get(); }
211 StructureID* functionStructure() const { return d()->functionStructure.get(); }
212 StructureID* numberObjectStructure() const { return d()->numberObjectStructure.get(); }
213 StructureID* prototypeFunctionStructure() const { return d()->prototypeFunctionStructure.get(); }
214 StructureID* regExpMatchesArrayStructure() const { return d()->regExpMatchesArrayStructure.get(); }
215 StructureID* regExpStructure() const { return d()->regExpStructure.get(); }
216 StructureID* stringObjectStructure() const { return d()->stringObjectStructure.get(); }
217
218 void setProfileGroup(unsigned value) { d()->profileGroup = value; }
219 unsigned profileGroup() const { return d()->profileGroup; }
220
221 void setTimeoutTime(unsigned timeoutTime);
222 void startTimeoutCheck();
223 void stopTimeoutCheck();
224
225 Debugger* debugger() const { return d()->debugger; }
226 void setDebugger(Debugger* debugger) { d()->debugger = debugger; }
227
228 int recursion() { return d()->recursion; }
229 void incRecursion() { ++d()->recursion; }
230 void decRecursion() { --d()->recursion; }
231
232 ScopeChain& globalScopeChain() { return d()->globalScopeChain; }
233
234 virtual bool isGlobalObject() const { return true; }
235 virtual JSGlobalObject* toGlobalObject(ExecState*) const;
236
237 virtual ExecState* globalExec();
238
239 virtual bool shouldInterruptScript() const { return true; }
240
241 virtual bool allowsAccessFrom(const JSGlobalObject*) const { return true; }
242
243 virtual bool isDynamicScope() const;
244
245 HashSet<JSObject*>& arrayVisitedElements() { if (!d()->arrayVisitedElements) d()->arrayVisitedElements.set(new HashSet<JSObject*>); return *d()->arrayVisitedElements; }
246
247 HashSet<ProgramCodeBlock*>& codeBlocks() { return d()->codeBlocks; }
248
249 void copyGlobalsFrom(RegisterFile&);
250 void copyGlobalsTo(RegisterFile&);
251
252 void resetPrototype(JSValue* prototype);
253
254 JSGlobalData* globalData() { return d()->globalData.get(); }
255 JSGlobalObjectData* d() const { return static_cast<JSGlobalObjectData*>(JSVariableObject::d); }
256
257 protected:
258 struct GlobalPropertyInfo {
259 GlobalPropertyInfo(const Identifier& i, JSValue* v, unsigned a)
260 : identifier(i)
261 , value(v)
262 , attributes(a)
263 {
264 }
265
266 const Identifier identifier;
267 JSValue* value;
268 unsigned attributes;
269 };
270 void addStaticGlobals(GlobalPropertyInfo*, int count);
271
272 private:
273 // FIXME: Fold these functions into the constructor.
274 void init(JSObject* thisValue);
275 void reset(JSValue* 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 inline void JSGlobalObject::setRegisters(Register* registers, Register* registerArray, size_t count)
283 {
284 JSVariableObject::setRegisters(registers, registerArray);
285 d()->registerArraySize = count;
286 }
287
288 inline void JSGlobalObject::addStaticGlobals(GlobalPropertyInfo* globals, int count)
289 {
290 size_t oldSize = d()->registerArraySize;
291 size_t newSize = oldSize + count;
292 Register* registerArray = new Register[newSize];
293 if (d()->registerArray)
294 memcpy(registerArray + count, d()->registerArray.get(), oldSize * sizeof(Register));
295 setRegisters(registerArray + newSize, registerArray, newSize);
296
297 for (int i = 0, index = -static_cast<int>(oldSize) - 1; i < count; ++i, --index) {
298 GlobalPropertyInfo& global = globals[i];
299 ASSERT(global.attributes & DontDelete);
300 SymbolTableEntry newEntry(index, global.attributes);
301 symbolTable().add(global.identifier.ustring().rep(), newEntry);
302 registerAt(index) = global.value;
303 }
304 }
305
306 inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot)
307 {
308 if (JSVariableObject::getOwnPropertySlot(exec, propertyName, slot))
309 return true;
310 return symbolTableGet(propertyName, slot);
311 }
312
313 inline bool JSGlobalObject::getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
314 {
315 if (JSVariableObject::getOwnPropertySlotForWrite(exec, propertyName, slot, slotIsWriteable))
316 return true;
317 return symbolTableGet(propertyName, slot, slotIsWriteable);
318 }
319
320 inline JSGlobalObject* ScopeChainNode::globalObject() const
321 {
322 JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(bottom());
323 ASSERT(globalObject->isGlobalObject());
324 return globalObject;
325 }
326
327 inline JSValue* StructureID::prototypeForLookup(ExecState* exec)
328 {
329 if (typeInfo().type() == ObjectType)
330 return m_prototype;
331
332 if (typeInfo().type() == StringType)
333 return exec->lexicalGlobalObject()->stringPrototype();
334
335 ASSERT(typeInfo().type() == NumberType);
336 return exec->lexicalGlobalObject()->numberPrototype();
337 }
338
339
340} // namespace JSC
341
342#endif // JSGlobalObject_h
Note: See TracBrowser for help on using the repository browser.