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

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

Fixed a crash seen on the GTK 64bit buildbot.

Reviewed by Oliver Hunt.

When JSArray is allocated for the vptr stealing hack, it's not allocated
in the heap, so the JSArray constructor can't safely call Heap::heap().

Since this was subtle enough to confuse smart people, I've changed JSArray
to have an explicit vptr stealing constructor.

(JSC::JSArray::JSArray):

  • runtime/JSArray.h:

(JSC::JSArray::):

  • runtime/JSGlobalData.cpp:

(JSC::JSGlobalData::storeVPtrs):

  • Property svn:eol-style set to native
File size: 10.1 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#include "RegExpCache.h"
53#include <wtf/WTFThreadData.h>
54
55#if ENABLE(JSC_MULTIPLE_THREADS)
56#include <wtf/Threading.h>
57#endif
58
59#if PLATFORM(MAC)
60#include "ProfilerServer.h"
61#include <CoreFoundation/CoreFoundation.h>
62#endif
63
64using namespace WTF;
65
66namespace JSC {
67
68extern JSC_CONST_HASHTABLE HashTable arrayTable;
69extern JSC_CONST_HASHTABLE HashTable jsonTable;
70extern JSC_CONST_HASHTABLE HashTable dateTable;
71extern JSC_CONST_HASHTABLE HashTable mathTable;
72extern JSC_CONST_HASHTABLE HashTable numberTable;
73extern JSC_CONST_HASHTABLE HashTable regExpTable;
74extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable;
75extern JSC_CONST_HASHTABLE HashTable stringTable;
76
77void* JSGlobalData::jsArrayVPtr;
78void* JSGlobalData::jsByteArrayVPtr;
79void* JSGlobalData::jsStringVPtr;
80void* JSGlobalData::jsFunctionVPtr;
81
82void JSGlobalData::storeVPtrs()
83{
84 CollectorCell cell;
85 void* storage = &cell;
86
87 COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell);
88 JSCell* jsArray = new (storage) JSArray(JSArray::VPtrStealingHack);
89 JSGlobalData::jsArrayVPtr = jsArray->vptr();
90 jsArray->~JSCell();
91
92 COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell);
93 JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack);
94 JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr();
95 jsByteArray->~JSCell();
96
97 COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell);
98 JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack);
99 JSGlobalData::jsStringVPtr = jsString->vptr();
100 jsString->~JSCell();
101
102 COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell);
103 JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull()));
104 JSGlobalData::jsFunctionVPtr = jsFunction->vptr();
105 jsFunction->~JSCell();
106}
107
108JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType)
109 : globalDataType(globalDataType)
110 , clientData(0)
111 , arrayTable(fastNew<HashTable>(JSC::arrayTable))
112 , dateTable(fastNew<HashTable>(JSC::dateTable))
113 , jsonTable(fastNew<HashTable>(JSC::jsonTable))
114 , mathTable(fastNew<HashTable>(JSC::mathTable))
115 , numberTable(fastNew<HashTable>(JSC::numberTable))
116 , regExpTable(fastNew<HashTable>(JSC::regExpTable))
117 , regExpConstructorTable(fastNew<HashTable>(JSC::regExpConstructorTable))
118 , stringTable(fastNew<HashTable>(JSC::stringTable))
119 , activationStructure(JSActivation::createStructure(jsNull()))
120 , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull()))
121 , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull()))
122 , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull()))
123 , stringStructure(JSString::createStructure(jsNull()))
124 , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull()))
125 , notAnObjectStructure(JSNotAnObject::createStructure(jsNull()))
126 , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull()))
127 , getterSetterStructure(GetterSetter::createStructure(jsNull()))
128 , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull()))
129 , dummyMarkableCellStructure(JSCell::createDummyStructure())
130#if USE(JSVALUE32)
131 , numberStructure(JSNumberCell::createStructure(jsNull()))
132#endif
133 , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable())
134 , propertyNames(new CommonIdentifiers(this))
135 , emptyList(new MarkedArgumentBuffer)
136 , lexer(new Lexer(this))
137 , parser(new Parser)
138 , interpreter(new Interpreter)
139 , heap(this)
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 , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth)
148 , m_regExpCache(new RegExpCache(this))
149#ifndef NDEBUG
150 , exclusiveThread(0)
151#endif
152{
153#if PLATFORM(MAC)
154 startProfilerServerIfNeeded();
155#endif
156#if ENABLE(JIT) && ENABLE(INTERPRETER)
157#if PLATFORM(CF)
158 CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman);
159 CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication);
160 if (canUseJIT) {
161 m_canUseJIT = kCFBooleanTrue == canUseJIT;
162 CFRelease(canUseJIT);
163 } else
164 m_canUseJIT = !getenv("JavaScriptCoreUseJIT");
165 CFRelease(canUseJITKey);
166#elif OS(UNIX)
167 m_canUseJIT = !getenv("JavaScriptCoreUseJIT");
168#else
169 m_canUseJIT = true;
170#endif
171#endif
172#if ENABLE(JIT)
173#if ENABLE(INTERPRETER)
174 if (m_canUseJIT)
175 m_canUseJIT = executableAllocator.isValid();
176#endif
177 jitStubs = new JITThunks(this);
178#endif
179}
180
181JSGlobalData::~JSGlobalData()
182{
183 // By the time this is destroyed, heap.destroy() must already have been called.
184
185 delete interpreter;
186#ifndef NDEBUG
187 // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance.
188 interpreter = 0;
189#endif
190
191 arrayTable->deleteTable();
192 dateTable->deleteTable();
193 jsonTable->deleteTable();
194 mathTable->deleteTable();
195 numberTable->deleteTable();
196 regExpTable->deleteTable();
197 regExpConstructorTable->deleteTable();
198 stringTable->deleteTable();
199
200 fastDelete(const_cast<HashTable*>(arrayTable));
201 fastDelete(const_cast<HashTable*>(dateTable));
202 fastDelete(const_cast<HashTable*>(jsonTable));
203 fastDelete(const_cast<HashTable*>(mathTable));
204 fastDelete(const_cast<HashTable*>(numberTable));
205 fastDelete(const_cast<HashTable*>(regExpTable));
206 fastDelete(const_cast<HashTable*>(regExpConstructorTable));
207 fastDelete(const_cast<HashTable*>(stringTable));
208
209 delete parser;
210 delete lexer;
211
212 deleteAllValues(opaqueJSClassData);
213
214 delete emptyList;
215
216 delete propertyNames;
217 if (globalDataType != Default)
218 deleteIdentifierTable(identifierTable);
219
220 delete clientData;
221 delete m_regExpCache;
222}
223
224PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type)
225{
226 return adoptRef(new JSGlobalData(APIContextGroup, type));
227}
228
229PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type)
230{
231 return adoptRef(new JSGlobalData(Default, type));
232}
233
234PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type)
235{
236 Structure::startIgnoringLeaks();
237 RefPtr<JSGlobalData> data = create(type);
238 Structure::stopIgnoringLeaks();
239 return data.release();
240}
241
242bool JSGlobalData::sharedInstanceExists()
243{
244 return sharedInstanceInternal();
245}
246
247JSGlobalData& JSGlobalData::sharedInstance()
248{
249 JSGlobalData*& instance = sharedInstanceInternal();
250 if (!instance) {
251 instance = adoptRef(new JSGlobalData(APIShared, ThreadStackTypeSmall)).leakRef();
252#if ENABLE(JSC_MULTIPLE_THREADS)
253 instance->makeUsableFromMultipleThreads();
254#endif
255 }
256 return *instance;
257}
258
259JSGlobalData*& JSGlobalData::sharedInstanceInternal()
260{
261 ASSERT(JSLock::currentThreadIsHoldingLock());
262 static JSGlobalData* sharedInstance;
263 return sharedInstance;
264}
265
266#if ENABLE(JIT)
267PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function)
268{
269 return jitStubs->hostFunctionStub(this, function);
270}
271PassRefPtr<NativeExecutable> JSGlobalData::getHostFunction(NativeFunction function, ThunkGenerator generator)
272{
273 return jitStubs->hostFunctionStub(this, function, generator);
274}
275#endif
276
277JSGlobalData::ClientData::~ClientData()
278{
279}
280
281void JSGlobalData::resetDateCache()
282{
283 cachedUTCOffset = NaN;
284 dstOffsetCache.reset();
285 cachedDateString = UString();
286 dateInstanceCache.reset();
287}
288
289void JSGlobalData::startSampling()
290{
291 interpreter->startSampling();
292}
293
294void JSGlobalData::stopSampling()
295{
296 interpreter->stopSampling();
297}
298
299void JSGlobalData::dumpSampleData(ExecState* exec)
300{
301 interpreter->dumpSampleData(exec);
302}
303
304} // namespace JSC
Note: See TracBrowser for help on using the repository browser.