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 61 using namespace WTF; 62 63 namespace JSC { 64 65 extern JSC_CONST_HASHTABLE HashTable arrayTable; 66 extern JSC_CONST_HASHTABLE HashTable jsonTable; 67 extern JSC_CONST_HASHTABLE HashTable dateTable; 68 extern JSC_CONST_HASHTABLE HashTable mathTable; 69 extern JSC_CONST_HASHTABLE HashTable numberTable; 70 extern JSC_CONST_HASHTABLE HashTable regExpTable; 71 extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable; 72 extern JSC_CONST_HASHTABLE HashTable stringTable; 73 74 void* JSGlobalData::jsArrayVPtr; 75 void* JSGlobalData::jsByteArrayVPtr; 76 void* JSGlobalData::jsStringVPtr; 77 void* JSGlobalData::jsFunctionVPtr; 78 79 void 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 105 JSGlobalData::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 156 JSGlobalData::~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 197 PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault() 198 { 199 return adoptRef(new JSGlobalData(false)); 200 } 201 202 PassRefPtr<JSGlobalData> JSGlobalData::create() 203 { 204 JSGlobalData* globalData = new JSGlobalData(false); 205 setDefaultIdentifierTable(globalData->identifierTable); 206 setCurrentIdentifierTable(globalData->identifierTable); 207 return adoptRef(globalData); 208 } 209 210 PassRefPtr<JSGlobalData> JSGlobalData::createLeaked() 211 { 212 Structure::startIgnoringLeaks(); 213 RefPtr<JSGlobalData> data = create(); 214 Structure::stopIgnoringLeaks(); 215 return data.release(); 216 } 217 218 bool JSGlobalData::sharedInstanceExists() 219 { 220 return sharedInstanceInternal(); 221 } 222 223 JSGlobalData& 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 235 JSGlobalData*& 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. 243 const 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 255 JSGlobalData::ClientData::~ClientData() 256 { 257 } 258 259 void JSGlobalData::resetDateCache() 260 { 261 cachedUTCOffset = NaN; 262 dstOffsetCache.reset(); 263 cachedDateString = UString(); 264 dateInstanceCache.reset(); 265 } 266 267 void JSGlobalData::startSampling() 268 { 269 interpreter->startSampling(); 270 } 271 272 void JSGlobalData::stopSampling() 273 { 274 interpreter->stopSampling(); 275 } 276 277 void JSGlobalData::dumpSampleData(ExecState* exec) 278 { 279 interpreter->dumpSampleData(exec); 280 } 281 282 } // namespace JSC 283