| 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(prototype: 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(prototype: 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(proto: jsNull())) | 
| 117 |     , interruptedExecutionErrorStructure(JSObject::createStructure(prototype: jsNull())) | 
| 118 |     , staticScopeStructure(JSStaticScopeObject::createStructure(proto: jsNull())) | 
| 119 |     , stringStructure(JSString::createStructure(proto: jsNull())) | 
| 120 |     , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(prototype: jsNull())) | 
| 121 |     , notAnObjectStructure(JSNotAnObject::createStructure(prototype: jsNull())) | 
| 122 |     , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(prototype: jsNull())) | 
| 123 |     , getterSetterStructure(GetterSetter::createStructure(prototype: jsNull())) | 
| 124 |     , apiWrapperStructure(JSAPIValueWrapper::createStructure(prototype: 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 |     , timeoutChecker(new TimeoutChecker) | 
| 139 |     , heap(this) | 
| 140 |     , initializingLazyNumericCompareFunction(false) | 
| 141 |     , head(0) | 
| 142 |     , dynamicGlobalObject(0) | 
| 143 |     , functionCodeBlockBeingReparsed(0) | 
| 144 |     , firstStringifierToMark(0) | 
| 145 |     , markStack(jsArrayVPtr) | 
| 146 | #ifndef NDEBUG | 
| 147 |     , mainThreadOnly(false) | 
| 148 | #endif | 
| 149 | { | 
| 150 | #if PLATFORM(MAC) | 
| 151 |     startProfilerServerIfNeeded(); | 
| 152 | #endif | 
| 153 | } | 
| 154 |  | 
| 155 | JSGlobalData::~JSGlobalData() | 
| 156 | { | 
| 157 |     // By the time this is destroyed, heap.destroy() must already have been called. | 
| 158 |  | 
| 159 |     delete interpreter; | 
| 160 | #ifndef NDEBUG | 
| 161 |     // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance. | 
| 162 |     interpreter = 0; | 
| 163 | #endif | 
| 164 |  | 
| 165 |     arrayTable->deleteTable(); | 
| 166 |     dateTable->deleteTable(); | 
| 167 |     jsonTable->deleteTable(); | 
| 168 |     mathTable->deleteTable(); | 
| 169 |     numberTable->deleteTable(); | 
| 170 |     regExpTable->deleteTable(); | 
| 171 |     regExpConstructorTable->deleteTable(); | 
| 172 |     stringTable->deleteTable(); | 
| 173 |  | 
| 174 |     fastDelete(p: const_cast<HashTable*>(arrayTable)); | 
| 175 |     fastDelete(p: const_cast<HashTable*>(dateTable)); | 
| 176 |     fastDelete(p: const_cast<HashTable*>(jsonTable)); | 
| 177 |     fastDelete(p: const_cast<HashTable*>(mathTable)); | 
| 178 |     fastDelete(p: const_cast<HashTable*>(numberTable)); | 
| 179 |     fastDelete(p: const_cast<HashTable*>(regExpTable)); | 
| 180 |     fastDelete(p: const_cast<HashTable*>(regExpConstructorTable)); | 
| 181 |     fastDelete(p: const_cast<HashTable*>(stringTable)); | 
| 182 |  | 
| 183 |     delete parser; | 
| 184 |     delete lexer; | 
| 185 |     delete timeoutChecker; | 
| 186 |  | 
| 187 |     deleteAllValues(collection: 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(p: 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(p: 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(source: UString("(function (v1, v2) { return v1 - v2; })" )), errLine: 0, errMsg: 0); | 
| 248 |         lazyNumericCompareFunction = function->bytecode(exec, scopeChainNode: 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 |     localTimeOffsetCache.reset(); | 
| 262 |     cachedDateString = UString(); | 
| 263 |     dateInstanceCache.reset(); | 
| 264 | } | 
| 265 |  | 
| 266 | void JSGlobalData::startSampling() | 
| 267 | { | 
| 268 |     interpreter->startSampling(); | 
| 269 | } | 
| 270 |  | 
| 271 | void JSGlobalData::stopSampling() | 
| 272 | { | 
| 273 |     interpreter->stopSampling(); | 
| 274 | } | 
| 275 |  | 
| 276 | void JSGlobalData::dumpSampleData(ExecState* exec) | 
| 277 | { | 
| 278 |     interpreter->dumpSampleData(exec); | 
| 279 | } | 
| 280 |  | 
| 281 | } // namespace JSC | 
| 282 |  |