source: webkit/trunk/JavaScriptCore/runtime/JSGlobalData.cpp@ 53400

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

Reviewed by Geoffrey Garen.

https://bugs.webkit.org/show_bug.cgi?id=33057
REGRESSION(r49365): typeof(xhr.responseText) != "string" in Windows

<rdar://problem/7296920> REGRESSION: WebKit fails to start PeaceKeeper benchmark

Test: fast/js/webcore-string-comparison.html

In r49365, some code was moved from JSString.cpp to JSString.h, and as a result, WebCore
got a way to directly instantiate JSStrings over DLL borders. Since vftable for JSString was
not exported, objects created from WebCore got a different vptr, and JavaScriptCore
optimizations that relied on vptr of all JSString objects being equal failed.

  • config.h: Added a JS_EXPORTCLASS macro for exporting classes. It's currently the same as JS_EXPORTDATA, but it clearly needed a new name.
  • runtime/InitializeThreading.cpp: (JSC::initializeThreadingOnce):
  • runtime/JSGlobalData.cpp: (JSC::JSGlobalData::storeVPtrs): (JSC::JSGlobalData::JSGlobalData): (JSC::JSGlobalData::createNonDefault): (JSC::JSGlobalData::create): (JSC::JSGlobalData::sharedInstance):
  • runtime/JSGlobalData.h: Store vptrs just once, no need to repeatedly pick and copy them. This makes it possible to assert vptr correctness in object destructors (which don't have access to JSGlobalData, and even Heap::heap(this) will fail for fake objects created from storeVPtrs()).
  • runtime/JSArray.cpp: (JSC::JSArray::~JSArray): Assert that vptr is what we expect it to be. It's important to assert in destructor, because MSVC changes the vptr after constructor is invoked.
  • runtime/JSByteArray.cpp: (JSC::JSByteArray::~JSByteArray): Ditto.
  • runtime/JSByteArray.h: Ditto.
  • runtime/JSFunction.h: Ditto.
  • runtime/JSFunction.cpp: (JSC::JSFunction::~JSFunction): Ditto.
  • runtime/JSCell.h: (JSC::JSCell::setVPtr): Added a method to substitute vptr for another one.
  • runtime/JSString.h: Export JSString class together with its vftable, and tell other libraries tp import it. This is needed on platforms that have a separate JavaScriptCore dynamic library - and on Mac, we already did the export via JavaScriptCore.exp. (JSC::JSString::~JSString): Assert tha vptr is what we expect it to be. (JSC::fixupVPtr): Store a previously saved primary vftable pointer (do nothing if building JavaScriptCore itself). (JSC::jsSingleCharacterString): Call fixupVPtr in case this is call across DLL boundary. (JSC::jsSingleCharacterSubstring): Ditto. (JSC::jsNontrivialString): Ditto. (JSC::jsString): Ditto. (JSC::jsSubstring): Ditto. (JSC::jsOwnedString): Ditto.
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Export the new static JSGlobalData members that are used in WebCore via inline functions.
  • Property svn:eol-style set to native
File size: 9.3 KB
Line 
1/*
2 * Copyright (C) 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#include "config.h"
30#include "JSGlobalData.h"
31
32#include "ArgList.h"
33#include "Collector.h"
34#include "CommonIdentifiers.h"
35#include "FunctionConstructor.h"
36#include "GetterSetter.h"
37#include "Interpreter.h"
38#include "JSActivation.h"
39#include "JSAPIValueWrapper.h"
40#include "JSArray.h"
41#include "JSByteArray.h"
42#include "JSClassRef.h"
43#include "JSFunction.h"
44#include "JSLock.h"
45#include "JSNotAnObject.h"
46#include "JSPropertyNameIterator.h"
47#include "JSStaticScopeObject.h"
48#include "Lexer.h"
49#include "Lookup.h"
50#include "Nodes.h"
51#include "Parser.h"
52
53#if ENABLE(JSC_MULTIPLE_THREADS)
54#include <wtf/Threading.h>
55#endif
56
57#if PLATFORM(MAC)
58#include "ProfilerServer.h"
59#endif
60
61using namespace WTF;
62
63namespace JSC {
64
65extern JSC_CONST_HASHTABLE HashTable arrayTable;
66extern JSC_CONST_HASHTABLE HashTable jsonTable;
67extern JSC_CONST_HASHTABLE HashTable dateTable;
68extern JSC_CONST_HASHTABLE HashTable mathTable;
69extern JSC_CONST_HASHTABLE HashTable numberTable;
70extern JSC_CONST_HASHTABLE HashTable regExpTable;
71extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
72extern JSC_CONST_HASHTABLE HashTable stringTable;
73
74void* JSGlobalData::jsArrayVPtr;
75void* JSGlobalData::jsByteArrayVPtr;
76void* JSGlobalData::jsStringVPtr;
77void* JSGlobalData::jsFunctionVPtr;
78
79void JSGlobalData::storeVPtrs()
80{
81 CollectorCell cell;
82 void* storage = &cell;
83
84 COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell);
85 JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull()));
86 JSGlobalData::jsArrayVPtr = jsArray->vptr();
87 jsArray->~JSCell();
88
89 COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell);
90 JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
91 JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
92 jsByteArray->~JSCell();
93
94 COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell);
95 JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
96 JSGlobalData::jsStringVPtr = jsString->vptr();
97 jsString->~JSCell();
98
99 COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell);
100 JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
101 JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
102 jsFunction->~JSCell();
103}
104
105JSGlobalData::JSGlobalData(bool isShared)
106 : isSharedInstance(isShared)
107 , clientData(0)
108 , arrayTable(fastNew<HashTable>(JSC::arrayTable))
109 , dateTable(fastNew<HashTable>(JSC::dateTable))
110 , jsonTable(fastNew<HashTable>(JSC::jsonTable))
111 , mathTable(fastNew<HashTable>(JSC::mathTable))
112 , numberTable(fastNew<HashTable>(JSC::numberTable))
113 , regExpTable(fastNew<HashTable>(JSC::regExpTable))
114 , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
115 , stringTable(fastNew<HashTable>(JSC::stringTable))
116 , activationStructure(JSActivation::createStructure(jsNull()))
117 , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull()))
118 , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
119 , stringStructure(JSString::createStructure(jsNull()))
120 , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
121 , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
122 , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
123 , getterSetterStructure(GetterSetter::createStructure(jsNull()))
124 , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
125 , dummyMarkableCellStructure(JSCell::createDummyStructure())
126#if USE(JSVALUE32)
127 , numberStructure(JSNumberCell::createStructure(jsNull()))
128#endif
129 , identifierTable(createIdentifierTable())
130 , propertyNames(new CommonIdentifiers(this))
131 , emptyList(new MarkedArgumentBuffer)
132 , lexer(new Lexer(this))
133 , parser(new Parser)
134 , interpreter(new Interpreter)
135#if ENABLE(JIT)
136 , jitStubs(this)
137#endif
138 , heap(this)
139 , initializingLazyNumericCompareFunction(false)
140 , head(0)
141 , dynamicGlobalObject(0)
142 , functionCodeBlockBeingReparsed(0)
143 , firstStringifierToMark(0)
144 , markStack(jsArrayVPtr)
145 , cachedUTCOffset(NaN)
146 , weakRandom(static_cast<int>(currentTime()))
147#ifndef NDEBUG
148 , mainThreadOnly(false)
149#endif
150{
151#if PLATFORM(MAC)
152 startProfilerServerIfNeeded();
153#endif
154}
155
156JSGlobalData::~JSGlobalData()
157{
158 // By the time this is destroyed, heap.destroy() must already have been called.
159
160 delete interpreter;
161#ifndef NDEBUG
162 // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
163 interpreter = 0;
164#endif
165
166 arrayTable->deleteTable();
167 dateTable->deleteTable();
168 jsonTable->deleteTable();
169 mathTable->deleteTable();
170 numberTable->deleteTable();
171 regExpTable->deleteTable();
172 regExpConstructorTable->deleteTable();
173 stringTable->deleteTable();
174
175 fastDelete(const_cast<HashTable*>(arrayTable));
176 fastDelete(const_cast<HashTable*>(dateTable));
177 fastDelete(const_cast<HashTable*>(jsonTable));
178 fastDelete(const_cast<HashTable*>(mathTable));
179 fastDelete(const_cast<HashTable*>(numberTable));
180 fastDelete(const_cast<HashTable*>(regExpTable));
181 fastDelete(const_cast<HashTable*>(regExpConstructorTable));
182 fastDelete(const_cast<HashTable*>(stringTable));
183
184 delete parser;
185 delete lexer;
186
187 deleteAllValues(opaqueJSClassData);
188
189 delete emptyList;
190
191 delete propertyNames;
192 deleteIdentifierTable(identifierTable);
193
194 delete clientData;
195}
196
197PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault()
198{
199 return adoptRef(new JSGlobalData(false));
200}
201
202PassRefPtr<JSGlobalData> JSGlobalData::create()
203{
204 JSGlobalData* globalData = new JSGlobalData(false);
205 setDefaultIdentifierTable(globalData->identifierTable);
206 setCurrentIdentifierTable(globalData->identifierTable);
207 return adoptRef(globalData);
208}
209
210PassRefPtr<JSGlobalData> JSGlobalData::createLeaked()
211{
212 Structure::startIgnoringLeaks();
213 RefPtr<JSGlobalData> data = create();
214 Structure::stopIgnoringLeaks();
215 return data.release();
216}
217
218bool JSGlobalData::sharedInstanceExists()
219{
220 return sharedInstanceInternal();
221}
222
223JSGlobalData& JSGlobalData::sharedInstance()
224{
225 JSGlobalData*& instance = sharedInstanceInternal();
226 if (!instance) {
227 instance = new JSGlobalData(true);
228#if ENABLE(JSC_MULTIPLE_THREADS)
229 instance->makeUsableFromMultipleThreads();
230#endif
231 }
232 return *instance;
233}
234
235JSGlobalData*& JSGlobalData::sharedInstanceInternal()
236{
237 ASSERT(JSLock::currentThreadIsHoldingLock());
238 static JSGlobalData* sharedInstance;
239 return sharedInstance;
240}
241
242// FIXME: We can also detect forms like v1 < v2 ? -1 : 0, reverse comparison, etc.
243const Vector<Instruction>& JSGlobalData::numericCompareFunction(ExecState* exec)
244{
245 if (!lazyNumericCompareFunction.size() && !initializingLazyNumericCompareFunction) {
246 initializingLazyNumericCompareFunction = true;
247 RefPtr<FunctionExecutable> function = FunctionExecutable::fromGlobalCode(Identifier(exec, "numericCompare"), exec, 0, makeSource(UString("(function (v1, v2) { return v1 - v2; })")), 0, 0);
248 lazyNumericCompareFunction = function->bytecode(exec, exec->scopeChain()).instructions();
249 initializingLazyNumericCompareFunction = false;
250 }
251
252 return lazyNumericCompareFunction;
253}
254
255JSGlobalData::ClientData::~ClientData()
256{
257}
258
259void JSGlobalData::resetDateCache()
260{
261 cachedUTCOffset = NaN;
262 dstOffsetCache.reset();
263 cachedDateString = UString();
264 dateInstanceCache.reset();
265}
266
267void JSGlobalData::startSampling()
268{
269 interpreter->startSampling();
270}
271
272void JSGlobalData::stopSampling()
273{
274 interpreter->stopSampling();
275}
276
277void JSGlobalData::dumpSampleData(ExecState* exec)
278{
279 interpreter->dumpSampleData(exec);
280}
281
282} // namespace JSC
Note: See TracBrowser for help on using the repository browser.