source: webkit/trunk/JavaScriptCore/kjs/JSVariableObject.h@ 34854

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

JavaScriptCore:

2008-06-27 Geoffrey Garen <[email protected]>

Reviewed by Oliver Hunt.


One RegisterFile to rule them all!


SunSpider reports a 0.2% speedup.

This patch removes the RegisterFileStack abstraction and replaces it with
a single register file that


(a) allocates a fixed storage area, including a fixed area for global
vars, so that no operation may cause the register file to reallocate


and

(b) swaps between global storage areas when executing code in different
global objects.


This patch also changes the layout of the register file so that all call
frames, including call frames for global code, get a header. This is
required to support re-entrant global code. It also just makes things simpler.


  • VM/CodeGenerator.cpp: (KJS::CodeGenerator::addGlobalVar): New function. Differs from addVar in that


(a) global vars don't contribute to a CodeBlock's numLocals count, since
global storage is fixed and allocated at startup


and


(b) references to global vars get shifted to elide intermediate stack
between "r" and the global storage area.


  • VM/Machine.cpp: (KJS::Machine::dumpRegisters): Updated this function to match the new register file layout, and added the ability to dump exact identifiers for the different parts of a call frame.


(KJS::Machine::unwindCallFrame): Updated this function to match the new
register file layout.


(KJS::Machine::execute): Updated this function to initialize a call frame
header for global code, and to swap global storage areas when switching
to execution in a new global object.


(KJS::Machine::privateExecute): Got rid of "safeForReentry" and re-reading
of registerBase because the register file is always safe for reentry now,
and registerBase never changes.


  • VM/Machine.h: Moved the call frame header enum from Machine to RegisterFile, to resolve a header dependency problem (a good sign that the enum belonged in RegisterFile all along!)
  • VM/RegisterFile.cpp:
  • VM/RegisterFile.h: Changed RegisterFile to mmap a fixed size register area. This allows us to avoid re-allocting the register file later on. Instead, we rely on the OS to allocate physical pages to the register file as necessary.
  • VM/RegisterFileStack.cpp: Removed. Tada!
  • VM/RegisterFileStack.h: Removed. Tada!
  • kjs/DebuggerCallFrame.cpp: Updated this class to match the new register file layout, greatly simplifying it in the process.
  • kjs/JSActivation.h:
  • kjs/JSActivation.cpp: Moved some of this logic up to JSVariableObject, since the global object now needs to be able to tear off its registers just like the activation object.
  • kjs/JSFunction.cpp: No need to fiddle with the register file anymore.
  • kjs/JSGlobalObject.h:
  • kjs/JSGlobalObject.cpp: Updated JSGlobalObject to support moving its global storage area into and out of the register file.
  • kjs/PropertySlot.cpp: No need to fiddle with the register file anymore.
  • kjs/collector.cpp: Renamed markStackObjectConservatively to markConservatively, since we don't just mark stack objects this way.


Also, added code to mark the machine's register file.

  • kjs/config.h: Moved some platforms #defines from here...
  • wtf/Platform.h: ...to here, to support mmap/VirtualAlloc detection in RegisterFile.h.

LayoutTests:

2008-06-26 Geoffrey Garen <[email protected]>

Reviewed by Oliver Hunt.


Added a test for what happens when a script exceeds the limit on declared
global variables.

  • fast/js/global-var-limit-expected.txt: Added.
  • fast/js/global-var-limit.html: Added.
  • fast/js/global-recursion-on-full-stack-expected.txt: Updated for new (slightly more correct) behavior. Since the stack overflow happens in the middle of a try/catch block, it should be caught, instead of logged to the console.
  • Property svn:eol-style set to native
