diff options
author | Ben Murdoch <benm@google.com> | 2010-05-11 18:35:50 +0100 |
---|---|---|
committer | Ben Murdoch <benm@google.com> | 2010-05-14 10:23:05 +0100 |
commit | 21939df44de1705786c545cd1bf519d47250322d (patch) | |
tree | ef56c310f5c0cdc379c2abb2e212308a3281ce20 /JavaScriptCore/runtime | |
parent | 4ff1d8891d520763f17675827154340c7c740f90 (diff) | |
download | external_webkit-21939df44de1705786c545cd1bf519d47250322d.zip external_webkit-21939df44de1705786c545cd1bf519d47250322d.tar.gz external_webkit-21939df44de1705786c545cd1bf519d47250322d.tar.bz2 |
Merge Webkit at r58956: Initial merge by Git.
Change-Id: I1d9fb60ea2c3f2ddc04c17a871acdb39353be228
Diffstat (limited to 'JavaScriptCore/runtime')
23 files changed, 268 insertions, 57 deletions
diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index bd14e64..4c4eb48 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -268,7 +268,24 @@ JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thi separator = args.at(0).toString(exec); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); - for (unsigned k = 0; k < length; k++) { + unsigned k = 0; + if (isJSArray(&exec->globalData(), thisObj)) { + JSArray* array = asArray(thisObj); + for (; k < length; k++) { + if (!array->canGetIndex(k)) + break; + if (k >= 1) { + if (separator.isNull()) + strBuffer.append(','); + else + strBuffer.append(separator); + } + JSValue element = array->getIndex(k); + if (!element.isUndefinedOrNull()) + strBuffer.append(element.toString(exec)); + } + } + for (; k < length; k++) { if (k >= 1) { if (separator.isNull()) strBuffer.append(','); diff --git a/JavaScriptCore/runtime/CachedTranscendentalFunction.h b/JavaScriptCore/runtime/CachedTranscendentalFunction.h new file mode 100644 index 0000000..04f7f62 --- /dev/null +++ b/JavaScriptCore/runtime/CachedTranscendentalFunction.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CachedTranscendentalFunction_h +#define CachedTranscendentalFunction_h + +#include "JSValue.h" + +namespace JSC { + +extern const double NaN; + +typedef double (*TranscendentalFunctionPtr)(double); + +// CachedTranscendentalFunction provides a generic mechanism to cache results +// for pure functions with the signature "double func(double)", and where NaN +// maps to NaN. +template<TranscendentalFunctionPtr orignalFunction> +class CachedTranscendentalFunction { + struct CacheEntry { + double operand; + double result; + }; + +public: + CachedTranscendentalFunction() + : m_cache(0) + { + } + + ~CachedTranscendentalFunction() + { + if (m_cache) + fastFree(m_cache); + } + + JSValue operator() (ExecState* exec, double operand) + { + if (UNLIKELY(!m_cache)) + initialize(); + CacheEntry* entry = &m_cache[hash(operand)]; + + if (entry->operand == operand) + return jsDoubleNumber(exec, entry->result); + double result = orignalFunction(operand); + entry->operand = operand; + entry->result = result; + return jsDoubleNumber(exec, result); + } + +private: + void initialize() + { + // Lazily allocate the table, populate with NaN->NaN mapping. + m_cache = static_cast<CacheEntry*>(fastMalloc(s_cacheSize * sizeof(CacheEntry))); + for (unsigned x = 0; x < s_cacheSize; ++x) { + m_cache[x].operand = NaN; + m_cache[x].result = NaN; + } + } + + static unsigned hash(double d) + { + union doubleAndUInt64 { + double d; + uint32_t is[2]; + } u; + u.d = d; + + unsigned x = u.is[0] ^ u.is[1]; + x = (x >> 20) ^ (x >> 8); + return x & (s_cacheSize - 1); + } + + static const unsigned s_cacheSize = 0x1000; + CacheEntry* m_cache; +}; + +} + +#endif // CachedTranscendentalFunction_h diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp index 9b72755..05f2bb5 100644 --- a/JavaScriptCore/runtime/Collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -449,7 +449,7 @@ void Heap::shrinkBlocks(size_t neededBlocks) } #if OS(WINCE) -void* g_stackBase = 0; +JS_EXPORTDATA void* g_stackBase = 0; inline bool isPageWritable(void* page) { @@ -558,6 +558,8 @@ static inline void* currentThreadStackBase() PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); return reinterpret_cast<void*>(pTib->StackBase); #elif OS(QNX) + AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); + MutexLocker locker(mutex); return currentThreadStackBaseQNX(); #elif OS(SOLARIS) stack_t s; @@ -569,19 +571,17 @@ static inline void* currentThreadStackBase() pthread_stackseg_np(thread, &stack); return stack.ss_sp; #elif OS(SYMBIAN) - static void* stackBase = 0; - if (stackBase == 0) { - TThreadStackInfo info; - RThread thread; - thread.StackInfo(info); - stackBase = (void*)info.iBase; - } - return (void*)stackBase; + TThreadStackInfo info; + RThread thread; + thread.StackInfo(info); + return (void*)info.iBase; #elif OS(HAIKU) thread_info threadInfo; get_thread_info(find_thread(NULL), &threadInfo); return threadInfo.stack_end; #elif OS(UNIX) + AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); + MutexLocker locker(mutex); static void* stackBase = 0; static size_t stackSize = 0; static pthread_t stackThread; @@ -604,6 +604,8 @@ static inline void* currentThreadStackBase() } return static_cast<char*>(stackBase) + stackSize; #elif OS(WINCE) + AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); + MutexLocker locker(mutex); if (g_stackBase) return g_stackBase; else { @@ -972,7 +974,7 @@ void Heap::markStackObjectsConservatively(MarkStack& markStack) void Heap::protect(JSValue k) { ASSERT(k); - ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance); + ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); if (!k.isCell()) return; @@ -983,7 +985,7 @@ void Heap::protect(JSValue k) bool Heap::unprotect(JSValue k) { ASSERT(k); - ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance); + ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance()); if (!k.isCell()) return false; @@ -1064,7 +1066,7 @@ void Heap::sweep() void Heap::markRoots() { #ifndef NDEBUG - if (m_globalData->isSharedInstance) { + if (m_globalData->isSharedInstance()) { ASSERT(JSLock::lockCount() > 0); ASSERT(JSLock::currentThreadIsHoldingLock()); } diff --git a/JavaScriptCore/runtime/Executable.h b/JavaScriptCore/runtime/Executable.h index f74abe9..ac691e4 100644 --- a/JavaScriptCore/runtime/Executable.h +++ b/JavaScriptCore/runtime/Executable.h @@ -85,7 +85,12 @@ namespace JSC { NativeExecutable(ExecState* exec) : ExecutableBase(NUM_PARAMETERS_IS_HOST) { - m_jitCode = JITCode(JITCode::HostFunction(exec->globalData().jitStubs.ctiNativeCallThunk())); + m_jitCode = exec->globalData().jitStubs.ctiNativeCallThunk()->m_jitCode; + } + NativeExecutable(JITCode thunk) + : ExecutableBase(NUM_PARAMETERS_IS_HOST) + { + m_jitCode = thunk; } ~NativeExecutable(); diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h index 91c960c..ece8753 100644 --- a/JavaScriptCore/runtime/JSActivation.h +++ b/JavaScriptCore/runtime/JSActivation.h @@ -31,7 +31,6 @@ #include "CodeBlock.h" #include "JSVariableObject.h" -#include "RegisterFile.h" #include "SymbolTable.h" #include "Nodes.h" diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp index cba6795..5b73642 100644 --- a/JavaScriptCore/runtime/JSFunction.cpp +++ b/JavaScriptCore/runtime/JSFunction.cpp @@ -56,10 +56,27 @@ JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure) { } +JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeExecutable* thunk, NativeFunction func) + : Base(&exec->globalData(), structure, name) +#if ENABLE(JIT) + , m_executable(thunk) +#endif +{ +#if ENABLE(JIT) + setNativeFunction(func); + putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum); +#else + UNUSED_PARAM(thunk); + UNUSED_PARAM(length); + UNUSED_PARAM(func); + ASSERT_NOT_REACHED(); +#endif +} + JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func) : Base(&exec->globalData(), structure, name) #if ENABLE(JIT) - , m_executable(adoptRef(new NativeExecutable(exec))) + , m_executable(exec->globalData().jitStubs.ctiNativeCallThunk()) #endif { #if ENABLE(JIT) diff --git a/JavaScriptCore/runtime/JSFunction.h b/JavaScriptCore/runtime/JSFunction.h index afa24a8..301b908 100644 --- a/JavaScriptCore/runtime/JSFunction.h +++ b/JavaScriptCore/runtime/JSFunction.h @@ -33,6 +33,7 @@ namespace JSC { class FunctionPrototype; class JSActivation; class JSGlobalObject; + class NativeExecutable; class JSFunction : public InternalFunction { friend class JIT; @@ -42,6 +43,7 @@ namespace JSC { public: JSFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction); + JSFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeExecutable*, NativeFunction); JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*); virtual ~JSFunction(); diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp index 2948d1c..12fa2be 100644 --- a/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/JavaScriptCore/runtime/JSGlobalData.cpp @@ -103,8 +103,8 @@ void JSGlobalData::storeVPtrs() jsFunction->~JSCell(); } -JSGlobalData::JSGlobalData(bool isShared, ThreadStackType threadStackType) - : isSharedInstance(isShared) +JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType) + : globalDataType(globalDataType) , clientData(0) , arrayTable(fastNew<HashTable>(JSC::arrayTable)) , dateTable(fastNew<HashTable>(JSC::dateTable)) @@ -128,7 +128,7 @@ JSGlobalData::JSGlobalData(bool isShared, ThreadStackType threadStackType) #if USE(JSVALUE32) , numberStructure(JSNumberCell::createStructure(jsNull())) #endif - , identifierTable(createIdentifierTable()) + , identifierTable(globalDataType == Default ? wtfThreadData().currentIdentifierTable() : createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) , lexer(new Lexer(this)) @@ -192,21 +192,20 @@ JSGlobalData::~JSGlobalData() delete emptyList; delete propertyNames; - deleteIdentifierTable(identifierTable); + if (globalDataType != Default) + deleteIdentifierTable(identifierTable); delete clientData; } -PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault(ThreadStackType type) +PassRefPtr<JSGlobalData> JSGlobalData::createContextGroup(ThreadStackType type) { - return adoptRef(new JSGlobalData(false, type)); + return adoptRef(new JSGlobalData(APIContextGroup, type)); } PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type) { - JSGlobalData* globalData = new JSGlobalData(false, type); - wtfThreadData().initializeIdentifierTable(globalData->identifierTable); - return adoptRef(globalData); + return adoptRef(new JSGlobalData(Default, type)); } PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type) @@ -226,7 +225,7 @@ JSGlobalData& JSGlobalData::sharedInstance() { JSGlobalData*& instance = sharedInstanceInternal(); if (!instance) { - instance = new JSGlobalData(true, ThreadStackTypeSmall); + instance = new JSGlobalData(APIShared, ThreadStackTypeSmall); #if ENABLE(JSC_MULTIPLE_THREADS) instance->makeUsableFromMultipleThreads(); #endif diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h index a90bf2c..711e148 100644 --- a/JavaScriptCore/runtime/JSGlobalData.h +++ b/JavaScriptCore/runtime/JSGlobalData.h @@ -29,6 +29,7 @@ #ifndef JSGlobalData_h #define JSGlobalData_h +#include "CachedTranscendentalFunction.h" #include "Collector.h" #include "DateInstanceCache.h" #include "ExecutableAllocator.h" @@ -91,16 +92,27 @@ namespace JSC { class JSGlobalData : public RefCounted<JSGlobalData> { public: + // WebCore has a one-to-one mapping of threads to JSGlobalDatas; + // either create() or createLeaked() should only be called once + // on a thread, this is the 'default' JSGlobalData (it uses the + // thread's default string uniquing table from wtfThreadData). + // API contexts created using the new context group aware interface + // create APIContextGroup objects which require less locking of JSC + // than the old singleton APIShared JSGlobalData created for use by + // the original API. + enum GlobalDataType { Default, APIContextGroup, APIShared }; + struct ClientData { virtual ~ClientData() = 0; }; + bool isSharedInstance() { return globalDataType == APIShared; } static bool sharedInstanceExists(); static JSGlobalData& sharedInstance(); static PassRefPtr<JSGlobalData> create(ThreadStackType); static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType); - static PassRefPtr<JSGlobalData> createNonDefault(ThreadStackType); + static PassRefPtr<JSGlobalData> createContextGroup(ThreadStackType); ~JSGlobalData(); #if ENABLE(JSC_MULTIPLE_THREADS) @@ -108,7 +120,7 @@ namespace JSC { void makeUsableFromMultipleThreads() { heap.makeUsableFromMultipleThreads(); } #endif - bool isSharedInstance; + GlobalDataType globalDataType; ClientData* clientData; const HashTable* arrayTable; @@ -158,6 +170,10 @@ namespace JSC { Interpreter* interpreter; #if ENABLE(JIT) JITThunks jitStubs; + NativeExecutable* getThunk(ThunkGenerator generator) + { + return jitStubs.specializedThunk(this, generator); + } #endif TimeoutChecker timeoutChecker; Terminator terminator; @@ -197,17 +213,19 @@ namespace JSC { ThreadIdentifier exclusiveThread; #endif + CachedTranscendentalFunction<sin> cachedSin; + void resetDateCache(); void startSampling(); void stopSampling(); void dumpSampleData(ExecState* exec); private: - JSGlobalData(bool isShared, ThreadStackType); + JSGlobalData(GlobalDataType, ThreadStackType); static JSGlobalData*& sharedInstanceInternal(); void createNativeThunk(); }; - + } // namespace JSC #endif // JSGlobalData_h diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp index 86690bd..7568ffd 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -117,10 +117,8 @@ JSGlobalObject::~JSGlobalObject() (*it)->clearGlobalObject(); RegisterFile& registerFile = globalData()->interpreter->registerFile(); - if (registerFile.globalObject() == this) { - registerFile.setGlobalObject(0); + if (registerFile.clearGlobalObject(this)) registerFile.setNumGlobals(0); - } d()->destructor(d()); } diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 5b6369a..5da5194 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -241,6 +241,7 @@ static double parseInt(const UString& s, int radix) } if (number >= mantissaOverflowLowerBound) { + // FIXME: It is incorrect to use UString::ascii() here because it's not thread-safe. if (radix == 10) number = WTF::strtod(s.substr(firstDigitPosition, p - firstDigitPosition).ascii(), 0); else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32) @@ -269,6 +270,8 @@ static double parseFloat(const UString& s) if (length - p >= 2 && data[p] == '0' && (data[p + 1] == 'x' || data[p + 1] == 'X')) return 0; + // FIXME: UString::toDouble will ignore leading ASCII spaces, but we need to ignore + // other StrWhiteSpaceChar values as well. return s.toDouble(true /*tolerant*/, false /* NaN for empty string */); } diff --git a/JavaScriptCore/runtime/JSImmediate.h b/JavaScriptCore/runtime/JSImmediate.h index 0f54f60..9127b6a 100644 --- a/JavaScriptCore/runtime/JSImmediate.h +++ b/JavaScriptCore/runtime/JSImmediate.h @@ -136,6 +136,8 @@ namespace JSC { friend class JIT; friend class JSValue; friend class JSFastMath; + friend class JSInterfaceJIT; + friend class SpecializedThunkJIT; friend JSValue jsNumber(ExecState* exec, double d); friend JSValue jsNumber(ExecState*, char i); friend JSValue jsNumber(ExecState*, unsigned char i); @@ -164,7 +166,7 @@ namespace JSC { // This value is 2^48, used to encode doubles such that the encoded value will begin // with a 16-bit pattern within the range 0x0001..0xFFFE. static const intptr_t DoubleEncodeOffset = 0x1000000000000ll; -#else +#elif USE(JSVALUE32) static const intptr_t TagTypeNumber = 0x1; // bottom bit set indicates integer, this dominates the following bit #endif static const intptr_t TagBitTypeOther = 0x2; // second bit set indicates immediate other than an integer diff --git a/JavaScriptCore/runtime/JSLock.cpp b/JavaScriptCore/runtime/JSLock.cpp index 8f056c8..a1cffbd 100644 --- a/JavaScriptCore/runtime/JSLock.cpp +++ b/JavaScriptCore/runtime/JSLock.cpp @@ -60,7 +60,7 @@ static void setLockCount(intptr_t count) } JSLock::JSLock(ExecState* exec) - : m_lockBehavior(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly) + : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly) { lock(m_lockBehavior); } @@ -105,12 +105,12 @@ void JSLock::unlock(JSLockBehavior lockBehavior) void JSLock::lock(ExecState* exec) { - lock(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly); + lock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly); } void JSLock::unlock(ExecState* exec) { - unlock(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly); + unlock(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly); } bool JSLock::currentThreadIsHoldingLock() @@ -162,7 +162,7 @@ bool JSLock::currentThreadIsHoldingLock() static unsigned lockDropDepth = 0; JSLock::DropAllLocks::DropAllLocks(ExecState* exec) - : m_lockBehavior(exec->globalData().isSharedInstance ? LockForReal : SilenceAssertionsOnly) + : m_lockBehavior(exec->globalData().isSharedInstance() ? LockForReal : SilenceAssertionsOnly) { pthread_once(&createJSLockCountOnce, createJSLockCount); diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h index b1dccfa..85d3c8e 100644 --- a/JavaScriptCore/runtime/JSString.h +++ b/JavaScriptCore/runtime/JSString.h @@ -66,6 +66,8 @@ namespace JSC { public: friend class JIT; friend class JSGlobalData; + friend class SpecializedThunkJIT; + friend struct ThunkHelpers; class RopeBuilder { public: diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h index b37adc0..bcf82ee 100644 --- a/JavaScriptCore/runtime/JSValue.h +++ b/JavaScriptCore/runtime/JSValue.h @@ -66,6 +66,8 @@ namespace JSC { friend class JIT; friend class JITStubs; friend class JITStubCall; + friend class JSInterfaceJIT; + friend class SpecializedThunkJIT; public: static EncodedJSValue encode(JSValue value); @@ -214,6 +216,10 @@ namespace JSC { JSObject* toObjectSlowCase(ExecState*) const; JSObject* toThisObjectSlowCase(ExecState*) const; + JSObject* synthesizePrototype(ExecState*) const; + JSObject* synthesizeObject(ExecState*) const; + +#if USE(JSVALUE32_64) enum { Int32Tag = 0xffffffff }; enum { CellTag = 0xfffffffe }; enum { TrueTag = 0xfffffffd }; @@ -222,16 +228,12 @@ namespace JSC { enum { UndefinedTag = 0xfffffffa }; enum { EmptyValueTag = 0xfffffff9 }; enum { DeletedValueTag = 0xfffffff8 }; - + enum { LowestTag = DeletedValueTag }; - + uint32_t tag() const; int32_t payload() const; - JSObject* synthesizePrototype(ExecState*) const; - JSObject* synthesizeObject(ExecState*) const; - -#if USE(JSVALUE32_64) union { EncodedJSValue asEncodedJSValue; double asDouble; diff --git a/JavaScriptCore/runtime/Lookup.cpp b/JavaScriptCore/runtime/Lookup.cpp index 4e9e086..0042e4d 100644 --- a/JavaScriptCore/runtime/Lookup.cpp +++ b/JavaScriptCore/runtime/Lookup.cpp @@ -46,7 +46,11 @@ void HashTable::createTable(JSGlobalData* globalData) const entry = entry->next(); } - entry->initialize(identifier, values[i].attributes, values[i].value1, values[i].value2); + entry->initialize(identifier, values[i].attributes, values[i].value1, values[i].value2 +#if ENABLE(JIT) + , values[i].generator +#endif + ); } table = entries; } @@ -70,7 +74,13 @@ void setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* JSValue* location = thisObj->getDirectLocation(propertyName); if (!location) { - InternalFunction* function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function()); + InternalFunction* function; +#if ENABLE(JIT) + if (entry->generator()) + function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, exec->globalData().getThunk(entry->generator()), entry->function()); + else +#endif + function = new (exec) NativeFunctionWrapper(exec, exec->lexicalGlobalObject()->prototypeFunctionStructure(), entry->functionLength(), propertyName, entry->function()); thisObj->putDirectFunction(propertyName, function, entry->attributes()); location = thisObj->getDirectLocation(propertyName); diff --git a/JavaScriptCore/runtime/Lookup.h b/JavaScriptCore/runtime/Lookup.h index 995aeee..dd36400 100644 --- a/JavaScriptCore/runtime/Lookup.h +++ b/JavaScriptCore/runtime/Lookup.h @@ -37,13 +37,15 @@ #endif namespace JSC { - // Hash table generated by the create_hash_table script. struct HashTableValue { const char* key; // property name unsigned char attributes; // JSObject attributes intptr_t value1; intptr_t value2; +#if ENABLE(JIT) + ThunkGenerator generator; +#endif }; // FIXME: There is no reason this get function can't be simpler. @@ -53,12 +55,19 @@ namespace JSC { class HashEntry : public FastAllocBase { public: - void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2) + void initialize(UString::Rep* key, unsigned char attributes, intptr_t v1, intptr_t v2 +#if ENABLE(JIT) + , ThunkGenerator generator = 0 +#endif + ) { m_key = key; m_attributes = attributes; m_u.store.value1 = v1; m_u.store.value2 = v2; +#if ENABLE(JIT) + m_u.function.generator = generator; +#endif m_next = 0; } @@ -67,6 +76,9 @@ namespace JSC { unsigned char attributes() const { return m_attributes; } +#if ENABLE(JIT) + ThunkGenerator generator() const { ASSERT(m_attributes & Function); return m_u.function.generator; } +#endif NativeFunction function() const { ASSERT(m_attributes & Function); return m_u.function.functionValue; } unsigned char functionLength() const { ASSERT(m_attributes & Function); return static_cast<unsigned char>(m_u.function.length); } @@ -90,6 +102,9 @@ namespace JSC { struct { NativeFunction functionValue; intptr_t length; // number of arguments for function +#if ENABLE(JIT) + ThunkGenerator generator; +#endif } function; struct { GetFunction get; diff --git a/JavaScriptCore/runtime/MathObject.cpp b/JavaScriptCore/runtime/MathObject.cpp index 16d32a0..1e28dfa 100644 --- a/JavaScriptCore/runtime/MathObject.cpp +++ b/JavaScriptCore/runtime/MathObject.cpp @@ -223,7 +223,7 @@ JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, co JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsDoubleNumber(exec, sin(args.at(0).toNumber(exec))); + return exec->globalData().cachedSin(exec, args.at(0).toNumber(exec)); } JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args) diff --git a/JavaScriptCore/runtime/SmallStrings.h b/JavaScriptCore/runtime/SmallStrings.h index cc11d0a..bc337c9 100644 --- a/JavaScriptCore/runtime/SmallStrings.h +++ b/JavaScriptCore/runtime/SmallStrings.h @@ -60,7 +60,9 @@ namespace JSC { void clear(); unsigned count() const; - +#if ENABLE(JIT) + JSString** singleCharacterStrings() { return m_singleCharacterStrings; } +#endif private: void createEmptyString(JSGlobalData*); void createSingleCharacterString(JSGlobalData*, unsigned char); diff --git a/JavaScriptCore/runtime/StringConstructor.cpp b/JavaScriptCore/runtime/StringConstructor.cpp index c7b62bf..42f98c3 100644 --- a/JavaScriptCore/runtime/StringConstructor.cpp +++ b/JavaScriptCore/runtime/StringConstructor.cpp @@ -54,8 +54,11 @@ StringConstructor::StringConstructor(ExecState* exec, NonNullPassRefPtr<Structur putDirectWithoutTransition(exec->propertyNames().prototype, stringPrototype, ReadOnly | DontEnum | DontDelete); // ECMA 15.5.3.2 fromCharCode() +#if ENABLE(JIT) + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, exec->globalData().getThunk(fromCharCodeThunkGenerator), stringFromCharCode), DontEnum); +#else putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().fromCharCode, stringFromCharCode), DontEnum); - +#endif // no. of arguments for constructor putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 1), ReadOnly | DontEnum | DontDelete); } diff --git a/JavaScriptCore/runtime/Structure.cpp b/JavaScriptCore/runtime/Structure.cpp index 6f23c7d..6d13f4b 100644 --- a/JavaScriptCore/runtime/Structure.cpp +++ b/JavaScriptCore/runtime/Structure.cpp @@ -168,14 +168,14 @@ inline void Structure::transitionTableAdd(const StructureTransitionTableHash::Ke if (!specificValue) { TransitionTable::iterator find = transitionTable()->find(key); if (find == transitionTable()->end()) - transitionTable()->add(key, Transition(structure, 0)); + transitionTable()->add(key, Transition(structure, static_cast<Structure*>(0))); else find->second.first = structure; } else { // If we're adding a transition to a specific value, then there cannot be // an existing transition ASSERT(!transitionTable()->contains(key)); - transitionTable()->add(key, Transition(0, structure)); + transitionTable()->add(key, Transition(static_cast<Structure*>(0), structure)); } } diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp index ce91040..6b16274 100644 --- a/JavaScriptCore/runtime/UString.cpp +++ b/JavaScriptCore/runtime/UString.cpp @@ -254,7 +254,15 @@ double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) co return NaN; } + // FIXME: If tolerateTrailingJunk is true, then we want to tolerate junk + // after the number, even if it contains invalid UTF-16 sequences. So we + // shouldn't use the UTF8String function, which returns null when it + // encounters invalid UTF-16. Further, we have no need to convert the + // non-ASCII characters to UTF-8, so the UTF8String does quite a bit of + // unnecessary work. CString s = UTF8String(); + if (s.isNull()) + return NaN; const char* c = s.data(); // skip leading white space @@ -318,6 +326,7 @@ double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) co while (isASCIISpace(*c)) c++; // don't allow anything after - unless tolerant=true + // FIXME: If string contains a U+0000 character, then this check is incorrect. if (!tolerateTrailingJunk && *c != '\0') d = NaN; diff --git a/JavaScriptCore/runtime/WeakGCPtr.h b/JavaScriptCore/runtime/WeakGCPtr.h index 5f58374..9dce858 100644 --- a/JavaScriptCore/runtime/WeakGCPtr.h +++ b/JavaScriptCore/runtime/WeakGCPtr.h @@ -44,10 +44,13 @@ public: return m_ptr; } - void clear(JSCell* ptr) + bool clear(JSCell* ptr) { - if (ptr == m_ptr) + if (ptr == m_ptr) { m_ptr = 0; + return true; + } + return false; } T& operator*() const { return *get(); } @@ -72,8 +75,8 @@ public: private: void assign(T* ptr) { - if (ptr) - Heap::markCell(ptr); + ASSERT(ptr); + Heap::markCell(ptr); m_ptr = ptr; } |