File size: 6.1 KB
Line 
1/*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef JSVariableObject_h
30#define JSVariableObject_h
31
32#include "Register.h"
33#include "SymbolTable.h"
34#include "UnusedParam.h"
35#include "JSObject.h"
36#include <wtf/UnusedParam.h>
37
38namespace KJS {
39
40 class Register;
41
42 class JSVariableObject : public JSObject {
43 public:
44 SymbolTable& symbolTable() const { return *d->symbolTable; }
45
46 virtual void putWithAttributes(ExecState*, const Identifier&, JSValue*, unsigned attributes) = 0;
47
48 virtual bool deleteProperty(ExecState*, const Identifier&);
49 virtual void getPropertyNames(ExecState*, PropertyNameArray&);
50 virtual void mark();
51
52 virtual bool isVariableObject() const;
53 virtual bool isDynamicScope() const = 0;
54
55 virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const;
56
57 JSValue*& valueAt(int index) const { return registers()[index].u.jsValue; }
58
59 protected:
60 // Subclasses of JSVariableObject can subclass this struct to add data
61 // without increasing their own size (since there's a hard limit on the
62 // size of a JSCell).
63 struct JSVariableObjectData {
64 JSVariableObjectData(SymbolTable* symbolTable_, Register** registerBase_, int registerOffset_)
65 : symbolTable(symbolTable_)
66 , registerBase(registerBase_)
67 , registerOffset(registerOffset_)
68 , registerArray(0)
69 {
70 ASSERT(symbolTable_);
71 }
72
73 ~JSVariableObjectData()
74 {
75 delete registerArray;
76 }
77
78 SymbolTable* symbolTable; // Maps name -> offset from "r" in register file.
79
80 Register** registerBase; // Location where a pointer to the base of the register file is stored.
81 int registerOffset; // Offset of "r", the register past the end of local storage.
82
83 Register* registerArray; // Independent copy of registers that were once stored in the register file.
84 };
85
86 JSVariableObject(JSVariableObjectData* data)
87 : d(data) // Subclass owns this pointer.
88 {
89 }
90
91 JSVariableObject(JSValue* proto, JSVariableObjectData* data)
92 : JSObject(proto)
93 , d(data) // Subclass owns this pointer.
94 {
95 }
96
97 Register** registerBase() const { return d->registerBase; }
98 Register* registers() const { return *registerBase() + d->registerOffset; }
99
100 void copyRegisterArray(Register* src, size_t count);
101 void setRegisterArray(Register* registerArray, size_t count);
102
103 bool symbolTableGet(const Identifier&, PropertySlot&);
104 bool symbolTableGet(const Identifier&, PropertySlot&, bool& slotIsWriteable);
105 bool symbolTablePut(const Identifier&, JSValue*);
106 bool symbolTablePutWithAttributes(const Identifier&, JSValue*, unsigned attributes);
107
108 JSVariableObjectData* d;
109 };
110
111 inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot)
112 {
113 SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
114 if (!entry.isNull()) {
115 slot.setValueSlot(&valueAt(entry.getIndex()));
116 return true;
117 }
118 return false;
119 }
120
121 inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot, bool& slotIsWriteable)
122 {
123 SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
124 if (!entry.isNull()) {
125 slot.setValueSlot(&valueAt(entry.getIndex()));
126 slotIsWriteable = !entry.isReadOnly();
127 return true;
128 }
129 return false;
130 }
131
132 inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue* value)
133 {
134 SymbolTableEntry entry = symbolTable().inlineGet(propertyName.ustring().rep());
135 if (entry.isNull())
136 return false;
137 if (entry.isReadOnly())
138 return true;
139 valueAt(entry.getIndex()) = value;
140 return true;
141 }
142
143 inline bool JSVariableObject::symbolTablePutWithAttributes(const Identifier& propertyName, JSValue* value, unsigned attributes)
144 {
145 SymbolTable::iterator iter = symbolTable().find(propertyName.ustring().rep());
146 if (iter == symbolTable().end())
147 return false;
148 SymbolTableEntry& entry = iter->second;
149 ASSERT(!entry.isNull());
150 entry.setAttributes(attributes);
151 valueAt(entry.getIndex()) = value;
152 return true;
153 }
154
155} // namespace KJS
156
157#endif // JSVariableObject_h
Note: See TracBrowser for help on using the repository browser.