diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-03-17 05:44:14 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-03-17 05:44:14 (GMT) |
commit | 67d8b96d11b560367f068c2466664898a6fb5aed (patch) | |
tree | b60a7fd15f68d49c530bfa3ca326bdcfe070a9c3 /src | |
parent | 53fd1e2fd9c75d7d55606d4ac5df75eda96b9cc9 (diff) | |
parent | da8eb86480e188112193b66a265a7e957efc9de1 (diff) | |
download | Qt-67d8b96d11b560367f068c2466664898a6fb5aed.zip Qt-67d8b96d11b560367f068c2466664898a6fb5aed.tar.gz Qt-67d8b96d11b560367f068c2466664898a6fb5aed.tar.bz2 |
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-1: (83 commits)
probably need to update user configurations once in a while too
use dynamicstore instead
Define JS_NO_EXPORT to avoid JSC C API functions being exported
Don't use QScriptValueIterator to iterate over an array
QtScript: Fix regression when calling newQObject() from native constructor
Added note to OS X installation instructions.
Keypress events ignored in listview on Cocoa (64 Bit) with Japanese IME
Update only appropriate rectangles during update_sys().
Marked QTDS obsolete from Qt 4.7.
QNetworkReply: Fix canReadLine()
Abort waiting replies on session error.
different approach to fixing "the other" aliasing issue
fix aliasing issue in node_construct()
detach in fewer cases, remove redundant calculation
SSL: Fix memleak related to local certificate
Improve keyboard layout detection on X11
Compile on ARM with -Werror -Wold-style-cast
Use the vista-style native dialog for QFileDialog::getExistingDirectory
Apply the stdset attribute for resource properties
doc: Completed sentence about HideNameFilterDetails
...
Diffstat (limited to 'src')
433 files changed, 23860 insertions, 10296 deletions
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/APICast.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/APICast.h index b6d1532..4284c44 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/APICast.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/APICast.h @@ -27,6 +27,7 @@ #define APICast_h #include "JSAPIValueWrapper.h" +#include "JSGlobalObject.h" #include "JSValue.h" #include <wtf/Platform.h> #include <wtf/UnusedParam.h> @@ -50,16 +51,20 @@ typedef struct OpaqueJSValue* JSObjectRef; inline JSC::ExecState* toJS(JSContextRef c) { + ASSERT(c); return reinterpret_cast<JSC::ExecState*>(const_cast<OpaqueJSContext*>(c)); } inline JSC::ExecState* toJS(JSGlobalContextRef c) { + ASSERT(c); return reinterpret_cast<JSC::ExecState*>(c); } -inline JSC::JSValue toJS(JSC::ExecState*, JSValueRef v) +inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v) { + ASSERT_UNUSED(exec, exec); + ASSERT(v); #if USE(JSVALUE32_64) JSC::JSCell* jsCell = reinterpret_cast<JSC::JSCell*>(const_cast<OpaqueJSValue*>(v)); if (!jsCell) @@ -72,6 +77,20 @@ inline JSC::JSValue toJS(JSC::ExecState*, JSValueRef v) #endif } +inline JSC::JSValue toJSForGC(JSC::ExecState* exec, JSValueRef v) +{ + ASSERT_UNUSED(exec, exec); + ASSERT(v); +#if USE(JSVALUE32_64) + JSC::JSCell* jsCell = reinterpret_cast<JSC::JSCell*>(const_cast<OpaqueJSValue*>(v)); + if (!jsCell) + return JSC::JSValue(); + return jsCell; +#else + return JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(const_cast<OpaqueJSValue*>(v))); +#endif +} + inline JSC::JSObject* toJS(JSObjectRef o) { return reinterpret_cast<JSC::JSObject*>(o); @@ -118,6 +137,7 @@ inline JSContextRef toRef(JSC::ExecState* e) inline JSGlobalContextRef toGlobalRef(JSC::ExecState* e) { + ASSERT(e == e->lexicalGlobalObject()->globalExec()); return reinterpret_cast<JSGlobalContextRef>(e); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/APIShims.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/APIShims.h new file mode 100644 index 0000000..f809d5d --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/APIShims.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2009 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 COMPUTER, 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 COMPUTER, 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 APIShims_h +#define APIShims_h + +#include "CallFrame.h" +#include "JSLock.h" + +namespace JSC { + +class APIEntryShimWithoutLock { +protected: + APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread) + : m_globalData(globalData) + , m_entryIdentifierTable(setCurrentIdentifierTable(globalData->identifierTable)) + { + if (registerThread) + globalData->heap.registerThread(); + m_globalData->timeoutChecker->start(); + } + + ~APIEntryShimWithoutLock() + { + m_globalData->timeoutChecker->stop(); + setCurrentIdentifierTable(m_entryIdentifierTable); + } + +private: + JSGlobalData* m_globalData; + IdentifierTable* m_entryIdentifierTable; +}; + +class APIEntryShim : public APIEntryShimWithoutLock { +public: + // Normal API entry + APIEntryShim(ExecState* exec, bool registerThread = true) + : APIEntryShimWithoutLock(&exec->globalData(), registerThread) + , m_lock(exec) + { + } + + // JSPropertyNameAccumulator only has a globalData. + APIEntryShim(JSGlobalData* globalData, bool registerThread = true) + : APIEntryShimWithoutLock(globalData, registerThread) + , m_lock(globalData->isSharedInstance ? LockForReal : SilenceAssertionsOnly) + { + } + +private: + JSLock m_lock; +}; + +class APICallbackShim { +public: + APICallbackShim(ExecState* exec) + : m_dropAllLocks(exec) + , m_globalData(&exec->globalData()) + { + resetCurrentIdentifierTable(); + m_globalData->timeoutChecker->start(); + } + + ~APICallbackShim() + { + m_globalData->timeoutChecker->stop(); + setCurrentIdentifierTable(m_globalData->identifierTable); + } + +private: + JSLock::DropAllLocks m_dropAllLocks; + JSGlobalData* m_globalData; +}; + +} + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSBase.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSBase.cpp index 4a32d35..ebfeafa 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSBase.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSBase.cpp @@ -28,6 +28,7 @@ #include "JSBasePrivate.h" #include "APICast.h" +#include "APIShims.h" #include "Completion.h" #include "OpaqueJSString.h" #include "SourceCode.h" @@ -43,8 +44,7 @@ using namespace JSC; JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef thisObject, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsThisObject = toJS(thisObject); @@ -69,8 +69,7 @@ JSValueRef JSEvaluateScript(JSContextRef ctx, JSStringRef script, JSObjectRef th bool JSCheckScriptSyntax(JSContextRef ctx, JSStringRef script, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); SourceCode source = makeSource(script->ustring(), sourceURL->ustring(), startingLineNumber); Completion completion = checkSyntax(exec->dynamicGlobalObject()->globalExec(), source); @@ -94,12 +93,11 @@ void JSGarbageCollect(JSContextRef ctx) return; ExecState* exec = toJS(ctx); - JSGlobalData& globalData = exec->globalData(); - - JSLock lock(globalData.isSharedInstance ? LockForReal : SilenceAssertionsOnly); + APIEntryShim entryShim(exec, false); + JSGlobalData& globalData = exec->globalData(); if (!globalData.heap.isBusy()) - globalData.heap.collect(); + globalData.heap.collectAllGarbage(); // FIXME: Perhaps we should trigger a second mark and sweep // once the garbage collector is done if this is called when @@ -109,8 +107,6 @@ void JSGarbageCollect(JSContextRef ctx) void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); - + APIEntryShim entryShim(exec); exec->globalData().heap.reportExtraMemoryCost(size); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSBase.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSBase.h index 0a0dcda..2e16720 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSBase.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSBase.h @@ -64,33 +64,20 @@ typedef struct OpaqueJSValue* JSObjectRef; /* JavaScript symbol exports */ -#if !defined(JS_EXPORT) -#if defined(BUILDING_WX__) +#undef JS_EXPORT +#if defined(JS_NO_EXPORT) #define JS_EXPORT #elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__) #define JS_EXPORT __attribute__((visibility("default"))) -#elif defined(_WIN32_WCE) - #if defined(JS_BUILDING_JS) - #define JS_EXPORT __declspec(dllexport) - #elif defined(JS_IMPORT_JS) - #define JS_EXPORT __declspec(dllimport) - #else - #define JS_EXPORT - #endif -#elif defined(WIN32) || defined(_WIN32) - /* - * TODO: Export symbols with JS_EXPORT when using MSVC. - * See http://bugs.webkit.org/show_bug.cgi?id=16227 - */ +#elif defined(WIN32) || defined(_WIN32) || defined(_WIN32_WCE) #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) - #define JS_EXPORT __declspec(dllexport) + #define JS_EXPORT __declspec(dllexport) #else - #define JS_EXPORT __declspec(dllimport) + #define JS_EXPORT __declspec(dllimport) #endif #else #define JS_EXPORT #endif -#endif #ifdef __cplusplus extern "C" { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackConstructor.cpp index 64c83cb..9c5f6d7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackConstructor.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "JSCallbackConstructor.h" +#include "APIShims.h" #include "APICast.h" #include <runtime/JSGlobalObject.h> #include <runtime/JSLock.h> @@ -36,7 +37,7 @@ namespace JSC { const ClassInfo JSCallbackConstructor::info = { "CallbackConstructor", 0, 0, 0 }; -JSCallbackConstructor::JSCallbackConstructor(PassRefPtr<Structure> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback) +JSCallbackConstructor::JSCallbackConstructor(NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, JSObjectCallAsConstructorCallback callback) : JSObject(structure) , m_class(jsClass) , m_callback(callback) @@ -66,7 +67,7 @@ static JSObject* constructJSCallback(ExecState* exec, JSObject* constructor, con JSValueRef exception = 0; JSObjectRef result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = callback(ctx, constructorRef, argumentCount, arguments.data(), &exception); } if (exception) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackConstructor.h index 0497aa2..c4bd7ad 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackConstructor.h @@ -33,7 +33,7 @@ namespace JSC { class JSCallbackConstructor : public JSObject { public: - JSCallbackConstructor(PassRefPtr<Structure>, JSClassRef, JSObjectCallAsConstructorCallback); + JSCallbackConstructor(NonNullPassRefPtr<Structure>, JSClassRef, JSObjectCallAsConstructorCallback); virtual ~JSCallbackConstructor(); JSClassRef classRef() const { return m_class; } JSObjectCallAsConstructorCallback callback() const { return m_callback; } @@ -41,9 +41,12 @@ public: static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); } +protected: + static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags; + private: virtual ConstructType getConstructData(ConstructData&); virtual const ClassInfo* classInfo() const { return &info; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackFunction.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackFunction.cpp index b7dd768..0e434d9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackFunction.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackFunction.cpp @@ -27,6 +27,7 @@ #include <wtf/Platform.h> #include "JSCallbackFunction.h" +#include "APIShims.h" #include "APICast.h" #include "CodeBlock.h" #include "JSFunction.h" @@ -61,7 +62,7 @@ JSValue JSCallbackFunction::call(ExecState* exec, JSObject* functionObject, JSVa JSValueRef exception = 0; JSValueRef result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = static_cast<JSCallbackFunction*>(functionObject)->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); } if (exception) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackFunction.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackFunction.h index 3a17fa2..0cf25c4 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackFunction.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackFunction.h @@ -41,7 +41,7 @@ public: // refactor the code so this override isn't necessary static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); } private: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackObject.h index e767cb5..2e25991 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackObject.h @@ -36,7 +36,7 @@ namespace JSC { template <class Base> class JSCallbackObject : public Base { public: - JSCallbackObject(ExecState*, PassRefPtr<Structure>, JSClassRef, void* data); + JSCallbackObject(ExecState*, NonNullPassRefPtr<Structure>, JSClassRef, void* data); JSCallbackObject(JSClassRef); virtual ~JSCallbackObject(); @@ -50,23 +50,27 @@ public: static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | OverridesHasInstance)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); } +protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | Base::StructureFlags; + private: virtual UString className() const; virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier&, bool checkDontDelete = true); - virtual bool deleteProperty(ExecState*, unsigned, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, const Identifier&); + virtual bool deleteProperty(ExecState*, unsigned); virtual bool hasInstance(ExecState* exec, JSValue value, JSValue proto); - virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual double toNumber(ExecState*) const; virtual UString toString(ExecState*) const; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackObjectFunctions.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackObjectFunctions.h index c84c191..4b28a99 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackObjectFunctions.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSCallbackObjectFunctions.h @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "APIShims.h" #include "APICast.h" #include "Error.h" #include "JSCallbackFunction.h" @@ -47,7 +48,7 @@ inline JSCallbackObject<Base>* JSCallbackObject<Base>::asCallbackObject(JSValue } template <class Base> -JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, PassRefPtr<Structure> structure, JSClassRef jsClass, void* data) +JSCallbackObject<Base>::JSCallbackObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, JSClassRef jsClass, void* data) : Base(structure) , m_callbackObjectData(new JSCallbackObjectData(data, jsClass)) { @@ -79,7 +80,7 @@ void JSCallbackObject<Base>::init(ExecState* exec) // initialize from base to derived for (int i = static_cast<int>(initRoutines.size()) - 1; i >= 0; i--) { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); JSObjectInitializeCallback initialize = initRoutines[i]; initialize(toRef(exec), toRef(this)); } @@ -117,7 +118,7 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie if (JSObjectHasPropertyCallback hasProperty = jsClass->hasProperty) { if (!propertyNameRef) propertyNameRef = OpaqueJSString::create(propertyName.ustring()); - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); if (hasProperty(ctx, thisRef, propertyNameRef.get())) { slot.setCustom(this, callbackGetter); return true; @@ -128,18 +129,18 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, const Identifie JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = getProperty(ctx, thisRef, propertyNameRef.get(), &exception); } - exec->setException(toJS(exec, exception)); - if (value) { - slot.setValue(toJS(exec, value)); - return true; - } if (exception) { + exec->setException(toJS(exec, exception)); slot.setValue(jsUndefined()); return true; } + if (value) { + slot.setValue(toJS(exec, value)); + return true; + } } if (OpaqueJSClassStaticValuesTable* staticValues = jsClass->staticValues(exec)) { @@ -167,6 +168,25 @@ bool JSCallbackObject<Base>::getOwnPropertySlot(ExecState* exec, unsigned proper } template <class Base> +bool JSCallbackObject<Base>::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) +{ + PropertySlot slot; + if (getOwnPropertySlot(exec, propertyName, slot)) { + // Ideally we should return an access descriptor, but returning a value descriptor is better than nothing. + JSValue value = slot.getValue(exec, propertyName); + if (!exec->hadException()) + descriptor.setValue(value); + // We don't know whether the property is configurable, but assume it is. + descriptor.setConfigurable(true); + // We don't know whether the property is enumerable (we could call getOwnPropertyNames() to find out), but assume it isn't. + descriptor.setEnumerable(false); + return true; + } + + return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + +template <class Base> void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { JSContextRef ctx = toRef(exec); @@ -181,10 +201,11 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName JSValueRef exception = 0; bool result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); } - exec->setException(toJS(exec, exception)); + if (exception) + exec->setException(toJS(exec, exception)); if (result || exception) return; } @@ -199,10 +220,11 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName JSValueRef exception = 0; bool result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = setProperty(ctx, thisRef, propertyNameRef.get(), valueRef, &exception); } - exec->setException(toJS(exec, exception)); + if (exception) + exec->setException(toJS(exec, exception)); if (result || exception) return; } else @@ -224,7 +246,7 @@ void JSCallbackObject<Base>::put(ExecState* exec, const Identifier& propertyName } template <class Base> -bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) +bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& propertyName) { JSContextRef ctx = toRef(exec); JSObjectRef thisRef = toRef(this); @@ -237,10 +259,11 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p JSValueRef exception = 0; bool result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = deleteProperty(ctx, thisRef, propertyNameRef.get(), &exception); } - exec->setException(toJS(exec, exception)); + if (exception) + exec->setException(toJS(exec, exception)); if (result || exception) return true; } @@ -262,13 +285,13 @@ bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, const Identifier& p } } - return Base::deleteProperty(exec, propertyName, checkDontDelete); + return Base::deleteProperty(exec, propertyName); } template <class Base> -bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, unsigned propertyName, bool checkDontDelete) +bool JSCallbackObject<Base>::deleteProperty(ExecState* exec, unsigned propertyName) { - return deleteProperty(exec, Identifier::from(exec, propertyName), checkDontDelete); + return deleteProperty(exec, Identifier::from(exec, propertyName)); } template <class Base> @@ -298,10 +321,11 @@ JSObject* JSCallbackObject<Base>::construct(ExecState* exec, JSObject* construct JSValueRef exception = 0; JSObject* result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = toJS(callAsConstructor(execRef, constructorRef, argumentCount, arguments.data(), &exception)); } - exec->setException(toJS(exec, exception)); + if (exception) + exec->setException(toJS(exec, exception)); return result; } } @@ -322,10 +346,11 @@ bool JSCallbackObject<Base>::hasInstance(ExecState* exec, JSValue value, JSValue JSValueRef exception = 0; bool result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = hasInstance(execRef, thisRef, valueRef, &exception); } - exec->setException(toJS(exec, exception)); + if (exception) + exec->setException(toJS(exec, exception)); return result; } } @@ -360,10 +385,11 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, JSValueRef exception = 0; JSValue result; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); result = toJS(exec, callAsFunction(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception)); } - exec->setException(toJS(exec, exception)); + if (exception) + exec->setException(toJS(exec, exception)); return result; } } @@ -373,14 +399,14 @@ JSValue JSCallbackObject<Base>::call(ExecState* exec, JSObject* functionObject, } template <class Base> -void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) +void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { JSContextRef execRef = toRef(exec); JSObjectRef thisRef = toRef(this); for (JSClassRef jsClass = classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectGetPropertyNamesCallback getPropertyNames = jsClass->getPropertyNames) { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); getPropertyNames(execRef, thisRef, toRef(&propertyNames)); } @@ -390,7 +416,7 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr for (iterator it = staticValues->begin(); it != end; ++it) { UString::Rep* name = it->first.get(); StaticValueEntry* entry = it->second; - if (entry->getProperty && !(entry->attributes & kJSPropertyAttributeDontEnum)) + if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))) propertyNames.add(Identifier(exec, name)); } } @@ -401,13 +427,13 @@ void JSCallbackObject<Base>::getOwnPropertyNames(ExecState* exec, PropertyNameAr for (iterator it = staticFunctions->begin(); it != end; ++it) { UString::Rep* name = it->first.get(); StaticFunctionEntry* entry = it->second; - if (!(entry->attributes & kJSPropertyAttributeDontEnum)) + if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)) propertyNames.add(Identifier(exec, name)); } } } - Base::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + Base::getOwnPropertyNames(exec, propertyNames, mode); } template <class Base> @@ -426,7 +452,7 @@ double JSCallbackObject<Base>::toNumber(ExecState* exec) const JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = convertToType(ctx, thisRef, kJSTypeNumber, &exception); } if (exception) { @@ -435,7 +461,8 @@ double JSCallbackObject<Base>::toNumber(ExecState* exec) const } double dValue; - return toJS(exec, value).getNumber(dValue) ? dValue : NaN; + if (value) + return toJS(exec, value).getNumber(dValue) ? dValue : NaN; } return Base::toNumber(exec); @@ -452,14 +479,15 @@ UString JSCallbackObject<Base>::toString(ExecState* exec) const JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = convertToType(ctx, thisRef, kJSTypeString, &exception); } if (exception) { exec->setException(toJS(exec, exception)); return ""; } - return toJS(exec, value).getString(); + if (value) + return toJS(exec, value).getString(exec); } return Base::toString(exec); @@ -504,16 +532,17 @@ JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identif JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception); } - exec->setException(toJS(exec, exception)); + if (exception) { + exec->setException(toJS(exec, exception)); + return jsUndefined(); + } if (value) return toJS(exec, value); - if (exception) - return jsUndefined(); } - + return throwError(exec, ReferenceError, "Static value property defined with NULL getProperty callback."); } @@ -557,14 +586,15 @@ JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier JSValueRef exception = 0; JSValueRef value; { - JSLock::DropAllLocks dropAllLocks(exec); + APICallbackShim callbackShim(exec); value = getProperty(toRef(exec), thisRef, propertyNameRef.get(), &exception); } - exec->setException(toJS(exec, exception)); + if (exception) { + exec->setException(toJS(exec, exception)); + return jsUndefined(); + } if (value) return toJS(exec, value); - if (exception) - return jsUndefined(); } return throwError(exec, ReferenceError, "hasProperty callback returned true for a property that doesn't exist."); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSClassRef.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSClassRef.cpp index afde7ce..c6685bf 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSClassRef.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSClassRef.cpp @@ -34,6 +34,7 @@ #include <runtime/ObjectPrototype.h> #include <runtime/Identifier.h> +using namespace std; using namespace JSC; const JSClassDefinition kJSClassDefinitionEmpty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; @@ -52,7 +53,7 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* , callAsConstructor(definition->callAsConstructor) , hasInstance(definition->hasInstance) , convertToType(definition->convertToType) - , m_className(UString::Rep::createFromUTF8(definition->className)) + , m_className(UString::createFromUTF8(definition->className).rep()->ref()) , m_staticValues(0) , m_staticFunctions(0) { @@ -61,8 +62,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* if (const JSStaticValue* staticValue = definition->staticValues) { m_staticValues = new OpaqueJSClassStaticValuesTable(); while (staticValue->name) { - m_staticValues->add(UString::Rep::createFromUTF8(staticValue->name), - new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes)); + // Use a local variable here to sidestep an RVCT compiler bug. + StaticValueEntry* entry = new StaticValueEntry(staticValue->getProperty, staticValue->setProperty, staticValue->attributes); + m_staticValues->add(UString::createFromUTF8(staticValue->name).rep()->ref(), entry); ++staticValue; } } @@ -70,8 +72,9 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* if (const JSStaticFunction* staticFunction = definition->staticFunctions) { m_staticFunctions = new OpaqueJSClassStaticFunctionsTable(); while (staticFunction->name) { - m_staticFunctions->add(UString::Rep::createFromUTF8(staticFunction->name), - new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes)); + // Use a local variable here to sidestep an RVCT compiler bug. + StaticFunctionEntry* entry = new StaticFunctionEntry(staticFunction->callAsFunction, staticFunction->attributes); + m_staticFunctions->add(UString::createFromUTF8(staticFunction->name).rep()->ref(), entry); ++staticFunction; } } @@ -82,12 +85,12 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* OpaqueJSClass::~OpaqueJSClass() { - ASSERT(!m_className.rep()->identifierTable()); + ASSERT(!m_className.rep()->isIdentifier()); if (m_staticValues) { OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end(); for (OpaqueJSClassStaticValuesTable::const_iterator it = m_staticValues->begin(); it != end; ++it) { - ASSERT(!it->first->identifierTable()); + ASSERT(!it->first->isIdentifier()); delete it->second; } delete m_staticValues; @@ -96,7 +99,7 @@ OpaqueJSClass::~OpaqueJSClass() if (m_staticFunctions) { OpaqueJSClassStaticFunctionsTable::const_iterator end = m_staticFunctions->end(); for (OpaqueJSClassStaticFunctionsTable::const_iterator it = m_staticFunctions->begin(); it != end; ++it) { - ASSERT(!it->first->identifierTable()); + ASSERT(!it->first->isIdentifier()); delete it->second; } delete m_staticFunctions; @@ -118,39 +121,32 @@ static void clearReferenceToPrototype(JSObjectRef prototype) jsClassData->cachedPrototype = 0; } -PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* definition) +PassRefPtr<OpaqueJSClass> OpaqueJSClass::create(const JSClassDefinition* clientDefinition) { - if (const JSStaticFunction* staticFunctions = definition->staticFunctions) { - // copy functions into a prototype class - JSClassDefinition protoDefinition = kJSClassDefinitionEmpty; - protoDefinition.staticFunctions = staticFunctions; - protoDefinition.finalize = clearReferenceToPrototype; - - // We are supposed to use JSClassRetain/Release but since we know that we currently have - // the only reference to this class object we cheat and use a RefPtr instead. - RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0)); - - // remove functions from the original class - JSClassDefinition objectDefinition = *definition; - objectDefinition.staticFunctions = 0; - - return adoptRef(new OpaqueJSClass(&objectDefinition, protoClass.get())); - } + JSClassDefinition definition = *clientDefinition; // Avoid modifying client copy. - return adoptRef(new OpaqueJSClass(definition, 0)); + JSClassDefinition protoDefinition = kJSClassDefinitionEmpty; + protoDefinition.finalize = clearReferenceToPrototype; + swap(definition.staticFunctions, protoDefinition.staticFunctions); // Move static functions to the prototype. + + // We are supposed to use JSClassRetain/Release but since we know that we currently have + // the only reference to this class object we cheat and use a RefPtr instead. + RefPtr<OpaqueJSClass> protoClass = adoptRef(new OpaqueJSClass(&protoDefinition, 0)); + return adoptRef(new OpaqueJSClass(&definition, protoClass.get())); } OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass) : m_class(jsClass) - , cachedPrototype(0) { if (jsClass->m_staticValues) { staticValues = new OpaqueJSClassStaticValuesTable; OpaqueJSClassStaticValuesTable::const_iterator end = jsClass->m_staticValues->end(); for (OpaqueJSClassStaticValuesTable::const_iterator it = jsClass->m_staticValues->begin(); it != end; ++it) { - ASSERT(!it->first->identifierTable()); - staticValues->add(UString::Rep::createCopying(it->first->data(), it->first->size()), - new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes)); + ASSERT(!it->first->isIdentifier()); + // Use a local variable here to sidestep an RVCT compiler bug. + StaticValueEntry* entry = new StaticValueEntry(it->second->getProperty, it->second->setProperty, it->second->attributes); + staticValues->add(UString::Rep::create(it->first->data(), it->first->size()), entry); + } } else @@ -161,9 +157,10 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass) staticFunctions = new OpaqueJSClassStaticFunctionsTable; OpaqueJSClassStaticFunctionsTable::const_iterator end = jsClass->m_staticFunctions->end(); for (OpaqueJSClassStaticFunctionsTable::const_iterator it = jsClass->m_staticFunctions->begin(); it != end; ++it) { - ASSERT(!it->first->identifierTable()); - staticFunctions->add(UString::Rep::createCopying(it->first->data(), it->first->size()), - new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes)); + ASSERT(!it->first->isIdentifier()); + // Use a local variable here to sidestep an RVCT compiler bug. + StaticFunctionEntry* entry = new StaticFunctionEntry(it->second->callAsFunction, it->second->attributes); + staticFunctions->add(UString::Rep::create(it->first->data(), it->first->size()), entry); } } else @@ -240,5 +237,5 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec) jsClassData.cachedPrototype->setPrototype(prototype); } } - return jsClassData.cachedPrototype; + return jsClassData.cachedPrototype.get(); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSClassRef.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSClassRef.h index c4777dd..ae60aad 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSClassRef.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSClassRef.h @@ -31,6 +31,7 @@ #include <runtime/JSObject.h> #include <runtime/Protect.h> #include <runtime/UString.h> +#include <runtime/WeakGCPtr.h> #include <wtf/HashMap.h> #include <wtf/RefCounted.h> @@ -76,7 +77,7 @@ struct OpaqueJSClassContextData : Noncopyable { OpaqueJSClassStaticValuesTable* staticValues; OpaqueJSClassStaticFunctionsTable* staticFunctions; - JSC::JSObject* cachedPrototype; + JSC::WeakGCPtr<JSC::JSObject> cachedPrototype; }; struct OpaqueJSClass : public ThreadSafeShared<OpaqueJSClass> { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSContextRef.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSContextRef.cpp index c358a84..6bdc3c8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSContextRef.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSContextRef.cpp @@ -25,6 +25,7 @@ #include "config.h" #include "JSContextRef.h" +#include "JSContextRefPrivate.h" #include "APICast.h" #include "InitializeThreading.h" @@ -34,7 +35,7 @@ #include "JSObject.h" #include <wtf/Platform.h> -#if PLATFORM(DARWIN) +#if OS(DARWIN) #include <mach-o/dyld.h> static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0 @@ -45,7 +46,7 @@ using namespace JSC; JSContextGroupRef JSContextGroupCreate() { initializeThreading(); - return toRef(JSGlobalData::create().releaseRef()); + return toRef(JSGlobalData::createNonDefault().releaseRef()); } JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) @@ -62,7 +63,7 @@ void JSContextGroupRelease(JSContextGroupRef group) JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) { initializeThreading(); -#if PLATFORM(DARWIN) +#if OS(DARWIN) // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed // to use a unique JSGlobalData, we use a shared one for compatibility. #if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) @@ -73,7 +74,7 @@ JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) JSLock lock(LockForReal); return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass); } -#endif // PLATFORM(DARWIN) +#endif // OS(DARWIN) return JSGlobalContextCreateInGroup(0, globalObjectClass); } @@ -83,8 +84,9 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass initializeThreading(); JSLock lock(LockForReal); + RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::createNonDefault(); - RefPtr<JSGlobalData> globalData = group ? PassRefPtr<JSGlobalData>(toJS(group)) : JSGlobalData::create(); + APIEntryShim entryShim(globalData.get(), false); #if ENABLE(JSC_MULTIPLE_THREADS) globalData->makeUsableFromMultipleThreads(); @@ -107,12 +109,9 @@ JSGlobalContextRef JSGlobalContextCreateInGroup(JSContextGroupRef group, JSClass JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx) { ExecState* exec = toJS(ctx); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSGlobalData& globalData = exec->globalData(); - - globalData.heap.registerThread(); - gcProtect(exec->dynamicGlobalObject()); globalData.ref(); return ctx; @@ -121,18 +120,16 @@ JSGlobalContextRef JSGlobalContextRetain(JSGlobalContextRef ctx) void JSGlobalContextRelease(JSGlobalContextRef ctx) { ExecState* exec = toJS(ctx); - JSLock lock(exec); + APIEntryShim entryShim(exec, false); gcUnprotect(exec->dynamicGlobalObject()); JSGlobalData& globalData = exec->globalData(); if (globalData.refCount() == 2) { // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain(). // The last reference was released, this is our last chance to collect. - ASSERT(!globalData.heap.protectedObjectCount()); - ASSERT(!globalData.heap.isBusy()); globalData.heap.destroy(); } else - globalData.heap.collect(); + globalData.heap.collectAllGarbage(); globalData.deref(); } @@ -140,8 +137,7 @@ void JSGlobalContextRelease(JSGlobalContextRef ctx) JSObjectRef JSContextGetGlobalObject(JSContextRef ctx) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); // It is necessary to call toThisObject to get the wrapper object when used with WebCore. return toRef(exec->lexicalGlobalObject()->toThisObject(exec)); @@ -152,3 +148,11 @@ JSContextGroupRef JSContextGetGroup(JSContextRef ctx) ExecState* exec = toJS(ctx); return toRef(&exec->globalData()); } + +JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + + return toGlobalRef(exec->lexicalGlobalObject()->globalExec()); +} diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSContextRefPrivate.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSContextRefPrivate.h new file mode 100644 index 0000000..ff014ec --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSContextRefPrivate.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 Apple Computer, 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 COMPUTER, 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 COMPUTER, 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 JSContextRefPrivate_h +#define JSContextRefPrivate_h + +#include <JavaScriptCore/JSObjectRef.h> +#include <JavaScriptCore/JSValueRef.h> +#include <JavaScriptCore/WebKitAvailability.h> + +#ifndef __cplusplus +#include <stdbool.h> +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@function +@abstract Gets the global context of a JavaScript execution context. +@param ctx The JSContext whose global context you want to get. +@result ctx's global context. +*/ +JS_EXPORT JSGlobalContextRef JSContextGetGlobalContext(JSContextRef ctx); + +#ifdef __cplusplus +} +#endif + +#endif /* JSContextRefPrivate_h */ diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSObjectRef.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSObjectRef.cpp index 06ef578..faaa4eb 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSObjectRef.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSObjectRef.cpp @@ -76,8 +76,7 @@ void JSClassRelease(JSClassRef jsClass) JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); if (!jsClass) return toRef(new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient @@ -92,8 +91,7 @@ JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data) JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous"); @@ -103,8 +101,7 @@ JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0; if (!jsPrototype) @@ -118,8 +115,7 @@ JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObje JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous"); @@ -141,8 +137,7 @@ JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned pa JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* result; if (argumentCount) { @@ -167,8 +162,7 @@ JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSVa JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); MarkedArgumentBuffer argList; for (size_t i = 0; i < argumentCount; ++i) @@ -188,8 +182,7 @@ JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSVal JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); MarkedArgumentBuffer argList; for (size_t i = 0; i < argumentCount; ++i) @@ -209,8 +202,7 @@ JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSVa JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); MarkedArgumentBuffer argList; for (size_t i = 0; i < argumentCount; ++i) @@ -230,8 +222,7 @@ JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSV JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); return toRef(exec, jsObject->prototype()); @@ -240,8 +231,7 @@ JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object) void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); JSValue jsValue = toJS(exec, value); @@ -252,8 +242,7 @@ void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -263,8 +252,7 @@ bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef prope JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -280,8 +268,7 @@ JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); Identifier name(propertyName->identifier(&exec->globalData())); @@ -304,8 +291,7 @@ void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef prope JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -322,8 +308,7 @@ JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsi void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); JSValue jsValue = toJS(exec, value); @@ -339,8 +324,7 @@ void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned p bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -389,8 +373,7 @@ bool JSObjectIsFunction(JSContextRef, JSObjectRef object) JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); JSObject* jsThisObject = toJS(thisObject); @@ -427,8 +410,7 @@ bool JSObjectIsConstructor(JSContextRef, JSObjectRef object) JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); @@ -466,8 +448,7 @@ JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef o { JSObject* jsObject = toJS(object); ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSGlobalData* globalData = &exec->globalData(); @@ -492,7 +473,7 @@ JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array) void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array) { if (--array->refCount == 0) { - JSLock lock(array->globalData->isSharedInstance ? LockForReal : SilenceAssertionsOnly); + APIEntryShim entryShim(array->globalData, false); delete array; } } @@ -510,9 +491,6 @@ JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName) { PropertyNameArray* propertyNames = toJS(array); - - propertyNames->globalData()->heap.registerThread(); - JSLock lock(propertyNames->globalData()->isSharedInstance ? LockForReal : SilenceAssertionsOnly); - + APIEntryShim entryShim(propertyNames->globalData()); propertyNames->add(propertyName->identifier(propertyNames->globalData())); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSStringRef.h b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSStringRef.h index 41d8978..c58b958 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSStringRef.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSStringRef.h @@ -37,7 +37,7 @@ extern "C" { #endif -#if (!defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__)) +#if !defined(WIN32) && !defined(_WIN32) && !defined(__WINSCW__) /*! @typedef JSChar @abstract A Unicode character. diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSValueRef.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSValueRef.cpp index 2207181..a12cc34 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/JSValueRef.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/JSValueRef.cpp @@ -28,6 +28,7 @@ #include <wtf/Platform.h> #include "APICast.h" +#include "APIShims.h" #include "JSCallbackObject.h" #include <runtime/JSGlobalObject.h> @@ -41,13 +42,14 @@ #include <algorithm> // for std::min -JSType JSValueGetType(JSContextRef ctx, JSValueRef value) +using namespace JSC; + +::JSType JSValueGetType(JSContextRef ctx, JSValueRef value) { - JSC::ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSC::JSLock lock(exec); + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); - JSC::JSValue jsValue = toJS(exec, value); + JSValue jsValue = toJS(exec, value); if (jsValue.isUndefined()) return kJSTypeUndefined; @@ -63,13 +65,10 @@ JSType JSValueGetType(JSContextRef ctx, JSValueRef value) return kJSTypeObject; } -using namespace JSC; // placed here to avoid conflict between JSC::JSType and JSType, above. - bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isUndefined(); @@ -78,8 +77,7 @@ bool JSValueIsUndefined(JSContextRef ctx, JSValueRef value) bool JSValueIsNull(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNull(); @@ -88,8 +86,7 @@ bool JSValueIsNull(JSContextRef ctx, JSValueRef value) bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isBoolean(); @@ -98,8 +95,7 @@ bool JSValueIsBoolean(JSContextRef ctx, JSValueRef value) bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isNumber(); @@ -108,8 +104,7 @@ bool JSValueIsNumber(JSContextRef ctx, JSValueRef value) bool JSValueIsString(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isString(); @@ -118,8 +113,7 @@ bool JSValueIsString(JSContextRef ctx, JSValueRef value) bool JSValueIsObject(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.isObject(); @@ -128,8 +122,7 @@ bool JSValueIsObject(JSContextRef ctx, JSValueRef value) bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsClass) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -145,8 +138,7 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsA = toJS(exec, a); JSValue jsB = toJS(exec, b); @@ -163,20 +155,18 @@ bool JSValueIsEqual(JSContextRef ctx, JSValueRef a, JSValueRef b, JSValueRef* ex bool JSValueIsStrictEqual(JSContextRef ctx, JSValueRef a, JSValueRef b) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsA = toJS(exec, a); JSValue jsB = toJS(exec, b); - return JSValue::strictEqual(jsA, jsB); + return JSValue::strictEqual(exec, jsA, jsB); } bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObjectRef constructor, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -195,8 +185,7 @@ bool JSValueIsInstanceOfConstructor(JSContextRef ctx, JSValueRef value, JSObject JSValueRef JSValueMakeUndefined(JSContextRef ctx) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsUndefined()); } @@ -204,8 +193,7 @@ JSValueRef JSValueMakeUndefined(JSContextRef ctx) JSValueRef JSValueMakeNull(JSContextRef ctx) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsNull()); } @@ -213,8 +201,7 @@ JSValueRef JSValueMakeNull(JSContextRef ctx) JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsBoolean(value)); } @@ -222,8 +209,7 @@ JSValueRef JSValueMakeBoolean(JSContextRef ctx, bool value) JSValueRef JSValueMakeNumber(JSContextRef ctx, double value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsNumber(exec, value)); } @@ -231,8 +217,7 @@ JSValueRef JSValueMakeNumber(JSContextRef ctx, double value) JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); return toRef(exec, jsString(exec, string->ustring())); } @@ -240,8 +225,7 @@ JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); return jsValue.toBoolean(exec); @@ -250,8 +234,7 @@ bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -268,8 +251,7 @@ double JSValueToNumber(JSContextRef ctx, JSValueRef value, JSValueRef* exception JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -286,8 +268,7 @@ JSStringRef JSValueToStringCopy(JSContextRef ctx, JSValueRef value, JSValueRef* JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); @@ -304,19 +285,17 @@ JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exce void JSValueProtect(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); - JSValue jsValue = toJS(exec, value); + JSValue jsValue = toJSForGC(exec, value); gcProtect(jsValue); } void JSValueUnprotect(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); - exec->globalData().heap.registerThread(); - JSLock lock(exec); + APIEntryShim entryShim(exec); - JSValue jsValue = toJS(exec, value); + JSValue jsValue = toJSForGC(exec, value); gcUnprotect(jsValue); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/API/OpaqueJSString.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/API/OpaqueJSString.cpp index 7c7b1af..f740abe 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/API/OpaqueJSString.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/API/OpaqueJSString.cpp @@ -42,7 +42,7 @@ PassRefPtr<OpaqueJSString> OpaqueJSString::create(const UString& ustring) UString OpaqueJSString::ustring() const { if (this && m_characters) - return UString(m_characters, m_length, true); + return UString(m_characters, m_length); return UString::null(); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog index 5fa56a7..35aabc9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog +++ b/src/3rdparty/javascriptcore/JavaScriptCore/ChangeLog @@ -1,3 +1,7410 @@ +2010-01-27 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Oliver Hunt. + + [BREWMP] Add MarkStack fastMalloc implementation for platforms without VirtualAlloc or mmap. + https://bugs.webkit.org/show_bug.cgi?id=33582 + + Use fastMalloc and fastFree to implement MarkStack::allocateStack and + MarkStack::releaseStack for platforms without page level allocation. + + * runtime/MarkStack.h: + (JSC::MarkStack::MarkStackArray::shrinkAllocation): + * runtime/MarkStackNone.cpp: Added. + (JSC::MarkStack::initializePagesize): + (JSC::MarkStack::allocateStack): + (JSC::MarkStack::releaseStack): + +2010-01-27 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Eric Seidel. + + [BREWMP] Don't use time function + https://bugs.webkit.org/show_bug.cgi?id=33577 + + Calling time(0) in BREW devices causes a crash because time + is not properly ported in most devices. Cast currentTime() to + time_t to get the same result as time(0). + + * wtf/DateMath.cpp: + (WTF::calculateUTCOffset): + +2010-01-27 Alexey Proskuryakov <ap@apple.com> + + Revert r53899 (HashMap<AtomicStringImpl*, Value> key checks) and subsequent build fixes, + because they make SVG tests crash in release builds. + + * wtf/HashMap.h: + (WTF::::remove): + * wtf/HashSet.h: + (WTF::::remove): + * wtf/HashTable.h: + (WTF::::add): + (WTF::::addPassingHashCode): + (WTF::::removeAndInvalidate): + (WTF::::remove): + (WTF::::rehash): + (WTF::::checkTableConsistency): + (WTF::::checkTableConsistencyExceptSize): + * wtf/HashTraits.h: + (WTF::GenericHashTraits::emptyValue): + (WTF::): + * wtf/RefPtrHashMap.h: + (WTF::::remove): + +2010-01-26 Alexey Proskuryakov <ap@apple.com> + + More Windows build fixing. + + * wtf/HashTraits.h: _msize takes void*, remove const qualifier from type. + +2010-01-26 Alexey Proskuryakov <ap@apple.com> + + Windows build fix. + + * wtf/HashTraits.h: Include malloc.h for _msize(). + +2010-01-26 Alexey Proskuryakov <ap@apple.com> + + Build fix. + + * wtf/HashTable.h: (WTF::HashTable::checkTableConsistencyExceptSize): Remove const from a + static (empty) version of this function. + +2010-01-26 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=34150 + WebKit needs a mechanism to catch stale HashMap entries + + It is very difficult to catch stale pointers that are HashMap keys - since a pointer's hash + is just its value, it is very unlikely that any observable problem is reproducible. + + This extends hash table consistency checks to check that pointers are referencing allocated + memory blocks, and makes it possible to invoke the checks explicitly (it is not feasible + to enable CHECK_HASHTABLE_CONSISTENCY by default, because that affects performance too much). + + * wtf/HashMap.h: (WTF::::checkConsistency): Call through to HashTable implementation. We can + add similar calls to HashSet and HashCountedSet, but I haven't seen hard to debug problems + with those yet. + + * wtf/HashSet.h: (WTF::::remove): The version of checkTableConsistency that's guarded by + CHECK_HASHTABLE_CONSISTENCY is now called internalCheckTableConsistency(). + + * wtf/HashTable.h: + (WTF::HashTable::internalCheckTableConsistency): + (WTF::HashTable::internalCheckTableConsistencyExceptSize): + (WTF::HashTable::checkTableConsistencyExceptSize): + Expose checkTableConsistency() even if CHECK_HASHTABLE_CONSISTENCY is off. + (WTF::::add): Updated for checkTableConsistency renaming. + (WTF::::addPassingHashCode): Ditto. + (WTF::::removeAndInvalidate): Ditto. + (WTF::::remove): Ditto. + (WTF::::rehash): Ditto. + (WTF::::checkTableConsistency): The assertion for !shouldExpand() was not correct - this + function returns true for tables with m_table == 0. + (WTF::::checkTableConsistencyExceptSize): Call checkValueConsistency for key. Potentially, + we could do the same for values. + + * wtf/HashTraits.h: + (WTF::GenericHashTraits::checkValueConsistency): An empty function that can be overridden + to add checks. Currently, the only override is for pointer hashes. + + * wtf/RefPtrHashMap.h: (WTF::::remove): Updated for checkTableConsistency renaming. + +2010-01-26 Lyon Chen <liachen@rim.com> + + Reviewed by Maciej Stachowiak. + + Opcode.h use const void* for Opcode cause error #1211 for RVCT compiler + https://bugs.webkit.org/show_bug.cgi?id=33902 + + * bytecode/Opcode.h: + +2010-01-26 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Oliver Hunt. + + Windows build references non-existent include paths + https://bugs.webkit.org/show_bug.cgi?id=34175 + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + * JavaScriptCore.vcproj/WTF/WTFCommon.vsprops: + * JavaScriptCore.vcproj/jsc/jscCommon.vsprops: + * JavaScriptCore.vcproj/testapi/testapi.vcproj: + * JavaScriptCore.vcproj/testapi/testapiCommon.vsprops: + +2010-01-26 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + Using JavaScriptCore API with a webkit vended context can result in slow script dialog + https://bugs.webkit.org/show_bug.cgi?id=34172 + + Make the APIShim correctly increment and decrement the timeout + entry counter. + + * API/APIShims.h: + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): + (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): + (JSC::APICallbackShim::APICallbackShim): + (JSC::APICallbackShim::~APICallbackShim): + +2010-01-26 Simon Hausmann <simon.hausmann@nokia.com> + + [Qt] Fix compilation of QtScript with non-gcc compilers + + Variable length stack arrays are a gcc extension. Use QVarLengthArray + as a more portable solution that still tries to allocate on the stack + first. + + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::call): + +2010-01-26 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Fix the build on platforms without JIT support. + + The JIT support should be determined at compile-time via wtf/Platform.h + + * qt/api/QtScript.pro: + +2010-01-26 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + First steps of the QtScript API. + + Two new classes were created; QScriptEngine and QScriptValue. + The first should encapsulate a javascript context and the second a script + value. + + This API is still in development, so it isn't compiled by default. + To trigger compilation, pass --qmakearg="CONFIG+=build-qtscript" to + build-webkit. + + https://bugs.webkit.org/show_bug.cgi?id=32565 + + * qt/api/QtScript.pro: Added. + * qt/api/qscriptconverter_p.h: Added. + (QScriptConverter::toString): + * qt/api/qscriptengine.cpp: Added. + (QScriptEngine::QScriptEngine): + (QScriptEngine::~QScriptEngine): + (QScriptEngine::evaluate): + (QScriptEngine::collectGarbage): + * qt/api/qscriptengine.h: Added. + * qt/api/qscriptengine_p.cpp: Added. + (QScriptEnginePrivate::QScriptEnginePrivate): + (QScriptEnginePrivate::~QScriptEnginePrivate): + (QScriptEnginePrivate::evaluate): + * qt/api/qscriptengine_p.h: Added. + (QScriptEnginePrivate::get): + (QScriptEnginePrivate::collectGarbage): + (QScriptEnginePrivate::makeJSValue): + (QScriptEnginePrivate::context): + * qt/api/qscriptvalue.cpp: Added. + (QScriptValue::QScriptValue): + (QScriptValue::~QScriptValue): + (QScriptValue::isValid): + (QScriptValue::isBool): + (QScriptValue::isBoolean): + (QScriptValue::isNumber): + (QScriptValue::isNull): + (QScriptValue::isString): + (QScriptValue::isUndefined): + (QScriptValue::isError): + (QScriptValue::isObject): + (QScriptValue::isFunction): + (QScriptValue::toString): + (QScriptValue::toNumber): + (QScriptValue::toBool): + (QScriptValue::toBoolean): + (QScriptValue::toInteger): + (QScriptValue::toInt32): + (QScriptValue::toUInt32): + (QScriptValue::toUInt16): + (QScriptValue::call): + (QScriptValue::engine): + (QScriptValue::operator=): + (QScriptValue::equals): + (QScriptValue::strictlyEquals): + * qt/api/qscriptvalue.h: Added. + (QScriptValue::): + * qt/api/qscriptvalue_p.h: Added. + (QScriptValuePrivate::): + (QScriptValuePrivate::get): + (QScriptValuePrivate::QScriptValuePrivate): + (QScriptValuePrivate::isValid): + (QScriptValuePrivate::isBool): + (QScriptValuePrivate::isNumber): + (QScriptValuePrivate::isNull): + (QScriptValuePrivate::isString): + (QScriptValuePrivate::isUndefined): + (QScriptValuePrivate::isError): + (QScriptValuePrivate::isObject): + (QScriptValuePrivate::isFunction): + (QScriptValuePrivate::toString): + (QScriptValuePrivate::toNumber): + (QScriptValuePrivate::toBool): + (QScriptValuePrivate::toInteger): + (QScriptValuePrivate::toInt32): + (QScriptValuePrivate::toUInt32): + (QScriptValuePrivate::toUInt16): + (QScriptValuePrivate::equals): + (QScriptValuePrivate::strictlyEquals): + (QScriptValuePrivate::assignEngine): + (QScriptValuePrivate::call): + (QScriptValuePrivate::engine): + (QScriptValuePrivate::context): + (QScriptValuePrivate::value): + (QScriptValuePrivate::object): + (QScriptValuePrivate::inherits): + (QScriptValuePrivate::isJSBased): + (QScriptValuePrivate::isNumberBased): + (QScriptValuePrivate::isStringBased): + * qt/api/qtscriptglobal.h: Added. + * qt/tests/qscriptengine/qscriptengine.pro: Added. + * qt/tests/qscriptengine/tst_qscriptengine.cpp: Added. + (tst_QScriptEngine::tst_QScriptEngine): + (tst_QScriptEngine::~tst_QScriptEngine): + (tst_QScriptEngine::init): + (tst_QScriptEngine::cleanup): + (tst_QScriptEngine::collectGarbage): + (tst_QScriptEngine::evaluate): + * qt/tests/qscriptvalue/qscriptvalue.pro: Added. + * qt/tests/qscriptvalue/tst_qscriptvalue.cpp: Added. + (tst_QScriptValue::tst_QScriptValue): + (tst_QScriptValue::~tst_QScriptValue): + (tst_QScriptValue::init): + (tst_QScriptValue::cleanup): + (tst_QScriptValue::ctor): + (tst_QScriptValue::toString_data): + (tst_QScriptValue::toString): + (tst_QScriptValue::copyConstructor_data): + (tst_QScriptValue::copyConstructor): + (tst_QScriptValue::assignOperator_data): + (tst_QScriptValue::assignOperator): + (tst_QScriptValue::dataSharing): + (tst_QScriptValue::constructors_data): + (tst_QScriptValue::constructors): + (tst_QScriptValue::call): + * qt/tests/tests.pri: Added. + * qt/tests/tests.pro: Added. + +2010-01-25 Dmitry Titov <dimich@chromium.org> + + Reviewed by David Levin. + + Fix Chromium Linux tests: the pthread functions on Linux produce segfault if they receive 0 thread handle. + After r53714, we can have 0 thread handles passed to pthread_join and pthread_detach if corresponding threads + were already terminated and their threadMap entries cleared. + Add a 0 check. + + * wtf/ThreadingPthreads.cpp: + (WTF::waitForThreadCompletion): + (WTF::detachThread): + +2010-01-24 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Maciej Stachowiak. + + Refactor JITStubs.cpp so that DEFINE_STUB_FUNCTION is only used once for each function + https://bugs.webkit.org/show_bug.cgi?id=33866 + + Place the guard USE(JSVALUE32_64) inside the body of the DEFINE_STUB_FUNCTION + macro for those functions that are always present. + + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + +2010-01-22 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + [wx] Remove the Bakefile build system, which is no longer being used. + + https://bugs.webkit.org/show_bug.cgi?id=34022 + + * JavaScriptCoreSources.bkl: Removed. + * jscore.bkl: Removed. + +2010-01-22 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=34025 + Enable client-based Geolocation abstraction for Mac, Windows AppleWebKit targets. + + * Configurations/FeatureDefines.xcconfig: + +2010-01-22 Dmitry Titov <dimich@chromium.org> + + Not reviewed, attempted Snow Leopard build fix. + + * wtf/ThreadingPthreads.cpp: Add a forward declaration of a function which is not 'static'. + +2009-01-22 Dmitry Titov <dimich@chromium.org> + + Reviewed by Maciej Stachowiak. + + Fix the leak of ThreadIdentifiers in threadMap across threads. + https://bugs.webkit.org/show_bug.cgi?id=32689 + + Test is added to DumpRenderTree.mm. + + * Android.mk: Added file ThreadIdentifierDataPthreads.(h|cpp) to build. + * Android.v8.wtf.mk: Ditto. + * GNUmakefile.am: Ditto. + * JavaScriptCore.gyp/JavaScriptCore.gyp: Ditto. + * JavaScriptCore.gypi: Ditto. + * JavaScriptCore.xcodeproj/project.pbxproj: Ditto. + + * wtf/ThreadIdentifierDataPthreads.cpp: Added. Contains custom implementation of thread-specific data that uses custom destructor. + (WTF::ThreadIdentifierData::~ThreadIdentifierData): Removes the ThreadIdentifier from the threadMap. + (WTF::ThreadIdentifierData::identifier): + (WTF::ThreadIdentifierData::initialize): + (WTF::ThreadIdentifierData::destruct): Custom thread-specific destructor. Resets the value for the key again to cause second invoke. + (WTF::ThreadIdentifierData::initializeKeyOnceHelper): + (WTF::ThreadIdentifierData::initializeKeyOnce): Need to use pthread_once since initialization may come on any thread(s). + * wtf/ThreadIdentifierDataPthreads.h: Added. + (WTF::ThreadIdentifierData::ThreadIdentifierData): + + * wtf/Threading.cpp: + (WTF::threadEntryPoint): Move initializeCurrentThreadInternal to after the lock to make + sure it is invoked when ThreadIdentifier is already established. + + * wtf/Threading.h: Rename setThreadNameInternal -> initializeCurrentThreadInternal since it does more then only set the name now. + * wtf/ThreadingNone.cpp: + (WTF::initializeCurrentThreadInternal): Ditto. + * wtf/ThreadingWin.cpp: + (WTF::initializeCurrentThreadInternal): Ditto. + (WTF::initializeThreading): Ditto. + * wtf/gtk/ThreadingGtk.cpp: + (WTF::initializeCurrentThreadInternal): Ditto. + * wtf/qt/ThreadingQt.cpp: + (WTF::initializeCurrentThreadInternal): Ditto. + + * wtf/ThreadingPthreads.cpp: + (WTF::establishIdentifierForPthreadHandle): + (WTF::clearPthreadHandleForIdentifier): Make it not 'static' so the ~ThreadIdentifierData() in another file can call it. + (WTF::initializeCurrentThreadInternal): Set the thread-specific data. The ThreadIdentifier is already established by creating thread. + (WTF::waitForThreadCompletion): Remove call to clearPthreadHandleForIdentifier(threadID) since it is now done in ~ThreadIdentifierData(). + (WTF::detachThread): Ditto. + (WTF::currentThread): Use the thread-specific data to get the ThreadIdentifier. It's many times faster then Mutex-protected iteration through the map. + Also, set the thread-specific data if called first time on the thread. + +2010-01-21 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Alexey Proskuryakov. + + Add ThreadSpecific for ENABLE(SINGLE_THREADED) + https://bugs.webkit.org/show_bug.cgi?id=33878 + + Implement ThreadSpecific with a simple getter/setter + when ENABLE(SINGLE_THREADED) is true. + + Due to the change in https://bugs.webkit.org/show_bug.cgi?id=33236, + an implementation of ThreadSpecific must be available to build WebKit. + This causes a build failure for platforms without a proper + ThreadSpecific implementation. + + * wtf/ThreadSpecific.h: + (WTF::::ThreadSpecific): + (WTF::::~ThreadSpecific): + (WTF::::get): + (WTF::::set): + (WTF::::destroy): + +2010-01-21 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Maciej Stachowiak. + + Add fastStrDup to FastMalloc + https://bugs.webkit.org/show_bug.cgi?id=33937 + + The new string returned by fastStrDup is obtained with fastMalloc, + and can be freed with fastFree. This makes the memory management + more consistent because we don't need to keep strdup allocated pointers + and free them with free(). Instead we can use fastFree everywhere. + + * wtf/FastMalloc.cpp: + (WTF::fastStrDup): + * wtf/FastMalloc.h: + +2010-01-21 Brady Eidson <beidson@apple.com> + + Reviewed by Maciej Stachowiak. + + history.back() for same-document history traversals isn't synchronous as the specification states. + <rdar://problem/7535011> and https://bugs.webkit.org/show_bug.cgi?id=33538 + + * wtf/Platform.h: Add a "HISTORY_ALWAYS_ASYNC" enable and turn it on for Chromium. + +2010-01-21 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Always create a prototype for automatically managed classes. + + This fixes some errors where prototype chains were not correctly hooked + up, and also ensures that API classes work correctly with features like + instanceof. + + * API/JSClassRef.cpp: + (OpaqueJSClass::create): Cleaned up some of this code. Also changed it + to always create a prototype class. + + * API/tests/testapi.c: + (Derived2_class): + (main): Fixed a null value crash in the exception checking code. + * API/tests/testapi.js: Added some tests for the case where a prototype + chain would not be hooked up correctly. + +2010-01-21 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + Force JSC to create a prototype chain for API classes with a + parent class but no static functions. + + * API/JSClassRef.cpp: + (OpaqueJSClass::create): + +2010-01-21 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Geoffrey Garen. + + Object.getOwnPropertyDescriptor always returns undefined for JS API objects + https://bugs.webkit.org/show_bug.cgi?id=33946 + + Ideally the getOwnPropertyDescriptor() reimplementation should return an + access descriptor that wraps the property getter and setter callbacks, but + that approach is much more involved than returning a value descriptor. + Keep it simple for now. + + * API/JSCallbackObject.h: + * API/JSCallbackObjectFunctions.h: + (JSC::::getOwnPropertyDescriptor): + * API/tests/testapi.js: + +2010-01-20 Mark Rowe <mrowe@apple.com> + + Build fix. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::initializeScavenger): Remove unnecessary function call. + +2010-01-20 Mark Rowe <mrowe@apple.com> + + Reviewed by Oliver Hunt. + + Use the inline i386 assembly for x86_64 as well rather than falling back to using pthread mutexes. + + * wtf/TCSpinLock.h: + (TCMalloc_SpinLock::Lock): + (TCMalloc_SpinLock::Unlock): + (TCMalloc_SlowLock): + +2010-01-20 Mark Rowe <mrowe@apple.com> + + Reviewed by Oliver Hunt. + + <rdar://problem/7215063> Use GCD instead of an extra thread for FastMalloc scavenging on platforms where it is supported + + Abstract the background scavenging slightly so that an alternate implementation that uses GCD can be used on platforms + where it is supported. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::init): + (WTF::TCMalloc_PageHeap::initializeScavenger): + (WTF::TCMalloc_PageHeap::signalScavenger): + (WTF::TCMalloc_PageHeap::shouldContinueScavenging): + (WTF::TCMalloc_PageHeap::Delete): + (WTF::TCMalloc_PageHeap::periodicScavenge): + * wtf/Platform.h: + +2010-01-20 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + <rdar://problem/7562708> REGRESSION(53460): Heap::destroy may not run + all destructors + + * runtime/Collector.cpp: + (JSC::Heap::freeBlocks): Instead of fully marking protected objects, + just set their mark bits. This prevents protected objects from keeping + unprotected objects alive. Destructor order is not guaranteed, so it's + OK to destroy objects pointed to by protected objects before destroying + protected objects. + +2010-01-19 David Levin <levin@chromium.org> + + Reviewed by Oliver Hunt. + + CrossThreadCopier needs to support ThreadSafeShared better. + https://bugs.webkit.org/show_bug.cgi?id=33698 + + * wtf/TypeTraits.cpp: Added tests for the new type traits. + * wtf/TypeTraits.h: + (WTF::IsSubclass): Determines if a class is a derived from another class. + (WTF::IsSubclassOfTemplate): Determines if a class is a derived from a + template class (with one parameter that is unknown). + (WTF::RemoveTemplate): Reveals the type for a template parameter. + +2010-01-20 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Darin Adler and Adam Roben. + + Feature defines are difficult to maintain on Windows builds + https://bugs.webkit.org/show_bug.cgi?id=33883 + + FeatureDefines.vsprops are now maintained in a way similar to + Configurations/FeatureDefines.xcconfig, with the added advantage + of having a single FeatureDefines file across all projects. + + * Configurations/FeatureDefines.xcconfig: Add comments about keeping feature definitions in sync. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Add FeatureDefines.vsprops inherited property sheet. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: Add FeatureDefines.vsprops inherited property sheet. + +2010-01-20 Csaba Osztrogonác <ossy@webkit.org> + + [Qt] Unreviewed buildfix for r53547. + + * DerivedSources.pro: + +2010-01-20 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Make extraCompilers for generated sources depend on their scripts + + * DerivedSources.pro: + +2010-01-19 Brian Weinstein <bweinstein@apple.com> + + Reviewed by Tim Hatcher. + + When JavaScriptCore calls Debugger::Exception, have it pass a + hasHandler variable that represents if exception is being handled + in the same function (not in a parent on the call stack). + + This just adds a new parameter, no behavior is changed. + + * debugger/Debugger.h: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): + +2010-01-18 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Adam Barth. + + Inline functions that are hot in DOM manipulation + https://bugs.webkit.org/show_bug.cgi?id=33820 + + (3% speedup on Dromaeo DOM Core tests) + + * runtime/WeakGCMap.h: + (JSC::::get): inline + +2010-01-19 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed build fix for JIT with RVCT. + + Remove IMPORT statement; cti_vm_throw is already defined in JITStubs.h. + Remove extra ')'. + + * jit/JITStubs.cpp: + (JSC::ctiVMThrowTrampoline): + +2010-01-19 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + REGRESSION (52082): Crash on worker thread when reloading http://radnan.public.iastate.edu/procedural/ + https://bugs.webkit.org/show_bug.cgi?id=33826 + + This bug was caused by a GC-protected object being destroyed early by + Heap::destroy. Clients of the GC protect APIs (reasonably) expect pointers + to GC-protected memory to be valid. + + The solution is to do two passes of tear-down in Heap::destroy. The first + pass tears down all unprotected objects. The second pass ASSERTs that all + previously protected objects are now unprotected, and then tears down + all perviously protected objects. These two passes simulate the two passes + that would have been required to free a protected object during normal GC. + + * API/JSContextRef.cpp: Removed some ASSERTs that have moved into Heap. + + * runtime/Collector.cpp: + (JSC::Heap::destroy): Moved ASSERTs to here. + (JSC::Heap::freeBlock): Tidied up the use of didShrink by moving its + setter to the function that does the shrinking. + (JSC::Heap::freeBlocks): Implemented above algorithm. + (JSC::Heap::shrinkBlocks): Tidied up the use of didShrink. + +2010-01-19 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix). + + Reverting r53455, breaks 2 javascriptcore tests. + + * API/JSContextRef.cpp: + * runtime/Collector.cpp: + (JSC::Heap::destroy): + (JSC::Heap::freeBlock): + (JSC::Heap::freeBlocks): + (JSC::Heap::shrinkBlocks): + +2010-01-18 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix). + + Revert r53454, since it causes much sadness in this world. + + * runtime/UString.cpp: + (JSC::UString::spliceSubstringsWithSeparators): + (JSC::UString::replaceRange): + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::baseSharedBuffer): + (JSC::UStringImpl::sharedBuffer): + (JSC::UStringImpl::~UStringImpl): + * runtime/UStringImpl.h: + (JSC::UntypedPtrAndBitfield::UntypedPtrAndBitfield): + (JSC::UntypedPtrAndBitfield::asPtr): + (JSC::UntypedPtrAndBitfield::operator&=): + (JSC::UntypedPtrAndBitfield::operator|=): + (JSC::UntypedPtrAndBitfield::operator&): + (JSC::UStringImpl::create): + (JSC::UStringImpl::cost): + (JSC::UStringImpl::isIdentifier): + (JSC::UStringImpl::setIsIdentifier): + (JSC::UStringImpl::ref): + (JSC::UStringImpl::deref): + (JSC::UStringImpl::checkConsistency): + (JSC::UStringImpl::UStringImpl): + (JSC::UStringImpl::bufferOwnerString): + (JSC::UStringImpl::bufferOwnership): + (JSC::UStringImpl::isStatic): + * wtf/StringHashFunctions.h: + (WTF::stringHash): + +2010-01-18 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + REGRESSION (52082): Crash on worker thread when reloading http://radnan.public.iastate.edu/procedural/ + https://bugs.webkit.org/show_bug.cgi?id=33826 + + This bug was caused by a GC-protected object being destroyed early by + Heap::destroy. Clients of the GC protect APIs (reasonably) expect pointers + to GC-protected memory to be valid. + + The solution is to do two passes of tear-down in Heap::destroy. The first + pass tears down all unprotected objects. The second pass ASSERTs that all + previously protected objects are now unprotected, and then tears down + all perviously protected objects. These two passes simulate the two passes + that would have been required to free a protected object during normal GC. + + * API/JSContextRef.cpp: Removed some ASSERTs that have moved into Heap. + + * runtime/Collector.cpp: + (JSC::Heap::destroy): Moved ASSERTs to here. + (JSC::Heap::freeBlock): Tidied up the use of didShrink by moving its + setter to the function that does the shrinking. + (JSC::Heap::freeBlocks): Implemented above algorithm. + (JSC::Heap::shrinkBlocks): Tidied up the use of didShrink. + +2010-01-18 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=33731 + Remove UntypedPtrAndBitfield from UStringImpl (akin to PtrAndFlags). + + This break the OS X Leaks tool. Instead, free up some more bits from the refCount. + + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::sharedBuffer): + (JSC::UStringImpl::~UStringImpl): + * runtime/UStringImpl.h: + (JSC::UStringImpl::cost): + (JSC::UStringImpl::checkConsistency): + (JSC::UStringImpl::UStringImpl): + (JSC::UStringImpl::bufferOwnerString): + (JSC::UStringImpl::): + * wtf/StringHashFunctions.h: + (WTF::stringHash): + +2010-01-18 Kent Tamura <tkent@chromium.org> + + Reviewed by Darin Adler. + + HTMLInputElement::valueAsDate setter support for type=month. + https://bugs.webkit.org/show_bug.cgi?id=33021 + + Expose the following functions to be used by WebCore: + - WTF::msToyear() + - WTF::dayInYear() + - WTF::monthFromDayInYear() + - WTF::dayInMonthFromDayInYear() + + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * wtf/DateMath.cpp: + (WTF::msToYear): Remove "static inline". + (WTF::dayInYear): Remove "static inline". + (WTF::monthFromDayInYear): Remove "static inline". + (WTF::dayInMonthFromDayInYear): Remove "static inline". + * wtf/DateMath.h: Declare the above functions. + +2010-01-18 Darin Adler <darin@apple.com> + + Fix build by reverting the previous change. + + * runtime/UString.h: Rolled out the FastAllocBase base class. + It was making UString larger, and therefore JSString larger, + and too big for a garbage collection cell. + + This raises the unpleasant possibility that many classes became + larger because we added the FastAllocBase base class. I am + worried about this, and it needs to be investigated. + +2010-01-18 Zoltan Horvath <zoltan@webkit.org> + + Reviewed by Darin Adler. + + Allow custom memory allocation control for UString class + https://bugs.webkit.org/show_bug.cgi?id=27831 + + Inherits the following class from FastAllocBase because it is + instantiated by 'new' and no need to be copyable: + + class name - instantiated at: + classs UString - JavaScriptCore/runtime/UString.cpp:160 + + * runtime/UString.h: + +2010-01-18 Evan Cheng <evan.cheng@apple.com> + + Reviewed by Darin Adler. + + Add some ALWAYS_INLINE for key functions not inlined by some versions of GCC. + rdar://problem/7553780 + + * runtime/JSObject.h: + (JSC::JSObject::getPropertySlot): ALWAYS_INLINE both overloads. + * runtime/JSString.h: + (JSC::JSString::JSString): ALWAYS_INLINE the version that takes a UString. + * runtime/UString.h: + (JSC::operator==): ALWAYS_INLINE the version that compares two UString objects. + +2010-01-18 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed by Darin Adler. + + Delete dftables-xxxxxxxx.in files automatically. + https://bugs.webkit.org/show_bug.cgi?id=33796 + + * pcre/dftables: unlink unnecessary temporary file. + +2010-01-18 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Force qmake to generate a single makefile for DerivedSources.pro + + * DerivedSources.pro: + +2010-01-18 Csaba Osztrogonác <ossy@webkit.org> + + Rubber-stamped by Gustavo Noronha Silva. + + Rolling out r53391 and r53392 because of random crashes on buildbots. + https://bugs.webkit.org/show_bug.cgi?id=33731 + + * bytecode/CodeBlock.h: + (JSC::CallLinkInfo::seenOnce): + (JSC::CallLinkInfo::setSeen): + (JSC::MethodCallLinkInfo::MethodCallLinkInfo): + (JSC::MethodCallLinkInfo::seenOnce): + (JSC::MethodCallLinkInfo::setSeen): + * jit/JIT.cpp: + (JSC::JIT::unlinkCall): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::patchMethodCallProto): + * runtime/UString.cpp: + (JSC::UString::spliceSubstringsWithSeparators): + (JSC::UString::replaceRange): + * runtime/UString.h: + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::baseSharedBuffer): + (JSC::UStringImpl::sharedBuffer): + (JSC::UStringImpl::~UStringImpl): + * runtime/UStringImpl.h: + (JSC::UntypedPtrAndBitfield::UntypedPtrAndBitfield): + (JSC::UntypedPtrAndBitfield::asPtr): + (JSC::UntypedPtrAndBitfield::operator&=): + (JSC::UntypedPtrAndBitfield::operator|=): + (JSC::UntypedPtrAndBitfield::operator&): + (JSC::UStringImpl::create): + (JSC::UStringImpl::cost): + (JSC::UStringImpl::isIdentifier): + (JSC::UStringImpl::setIsIdentifier): + (JSC::UStringImpl::ref): + (JSC::UStringImpl::deref): + (JSC::UStringImpl::checkConsistency): + (JSC::UStringImpl::UStringImpl): + (JSC::UStringImpl::bufferOwnerString): + (JSC::UStringImpl::bufferOwnership): + (JSC::UStringImpl::isStatic): + * wtf/StringHashFunctions.h: + (WTF::stringHash): + +2010-01-18 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Fix the build with strict gcc and RVCT versions: It's not legal to cast a + pointer to a function to a void* without an intermediate cast to a non-pointer + type. A cast to a ptrdiff_t inbetween fixes it. + + * runtime/JSString.h: + (JSC::Fiber::JSString): + +2010-01-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=33731 + Remove UntypedPtrAndBitfield from UStringImpl (akin to PtrAndFlags). + + This break the OS X Leaks tool. Instead, free up some more bits from the refCount. + + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::sharedBuffer): + (JSC::UStringImpl::~UStringImpl): + * runtime/UStringImpl.h: + (JSC::UStringImpl::cost): + (JSC::UStringImpl::checkConsistency): + (JSC::UStringImpl::UStringImpl): + (JSC::UStringImpl::bufferOwnerString): + (JSC::UStringImpl::): + * wtf/StringHashFunctions.h: + (WTF::stringHash): + +2010-01-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=33731 + Remove uses of PtrAndFlags from JIT data stuctures. + + These break the OS X Leaks tool. Free up a bit in CallLinkInfo, and invalid + permutation of pointer states in MethodCallLinkInfo to represent the removed bits. + + * bytecode/CodeBlock.h: + (JSC::CallLinkInfo::seenOnce): + (JSC::CallLinkInfo::setSeen): + (JSC::MethodCallLinkInfo::MethodCallLinkInfo): + (JSC::MethodCallLinkInfo::seenOnce): + (JSC::MethodCallLinkInfo::setSeen): + * jit/JIT.cpp: + (JSC::JIT::unlinkCall): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::patchMethodCallProto): + * runtime/UString.h: + +2010-01-16 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Oliver Hunt. + + Cache JS string values made from DOM strings (Dromaeo speedup) + https://bugs.webkit.org/show_bug.cgi?id=33768 + <rdar://problem/7353576> + + * runtime/JSString.h: + (JSC::jsStringWithFinalizer): Added new mechanism for a string to have an optional + finalizer callback, for the benefit of weak-referencing caches. + (JSC::): + (JSC::Fiber::JSString): + (JSC::Fiber::~JSString): + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): Clear fibers so this doesn't look like a string with a finalizer. + * runtime/WeakGCMap.h: Include "Collector.h" to make this header includable by itself. + +2010-01-15 Sam Weinig <sam@webkit.org> + + Reviewed by Maciej Stachowiak. + + Fix for <rdar://problem/7548432> + Add ALWAYS_INLINE to jsLess for a 1% speedup on llvm-gcc. + + * runtime/Operations.h: + (JSC::jsLess): + +2010-01-14 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + REGRESISON: Google maps buttons not working properly + https://bugs.webkit.org/show_bug.cgi?id=31871 + + REGRESSION(r52948): JavaScript exceptions thrown on Google Maps when + getting directions for a second time + https://bugs.webkit.org/show_bug.cgi?id=33446 + + SunSpider and v8 report no change. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::tryCacheGetByID): Update our cached offset in case + flattening the dictionary changed any of its offsets. + + * jit/JITStubs.cpp: + (JSC::JITThunks::tryCacheGetByID): + (JSC::DEFINE_STUB_FUNCTION): + * runtime/Operations.h: + (JSC::normalizePrototypeChain): ditto + +2010-01-14 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=33705 + UStringImpl::create() should use internal storage + + When creating a UStringImpl copying of a UChar*, we can use an internal buffer, + by calling UStringImpl::tryCreateUninitialized(). + + Also, remove duplicate of copyChars from JSString, call UStringImpl's version. + + Small (max 0.5%) progression on Sunspidey. + + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + * runtime/UStringImpl.h: + (JSC::UStringImpl::create): + +2010-01-14 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Make naming & behaviour of UString[Impl] methods more consistent. + https://bugs.webkit.org/show_bug.cgi?id=33702 + + UString::create() creates a copy of the UChar* passed, but UStringImpl::create() assumes + that it should assume ownership of the provided buffer (with UString::createNonCopying() + and UStringImpl::createCopying() providing the alternate behaviours). Unify on create() + taking a copy of the provided buffer. For non-copying cases, use the name 'adopt', and + make this method take a Vector<UChar>&. For cases where non-copying construction was being + used, other than from a Vector<UChar>, change the code to allocate the storage along with + the UStringImpl using UStringImpl::createUninitialized(). (The adopt() method also more + closely matches that of WebCore::StringImpl). + + Also, UString::createUninitialized() and UStringImpl::createUninitialized() have incompatible + behaviours, in that the UString form sets the provided UChar* to a null or non-null value to + indicate success or failure, but UStringImpl uses the returned PassRefPtr<UStringImpl> to + indicate when allocation has failed (potentially leaving the output Char* uninitialized). + This is also incompatible with WebCore::StringImpl's behaviour, in that + StringImpl::createUninitialized() will CRASH() if unable to allocate. Some uses of + createUninitialized() in JSC are unsafe, since they do not test the result for null. + UStringImpl's indication is preferable, since we may want a successful call to set the result + buffer to 0 (specifically, StringImpl returns 0 for the buffer where createUninitialized() + returns the empty string, which seems reasonable to catch bugs early). UString's method + cannot support UStringImpl's behaviour directly, since it returns an object rather than a + pointer. + - remove UString::createUninitialized(), replace with calls to UStringImpl::createUninitialized() + - create a UStringImpl::tryCreateUninitialized() form UStringImpl::createUninitialized(), + with current behaviour, make createUninitialized() crash on failure to allocate. + - make cases in JSC that do not check the result call createUninitialized(), and cases that do + check call tryCreateUninitialized(). + + Rename computedHash() to existingHash(), to bring this in line wih WebCore::StringImpl. + + * API/JSClassRef.cpp: + (OpaqueJSClassContextData::OpaqueJSClassContextData): + * JavaScriptCore.exp: + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + * runtime/Identifier.cpp: + (JSC::CStringTranslator::translate): + (JSC::UCharBufferTranslator::translate): + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + * runtime/Lookup.cpp: + (JSC::HashTable::createTable): + * runtime/Lookup.h: + (JSC::HashTable::entry): + * runtime/StringBuilder.h: + (JSC::StringBuilder::release): + * runtime/StringConstructor.cpp: + (JSC::stringFromCharCodeSlowCase): + * runtime/StringPrototype.cpp: + (JSC::substituteBackreferencesSlow): + (JSC::stringProtoFuncToLowerCase): + (JSC::stringProtoFuncToUpperCase): + (JSC::stringProtoFuncFontsize): + (JSC::stringProtoFuncLink): + * runtime/Structure.cpp: + (JSC::Structure::despecifyDictionaryFunction): + (JSC::Structure::get): + (JSC::Structure::despecifyFunction): + (JSC::Structure::put): + (JSC::Structure::remove): + (JSC::Structure::insertIntoPropertyMapHashTable): + (JSC::Structure::checkConsistency): + * runtime/Structure.h: + (JSC::Structure::get): + * runtime/StructureTransitionTable.h: + (JSC::StructureTransitionTableHash::hash): + * runtime/UString.cpp: + (JSC::createRep): + (JSC::UString::UString): + (JSC::UString::spliceSubstringsWithSeparators): + (JSC::UString::replaceRange): + (JSC::UString::operator=): + * runtime/UString.h: + (JSC::UString::adopt): + (JSC::IdentifierRepHash::hash): + (JSC::makeString): + * runtime/UStringImpl.h: + (JSC::UStringImpl::adopt): + (JSC::UStringImpl::create): + (JSC::UStringImpl::createUninitialized): + (JSC::UStringImpl::tryCreateUninitialized): + (JSC::UStringImpl::existingHash): + +2010-01-13 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Oliver Hunt. + + JSON.stringify and JSON.parse needlessly process properties in the prototype chain + https://bugs.webkit.org/show_bug.cgi?id=33053 + + * runtime/JSONObject.cpp: + (JSC::Stringifier::Holder::appendNextProperty): + (JSC::Walker::walk): + +2010-01-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (buildfix). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-01-13 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=33641 + Assertion failure in Lexer.cpp if input stream ends while in string escape + + Test: fast/js/end-in-string-escape.html + + * parser/Lexer.cpp: (JSC::Lexer::lex): Bail out quickly on end of stream, not giving the + assertion a chance to fire. + +2010-01-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (buildfix). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-01-13 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Sam Weinig & Darin Adler. + + Three quick fixes to UStringImpl. + - The destroy() method can be switched back to a normal destructor; since we've switched + the way we protect static strings to be using an odd ref-count the destroy() won't abort. + - The cost() calculation logic was wrong. If you have multiple JSStrings wrapping substrings + of a base string, they would each report the full cost of the base string to the heap. + Instead we should only be reporting once for the base string. + - Remove the overloaded new operator calling fastMalloc, replace this with a 'using' to pick + up the implementation from the parent class. + + * JavaScriptCore.exp: + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::~UStringImpl): + * runtime/UStringImpl.h: + (JSC::UStringImpl::cost): + (JSC::UStringImpl::deref): + +2010-01-13 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Split the build process in two different .pro files. + This allows qmake to be run once all source files are available. + + * DerivedSources.pro: Added. + * JavaScriptCore.pri: Moved source generation to DerivedSources.pro + * pcre/pcre.pri: Moved source generation to DerivedSources.pro + +2010-01-12 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Geoffrey Garen. + + [ES5] Implement Object.getOwnPropertyNames + https://bugs.webkit.org/show_bug.cgi?id=32242 + + Add an extra argument to getPropertyNames() and getOwnPropertyNames() + (and all reimplementations thereof) that indicates whether non-enumerable + properties should be added. + + * API/JSCallbackObject.h: + * API/JSCallbackObjectFunctions.h: + (JSC::::getOwnPropertyNames): + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * debugger/DebuggerActivation.cpp: + (JSC::DebuggerActivation::getOwnPropertyNames): + * debugger/DebuggerActivation.h: + * runtime/Arguments.cpp: + (JSC::Arguments::getOwnPropertyNames): + * runtime/Arguments.h: + * runtime/CommonIdentifiers.h: + * runtime/JSArray.cpp: + (JSC::JSArray::getOwnPropertyNames): + * runtime/JSArray.h: + * runtime/JSByteArray.cpp: + (JSC::JSByteArray::getOwnPropertyNames): + * runtime/JSByteArray.h: + * runtime/JSFunction.cpp: + (JSC::JSFunction::getOwnPropertyNames): + * runtime/JSFunction.h: + * runtime/JSNotAnObject.cpp: + (JSC::JSNotAnObject::getOwnPropertyNames): + * runtime/JSNotAnObject.h: + * runtime/JSObject.cpp: + (JSC::getClassPropertyNames): + (JSC::JSObject::getPropertyNames): + (JSC::JSObject::getOwnPropertyNames): + * runtime/JSObject.h: + * runtime/JSVariableObject.cpp: + (JSC::JSVariableObject::getOwnPropertyNames): + * runtime/JSVariableObject.h: + * runtime/ObjectConstructor.cpp: + (JSC::ObjectConstructor::ObjectConstructor): + (JSC::objectConstructorGetOwnPropertyNames): + * runtime/RegExpMatchesArray.h: + (JSC::RegExpMatchesArray::getOwnPropertyNames): + * runtime/StringObject.cpp: + (JSC::StringObject::getOwnPropertyNames): + * runtime/StringObject.h: + * runtime/Structure.cpp: Rename getEnumerablePropertyNames() to getPropertyNames(), which takes an extra argument. + (JSC::Structure::getPropertyNames): + * runtime/Structure.h: + (JSC::): + +2010-01-12 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=33540 + Make it possible to build in debug mode with assertions disabled + + * jit/JITStubs.cpp: (JSC::DEFINE_STUB_FUNCTION): + * runtime/Identifier.cpp: (JSC::Identifier::checkSameIdentifierTable): + * wtf/FastMalloc.cpp: + * wtf/HashTable.h: (WTF::HashTableConstIterator::checkValidity): + * yarr/RegexCompiler.cpp: (JSC::Yarr::compileRegex): + +2009-11-23 Yong Li <yoli@rim.com> + + Reviewed by Adam Treat. + + Make GIF decoder support down-sampling + https://bugs.webkit.org/show_bug.cgi?id=31806 + + * platform/image-decoders/ImageDecoder.cpp: + (WebCore::ImageDecoder::upperBoundScaledY): + (WebCore::ImageDecoder::lowerBoundScaledY): + * platform/image-decoders/ImageDecoder.h: + (WebCore::RGBA32Buffer::scaledRect): + (WebCore::RGBA32Buffer::setScaledRect): + (WebCore::ImageDecoder::scaledSize): + * platform/image-decoders/gif/GIFImageDecoder.cpp: + (WebCore::GIFImageDecoder::sizeNowAvailable): + (WebCore::GIFImageDecoder::initFrameBuffer): + (WebCore::copyOnePixel): + (WebCore::GIFImageDecoder::haveDecodedRow): + (WebCore::GIFImageDecoder::frameComplete): + +2010-01-12 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + ecma/Date/15.9.5.12-1.js fails every night at midnight + https://bugs.webkit.org/show_bug.cgi?id=28041 + + Change the test to use a concrete time instead of "now". + + * tests/mozilla/ecma/Date/15.9.5.10-1.js: + * tests/mozilla/ecma/Date/15.9.5.12-1.js: + +2010-01-11 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed by Ariya Hidayat. + + [Qt] Enable JIT and YARR_JIT if (CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100) + + * wtf/Platform.h: + +2010-01-11 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=33481 + Uninitialized data members in ArrayStorage + + SunSpider reports no change. + + * runtime/JSArray.cpp: + (JSC::JSArray::JSArray): Initialize missing data members in the two cases + where we don't use fastZeroedMalloc, so it doesn't happen automatically. + +2010-01-11 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Sam Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=33480 + + Improve debugging reliability for WTF on Windows. + Store WTF static library's PDB file into a better location. + + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + +2010-01-11 Steve Falkenburg <sfalken@apple.com> + + Windows build fix. + Remove extraneous entries from def file causing build warning. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-01-10 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Darin Adler. + + RegExp.prototype.toString returns "//" for empty regular expressions + https://bugs.webkit.org/show_bug.cgi?id=33319 + + "//" starts a single-line comment, hence "/(?:)/" should be used, according to ECMA. + + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncToString): + + * tests/mozilla/ecma_2/RegExp/properties-001.js: + (AddRegExpCases): + * tests/mozilla/js1_2/regexp/toString.js: + Update relevant Mozilla tests (Mozilla has had this behavior since November 2003). + +2010-01-10 Darin Adler <darin@apple.com> + + * tests/mozilla/ecma/Array/15.4.1.1.js: Added property allow-tabs. + * tests/mozilla/ecma/Array/15.4.1.2.js: Added property allow-tabs. + * tests/mozilla/ecma/Array/15.4.2.1-1.js: Added property allow-tabs. + * tests/mozilla/ecma/Array/15.4.2.2-1.js: Added property allow-tabs. + * tests/mozilla/ecma/Array/15.4.2.2-2.js: Added property allow-tabs. + * tests/mozilla/ecma/Array/15.4.2.3.js: Added property allow-tabs. + * tests/mozilla/ecma/Array/15.4.3.2.js: Added property allow-tabs. + * tests/mozilla/ecma/Array/15.4.3.js: Added property allow-tabs. + * tests/mozilla/ecma/Array/15.4.4.1.js: Added property allow-tabs. + * tests/mozilla/ecma/Array/15.4.4.js: Added property allow-tabs. + * tests/mozilla/ecma/LexicalConventions/7.7.4.js: Added property allow-tabs. + * tests/mozilla/ecma/Math/15.8.2.13.js: Added property allow-tabs. + * tests/mozilla/ecma/Math/15.8.2.16.js: Added property allow-tabs. + * tests/mozilla/ecma/Math/15.8.2.18.js: Added property allow-tabs. + * tests/mozilla/ecma/Math/15.8.2.2.js: Added property allow-tabs. + * tests/mozilla/ecma/Math/15.8.2.4.js: Added property allow-tabs. + * tests/mozilla/ecma/Math/15.8.2.5.js: Added property allow-tabs. + * tests/mozilla/ecma/Math/15.8.2.7.js: Added property allow-tabs. + * tests/mozilla/ecma/String/15.5.1.js: Added property allow-tabs. + * tests/mozilla/ecma/String/15.5.2.js: Added property allow-tabs. + * tests/mozilla/ecma/String/15.5.3.1-3.js: Added property allow-tabs. + * tests/mozilla/ecma/String/15.5.3.1-4.js: Added property allow-tabs. + * tests/mozilla/ecma/String/15.5.3.js: Added property allow-tabs. + * tests/mozilla/ecma/TypeConversion/9.5-2.js: Added property allow-tabs. + * tests/mozilla/ecma/jsref.js: Modified property allow-tabs. + * tests/mozilla/ecma/shell.js: Modified property allow-tabs. + * tests/mozilla/ecma_2/LexicalConventions/keywords-001.js: Added property allow-tabs. + * tests/mozilla/ecma_2/RegExp/exec-001.js: Added property allow-tabs. + * tests/mozilla/ecma_2/String/match-004.js: Added property allow-tabs. + * tests/mozilla/ecma_2/String/replace-001.js: Added property allow-tabs. + * tests/mozilla/ecma_2/String/split-002.js: Added property allow-tabs. + * tests/mozilla/ecma_2/jsref.js: Modified property allow-tabs. + * tests/mozilla/ecma_2/shell.js: Added property allow-tabs. + * tests/mozilla/ecma_3/Date/shell.js: Modified property allow-tabs. + * tests/mozilla/ecma_3/Exceptions/regress-181654.js: Added property allow-tabs. + * tests/mozilla/ecma_3/RegExp/regress-209067.js: Added property allow-tabs. + * tests/mozilla/ecma_3/RegExp/regress-85721.js: Added property allow-tabs. + * tests/mozilla/importList.html: Added property allow-tabs. + * tests/mozilla/js1_1/shell.js: Added property allow-tabs. + * tests/mozilla/js1_2/Array/general1.js: Added property allow-tabs. + * tests/mozilla/js1_2/Array/general2.js: Added property allow-tabs. + * tests/mozilla/js1_2/Array/slice.js: Added property allow-tabs. + * tests/mozilla/js1_2/Array/splice1.js: Added property allow-tabs. + * tests/mozilla/js1_2/Array/splice2.js: Added property allow-tabs. + * tests/mozilla/js1_2/Objects/toString-001.js: Added property allow-tabs. + * tests/mozilla/js1_2/String/charCodeAt.js: Added property allow-tabs. + * tests/mozilla/js1_2/String/concat.js: Modified property allow-tabs. + * tests/mozilla/js1_2/String/match.js: Added property allow-tabs. + * tests/mozilla/js1_2/String/slice.js: Added property allow-tabs. + * tests/mozilla/js1_2/function/Function_object.js: Added property allow-tabs. + * tests/mozilla/js1_2/function/Number.js: Modified property allow-tabs. + * tests/mozilla/js1_2/function/String.js: Modified property allow-tabs. + * tests/mozilla/js1_2/function/nesting.js: Added property allow-tabs. + * tests/mozilla/js1_2/function/regexparg-1.js: Added property allow-tabs. + * tests/mozilla/js1_2/function/regexparg-2-n.js: Added property allow-tabs. + * tests/mozilla/js1_2/jsref.js: Added property allow-tabs. + * tests/mozilla/js1_2/operator/equality.js: Added property allow-tabs. + * tests/mozilla/js1_2/operator/strictEquality.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_dollar_number.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_input.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_input_as_array.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_lastIndex.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_lastMatch.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_lastMatch_as_array.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_lastParen.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_lastParen_as_array.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_leftContext.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_leftContext_as_array.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_multiline.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_multiline_as_array.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_object.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_rightContext.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/RegExp_rightContext_as_array.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/alphanumeric.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/asterisk.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/backslash.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/backspace.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/beginLine.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/character_class.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/compile.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/control_characters.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/digit.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/dot.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/endLine.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/everything.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/exec.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/flags.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/global.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/hexadecimal.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/ignoreCase.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/interval.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/octal.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/parentheses.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/plus.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/question_mark.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/simple_form.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/source.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/special_characters.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/string_replace.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/string_search.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/string_split.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/test.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/toString.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/vertical_bar.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/whitespace.js: Added property allow-tabs. + * tests/mozilla/js1_2/regexp/word_boundary.js: Added property allow-tabs. + * tests/mozilla/js1_2/shell.js: Added property allow-tabs. + * tests/mozilla/js1_2/statements/break.js: Added property allow-tabs. + * tests/mozilla/js1_2/statements/continue.js: Added property allow-tabs. + * tests/mozilla/js1_2/statements/do_while.js: Added property allow-tabs. + * tests/mozilla/js1_2/statements/switch.js: Added property allow-tabs. + * tests/mozilla/js1_2/statements/switch2.js: Added property allow-tabs. + * tests/mozilla/js1_3/shell.js: Added property allow-tabs. + * tests/mozilla/js1_4/shell.js: Added property allow-tabs. + * tests/mozilla/js1_5/Regress/regress-111557.js: Added property allow-tabs. + * tests/mozilla/js1_5/Regress/regress-216320.js: Added property allow-tabs. + * tests/mozilla/menuhead.html: Added property allow-tabs. + * tests/mozilla/mklistpage.pl: Added property allow-tabs. + * tests/mozilla/runtests.pl: Added property allow-tabs. + +2010-01-08 Daniel Bates <dbates@webkit.org> + + Reviewed by Adam Barth. + + https://bugs.webkit.org/show_bug.cgi?id=33417 + + Cleans up style errors exposed by the patch for bug #33198. + Moreover, fixes all "Weird number of spaces at line-start. Are you using a 4-space indent?" + errors reported by check-webkit-style. + + No functionality was changed. So, no new tests. + + * wtf/Platform.h: + +2010-01-08 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Eric Seidel. + + Don't store RegExp flags string representation + https://bugs.webkit.org/show_bug.cgi?id=33321 + + It's unused; the string representation is reconstructed from flags. + + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + * runtime/RegExp.h: + +2010-01-08 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Memory use grows grows possibly unbounded in this JavaScript Array test case + https://bugs.webkit.org/show_bug.cgi?id=31675 + + This fixes one observed bug in this test case, which is that + arrays don't report extra cost for the sparse value maps. + + SunSpider reports a small speedup. + + * runtime/JSArray.cpp: + (JSC::JSArray::putSlowCase): Report extra memory cost for + the sparse value map. + * runtime/JSArray.h: + +2010-01-08 Yong Li <yoli@rim.com> + + Reviewed by Darin Adler. + + Remove unnecessary #include from FastMalloc.cpp + https://bugs.webkit.org/show_bug.cgi?id=33393 + + * wtf/FastMalloc.cpp: + +2010-01-08 Eric Seidel <eric@webkit.org> + + No review, rolling out r52983. + http://trac.webkit.org/changeset/52983 + https://bugs.webkit.org/show_bug.cgi?id=33321 + + Broke 59 JavaScriptCore tests. I don't think Kent knew about + run-javascriptcore-tests. Sadly neither does the commit-bot, + yet. + + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + * runtime/RegExp.h: + (JSC::RegExp::flags): + +2010-01-08 Eric Seidel <eric@webkit.org> + + No review, rolling out r52981. + http://trac.webkit.org/changeset/52981 + https://bugs.webkit.org/show_bug.cgi?id=33319 + + Caused two JS tests to start failing: + ecma_2/RegExp/properties-001.js and js1_2/regexp/toString.js + + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncToString): + +2010-01-08 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Darin Adler. + + Don't store RegExp flags string representation + https://bugs.webkit.org/show_bug.cgi?id=33321 + + It's unused; the string representation is reconstructed from flags. + + * runtime/RegExp.cpp: + (JSC::RegExp::RegExp): + * runtime/RegExp.h: + +2010-01-08 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Darin Adler. + + RegExp.prototype.toString returns "//" for empty regular expressions + https://bugs.webkit.org/show_bug.cgi?id=33319 + + "//" starts a single-line comment, hence "/(?:)/" should be used, according to ECMA. + + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncToString): + +2010-01-08 Norbert Leser <norbert.leser@nokia.com> + + Reviewed by Darin Adler. + + RVCT compiler with "-Otime -O3" optimization tries to optimize out + inline new'ed pointers that are passed as arguments. + Proposed patch assigns new'ed pointer explicitly outside function call. + + https://bugs.webkit.org/show_bug.cgi?id=33084 + + * API/JSClassRef.cpp: + (OpaqueJSClass::OpaqueJSClass): + (OpaqueJSClassContextData::OpaqueJSClassContextData): + +2010-01-08 Gabor Loki <loki@webkit.org> + + Reviewed by Gavin Barraclough. + + Remove an unnecessary cacheFlush from ARM_TRADITIONAL JIT + https://bugs.webkit.org/show_bug.cgi?id=33203 + + * assembler/ARMAssembler.cpp: Remove obsolete linkBranch function. + (JSC::ARMAssembler::executableCopy): Inline a clean linkBranch code. + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::getLdrImmAddress): Use inline function. + (JSC::ARMAssembler::getLdrImmAddressOnPool): Ditto. + (JSC::ARMAssembler::patchPointerInternal): Remove an unnecessary cacheFlush. + (JSC::ARMAssembler::linkJump): Use patchPointerInternal instead of linkBranch. + (JSC::ARMAssembler::linkCall): Ditto. + (JSC::ARMAssembler::relinkCall): Ditto. + +2010-01-07 Gabor Loki <loki@webkit.org> + + Reviewed by Gavin Barraclough. + + Build fix for JSVALUE32 when ENABLE_JIT_OPTIMIZE* are disabled + https://bugs.webkit.org/show_bug.cgi?id=33311 + + Move compileGetDirectOffset function to common part of JSVALUE32 + + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetDirectOffset): + +2010-01-07 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Maciej Stachowiak. + + Allow call sites to determine if ASSERT_* and LOG_* macros are operational + https://bugs.webkit.org/show_bug.cgi?id=33020 + + * wtf/Assertions.h: Set ASSERT_MSG_DISABLED, FATAL_DISABLED, + ERROR_DISABLED, LOG_DISABLED to 1 if the compiler does not support + variadic macros. Refactor for better readibility. + +2010-01-07 Daniel Bates <dbates@rim.com> + + Reviewed by Eric Seidel. + + https://bugs.webkit.org/show_bug.cgi?id=32987 + + Added ENABLE_XHTMLMP flag. Disabled by default. + + * Configurations/FeatureDefines.xcconfig: + +2010-01-07 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Gavin Barraclough. + + [Symbian] Port ARM traditional JIT Trampolines to RVCT + https://bugs.webkit.org/show_bug.cgi?id=30552 + + Take the GCC implementation and mechanically convert + it to RVCT syntax. + + Use 'bx rX' instead of 'mov pc, rX' when it is available. + + Developed in cooperation with Iain Campbell and Gabor Loki. + + * JavaScriptCore.pri: Extra step to generate RVCT stubs. The + script generation intentionally executed all the time not just + for RVCT targets. + + * create_rvct_stubs: Added. Perl script to expand precompiler macros + for RVCT assembler - the template is defined in JITStubs.cpp. + + * jit/JITStubs.cpp: + (JSC::ctiTrampoline): + (JSC::ctiVMThrowTrampoline): + (JSC::ctiOpThrowNotCaught): + +2010-01-07 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Fix a crash seen on the buildbots. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::init): Disable specific function tracking here, + instead of in WebCore, to ensure that the disabling happens before a + specific function can be registered. + +2010-01-07 Alexey Proskuryakov <ap@apple.com> + + Mac build fix. + + * JavaScriptCore.exp: Export new JSGlobalData static data members. + +2010-01-07 Alexey Proskuryakov <ap@apple.com> + + 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. + +2010-01-07 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Safari memory usage skyrockets using new Google AdWords interface + https://bugs.webkit.org/show_bug.cgi?id=33343 + + The memory use was caused by the global object creating too many structures + as it thrashed between different specific functions. + + * runtime/Structure.cpp: + (JSC::Structure::Structure): + (JSC::Structure::addPropertyTransition): + (JSC::Structure::changePrototypeTransition): + (JSC::Structure::despecifyFunctionTransition): + (JSC::Structure::addAnonymousSlotsTransition): + (JSC::Structure::getterSetterTransition): + (JSC::Structure::toDictionaryTransition): + (JSC::Structure::addPropertyWithoutTransition): + (JSC::Structure::despecifyAllFunctions): + * runtime/Structure.h: + (JSC::Structure::disableSpecificFunctionTracking): Track a thrash count + for specific functions. Disable specific function tracking once the + thrash count has been hit. + +2010-01-07 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed by Simon Hausmann. + + [Qt] Enable JIT in debug mode on win32 after r51141 fixed the crashes. + + * JavaScriptCore.pri: + +2010-01-07 Zoltan Horvath <zoltan@webkit.org> + + Reviewed by Holger Freyther. + + [Mac] Build fix when FAST_MALLOC_MATCH_VALIDATION=1 + https://bugs.webkit.org/show_bug.cgi?id=33312 + + Using of operator += cause compile error on Mac, so it is changed to + "= static_cast<AllocAlignmentInteger*>(old_ptr) + 1". + + * wtf/FastMalloc.cpp: + (WTF::TCMallocStats::realloc): + +2010-01-07 Zoltan Horvath <zoltan@webkit.org> + + Reviewed by Holger Freyther. + + [Qt] Build fix when FAST_MALLOC_MATCH_VALIDATION=1 + https://bugs.webkit.org/show_bug.cgi?id=33312 + + Remove pByte (committed in r42344 from #20422), because pByte doesn't + exist and it is unnecessary. + + * wtf/FastMalloc.cpp: + (WTF::TCMallocStats::realloc): + +2010-01-06 Gavin Barraclough <barraclough@apple.com> + + QT build fix. + + * runtime/Identifier.cpp: + (JSC::createIdentifierTableSpecific): + +2010-01-06 Gavin Barraclough <barraclough@apple.com> + + Windows build fix part I. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-01-06 Dan Bernstein <mitz@apple.com> + + Build fix + + * runtime/Identifier.cpp: + (JSC::createIdentifierTableSpecificCallback): + +2010-01-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=33236 + Remove m_identifierTable pointer from UString + + Currently every string holds a pointer so that during destruction, + if a string has been used as an identifier, it can remove itself + from the table. By instead accessing the identifierTable via a + thread specific tracking the table associated with the current + globaldata, we can save the memory cost of this pointer. + + * API/APIShims.h: + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): + (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): + (JSC::APICallbackShim::APICallbackShim): + (JSC::APICallbackShim::~APICallbackShim): + + - change the API shims to track the identifierTable of the current JSGlobalData. + + * API/JSContextRef.cpp: + (JSContextGroupCreate): + + - update creation of JSGlobalData for API usage to use new create method. + - fix shim instanciation bug in JSGlobalContextCreateInGroup. + + * JavaScriptCore.exp: + * runtime/Completion.cpp: + (JSC::checkSyntax): + (JSC::evaluate): + + - add asserts to check the identifierTable is being tracked correctly. + + * runtime/Identifier.cpp: + (JSC::IdentifierTable::~IdentifierTable): + (JSC::IdentifierTable::add): + (JSC::Identifier::remove): + (JSC::Identifier::checkSameIdentifierTable): + (JSC::createIdentifierTableSpecificCallback): + (JSC::createIdentifierTableSpecific): + (JSC::createDefaultDataSpecific): + + - Use currentIdentifierTable() instead of UStringImpl::m_identifierTable. + - Define methods to access the thread specific identifier tables. + + * runtime/Identifier.h: + (JSC::ThreadIdentifierTableData::ThreadIdentifierTableData): + (JSC::defaultIdentifierTable): + (JSC::setDefaultIdentifierTable): + (JSC::currentIdentifierTable): + (JSC::setCurrentIdentifierTable): + (JSC::resetCurrentIdentifierTable): + + - Declare methods to access the thread specific identifier tables. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::createNonDefault): + (JSC::JSGlobalData::create): + (JSC::JSGlobalData::sharedInstance): + + - creation of JSGlobalData objects, other than for API usage, associate themselves with the current thread. + + * runtime/JSGlobalData.h: + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::destroy): + + - destroy() method should be using isIdentifier(). + + * runtime/UStringImpl.h: + (JSC::UStringImpl::isIdentifier): + (JSC::UStringImpl::setIsIdentifier): + (JSC::UStringImpl::checkConsistency): + (JSC::UStringImpl::UStringImpl): + + - replace m_identifierTable with a single m_isIdentifier bit. + + * wtf/StringHashFunctions.h: + (WTF::stringHash): + + - change string hash result from 32-bit to 31-bit, to free a bit in UStringImpl for m_isIdentifier. + +2009-12-25 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Eric Seidel. + + Buildfix for WinCE + style fixes. + https://bugs.webkit.org/show_bug.cgi?id=32939 + + * jsc.cpp: + (functionPrint): + (functionQuit): + (parseArguments): + (fillBufferWithContentsOfFile): + +2010-01-05 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Eric Seidel. + + WinCE buildfix after r52791 (renamed PLATFORM(WINCE) to OS(WINCE)). + https://bugs.webkit.org/show_bug.cgi?id=33205 + + * jit/ExecutableAllocator.h: + +2010-01-05 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Darin Adler. + + Added compiler error for unsupported platforms. + https://bugs.webkit.org/show_bug.cgi?id=33112 + + * jit/JITStubs.cpp: + +2010-01-05 Gabor Loki <loki@webkit.org> + + Reviewed by Maciej Stachowiak. + + Follow r52729 in ARMAssembler. + https://bugs.webkit.org/show_bug.cgi?id=33208 + + Use WTF_ARM_ARCH_AT_LEAST instead of ARM_ARCH_VERSION + + * assembler/ARMAssembler.cpp: + (JSC::ARMAssembler::encodeComplexImm): Move tmp declaration to ARMv7 + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::): + (JSC::ARMAssembler::bkpt): + +2010-01-05 Maciej Stachowiak <mjs@apple.com> + + Unreviewed build fix for Gtk+ + + Don't use // comments in Platform.h, at least some of them seem to make the version of GCC + used on the Gtk buildbot unhappy. + + * wtf/Platform.h: + +2010-01-04 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Darin Fisher. + + Reorganize, document and rename OS() platform macros. + https://bugs.webkit.org/show_bug.cgi?id=33198 + + * wtf/Platform.h: Rename, reorganize and document OS() macros. + + Adapt to name changes. Also fixed a few incorrect OS checks. + + * API/JSContextRef.cpp: + * assembler/MacroAssemblerARM.cpp: + (JSC::isVFPPresent): + * assembler/MacroAssemblerX86Common.h: + * bytecode/SamplingTool.cpp: + * config.h: + * interpreter/RegisterFile.cpp: + (JSC::RegisterFile::~RegisterFile): + * interpreter/RegisterFile.h: + (JSC::RegisterFile::RegisterFile): + (JSC::RegisterFile::grow): + * jit/ExecutableAllocator.h: + * jit/ExecutableAllocatorFixedVMPool.cpp: + * jit/ExecutableAllocatorPosix.cpp: + * jit/ExecutableAllocatorSymbian.cpp: + * jit/ExecutableAllocatorWin.cpp: + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JITStubs.cpp: + * jsc.cpp: + (main): + * parser/Grammar.y: + * profiler/ProfileNode.cpp: + (JSC::getCount): + * runtime/Collector.cpp: + (JSC::Heap::Heap): + (JSC::Heap::allocateBlock): + (JSC::Heap::freeBlockPtr): + (JSC::currentThreadStackBase): + (JSC::getCurrentPlatformThread): + (JSC::suspendThread): + (JSC::resumeThread): + (JSC::getPlatformThreadRegisters): + (JSC::otherThreadStackPointer): + * runtime/Collector.h: + * runtime/DateConstructor.cpp: + * runtime/DatePrototype.cpp: + (JSC::formatLocaleDate): + * runtime/InitializeThreading.cpp: + (JSC::initializeThreading): + * runtime/MarkStack.h: + (JSC::MarkStack::MarkStackArray::shrinkAllocation): + * runtime/MarkStackPosix.cpp: + * runtime/MarkStackSymbian.cpp: + * runtime/MarkStackWin.cpp: + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncLastIndexOf): + * runtime/TimeoutChecker.cpp: + (JSC::getCPUTime): + * runtime/UString.cpp: + (JSC::UString::from): + * wtf/Assertions.cpp: + * wtf/Assertions.h: + * wtf/CurrentTime.cpp: + (WTF::lowResUTCTime): + * wtf/CurrentTime.h: + (WTF::getLocalTime): + * wtf/DateMath.cpp: + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_ThreadCache::InitModule): + (WTF::TCMallocStats::): + * wtf/FastMalloc.h: + * wtf/MathExtras.h: + * wtf/RandomNumber.cpp: + (WTF::randomNumber): + * wtf/RandomNumberSeed.h: + (WTF::initializeRandomNumberGenerator): + * wtf/StringExtras.h: + * wtf/TCSpinLock.h: + (TCMalloc_SpinLock::Unlock): + (TCMalloc_SlowLock): + * wtf/TCSystemAlloc.cpp: + * wtf/ThreadSpecific.h: + (WTF::::destroy): + * wtf/Threading.h: + * wtf/ThreadingPthreads.cpp: + (WTF::initializeThreading): + (WTF::isMainThread): + * wtf/ThreadingWin.cpp: + (WTF::wtfThreadEntryPoint): + (WTF::createThreadInternal): + * wtf/VMTags.h: + * wtf/unicode/icu/CollatorICU.cpp: + (WTF::Collator::userDefault): + * wtf/win/MainThreadWin.cpp: + (WTF::initializeMainThreadPlatform): + +2010-01-04 Gustavo Noronha Silva <gns@gnome.org> + + Add missing files to the build system - make distcheck build fix. + + * GNUmakefile.am: + +2010-01-04 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig, additional coding by Mark Rowe. + + https://bugs.webkit.org/show_bug.cgi?id=33163 + Add string hashing functions to WTF. + Use WTF's string hashing functions from UStringImpl. + + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/UStringImpl.cpp: + * runtime/UStringImpl.h: + (JSC::UStringImpl::computeHash): + * wtf/HashFunctions.h: + * wtf/StringHashFunctions.h: Added. + (WTF::stringHash): + +2010-01-04 Dmitry Titov <dimich@chromium.org> + + Not reviewed, attempt to fix ARM bulid. + + * wtf/Platform.h: + +2010-01-04 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Geoff Garen. + + Add an 'isIdentifier' to UStringImpl, use this where appropriate + (where previously 'identifierTable' was being tested). + + * API/JSClassRef.cpp: + (OpaqueJSClass::~OpaqueJSClass): + (OpaqueJSClassContextData::OpaqueJSClassContextData): + * runtime/Identifier.cpp: + (JSC::Identifier::addSlowCase): + * runtime/Identifier.h: + (JSC::Identifier::add): + * runtime/PropertyNameArray.cpp: + (JSC::PropertyNameArray::add): + * runtime/UStringImpl.h: + (JSC::UStringImpl::isIdentifier): + +2010-01-04 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam "Shimmey Shimmey" Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=33158 + Refactor JSC API entry/exit to use RAII instead of copy/pasting code. + Make it easier to change set of actions taken when passing across the API boundary. + + * API/APIShims.h: Added. + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): + (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): + (JSC::APIEntryShim::APIEntryShim): + (JSC::APICallbackShim::APICallbackShim): + (JSC::APICallbackShim::~APICallbackShim): + * API/JSBase.cpp: + (JSEvaluateScript): + (JSCheckScriptSyntax): + (JSGarbageCollect): + (JSReportExtraMemoryCost): + * API/JSCallbackConstructor.cpp: + (JSC::constructJSCallback): + * API/JSCallbackFunction.cpp: + (JSC::JSCallbackFunction::call): + * API/JSCallbackObjectFunctions.h: + (JSC::::init): + (JSC::::getOwnPropertySlot): + (JSC::::put): + (JSC::::deleteProperty): + (JSC::::construct): + (JSC::::hasInstance): + (JSC::::call): + (JSC::::getOwnPropertyNames): + (JSC::::toNumber): + (JSC::::toString): + (JSC::::staticValueGetter): + (JSC::::callbackGetter): + * API/JSContextRef.cpp: + * API/JSObjectRef.cpp: + (JSObjectMake): + (JSObjectMakeFunctionWithCallback): + (JSObjectMakeConstructor): + (JSObjectMakeFunction): + (JSObjectMakeArray): + (JSObjectMakeDate): + (JSObjectMakeError): + (JSObjectMakeRegExp): + (JSObjectGetPrototype): + (JSObjectSetPrototype): + (JSObjectHasProperty): + (JSObjectGetProperty): + (JSObjectSetProperty): + (JSObjectGetPropertyAtIndex): + (JSObjectSetPropertyAtIndex): + (JSObjectDeleteProperty): + (JSObjectCallAsFunction): + (JSObjectCallAsConstructor): + (JSObjectCopyPropertyNames): + (JSPropertyNameArrayRelease): + (JSPropertyNameAccumulatorAddName): + * API/JSValueRef.cpp: + (JSValueGetType): + (JSValueIsUndefined): + (JSValueIsNull): + (JSValueIsBoolean): + (JSValueIsNumber): + (JSValueIsString): + (JSValueIsObject): + (JSValueIsObjectOfClass): + (JSValueIsEqual): + (JSValueIsStrictEqual): + (JSValueIsInstanceOfConstructor): + (JSValueMakeUndefined): + (JSValueMakeNull): + (JSValueMakeBoolean): + (JSValueMakeNumber): + (JSValueMakeString): + (JSValueToBoolean): + (JSValueToNumber): + (JSValueToStringCopy): + (JSValueToObject): + (JSValueProtect): + (JSValueUnprotect): + * JavaScriptCore.xcodeproj/project.pbxproj: + +2010-01-04 Dan Bernstein <mitz@apple.com> + + Reviewed by Ada Chan and Mark Rowe. + + Updated copyright string + + * Info.plist: + * JavaScriptCore.vcproj/JavaScriptCore.resources/Info.plist: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.rc: + +2010-01-04 Adam Roben <aroben@apple.com> + + No review, rolling out r52741. + http://trac.webkit.org/changeset/52741 + https://bugs.webkit.org/show_bug.cgi?id=33056 + + * wtf/AlwaysInline.h: + +2010-01-04 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Darin Adler. + + Add cacheFlush support for WinCE + https://bugs.webkit.org/show_bug.cgi?id=33110 + + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::cacheFlush): + +2010-01-04 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Adam Roben. + + Implement NO_RETURN for COMPILER(MSVC). + https://bugs.webkit.org/show_bug.cgi?id=33056 + + * wtf/AlwaysInline.h: + +2010-01-04 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Simon Hausmann. + + Fix some PLATFORM(*_ENDIAN) uses to CPU() + https://bugs.webkit.org/show_bug.cgi?id=33148 + + * runtime/JSCell.cpp: + (JSC::): + * runtime/JSValue.h: + (JSC::JSValue::): + +2010-01-04 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Adam Barth. + + Document CPU() macros in comments. + https://bugs.webkit.org/show_bug.cgi?id=33147 + + * wtf/Platform.h: + +2010-01-04 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Adam Barth. + + Reorganize, document and rename CPU() platform macros. + https://bugs.webkit.org/show_bug.cgi?id=33145 + ExecutableAllocatorSymbian appears to have buggy ARM version check + https://bugs.webkit.org/show_bug.cgi?id=33138 + + * wtf/Platform.h: + Rename all macros related to detection of particular CPUs or + classes of CPUs to CPU(), reorganize and document them. + + All remaining changes are adapting to the renames, plus fixing the + second bug cited above. + + * assembler/ARMAssembler.cpp: + * assembler/ARMAssembler.h: + * assembler/ARMv7Assembler.h: + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::Imm32::Imm32): + * assembler/MacroAssembler.h: + * assembler/MacroAssemblerARM.cpp: + * assembler/MacroAssemblerARM.h: + * assembler/MacroAssemblerCodeRef.h: + (JSC::MacroAssemblerCodePtr::MacroAssemblerCodePtr): + * assembler/MacroAssemblerX86.h: + * assembler/MacroAssemblerX86Common.h: + * assembler/MacroAssemblerX86_64.h: + * assembler/X86Assembler.h: + (JSC::X86Registers::): + (JSC::X86Assembler::): + (JSC::X86Assembler::movl_mEAX): + (JSC::X86Assembler::movl_EAXm): + (JSC::X86Assembler::repatchLoadPtrToLEA): + (JSC::X86Assembler::X86InstructionFormatter::memoryModRM): + * jit/ExecutableAllocator.h: + * jit/ExecutableAllocatorFixedVMPool.cpp: + * jit/ExecutableAllocatorPosix.cpp: + * jit/ExecutableAllocatorSymbian.cpp: + (JSC::ExecutableAllocator::intializePageSize): + * jit/JIT.cpp: + * jit/JIT.h: + * jit/JITArithmetic.cpp: + * jit/JITInlineMethods.h: + (JSC::JIT::beginUninterruptedSequence): + (JSC::JIT::restoreArgumentReferenceForTrampoline): + (JSC::JIT::emitCount): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + * jit/JITStubs.cpp: + (JSC::JITThunks::JITThunks): + * jit/JITStubs.h: + * runtime/Collector.cpp: + (JSC::currentThreadStackBase): + (JSC::getPlatformThreadRegisters): + (JSC::otherThreadStackPointer): + * wrec/WREC.h: + * wrec/WRECGenerator.cpp: + (JSC::WREC::Generator::generateEnter): + (JSC::WREC::Generator::generateReturnSuccess): + (JSC::WREC::Generator::generateReturnFailure): + * wrec/WRECGenerator.h: + * wtf/FastMalloc.cpp: + * wtf/TCSpinLock.h: + (TCMalloc_SpinLock::Lock): + (TCMalloc_SpinLock::Unlock): + (TCMalloc_SlowLock): + * wtf/Threading.h: + * wtf/dtoa.cpp: + * yarr/RegexJIT.cpp: + (JSC::Yarr::RegexGenerator::generateEnter): + (JSC::Yarr::RegexGenerator::generateReturn): + * yarr/RegexJIT.h: + +2010-01-04 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Adam Barth. + + Clean up COMPILER macros and remove unused ones. + https://bugs.webkit.org/show_bug.cgi?id=33132 + + Removed values are COMPILER(BORLAND) and COMPILER(CYGWIN) - they were + not used anywhere. + + * wtf/Platform.h: + +2010-01-03 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Eric Seidel. + + Update wtf/Platform.h to document the new system for porting macros. + https://bugs.webkit.org/show_bug.cgi?id=33130 + + * wtf/Platform.h: + +2009-12-29 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Maciej Stachowiak. + + PLATFORM(CAIRO) should be defined by WIN_CAIRO define + https://bugs.webkit.org/show_bug.cgi?id=22250 + + * wtf/Platform.h: Define WTF_PLATFORM_CAIRO for GTK port only + For the WinCairo port WTF_PLATFORM_CAIRO is already defined in config.h + +2009-12-28 Shu Chang <Chang.Shu@nokia.com> + + Reviewed by Laszlo Gombos. + + [Qt] Delete ThreadPrivate instance after it is finished. + https://bugs.webkit.org/show_bug.cgi?id=32614 + + * wtf/qt/ThreadingQt.cpp: + (WTF::ThreadMonitor::instance): + (WTF::ThreadMonitor::threadFinished): + (WTF::createThreadInternal): + (WTF::detachThread): + +2009-12-28 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Maciej Stachowiak. + + Cleanup of #define JS_EXPORT. + + * API/JSBase.h: + +2009-12-27 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Adam Barth. + + WinCE buildfix (HWND_MESSAGE isn't supported there) + + * wtf/win/MainThreadWin.cpp: + (WTF::initializeMainThreadPlatform): + +2009-12-27 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Adam Barth. + + Added a file with WinMain function to link agains in WinCE. + + * os-win32/WinMain.cpp: Added. + (convertToUtf8): + (WinMain): + +2009-12-24 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed; revert of r52550. + + The change regressed the following LayoutTests for QtWebKit. + + fast/workers/worker-call.html -> crashed + fast/workers/worker-close.html -> crashed + + * wtf/qt/ThreadingQt.cpp: + (WTF::waitForThreadCompletion): + (WTF::detachThread): + +2009-12-24 Shu Chang <Chang.Shu@nokia.com> + + Reviewed by Laszlo Gombos. + + [Qt] Fix memory leak by deleting instance of ThreadPrivate + in function waitForThreadCompletion(), synchronously, or in + detachThread(), asynchronously. + https://bugs.webkit.org/show_bug.cgi?id=32614 + + * wtf/qt/ThreadingQt.cpp: + (WTF::waitForThreadCompletion): + (WTF::detachThread): + +2009-12-23 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Laszlo Gombos. + + Include stddef.h for ptrdiff_t + https://bugs.webkit.org/show_bug.cgi?id=32891 + + ptrdiff_t is typedef-ed in stddef.h. + Include stddef.h in jit/ExecutableAllocator.h. + + * jit/ExecutableAllocator.h: + +2009-12-23 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Eric Seidel. + + Buildfix after r47092. + + * wtf/wince/MemoryManager.cpp: + (WTF::tryFastMalloc): + (WTF::tryFastZeroedMalloc): + (WTF::tryFastCalloc): + (WTF::tryFastRealloc): + +2009-12-23 Kent Tamura <tkent@chromium.org> + + Reviewed by Darin Adler. + + HTMLInputElement::valueAsDate getter support. + https://bugs.webkit.org/show_bug.cgi?id=32876 + + Expose dateToDaysFrom1970(). + + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * wtf/DateMath.cpp: + (WTF::dateToDaysFrom1970): + * wtf/DateMath.h: + +2009-12-22 Darin Adler <darin@apple.com> + + Reviewed by Mark Rowe. + + Turn off datagrid by default, at least for all platforms Apple ships. + The datagrid implementation isn't ready for general web use yet. + + * Configurations/FeatureDefines.xcconfig: Turn off datagrid by default. + +2009-12-22 Steve Block <steveblock@google.com> + + Reviewed by David Levin. + + Updates Android's scheduleDispatchFunctionsOnMainThread() to use new + AndroidThreading class, rather than using JavaSharedClient directly. + This fixes the current layering violation. + https://bugs.webkit.org/show_bug.cgi?id=32651 + + The pattern is copied from Chromium, which uses the ChromiumThreading + class. This patch also fixes the style in ChromiumThreading.h. + + * wtf/android/AndroidThreading.h: Added. Declares AndroidThreading. + * wtf/android/MainThreadAndroid.cpp: Modified + (WTF::scheduleDispatchFunctionsOnMainThread): Uses AndroidThreading. + * wtf/chromium/ChromiumThreading.h: Modified. Fixes style. + +2009-12-22 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Fix a couple of problems with UntypedPtrAndBitfield. + + Add a m_leaksPtr to reduce false positives from leaks in debug builds + (this isn't perfect because we'd like a solution for release builds, + but this is now at least as good as a PtrAndFlags would be). + + Switch SmallStringsto use a regular string for the base, rather than + a static one. UntypedPtrAndBitfield assumes all strings are at least + 8 byte aligned; this migt not be true of static strings. Shared buffers + are heap allocated, as are all UStringImpls other than static strings. + Static strings cannot end up being the owner string of substrings, + since the only static strings are length 0. + + * runtime/SmallStrings.cpp: + (JSC::SmallStringsStorage::SmallStringsStorage): + * runtime/UStringImpl.h: + (JSC::UntypedPtrAndBitfield::UntypedPtrAndBitfield): + (JSC::UStringImpl::UStringImpl): + +2009-12-22 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Darin Adler. + + RVCT (__ARMCC_VERSION < 400000) does not provide strcasecmp and strncasecmp + https://bugs.webkit.org/show_bug.cgi?id=32857 + + Add implementation of strcasecmp and strncasecmp for RVCT < 4.0 + because earlier versions of RVCT 4.0 does not provide these functions. + + * wtf/StringExtras.cpp: Added. + (strcasecmp): + (strncasecmp): + * wtf/StringExtras.h: + +2009-12-22 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Darin Adler. + + Define ALWAYS_INLINE and WTF_PRIVATE_INLINE to __forceinline for RVCT + https://bugs.webkit.org/show_bug.cgi?id=32853 + + Use __forceinline forces RVCT to compile a C or C++ function + inline. The compiler attempts to inline the function, regardless of + the characteristics of the function. + + * wtf/AlwaysInline.h: + * wtf/FastMalloc.h: + +2009-12-21 Simon Hausmann <simon.hausmann@nokia.com> + + Prospective GTK build fix: Add UStringImpl.cpp/h to the build. + + * GNUmakefile.am: + +2009-12-21 Simon Hausmann <simon.hausmann@nokia.com> + + Fix the Qt build, add UStringImpl.cpp to the build. + + * JavaScriptCore.pri: + +2009-12-21 Gavin Barraclough <barraclough@apple.com> + + Windows Build fix part 5. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2009-12-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix). + Fix breakage of world introduced in build fix to r52463. + + * runtime/UStringImpl.h: + +2009-12-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=32831 + Replace UString::Rep implementation, following introduction of ropes to JSC. + + * Remove redundant overcapacity mechanisms. + * Reduce memory cost of Rep's. + * Add an inline storage mechanism akin to that in WebCore's StringImpl. + + ~1% Sunspider progression. + + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + * runtime/SmallStrings.cpp: + (JSC::SmallStringsStorage::SmallStringsStorage): + * runtime/UString.cpp: + (JSC::initializeUString): + (JSC::createRep): + (JSC::UString::createFromUTF8): + (JSC::UString::createUninitialized): + (JSC::UString::spliceSubstringsWithSeparators): + (JSC::UString::replaceRange): + (JSC::UString::ascii): + (JSC::UString::operator=): + (JSC::UString::toStrictUInt32): + (JSC::equal): + * runtime/UString.h: + (JSC::UString::isEmpty): + (JSC::UString::cost): + (JSC::makeString): + * runtime/UStringImpl.cpp: Added. + (JSC::UStringImpl::baseSharedBuffer): + (JSC::UStringImpl::sharedBuffer): + (JSC::UStringImpl::destroy): + (JSC::UStringImpl::computeHash): + * runtime/UStringImpl.h: Added. + (JSC::UntypedPtrAndBitfield::UntypedPtrAndBitfield): + (JSC::UntypedPtrAndBitfield::asPtr): + (JSC::UntypedPtrAndBitfield::operator&=): + (JSC::UntypedPtrAndBitfield::operator|=): + (JSC::UntypedPtrAndBitfield::operator&): + (JSC::UStringImpl::create): + (JSC::UStringImpl::createCopying): + (JSC::UStringImpl::createUninitialized): + (JSC::UStringImpl::data): + (JSC::UStringImpl::size): + (JSC::UStringImpl::cost): + (JSC::UStringImpl::hash): + (JSC::UStringImpl::computedHash): + (JSC::UStringImpl::setHash): + (JSC::UStringImpl::identifierTable): + (JSC::UStringImpl::setIdentifierTable): + (JSC::UStringImpl::ref): + (JSC::UStringImpl::deref): + (JSC::UStringImpl::allocChars): + (JSC::UStringImpl::copyChars): + (JSC::UStringImpl::computeHash): + (JSC::UStringImpl::null): + (JSC::UStringImpl::empty): + (JSC::UStringImpl::checkConsistency): + (JSC::UStringImpl::): + (JSC::UStringImpl::UStringImpl): + (JSC::UStringImpl::operator new): + (JSC::UStringImpl::bufferOwnerString): + (JSC::UStringImpl::bufferOwnership): + (JSC::UStringImpl::isStatic): + +2009-12-18 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Move some build decisions from Qt build system into source files + https://bugs.webkit.org/show_bug.cgi?id=31956 + + * JavaScriptCore.pri: Compile files unconditionally + * jit/ExecutableAllocatorPosix.cpp: Guard with PLATFORM(UNIX) && !PLATFORM(SYMBIAN) + * jit/ExecutableAllocatorWin.cpp: Guard with PLATFORM(WIN_OS) + * runtime/MarkStackPosix.cpp: Guard with PLATFORM(UNIX) && !PLATFORM(SYMBIAN) + * runtime/MarkStackSymbian.cpp: Guard with PLATFORM(SYMBIAN) + * runtime/MarkStackWin.cpp: Guard with PLATFORM(WIN_OS) + * wtf/Platform.h: Guard ENABLE_JSC_MULTIPLE_THREADS with ENABLE_SINGLE_THREADED for the Qt port + * wtf/ThreadingNone.cpp: Guard with ENABLE(SINGLE_THREADED) + * wtf/qt/ThreadingQt.cpp: Guard with !ENABLE(SINGLE_THREADED) + +2009-12-18 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Add createNonCopying method to UString to make replace constructor passed bool, + to make behaviour more explicit. Add createFromUTF8 to UString (wrapping method + on UString::Rep), since other cases of transliteration (e.g. from ascii) are + performed in UString constructors. Add/use setHash & size() accessors on Rep, + rather than accessing _hash/len directly. + + * API/JSClassRef.cpp: + (OpaqueJSClass::OpaqueJSClass): + * API/OpaqueJSString.cpp: + (OpaqueJSString::ustring): + * JavaScriptCore.exp: + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + * runtime/Identifier.cpp: + (JSC::Identifier::equal): + (JSC::CStringTranslator::translate): + (JSC::UCharBufferTranslator::translate): + (JSC::Identifier::addSlowCase): + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + * runtime/JSString.h: + (JSC::JSString::Rope::Fiber::refAndGetLength): + (JSC::JSString::Rope::append): + * runtime/StringBuilder.h: + (JSC::StringBuilder::release): + * runtime/StringConstructor.cpp: + (JSC::stringFromCharCodeSlowCase): + * runtime/StringPrototype.cpp: + (JSC::substituteBackreferencesSlow): + (JSC::stringProtoFuncToLowerCase): + (JSC::stringProtoFuncToUpperCase): + (JSC::stringProtoFuncFontsize): + (JSC::stringProtoFuncLink): + * runtime/UString.cpp: + (JSC::UString::UString): + (JSC::UString::createNonCopying): + (JSC::UString::createFromUTF8): + * runtime/UString.h: + (JSC::UString::Rep::setHash): + (JSC::UString::~UString): + (JSC::makeString): + +2009-12-18 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Cameron Zwarich and Gavin Barraclough. + + Changed Register constructors to assignment operators, to streamline + moving values into registers. (In theory, there's no difference between + the two, since the constructor should just inline away, but there seems + to be a big difference in the addled mind of the GCC optimizer.) + + In the interpreter, this is a 3.5% SunSpider speedup and a 1K-2K + reduction in stack usage per privateExecute stack frame. + + * interpreter/CallFrame.h: + (JSC::ExecState::setCalleeArguments): + (JSC::ExecState::setCallerFrame): + (JSC::ExecState::setScopeChain): + (JSC::ExecState::init): + (JSC::ExecState::setArgumentCount): + (JSC::ExecState::setCallee): + (JSC::ExecState::setCodeBlock): Added a little bit of casting so these + functions could use the new Register assignment operators. + + * interpreter/Register.h: + (JSC::Register::withInt): + (JSC::Register::Register): + (JSC::Register::operator=): Swapped in assignment operators for constructors. + +2009-12-18 Yongjun Zhang <yongjun.zhang@nokia.com> + + Reviewed by Simon Hausmann. + + https://bugs.webkit.org/show_bug.cgi?id=32713 + [Qt] make wtf/Assertions.h compile in winscw compiler. + + Add string arg before ellipsis to help winscw compiler resolve variadic + macro definitions in wtf/Assertions.h. + + * wtf/Assertions.h: + +2009-12-18 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Adam Roben. + + Fixed intermittent failure seen on Windows buildbot, and in other JSC + API clients. + + Added a WeakGCPtr class and changed OpaqueJSClass::cachedPrototype to + use it, to avoid vending a stale object as a prototype. + + * API/JSClassRef.cpp: + (OpaqueJSClassContextData::OpaqueJSClassContextData): + (OpaqueJSClass::prototype): + * API/JSClassRef.h: Use WeakGCPtr. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/WeakGCPtr.h: Added. + (JSC::WeakGCPtr::WeakGCPtr): + (JSC::WeakGCPtr::get): + (JSC::WeakGCPtr::clear): + (JSC::WeakGCPtr::operator*): + (JSC::WeakGCPtr::operator->): + (JSC::WeakGCPtr::operator!): + (JSC::WeakGCPtr::operator bool): + (JSC::WeakGCPtr::operator UnspecifiedBoolType): + (JSC::WeakGCPtr::assign): + (JSC::::operator): + (JSC::operator==): + (JSC::operator!=): + (JSC::static_pointer_cast): + (JSC::const_pointer_cast): + (JSC::getPtr): Added WeakGCPtr to the project. + +2009-12-18 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=32720 + + * JavaScriptCore.exp: + - Remove exports for UString::append + * JavaScriptCore.xcodeproj/project.pbxproj: + - Make StringBuilder a private header (was project). + +2009-12-18 Martin Robinson <martin.james.robinson@gmail.com> + + Reviewed by Gustavo Noronha Silva. + + [GTK] GRefPtr does not take a reference when assigned a raw pointer + https://bugs.webkit.org/show_bug.cgi?id=32709 + + Ensure that when assigning a raw pointer to a GRefPtr, the reference + count is incremented. Also remove the GRefPtr conversion overload as + GRefPtr types have necessarily incompatible reference counting. + + * wtf/gtk/GRefPtr.h: + (WTF::GRefPtr::operator=): + +2009-12-18 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Clean up the qmake build system to distinguish between trunk builds and package builds + + https://bugs.webkit.org/show_bug.cgi?id=32716 + + * pcre/pcre.pri: Use standalone_package instead of QTDIR_build + +2009-12-18 Martin Robinson <martin.james.robinson@gmail.com> + + Reviewed by Gustavo Noronha Silva. + + [GTK] Compile warning from line 29 of GRefPtr.cpp + https://bugs.webkit.org/show_bug.cgi?id=32703 + + Fix memory leak and compiler warning in GRefPtr GHashTable template + specialization. + + * wtf/gtk/GRefPtr.cpp: + (WTF::refGPtr): + +2009-12-17 Sam Weinig <sam@webkit.org> + + Reviewed by Mark Rowe. + + Add BUILDING_ON_SNOW_LEOPARD and TARGETING_SNOW_LEOPARD #defines. + + * wtf/Platform.h: + +2009-12-17 Adam Roben <aroben@apple.com> + + Sync JavaScriptCore.vcproj with JavaScriptCore.xcodeproj and the + source tree + + Fixes <http://webkit.org/b/32665>. + + Reviewed by Ada Chan. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Moved + around files and filters so that the structure matches + JavaScriptCore.xcodeproj and the source tree. A few headers that were + previously omitted have been added, as well as JSZombie.{cpp,h}. + +2009-12-17 Adam Roben <aroben@apple.com> + + Remove HeavyProfile and TreeProfile completely + + These were mostly removed in r42808, but the empty files were left in + place. + + Fixes <http://webkit.org/b/32664>. + + Reviewed by John Sullivan. + + * Android.mk: + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCoreSources.bkl: + Removed HeavyProfile/TreeProfile source files. + + * profiler/HeavyProfile.cpp: Removed. + * profiler/HeavyProfile.h: Removed. + * profiler/TreeProfile.cpp: Removed. + * profiler/TreeProfile.h: Removed. + +2009-12-17 Martin Robinson <martin.james.robinson@gmail.com> + + Reviewed by Gustavo Noronha Silva. + + [GTK] WebKit GTK needs a wrapper for ref counted glib/gobject structs + https://bugs.webkit.org/show_bug.cgi?id=21599 + + Implement GRefPtr, a smart pointer for reference counted GObject types. + + * GNUmakefile.am: + * wtf/gtk/GOwnPtr.cpp: + (WTF::GDir): + * wtf/gtk/GRefPtr.h: Added. + (WTF::): + (WTF::GRefPtr::GRefPtr): + (WTF::GRefPtr::~GRefPtr): + (WTF::GRefPtr::clear): + (WTF::GRefPtr::get): + (WTF::GRefPtr::operator*): + (WTF::GRefPtr::operator->): + (WTF::GRefPtr::operator!): + (WTF::GRefPtr::operator UnspecifiedBoolType): + (WTF::GRefPtr::hashTableDeletedValue): + (WTF::::operator): + (WTF::::swap): + (WTF::swap): + (WTF::operator==): + (WTF::operator!=): + (WTF::static_pointer_cast): + (WTF::const_pointer_cast): + (WTF::getPtr): + (WTF::adoptGRef): + (WTF::refGPtr): + (WTF::derefGPtr): + +2009-12-17 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Unreviewed. Build fixes for make distcheck. + + * GNUmakefile.am: + +2009-12-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Fixed <rdar://problem/7355025> Interpreter::privateExecute macro generates + bloated code + + This patch cuts Interpreter stack use by about a third. + + * bytecode/Opcode.h: Changed Opcode to const void* to work with the + const static initiliazation we want to do in Interpreter::privateExecute. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::Interpreter): Moved hashtable initialization here to + avoid polluting Interpreter::privateExecute's stack, and changed it from a + series of add() calls to one add() call in a loop, to cut down on code size. + + (JSC::Interpreter::privateExecute): Changed a series of label computations + to a copy of a compile-time constant array to cut down on code size. + +2009-12-16 Mark Rowe <mrowe@apple.com> + + Build fix. Disable debug variants of WebKit frameworks. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2009-12-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam "r=me" Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=32498 + <rdar://problem/7471495> + REGRESSION(r51978-r52039): AJAX "Mark This Forum Read" function no longer + works + + Fixed a tyop. + + * runtime/Operations.h: + (JSC::jsAdd): Use the '&&' operator, not the ',' operator. + +2009-12-15 Geoffrey Garen <ggaren@apple.com> + + Try to fix the windows build: don't export this inlined function. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2009-12-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Beth Dakin. + + Inlined JSCell's operator new. + + 3.7% speedup on bench-allocate-nonretained.js. + + * JavaScriptCore.exp: + * runtime/JSCell.cpp: + * runtime/JSCell.h: + (JSC::JSCell::operator new): + +2009-12-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Removed the number heap, replacing it with a one-item free list for + numbers, taking advantage of the fact that two number cells fit inside + the space for one regular cell, and number cells don't require destruction. + + SunSpider says 1.6% faster in JSVALUE32 mode (the only mode that + heap-allocates numbers). + + SunSpider says 1.1% faster in JSVALUE32_64 mode. v8 says 0.8% faster + in JSVALUE32_64 mode. 10% speedup on bench-alloc-nonretained.js. 6% + speedup on bench-alloc-retained.js. + + There's a lot of formulaic change in this patch, but not much substance. + + * JavaScriptCore.exp: + * debugger/Debugger.cpp: + (JSC::Debugger::recompileAllJSFunctions): + * runtime/Collector.cpp: + (JSC::Heap::Heap): + (JSC::Heap::destroy): + (JSC::Heap::allocateBlock): + (JSC::Heap::freeBlock): + (JSC::Heap::freeBlockPtr): + (JSC::Heap::freeBlocks): + (JSC::Heap::recordExtraCost): + (JSC::Heap::allocate): + (JSC::Heap::resizeBlocks): + (JSC::Heap::growBlocks): + (JSC::Heap::shrinkBlocks): + (JSC::Heap::markConservatively): + (JSC::Heap::clearMarkBits): + (JSC::Heap::markedCells): + (JSC::Heap::sweep): + (JSC::Heap::markRoots): + (JSC::Heap::objectCount): + (JSC::Heap::addToStatistics): + (JSC::Heap::statistics): + (JSC::Heap::isBusy): + (JSC::Heap::reset): + (JSC::Heap::collectAllGarbage): + (JSC::Heap::primaryHeapBegin): + (JSC::Heap::primaryHeapEnd): + * runtime/Collector.h: + (JSC::): Removed all code pertaining to the number heap, and changed all + heap template functions and classes to non-template functions and classes. + + (JSC::Heap::allocateNumber): A new optimization to replace the number + heap: allocate half-sized number cells in pairs, returning the first + cell and caching the second cell for the next allocation. + + * runtime/CollectorHeapIterator.h: + (JSC::LiveObjectIterator::LiveObjectIterator): + (JSC::LiveObjectIterator::operator++): + (JSC::DeadObjectIterator::DeadObjectIterator): + (JSC::DeadObjectIterator::operator++): + (JSC::ObjectIterator::ObjectIterator): + (JSC::ObjectIterator::operator++): + * runtime/JSCell.h: + (JSC::JSCell::isNumber): Removed all code pertaining to the number heap, + and changed all heap template functions and classes to non-template functions + and classes. + +2009-12-15 Zoltan Horvath <zoltan@webkit.org> + + Reviewed by Darin Adler. + + Allow custom memory allocation control for WeakGCMap class + https://bugs.webkit.org/show_bug.cgi?id=32547 + + Inherits WeakGCMap from FastAllocBase because it is instantiated by + 'new' at: WebCore/dom/Document.cpp:512. + + * runtime/WeakGCMap.h: + +2009-12-15 Zoltan Horvath <zoltan@webkit.org> + + Reviewed by Darin Adler. + + Allow custom memory allocation control for dtoa's P5Node struct + https://bugs.webkit.org/show_bug.cgi?id=32544 + + Inherits P5Node struct from Noncopyable because it is instantiated by + 'new' at wtf/dtoa.cpp:588 and don't need to be copyable. + + * wtf/dtoa.cpp: + +2009-12-14 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Simon Fraser. + + https://bugs.webkit.org/show_bug.cgi?id=32524 + REGRESSION(52084): fast/dom/prototypes.html failing two CSS tests + + * wtf/StdLibExtras.h: + (WTF::bitCount): The original patch put the parentheses in the wrong + place, completely changing the calculation and making it almost always + wrong. Moved the parentheses around the '+' operation, like the original + compiler warning suggested. + +2009-12-14 Gabor Loki <loki@inf.u-szeged.hu> + + Unreviewed trivial buildfix. + + Fix crosses initialization of usedPrimaryBlocks for JSValue32 + + * runtime/Collector.cpp: + (JSC::Heap::markConservatively): + +2009-12-14 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed by Simon Hausmann. + + GCC 4.3.x warning fixed. Suggested parantheses added. + warning: ../../../JavaScriptCore/wtf/StdLibExtras.h:77: warning: suggest parentheses around + or - in operand of & + + * wtf/StdLibExtras.h: + (WTF::bitCount): + +2009-12-13 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Changed GC from mark-sweep to mark-allocate. + + Added WeakGCMap to keep WebCore blissfully ignorant about objects that + have become garbage but haven't run their destructors yet. + + 1% SunSpider speedup. + 7.6% v8 speedup (37% splay speedup). + 17% speedup on bench-alloc-nonretained.js. + 18% speedup on bench-alloc-retained.js. + + * API/JSBase.cpp: + (JSGarbageCollect): + * API/JSContextRef.cpp: + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: Updated for renames and new + files. + + * debugger/Debugger.cpp: + (JSC::Debugger::recompileAllJSFunctions): Updated to use the Collector + iterator abstraction. + + * jsc.cpp: + (functionGC): Updated for rename. + + * runtime/Collector.cpp: Slightly reduced the number of allocations per + collection, so that small workloads only allocate on collector block, + rather than two. + + (JSC::Heap::Heap): Updated to use the new allocateBlock function. + + (JSC::Heap::destroy): Updated to use the new freeBlocks function. + + (JSC::Heap::allocateBlock): New function to initialize a block when + allocating it. + + (JSC::Heap::freeBlock): Consolidated the responsibility for running + destructors into this function. + + (JSC::Heap::freeBlocks): Updated to use freeBlock. + + (JSC::Heap::recordExtraCost): Sweep the heap in this reporting function, + so that allocation, which is more common, doesn't have to check extraCost. + + (JSC::Heap::heapAllocate): Run destructors right before recycling a + garbage cell. This has better cache utilization than a separate sweep phase. + + (JSC::Heap::resizeBlocks): + (JSC::Heap::growBlocks): + (JSC::Heap::shrinkBlocks): New set of functions for managing the size of + the heap, now that the heap doesn't maintain any information about its + size. + + (JSC::isPointerAligned): + (JSC::isHalfCellAligned): + (JSC::isPossibleCell): + (JSC::isCellAligned): + (JSC::Heap::markConservatively): Cleaned up this code a bit. + + (JSC::Heap::clearMarkBits): + (JSC::Heap::markedCells): Some helper functions for examining the the mark + bitmap. + + (JSC::Heap::sweep): Simplified this function by using a DeadObjectIterator. + + (JSC::Heap::markRoots): Reordered some operations for clarity. + + (JSC::Heap::objectCount): + (JSC::Heap::addToStatistics): + (JSC::Heap::statistics): Rewrote these functions to calculate an object + count on demand, since the heap doesn't maintain this information by + itself. + + (JSC::Heap::reset): New function for resetting the heap once we've + exhausted heap space. + + (JSC::Heap::collectAllGarbage): This function matches the old collect() + behavior, but it's now an uncommon function used only by API. + + * runtime/Collector.h: + (JSC::CollectorBitmap::count): + (JSC::CollectorBitmap::isEmpty): Added some helper functions for managing + the collector mark bitmap. + + (JSC::Heap::reportExtraMemoryCost): Changed reporting from cell equivalents + to bytes, so it's easier to understand. + + * runtime/CollectorHeapIterator.h: + (JSC::CollectorHeapIterator::CollectorHeapIterator): + (JSC::CollectorHeapIterator::operator!=): + (JSC::CollectorHeapIterator::operator*): + (JSC::CollectorHeapIterator::advance): + (JSC::::LiveObjectIterator): + (JSC::::operator): + (JSC::::DeadObjectIterator): + (JSC::::ObjectIterator): New iterators for encapsulating details about + heap layout, and what's live and dead on the heap. + + * runtime/JSArray.cpp: + (JSC::JSArray::putSlowCase): + (JSC::JSArray::increaseVectorLength): Delay reporting extra cost until + we're fully constructed, so the heap mark phase won't visit us in an + invalid state. + + * runtime/JSCell.h: + (JSC::JSCell::): + (JSC::JSCell::createDummyStructure): + (JSC::JSCell::JSCell): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: Added a dummy cell to simplify allocation logic. + + * runtime/JSString.h: + (JSC::jsSubstring): Don't report extra cost for substrings, since they + share a buffer that's already reported extra cost. + + * runtime/Tracing.d: + * runtime/Tracing.h: Changed these dtrace hooks not to report object + counts, since they're no longer cheap to compute. + + * runtime/UString.h: Updated for renames. + + * runtime/WeakGCMap.h: Added. + (JSC::WeakGCMap::isEmpty): + (JSC::WeakGCMap::uncheckedGet): + (JSC::WeakGCMap::uncheckedBegin): + (JSC::WeakGCMap::uncheckedEnd): + (JSC::::get): + (JSC::::take): + (JSC::::set): + (JSC::::uncheckedRemove): Mentioned above. + + * wtf/StdLibExtras.h: + (WTF::bitCount): Added a bit population count function, so the heap can + count live objects to fulfill statistics questions. + +The very last cell in the block is not allocated -- should not be marked. + +2009-12-13 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: Export some new symbols. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2009-12-13 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: Removed some old exports. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2009-12-13 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: Use unsigned instead of uint32_t to avoid dependencies. + + * wtf/StdLibExtras.h: + (WTF::bitCount): + +2009-12-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (speculative Windows build fix). + + * runtime/JSGlobalObjectFunctions.cpp: + +2009-12-13 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=32496 + Switch remaining cases of string construction to use StringBuilder. + Builds strings using a vector rather than using string append / addition. + + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/Executable.cpp: + (JSC::FunctionExecutable::paramString): + * runtime/FunctionConstructor.cpp: + (JSC::constructFunction): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::encode): + (JSC::decode): + (JSC::globalFuncEscape): + (JSC::globalFuncUnescape): + * runtime/JSONObject.cpp: + (JSC::Stringifier::stringify): + (JSC::Stringifier::indent): + * runtime/JSString.h: + * runtime/LiteralParser.cpp: + (JSC::LiteralParser::Lexer::lexString): + * runtime/NumberPrototype.cpp: + (JSC::integerPartNoExp): + (JSC::numberProtoFuncToFixed): + (JSC::numberProtoFuncToPrecision): + * runtime/Operations.h: + (JSC::jsString): + * runtime/StringPrototype.cpp: + (JSC::substituteBackreferencesSlow): + (JSC::substituteBackreferences): + (JSC::stringProtoFuncConcat): + +2009-12-08 Jeremy Moskovich <jeremy@chromium.org> + + Reviewed by Eric Seidel. + + Add code to allow toggling ATSUI/Core Text rendering at runtime in ComplexTextController. + https://bugs.webkit.org/show_bug.cgi?id=31802 + + The goal here is to allow for a zero runtime hit for ports that decide to select + the API at compile time. + When both USE(ATSUI) and USE(CORE_TEXT) are true, the API is toggled + at runtime. Core Text is used for OS Versions >= 10.6. + + * wtf/Platform.h: #define USE_CORE_TEXT and USE_ATSUI on Chrome/Mac. + +2009-12-11 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Oliver Hunt. + + Unify codegen for forward and backward variants of branches + https://bugs.webkit.org/show_bug.cgi?id=32463 + + * jit/JIT.h: + (JSC::JIT::emit_op_loop): Implemented in terms of forward variant. + (JSC::JIT::emit_op_loop_if_true): ditto + (JSC::JIT::emitSlow_op_loop_if_true): ditto + (JSC::JIT::emit_op_loop_if_false): ditto + (JSC::JIT::emitSlow_op_loop_if_false): ditto + (JSC::JIT::emit_op_loop_if_less): ditto + (JSC::JIT::emitSlow_op_loop_if_less): ditto + * jit/JITOpcodes.cpp: + +2009-12-11 Sam Weinig <sam@webkit.org> + + Reviewed by Anders Carlsson. + + Allow WTFs concept of the main thread to differ from pthreads when necessary. + + * wtf/ThreadingPthreads.cpp: + (WTF::initializeThreading): + (WTF::isMainThread): + * wtf/mac/MainThreadMac.mm: + (WTF::initializeMainThreadPlatform): + (WTF::scheduleDispatchFunctionsOnMainThread): + +2009-12-11 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=32454 + Refactor construction of simple strings to avoid string concatenation. + + Building strings through concatenation has a memory and performance cost - + a memory cost since we must over-allocate the buffer to leave space to append + into, and performance in that the string may still require reallocation (and + thus copying during construction). Instead move the full construction to + within a single function call (makeString), so that the arguments' lengths + can be calculated and an appropriate sized buffer allocated before copying + any characters. + + ~No performance change (~2% progression on date tests). + + * bytecode/CodeBlock.cpp: + (JSC::escapeQuotes): + (JSC::valueToSourceString): + (JSC::constantName): + (JSC::idName): + (JSC::CodeBlock::registerName): + (JSC::regexpToSourceString): + (JSC::regexpName): + * bytecompiler/NodesCodegen.cpp: + (JSC::substitute): + * profiler/Profiler.cpp: + (JSC::Profiler::createCallIdentifier): + * runtime/DateConstructor.cpp: + (JSC::callDate): + * runtime/DateConversion.cpp: + (JSC::formatDate): + (JSC::formatDateUTCVariant): + (JSC::formatTime): + (JSC::formatTimeUTC): + * runtime/DateConversion.h: + (JSC::): + * runtime/DatePrototype.cpp: + (JSC::dateProtoFuncToString): + (JSC::dateProtoFuncToUTCString): + (JSC::dateProtoFuncToDateString): + (JSC::dateProtoFuncToTimeString): + (JSC::dateProtoFuncToGMTString): + * runtime/ErrorPrototype.cpp: + (JSC::errorProtoFuncToString): + * runtime/ExceptionHelpers.cpp: + (JSC::createUndefinedVariableError): + (JSC::createErrorMessage): + (JSC::createInvalidParamError): + * runtime/FunctionPrototype.cpp: + (JSC::insertSemicolonIfNeeded): + (JSC::functionProtoFuncToString): + * runtime/ObjectPrototype.cpp: + (JSC::objectProtoFuncToString): + * runtime/RegExpConstructor.cpp: + (JSC::constructRegExp): + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::match): + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncCompile): + (JSC::regExpProtoFuncToString): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncBig): + (JSC::stringProtoFuncSmall): + (JSC::stringProtoFuncBlink): + (JSC::stringProtoFuncBold): + (JSC::stringProtoFuncFixed): + (JSC::stringProtoFuncItalics): + (JSC::stringProtoFuncStrike): + (JSC::stringProtoFuncSub): + (JSC::stringProtoFuncSup): + (JSC::stringProtoFuncFontcolor): + (JSC::stringProtoFuncFontsize): + (JSC::stringProtoFuncAnchor): + * runtime/UString.h: + (JSC::): + (JSC::makeString): + +2009-12-10 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=32400 + Switch remaining cases of string addition to use ropes. + + Re-landing r51975 - added toPrimitiveString method, + performs toPrimitive then subsequent toString operations. + + ~1% progression on Sunspidey. + + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * runtime/JSString.h: + (JSC::JSString::JSString): + (JSC::JSString::appendStringInConstruct): + * runtime/Operations.cpp: + (JSC::jsAddSlowCase): + * runtime/Operations.h: + (JSC::jsString): + (JSC::jsAdd): + +2009-12-11 Adam Roben <aroben@apple.com> + + Windows build fix + + * JavaScriptCore.vcproj/jsc/jscCommon.vsprops: Added + $(WebKitOutputDir)/include/private to the include path. + +2009-12-11 Adam Roben <aroben@apple.com> + + Move QuartzCorePresent.h to include/private + + This fixes other projects that use wtf/Platform.h + + Rubber-stamped by Steve Falkenburg. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Let VS do its thang. + * JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh: Write + QuartzCorePresent.h to $(WebKitOutputDir)/include/private. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + * JavaScriptCore.vcproj/WTF/WTFCommon.vsprops: + Added $(WebKitOutputDir)/include/private to the include path. + +2009-12-11 Adam Roben <aroben@apple.com> + + Fix clean builds and everything rebuilding on every build + + Reviewed by Sam Weinig. + + * JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh: Don't + write out QuartzCorePresent.h if it exists but is older than + QuartzCore.h. Also, create the directory we write QuartzCorePresent.h + into first. + +2009-12-11 Adam Roben <aroben@apple.com> + + Windows build fix for systems with spaces in their paths + + * JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh: Quote some paths. + +2009-12-11 Chris Marrin <cmarrin@apple.com> + + Reviewed by Adam Roben. + + Add check for presence of QuartzCore headers + https://bugs.webkit.org/show_bug.cgi?id=31856 + + The script now checks for the presence of QuartzCore.h. If present + it will turn on ACCELERATED_COMPOSITING and 3D_RENDERING to enable + HW compositing on Windows. The script writes QuartzCorePresent.h to + the build directory which has a define telling whether QuartzCore is + present. + + * JavaScriptCore.vcproj/JavaScriptCore/build-generated-files.sh: + * wtf/Platform.h: + +2009-12-11 Kent Tamura <tkent@chromium.org> + + Reviewed by Darin Adler. + + Fix a problem that JSC::gregorianDateTimeToMS() returns a negative + value for a huge year value. + https://bugs.webkit.org/show_bug.cgi?id=32304 + + * wtf/DateMath.cpp: + (WTF::dateToDaysFrom1970): Renamed from dateToDayInYear, and changed the return type to double. + (WTF::calculateDSTOffset): Follow the dateToDaysFrom1970() change. + (WTF::timeClip): Use maxECMAScriptTime. + (JSC::gregorianDateTimeToMS): Follow the dateToDaysFrom1970() change. + +2009-12-10 Adam Barth <abarth@webkit.org> + + No review, rolling out r51975. + http://trac.webkit.org/changeset/51975 + + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * runtime/JSString.h: + (JSC::JSString::JSString): + (JSC::JSString::appendStringInConstruct): + * runtime/Operations.cpp: + (JSC::jsAddSlowCase): + * runtime/Operations.h: + (JSC::jsString): + (JSC::jsAdd): + +2009-12-10 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Incorrect caching of prototype lookup with dictionary base + https://bugs.webkit.org/show_bug.cgi?id=32402 + + Make sure we don't add cached prototype lookup to the proto_list + lookup chain if the top level object is a dictionary. + + * jit/JITStubs.cpp: + (JSC::JITThunks::tryCacheGetByID): + +2009-12-10 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=32400 + Switch remaining cases of string addition to use ropes. + + ~1% progression on Sunspidey. + + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * runtime/JSString.h: + (JSC::JSString::JSString): + (JSC::JSString::appendStringInConstruct): + * runtime/Operations.cpp: + (JSC::jsAddSlowCase): + * runtime/Operations.h: + (JSC::jsString): + (JSC::jsAdd): + +2009-12-10 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Geoffrey Garen. + + Remove JSObject::getPropertyAttributes() and all usage of it. + https://bugs.webkit.org/show_bug.cgi?id=31933 + + getOwnPropertyDescriptor() should be used instead. + + * JavaScriptCore.exp: + * JavaScriptCore.order: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * debugger/DebuggerActivation.cpp: + (JSC::DebuggerActivation::getOwnPropertyDescriptor): + * debugger/DebuggerActivation.h: + * runtime/JSObject.cpp: + (JSC::JSObject::propertyIsEnumerable): + * runtime/JSObject.h: + * runtime/JSVariableObject.cpp: + * runtime/JSVariableObject.h: + +2009-12-10 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt & Mark Rowe. + + https://bugs.webkit.org/show_bug.cgi?id=32367 + Add support for short Ropes (up to 3 entries) inline within JSString. + (rather than externally allocating an object to hold the rope). + Switch jsAdd of (JSString* + JSString*) to now make use of Ropes. + + ~1% progression on Sunspidey. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + (JSC::JSString::toBoolean): + (JSC::JSString::getStringPropertyDescriptor): + * runtime/JSString.h: + (JSC::JSString::Rope::Fiber::deref): + (JSC::JSString::Rope::Fiber::ref): + (JSC::JSString::Rope::Fiber::refAndGetLength): + (JSC::JSString::Rope::append): + (JSC::JSString::JSString): + (JSC::JSString::~JSString): + (JSC::JSString::value): + (JSC::JSString::tryGetValue): + (JSC::JSString::length): + (JSC::JSString::canGetIndex): + (JSC::JSString::appendStringInConstruct): + (JSC::JSString::appendValueInConstructAndIncrementLength): + (JSC::JSString::isRope): + (JSC::JSString::string): + (JSC::JSString::ropeLength): + (JSC::JSString::getStringPropertySlot): + * runtime/Operations.h: + (JSC::jsString): + (JSC::jsAdd): + (JSC::resolveBase): + +2009-12-09 Anders Carlsson <andersca@apple.com> + + Reviewed by Geoffrey Garen. + + Fix three more things found by compiling with clang++. + + * runtime/Structure.h: + (JSC::StructureTransitionTable::reifySingleTransition): + Add the 'std' qualifier to the call to make_pair. + + * wtf/DateMath.cpp: + (WTF::initializeDates): + Incrementing a bool is deprecated according to the C++ specification. + + * wtf/PtrAndFlags.h: + (WTF::PtrAndFlags::PtrAndFlags): + Name lookup should not be done in dependent bases, so explicitly qualify the call to set. + +2009-12-09 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Oliver Hunt. + + Google reader gets stuck in the "Loading..." state and does not complete + https://bugs.webkit.org/show_bug.cgi?id=32256 + <rdar://problem/7456388> + + * jit/JITArithmetic.cpp: + (JSC::JIT::emitSlow_op_jless): Fix some backward branches. + +2009-12-09 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=32228 + Make destruction of ropes non-recursive to prevent stack exhaustion. + Also, pass a UString& into initializeFiber rather than a Ustring::Rep*, + since the Rep is not being ref counted this could result in usage of a + Rep with refcount zero (where the Rep comes from a temporary UString + returned from a function). + + * runtime/JSString.cpp: + (JSC::JSString::Rope::destructNonRecursive): + (JSC::JSString::Rope::~Rope): + * runtime/JSString.h: + (JSC::JSString::Rope::initializeFiber): + * runtime/Operations.h: + (JSC::concatenateStrings): + +2009-12-09 Zoltan Herczeg <zherczeg@inf.u-szeged.hu> + + Reviewed by Eric Seidel. + + https://bugs.webkit.org/show_bug.cgi?id=31930 + + Update to r51457. ASSERTs changed to COMPILE_ASSERTs. + The speedup is 25%. + + * runtime/JSGlobalData.cpp: + (JSC::VPtrSet::VPtrSet): + +2009-12-09 Steve Block <steveblock@google.com> + + Reviewed by Adam Barth. + + Updates Android Makefiles with latest additions. + https://bugs.webkit.org/show_bug.cgi?id=32278 + + * Android.mk: Modified. + * Android.v8.wtf.mk: Modified. + +2009-12-09 Sam Weinig <sam@webkit.org> + + Reviewed by Gavin Barraclough. + + Fix a bug found while trying to compile JavaScriptCore with clang++. + + * yarr/RegexPattern.h: + (JSC::Yarr::PatternTerm::PatternTerm): Don't self assign here. Use false instead. + +2009-12-09 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Attempt to fix the Windows build. + + * wtf/FastMalloc.h: + +2009-12-09 Anders Carlsson <andersca@apple.com> + + Reviewed by Sam Weinig. + + Fix some things found while trying to compile JavaScriptCore with clang++. + + * wtf/FastMalloc.h: + Add correct exception specifications for the allocation/deallocation operators. + + * wtf/Vector.h: + * wtf/VectorTraits.h: + Fix a bunch of struct/class mismatches. + +2009-12-08 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Darin Adler. + + move code generation portions of Nodes.cpp to bytecompiler directory + https://bugs.webkit.org/show_bug.cgi?id=32284 + + * bytecompiler/NodesCodegen.cpp: Copied from parser/Nodes.cpp. Removed parts that + are not about codegen. + * parser/Nodes.cpp: Removed everything that is about codegen. + + Update build systems: + + * Android.mk: + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * JavaScriptCoreSources.bkl: + +2009-12-08 Kevin Watters <kevinwatters@gmail.com> + + Reviewed by Kevin Ollivier. + + [wx] Mac plugins support. + + https://bugs.webkit.org/show_bug.cgi?id=32236 + + * wtf/Platform.h: + +2009-12-08 Dmitry Titov <dimich@chromium.org> + + Rubber-stamped by David Levin. + + Revert and reopen "Add asserts to RefCounted to make sure ref/deref happens on the right thread." + It may have caused massive increase of reported leaks on the bots. + https://bugs.webkit.org/show_bug.cgi?id=31639 + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/Structure.cpp: + (JSC::Structure::Structure): + * wtf/RefCounted.h: + (WTF::RefCountedBase::ref): + (WTF::RefCountedBase::hasOneRef): + (WTF::RefCountedBase::refCount): + (WTF::RefCountedBase::derefBase): + * wtf/ThreadVerifier.h: Removed. + +2009-12-08 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Reviewed by Darin Adler. + + Make WebKit build correctly on FreeBSD, IA64, and Alpha. + Based on work by Petr Salinger <Petr.Salinger@seznam.cz>, + and Colin Watson <cjwatson@ubuntu.com>. + + * wtf/Platform.h: + +2009-12-08 Dmitry Titov <dimich@chromium.org> + + Reviewed by Darin Adler. + + Add asserts to RefCounted to make sure ref/deref happens on the right thread. + https://bugs.webkit.org/show_bug.cgi?id=31639 + + * runtime/Structure.cpp: + (JSC::Structure::Structure): Disable thread verification on this class since it uses addressOfCount(). + * wtf/RefCounted.h: + (WTF::RefCountedBase::ref): Add ASSERT. + (WTF::RefCountedBase::hasOneRef): Ditto. + (WTF::RefCountedBase::refCount): Ditto. + (WTF::RefCountedBase::derefBase): Ditto. + (WTF::RefCountedBase::disableThreadVerification): delegate to ThreadVerifier method. + * wtf/ThreadVerifier.h: Added. + (WTF::ThreadVerifier::ThreadVerifier): New Debug-only class to verify that ref/deref of RefCounted is done on the same thread. + (WTF::ThreadVerifier::activate): Activates checks. Called when ref count becomes above 2. + (WTF::ThreadVerifier::deactivate): Deactivates checks. Called when ref count drops below 2. + (WTF::ThreadVerifier::disableThreadVerification): used on objects that should not be checked (StringImpl etc) + (WTF::ThreadVerifier::verifyThread): + * GNUmakefile.am: Add ThreadVerifier.h to the build file. + * JavaScriptCore.gypi: Ditto. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: Ditto. + * JavaScriptCore.xcodeproj/project.pbxproj: Ditto. + +2009-12-08 Steve Block <steveblock@google.com> + + Reviewed by Adam Barth. + + [Android] Adds Makefiles for Android port. + https://bugs.webkit.org/show_bug.cgi?id=31325 + + * Android.mk: Added. + * Android.v8.wtf.mk: Added. + +2009-12-07 Dmitry Titov <dimich@chromium.org> + + Rubber-stamped by Darin Adler. + + Remove ENABLE_SHARED_SCRIPT flags + https://bugs.webkit.org/show_bug.cgi?id=32245 + This patch was obtained by "git revert" command and then un-reverting of ChangeLog files. + + * Configurations/FeatureDefines.xcconfig: + * wtf/Platform.h: + +2009-12-07 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (Windows build fixage part I). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2009-12-05 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=32184 + Handle out-of-memory conditions with JSC Ropes with a JS exception, rather than crashing. + Switch from using fastMalloc to tryFastMalloc, pass an ExecState to record the exception on. + + * API/JSCallbackObjectFunctions.h: + (JSC::::toString): + * API/JSValueRef.cpp: + (JSValueIsStrictEqual): + * JavaScriptCore.exp: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitEqualityOp): + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::functionName): + (JSC::DebuggerCallFrame::calculatedFunctionName): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::callEval): + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * profiler/ProfileGenerator.cpp: + (JSC::ProfileGenerator::addParentForConsoleStart): + * profiler/Profiler.cpp: + (JSC::Profiler::willExecute): + (JSC::Profiler::didExecute): + (JSC::Profiler::createCallIdentifier): + (JSC::createCallIdentifierFromFunctionImp): + * profiler/Profiler.h: + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncIndexOf): + (JSC::arrayProtoFuncLastIndexOf): + * runtime/DateConstructor.cpp: + (JSC::constructDate): + * runtime/FunctionPrototype.cpp: + (JSC::functionProtoFuncToString): + * runtime/InternalFunction.cpp: + (JSC::InternalFunction::name): + (JSC::InternalFunction::displayName): + (JSC::InternalFunction::calculatedDisplayName): + * runtime/InternalFunction.h: + * runtime/JSCell.cpp: + (JSC::JSCell::getString): + * runtime/JSCell.h: + (JSC::JSValue::getString): + * runtime/JSONObject.cpp: + (JSC::gap): + (JSC::Stringifier::Stringifier): + (JSC::Stringifier::appendStringifiedValue): + * runtime/JSObject.cpp: + (JSC::JSObject::putDirectFunction): + (JSC::JSObject::putDirectFunctionWithoutTransition): + (JSC::JSObject::defineOwnProperty): + * runtime/JSObject.h: + * runtime/JSPropertyNameIterator.cpp: + (JSC::JSPropertyNameIterator::get): + * runtime/JSString.cpp: + (JSC::JSString::Rope::~Rope): + (JSC::JSString::resolveRope): + (JSC::JSString::getPrimitiveNumber): + (JSC::JSString::toNumber): + (JSC::JSString::toString): + (JSC::JSString::toThisString): + (JSC::JSString::getStringPropertyDescriptor): + * runtime/JSString.h: + (JSC::JSString::Rope::createOrNull): + (JSC::JSString::Rope::operator new): + (JSC::JSString::value): + (JSC::JSString::tryGetValue): + (JSC::JSString::getIndex): + (JSC::JSString::getStringPropertySlot): + (JSC::JSValue::toString): + * runtime/JSValue.h: + * runtime/NativeErrorConstructor.cpp: + (JSC::NativeErrorConstructor::NativeErrorConstructor): + * runtime/Operations.cpp: + (JSC::JSValue::strictEqualSlowCase): + * runtime/Operations.h: + (JSC::JSValue::equalSlowCaseInline): + (JSC::JSValue::strictEqualSlowCaseInline): + (JSC::JSValue::strictEqual): + (JSC::jsLess): + (JSC::jsLessEq): + (JSC::jsAdd): + (JSC::concatenateStrings): + * runtime/PropertyDescriptor.cpp: + (JSC::PropertyDescriptor::equalTo): + * runtime/PropertyDescriptor.h: + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncReplace): + (JSC::stringProtoFuncToLowerCase): + (JSC::stringProtoFuncToUpperCase): + +2009-12-07 Nikolas Zimmermann <nzimmermann@rim.com> + + Reviewed by Holger Freyther. + + Turn on (SVG) Filters support, by default. + https://bugs.webkit.org/show_bug.cgi?id=32224 + + * Configurations/FeatureDefines.xcconfig: Enable FILTERS build flag. + +2009-12-07 Steve Falkenburg <sfalken@apple.com> + + Build fix. Be flexible about which version of ICU is used on Windows. + + * JavaScriptCore.vcproj/jsc/jscCommon.vsprops: Add optional xcopy commands to copy ICU 4.2. + +2009-12-07 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Oliver Hunt. + + op_loop_if_less JIT codegen is broken for 64-bit + https://bugs.webkit.org/show_bug.cgi?id=32221 + + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_loop_if_false): Fix codegen in this version - test was backwards. + +2009-12-07 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Object.create fails if properties on the descriptor are getters + https://bugs.webkit.org/show_bug.cgi?id=32219 + + Correctly initialise the PropertySlots with the descriptor object. + + * runtime/ObjectConstructor.cpp: + (JSC::toPropertyDescriptor): + +2009-12-06 Maciej Stachowiak <mjs@apple.com> + + Not reviewed, build fix. + + Actually tested 64-bit *and* 32-bit build this time. + + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_loop_if_false): + +2009-12-06 Maciej Stachowiak <mjs@apple.com> + + Not reviewed, build fix. + + Really really fix 64-bit build for prior patch (actually tested this time). + + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_loop_if_false): + (JSC::JIT::emitSlow_op_loop_if_false): + +2009-12-06 Maciej Stachowiak <mjs@apple.com> + + Not reviewed, build fix. + + Really fix 64-bit build for prior patch. + + * jit/JITArithmetic.cpp: + (JSC::JIT::emitSlow_op_jless): + +2009-12-06 Maciej Stachowiak <mjs@apple.com> + + Not reviewed, build fix. + + Fix 64-bit build for prior patch. + + * jit/JITOpcodes.cpp: + (JSC::JIT::emitSlow_op_loop_if_less): + +2009-12-05 Maciej Stachowiak <mjs@apple.com> + + Reviewed by Oliver Hunt. + + conway benchmark spends half it's time in op_less (jump fusion fails) + https://bugs.webkit.org/show_bug.cgi?id=32190 + + <1% speedup on SunSpider and V8 + 2x speedup on "conway" benchmark + + Two optimizations: + 1) Improve codegen for logical operators &&, || and ! in a condition context + + When generating code for combinations of &&, || and !, in a + condition context (i.e. in an if statement or loop condition), we + used to produce a value, and then separately jump based on its + truthiness. Now we pass the false and true targets in, and let the + logical operators generate jumps directly. This helps in four + ways: + + a) Individual clauses of a short-circuit logical operator can now + jump directly to the then or else clause of an if statement (or to + the top or exit of a loop) instead of jumping to a jump. + + b) It used to be that jump fusion with the condition of the first + clause of a logical operator was inhibited, because the register + was ref'd to be used later, in the actual condition jump; this no + longer happens since a jump straight to the final target is + generated directly. + + c) It used to be that jump fusion with the condition of the second + clause of a logical operator was inhibited, because there was a + jump target right after the second clause and before the actual + condition jump. But now it's no longer necessary for the first + clause to jump there so jump fusion is not blocked. + + d) We avoid generating excess mov statements in some cases. + + As a concrete example this source: + + if (!((x < q && y < q) || (t < q && z < q))) { + // ... + } + + Used to generate this bytecode: + + [ 34] less r1, r-15, r-19 + [ 38] jfalse r1, 7(->45) + [ 41] less r1, r-16, r-19 + [ 45] jtrue r1, 14(->59) + [ 48] less r1, r-17, r-19 + [ 52] jfalse r1, 7(->59) + [ 55] less r1, r-18, r-19 + [ 59] jtrue r1, 17(->76) + + And now generates this bytecode (also taking advantage of the second optimization below): + + [ 34] jnless r-15, r-19, 8(->42) + [ 38] jless r-16, r-19, 26(->64) + [ 42] jnless r-17, r-19, 8(->50) + [ 46] jless r-18, r-19, 18(->64) + + Note the jump fusion and the fact that there's less jump + indirection - three of the four jumps go straight to the target + clause instead of indirecting through another jump. + + 2) Implement jless opcode to take advantage of the above, since we'll now often generate + a less followed by a jtrue where fusion is not forbidden. + + * parser/Nodes.h: + (JSC::ExpressionNode::hasConditionContextCodegen): Helper function to determine + whether a node supports special conditional codegen. Return false as this is the default. + (JSC::ExpressionNode::emitBytecodeInConditionContext): Assert not reached - only really + defined for nodes that do have conditional codegen. + (JSC::UnaryOpNode::expr): Add const version. + (JSC::LogicalNotNode::hasConditionContextCodegen): Returne true only if subexpression + supports it. + (JSC::LogicalOpNode::hasConditionContextCodegen): Return true. + * parser/Nodes.cpp: + (JSC::LogicalNotNode::emitBytecodeInConditionContext): Implemented - just swap + the true and false targets for the child node. + (JSC::LogicalOpNode::emitBytecodeInConditionContext): Implemented - handle jumps + directly, improving codegen quality. Also handles further nested conditional codegen. + (JSC::ConditionalNode::emitBytecode): Use condition context codegen when available. + (JSC::IfNode::emitBytecode): ditto + (JSC::IfElseNode::emitBytecode): ditto + (JSC::DoWhileNode::emitBytecode): ditto + (JSC::WhileNode::emitBytecode): ditto + (JSC::ForNode::emitBytecode): ditto + + * bytecode/Opcode.h: + - Added loop_if_false opcode - needed now that falsey jumps can be backwards. + - Added jless opcode to take advantage of new fusion opportunities. + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): Handle above. + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitJumpIfTrue): Add peephole for less + jtrue ==> jless. + (JSC::BytecodeGenerator::emitJumpIfFalse): Add handling of backwrds falsey jumps. + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::emitNodeInConditionContext): Wrapper to handle tracking of + overly deep expressions etc. + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): Implement the two new opcodes (loop_if_false, jless). + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): Implement JIT support for the two new opcodes. + (JSC::JIT::privateCompileSlowCases): ditto + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_jless): + (JSC::JIT::emitSlow_op_jless): ditto + (JSC::JIT::emitBinaryDoubleOp): ditto + * jit/JITOpcodes.cpp: + (JSC::JIT::emitSlow_op_loop_if_less): ditto + (JSC::JIT::emit_op_loop_if_false): ditto + (JSC::JIT::emitSlow_op_loop_if_false): ditto + * jit/JITStubs.cpp: + * jit/JITStubs.h: + (JSC::): + +2009-12-04 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Darin Adler. + + JavaScript delete operator should return false for string properties + https://bugs.webkit.org/show_bug.cgi?id=32012 + + * runtime/StringObject.cpp: + (JSC::StringObject::deleteProperty): + +2009-12-03 Drew Wilson <atwilson@chromium.org> + + Rolled back r51633 because it causes a perf regression in Chromium. + + * wtf/Platform.h: + +2009-12-03 Gavin Barraclough <barraclough@apple.com> + + Try and fix the Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Export a symbol that should be exported. + +2009-12-03 Mark Rowe <mrowe@apple.com> + + Try and fix the Mac build. + + * JavaScriptCore.exp: Export a symbol that should be exported. + +2009-12-03 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + REGRESSION(4.0.3-48777): Crash in JSC::ExecState::propertyNames() (Debug-only?) + https://bugs.webkit.org/show_bug.cgi?id=32133 + + Work around odd GCC-ism and correct the scopechain for use by + calls made while a cachedcall is active on the callstack. + + * interpreter/CachedCall.h: + (JSC::CachedCall::newCallFrame): + * runtime/JSArray.cpp: + (JSC::AVLTreeAbstractorForArrayCompare::compare_key_key): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncReplace): + +2009-12-03 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver "Brraaaaiiiinnnnnzzzzzzzz" Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=32136 + Add a rope representation to JSString. Presently JSString always holds its data in UString form. + Instead, allow the result of a string concatenation to be represented in a tree form - with a + variable sized, reference-counted rope node retaining a set of UString::Reps (or other rope nopes). + + Strings must still currently be resolved down to a flat UString representation before being used, + but by holding the string in a rope representation during construction we can avoid copying data + until we know the final size of the string. + + ~2% progression on SunSpider (~25% on date-format-xparb, ~20% on string-validate-input). + + * JavaScriptCore.exp: + + - Update exports. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + + - Make use of new JSString::length() method to avoid prematurely resolving ropes. + + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + + - Switch the string length trampoline to read the length directly from JSString::m_length, + rather than from the JSString's UString::Rep's 'len' property. + + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + + - Modify op_add such that addition of two strings, where either or both strings are already + in rope representation, produces a rope as a result. + + * runtime/JSString.cpp: + (JSC::JSString::Rope::~Rope): + (JSC::copyChars): + (JSC::JSString::resolveRope): + (JSC::JSString::getPrimitiveNumber): + (JSC::JSString::toBoolean): + (JSC::JSString::toNumber): + (JSC::JSString::toString): + (JSC::JSString::toThisString): + (JSC::JSString::getStringPropertyDescriptor): + * runtime/JSString.h: + (JSC::JSString::Rope::Fiber::Fiber): + (JSC::JSString::Rope::Fiber::destroy): + (JSC::JSString::Rope::Fiber::isRope): + (JSC::JSString::Rope::Fiber::rope): + (JSC::JSString::Rope::Fiber::string): + (JSC::JSString::Rope::create): + (JSC::JSString::Rope::initializeFiber): + (JSC::JSString::Rope::ropeLength): + (JSC::JSString::Rope::stringLength): + (JSC::JSString::Rope::fibers): + (JSC::JSString::Rope::Rope): + (JSC::JSString::Rope::operator new): + (JSC::JSString::JSString): + (JSC::JSString::value): + (JSC::JSString::length): + (JSC::JSString::isRope): + (JSC::JSString::rope): + (JSC::JSString::string): + (JSC::JSString::canGetIndex): + (JSC::jsSingleCharacterSubstring): + (JSC::JSString::getIndex): + (JSC::jsSubstring): + (JSC::JSString::getStringPropertySlot): + + - Add rope form. + + * runtime/Operations.h: + (JSC::jsAdd): + (JSC::concatenateStrings): + + - Update string concatenation, and addition of ropes, to produce ropes. + + * runtime/StringObject.cpp: + (JSC::StringObject::getOwnPropertyNames): + + - Make use of new JSString::length() method to avoid prematurely resolving ropes. + +2009-11-23 Jeremy Moskovich <jeremy@chromium.org> + + Reviewed by Eric Seidel. + + Switch Chrome/Mac to use Core Text APIs rather than ATSUI APIs. + https://bugs.webkit.org/show_bug.cgi?id=31802 + + No test since this is already covered by existing pixel tests. + + * wtf/Platform.h: #define USE_CORE_TEXT for Chrome/Mac. + +2009-12-02 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Add files missed in prior patch. + + * runtime/JSZombie.cpp: + (JSC::): + (JSC::JSZombie::leakedZombieStructure): + * runtime/JSZombie.h: Added. + (JSC::JSZombie::JSZombie): + (JSC::JSZombie::isZombie): + (JSC::JSZombie::classInfo): + (JSC::JSZombie::isGetterSetter): + (JSC::JSZombie::isAPIValueWrapper): + (JSC::JSZombie::isPropertyNameIterator): + (JSC::JSZombie::getCallData): + (JSC::JSZombie::getConstructData): + (JSC::JSZombie::getUInt32): + (JSC::JSZombie::toPrimitive): + (JSC::JSZombie::getPrimitiveNumber): + (JSC::JSZombie::toBoolean): + (JSC::JSZombie::toNumber): + (JSC::JSZombie::toString): + (JSC::JSZombie::toObject): + (JSC::JSZombie::markChildren): + (JSC::JSZombie::put): + (JSC::JSZombie::deleteProperty): + (JSC::JSZombie::toThisObject): + (JSC::JSZombie::toThisString): + (JSC::JSZombie::toThisJSString): + (JSC::JSZombie::getJSNumber): + (JSC::JSZombie::getOwnPropertySlot): + +2009-12-02 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Add zombies to JSC + https://bugs.webkit.org/show_bug.cgi?id=32103 + + Add a compile time flag to make the JSC collector replace "unreachable" + objects with zombie objects. The zombie object is a JSCell subclass that + ASSERTs on any attempt to use the JSCell methods. In addition there are + a number of additional assertions in bottleneck code to catch zombie usage + as quickly as possible. + + Grrr. Argh. Brains. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * interpreter/Register.h: + (JSC::Register::Register): + * runtime/ArgList.h: + (JSC::MarkedArgumentBuffer::append): + (JSC::ArgList::ArgList): + * runtime/Collector.cpp: + (JSC::Heap::destroy): + (JSC::Heap::sweep): + * runtime/Collector.h: + * runtime/JSCell.h: + (JSC::JSCell::isZombie): + (JSC::JSValue::isZombie): + * runtime/JSValue.h: + (JSC::JSValue::decode): + (JSC::JSValue::JSValue): + * wtf/Platform.h: + +2009-12-01 Jens Alfke <snej@chromium.org> + + Reviewed by Darin Adler. + + Added variants of find/contains/add that allow a foreign key type to be used. + This will allow AtomicString-keyed maps to be queried by C string without + having to create a temporary AtomicString (see HTTPHeaderMap.) + The code for this is adapted from the equivalent in HashSet.h. + + * wtf/HashMap.h: + (WTF::HashMap::find): + (WTF::HashMap::contains): + (WTF::HashMap::add): + * wtf/HashSet.h: Changed "method" to "function member" in a comment. + +2009-12-01 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Revert 51551 because it broke GTK+. + + * wtf/Platform.h: + +2009-11-30 Gavin Barraclough <barraclough@apple.com> + + Windows Build fix. Reviewed by NOBODY. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2009-11-24 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Bug 31859 - Make world selection for JSC IsolatedWorlds automagical. + + WebCore presently has to explicitly specify the world before entering into JSC, + which is a little fragile (particularly since property access via a + getter/setter might invoke execution). Instead derive the current world from + the lexical global object. + + Remove the temporary duct tape of willExecute/didExecute virtual hooks on the JSGlobalData::ClientData - these are no longer necessary. + + * API/JSBase.cpp: + (JSEvaluateScript): + * API/JSObjectRef.cpp: + (JSObjectCallAsFunction): + * JavaScriptCore.exp: + * runtime/JSGlobalData.cpp: + * runtime/JSGlobalData.h: + +2009-11-30 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Remove obsolete PLATFORM(KDE) code + https://bugs.webkit.org/show_bug.cgi?id=31958 + + KDE is now using unpatched QtWebKit. + + * parser/Lexer.cpp: Remove obsolete KDE_USE_FINAL guard + * wtf/Platform.h: Remove PLATFORM(KDE) definition and code + section that is guarded with it. + +2009-11-30 Jan-Arve Sæther <jan-arve.saether@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix compilation with win32-icc + + The Intel compiler does not support the __has_trivial_constructor type + trait. The Intel Compiler can report itself as _MSC_VER >= 1400. The + reason for that is that the Intel Compiler depends on the Microsoft + Platform SDK, and in order to try to be "fully" MS compatible it will + "pretend" to be the same MS compiler as was shipped with the MS PSDK. + (Thus, compiling with win32-icc with VC8 SDK will make the source code + "think" the compiler at hand supports this type trait). + + * wtf/TypeTraits.h: + +2009-11-29 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Eric Seidel. + + [Qt] Mac build has JIT disabled + https://bugs.webkit.org/show_bug.cgi?id=31828 + + * wtf/Platform.h: Enable JIT for Qt Mac builds + +2009-11-28 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Eric Seidel. + + Apply workaround for the limitation of VirtualFree with MEM_RELEASE to all ports running on Windows + https://bugs.webkit.org/show_bug.cgi?id=31943 + + * runtime/MarkStack.h: + (JSC::MarkStack::MarkStackArray::shrinkAllocation): + +2009-11-28 Zoltan Herczeg <zherczeg@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + https://bugs.webkit.org/show_bug.cgi?id=31930 + + Seems a typo. We don't need ~270k memory to determine the vptrs. + + * runtime/JSGlobalData.cpp: + (JSC::VPtrSet::VPtrSet): + +2009-11-27 Shinichiro Hamaji <hamaji@chromium.org> + + Unreviewed. + + Move GOwnPtr* from wtf to wtf/gtk + https://bugs.webkit.org/show_bug.cgi?id=31793 + + Build fix for chromium after r51423. + Exclude gtk directory from chromium build. + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2009-11-25 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Incorrect behaviour of jneq_null in the interpreter + https://bugs.webkit.org/show_bug.cgi?id=31901 + + Correct the logic of jneq_null. This is already covered by existing tests. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + +2009-11-26 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Oliver Hunt. + + Move GOwnPtr* from wtf to wtf/gtk + https://bugs.webkit.org/show_bug.cgi?id=31793 + + * GNUmakefile.am: Change the path for GOwnPtr.*. + * JavaScriptCore.gyp/JavaScriptCore.gyp: Remove + GOwnPtr.cpp from the exclude list. + * JavaScriptCore.gypi: Change the path for GOwnPtr.*. + * wscript: Remove GOwnPtr.cpp from the exclude list. + * wtf/GOwnPtr.cpp: Removed. + * wtf/GOwnPtr.h: Removed. + * wtf/Threading.h: Change the path for GOwnPtr.h. + * wtf/gtk/GOwnPtr.cpp: Copied from JavaScriptCore/wtf/GOwnPtr.cpp. + * wtf/gtk/GOwnPtr.h: Copied from JavaScriptCore/wtf/GOwnPtr.h. + * wtf/unicode/glib/UnicodeGLib.h: Change the path for GOwnPtr.h. + +2009-11-24 Dmitry Titov <dimich@chromium.org> + + Reviewed by Eric Seidel. + + Add ENABLE_SHARED_SCRIPT feature define and flag for build-webkit + https://bugs.webkit.org/show_bug.cgi?id=31444 + + * Configurations/FeatureDefines.xcconfig: + * wtf/Platform.h: + +2009-11-24 Chris Marrin <cmarrin@apple.com> + + Reviewed by Simon Fraser. + + Add ability to enable ACCELERATED_COMPOSITING on Windows (currently disabled) + https://bugs.webkit.org/show_bug.cgi?id=27314 + + * wtf/Platform.h: + +2009-11-24 Jason Smith <dark.panda@gmail.com> + + Reviewed by Alexey Proskuryakov. + + RegExp#exec's returned Array-like object behaves differently from + regular Arrays + https://bugs.webkit.org/show_bug.cgi?id=31689 + + * JavaScriptCore/runtime/RegExpConstructor.cpp: ensure that undefined + values are added to the returned RegExpMatchesArray + +2009-11-24 Oliver Hunt <oliver@apple.com> + + Reviewed by Alexey Proskuryakov. + + JSON.stringify performance on undefined is very poor + https://bugs.webkit.org/show_bug.cgi?id=31839 + + Switch from a UString to a Vector<UChar> when building + the JSON string, allowing us to safely remove the substr-copy + we otherwise did when unwinding an undefined property. + + Also turns out to be a ~5% speedup on stringification. + + * runtime/JSONObject.cpp: + (JSC::Stringifier::StringBuilder::append): + (JSC::Stringifier::stringify): + (JSC::Stringifier::Holder::appendNextProperty): + +2009-11-24 Mark Rowe <mrowe@apple.com> + + Fix production builds where the source tree may be read-only. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2009-11-23 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Include "config.h" to meet Coding Style Guidelines + https://bugs.webkit.org/show_bug.cgi?id=31792 + + * wtf/unicode/UTF8.cpp: + * wtf/unicode/glib/UnicodeGLib.cpp: + * wtf/unicode/wince/UnicodeWince.cpp: + +2009-11-23 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Streamlined some Math functions where we expect or know the result not + to be representable as an int. + + SunSpider says 0.6% faster. + + * runtime/JSNumberCell.h: + (JSC::JSValue::JSValue): + * runtime/JSValue.h: + (JSC::JSValue::): + (JSC::jsDoubleNumber): + (JSC::JSValue::JSValue): Added a function for making a numeric JSValue + and skipping the "can I encode this as an int?" check, avoiding the + overhead of int <-> double roundtripping and double <-> double comparison + and branching. + + * runtime/MathObject.cpp: + (JSC::mathProtoFuncACos): + (JSC::mathProtoFuncASin): + (JSC::mathProtoFuncATan): + (JSC::mathProtoFuncATan2): + (JSC::mathProtoFuncCos): + (JSC::mathProtoFuncExp): + (JSC::mathProtoFuncLog): + (JSC::mathProtoFuncRandom): + (JSC::mathProtoFuncSin): + (JSC::mathProtoFuncSqrt): + (JSC::mathProtoFuncTan): For these functions, which we expect or know + to produce results not representable as ints, call jsDoubleNumber instead + of jsNumber. + +2009-11-23 Mark Rowe <mrowe@apple.com> + + Unreviewed. Unbreak the regression tests after r51329. + + * API/JSBase.cpp: + (JSEvaluateScript): Null-check clientData before dereferencing it. + * API/JSObjectRef.cpp: + (JSObjectCallAsFunction): Ditto. + +2009-11-23 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Part 1/3 of <rdar://problem/7377477> REGRESSION: Many web pages fail to render after interesting script runs in isolated world + + Some clients of the JavaScriptCore API expect to be able to make callbacks over the JSC API, + and for this to automagically cause execution to take place in the world associated with the + global object associated with the ExecState (JSContextRef) passed. However this is not how + things work - the world must be explicitly set within WebCore. + + Making this work just for API calls to evaluate & call will be a far from perfect solution, + since direct (non-API) use of JSC still relies on WebCore setting the current world correctly. + A better solution would be to make this all work automagically all throughout WebCore, but this + will require more refactoring. + + Since the API is in JSC but worlds only exist in WebCore, add callbacks on the JSGlobalData::ClientData + to allow it to update the current world on entry/exit via the JSC API. This is temporary duck + tape, and should be removed once the current world no longer needs to be explicitly tracked. + + * API/JSBase.cpp: + (JSEvaluateScript): + * API/JSObjectRef.cpp: + (JSObjectCallAsFunction): + * JavaScriptCore.exp: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::ClientData::beginningExecution): + (JSC::JSGlobalData::ClientData::completedExecution): + * runtime/JSGlobalData.h: + +2009-11-23 Steve Block <steveblock@google.com> + + Reviewed by Dmitry Titov. + + Adds MainThreadAndroid.cpp with Android-specific WTF threading functions. + https://bugs.webkit.org/show_bug.cgi?id=31807 + + * wtf/android: Added. + * wtf/android/MainThreadAndroid.cpp: Added. + (WTF::timeoutFired): + (WTF::initializeMainThreadPlatform): + (WTF::scheduleDispatchFunctionsOnMainThread): + +2009-11-23 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Brady Eidson. + + https://bugs.webkit.org/show_bug.cgi?id=31748 + Make WebSocketHandleCFNet respect proxy auto-configuration files via CFProxySupport + + * JavaScriptCore.exp: Export callOnMainThreadAndWait. + +2009-11-23 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Symbian] Fix lastIndexOf() for Symbian + https://bugs.webkit.org/show_bug.cgi?id=31773 + + Symbian soft floating point library has problems with operators + comparing NaN to numbers. Without a workaround lastIndexOf() + function does not work. + + Patch developed by David Leong. + + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncLastIndexOf):Add an extra test + to check for NaN for Symbian. + +2009-11-23 Steve Block <steveblock@google.com> + + Reviewed by Eric Seidel. + + Android port lacks implementation of atomicIncrement and atomicDecrement. + https://bugs.webkit.org/show_bug.cgi?id=31715 + + * wtf/Threading.h: Modified. + (WTF::atomicIncrement): Added Android implementation. + (WTF::atomicDecrement): Added Android implementation. + +2009-11-22 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed. + + [Qt] Sort source lists and remove obsolete comments + from the build system. + + * JavaScriptCore.pri: + +2009-11-21 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Eric Seidel. + + [Qt][Mac] Turn on multiple JavaScript threads for QtWebkit on Mac + https://bugs.webkit.org/show_bug.cgi?id=31753 + + * wtf/Platform.h: + +2009-11-19 Steve Block <steveblock@google.com> + + Android port lacks configuration in Platform.h and config.h. + https://bugs.webkit.org/show_bug.cgi?id=31671 + + * wtf/Platform.h: Modified. Added Android-specific configuration. + +2009-11-19 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=31690 + Make SocketStreamHandleCFNet work on Windows + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * wtf/MainThread.cpp: + (WTF::FunctionWithContext::FunctionWithContext): + (WTF::dispatchFunctionsFromMainThread): + (WTF::callOnMainThreadAndWait): + * wtf/MainThread.h: + Re-add callOnMainThreadAndWait(), which was removed in bug 23926. + +2009-11-19 Dmitry Titov <dimich@chromium.org> + + Reviewed by David Levin. + + isMainThread() on Chromium (Mac and Linux) is so slow it timeouts LayoutTests.. + https://bugs.webkit.org/show_bug.cgi?id=31693 + + * wtf/ThreadingPthreads.cpp: + (WTF::initializeThreading): grab and use the pthread_t of the main thread instead of ThreadIdentifier. + (WTF::isMainThread): Ditto. + +2009-11-19 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Darin Adler. + + Remove HAVE(STRING_H) guard from JavaScriptCore + https://bugs.webkit.org/show_bug.cgi?id=31668 + + * config.h: + * runtime/UString.cpp: + +2009-11-19 Dumitru Daniliuc <dumi@chromium.org> + + Reviewed by Dmitry Titov. + + Fixing a bug in MessageQueue::removeIf() that leads to an + assertion failure. + + https://bugs.webkit.org/show_bug.cgi?id=31657 + + * wtf/MessageQueue.h: + (WTF::MessageQueue::removeIf): + +2009-11-19 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Darin Adler. + + Remove HAVE(FLOAT_H) guard + https://bugs.webkit.org/show_bug.cgi?id=31661 + + JavaScriptCore has a dependency on float.h, there is + no need to guard float.h. + + * runtime/DatePrototype.cpp: Remove include directive + for float.h as it is included in MathExtras.h already. + * runtime/Operations.cpp: Ditto. + * runtime/UString.cpp: Ditto. + * wtf/dtoa.cpp: Ditto. + * wtf/MathExtras.h: Remove HAVE(FLOAT_H) guard. + * wtf/Platform.h: Ditto. + +2009-11-19 Thiago Macieira <thiago.macieira@nokia.com> + + Reviewed by Simon Hausmann. + + Build fix for 32-bit Sparc machines: these machines are big-endian. + + * wtf/Platform.h: + +2009-11-18 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Remove support for Qt v4.3 or older versions + https://bugs.webkit.org/show_bug.cgi?id=29469 + + * JavaScriptCore.pro: + * jsc.pro: + * wtf/unicode/qt4/UnicodeQt4.h: + +2009-11-18 Kent Tamura <tkent@chromium.org> + + Reviewed by Darin Adler. + + Move UString::from(double) implementation to new + WTF::doubleToStringInJavaScriptFormat(), and expose it because WebCore + code will use it. + https://bugs.webkit.org/show_bug.cgi?id=31330 + + - Introduce new function createRep(const char*, unsigned) and + UString::UString(const char*, unsigned) to reduce 2 calls to strlen(). + - Fix a bug that dtoa() doesn't update *rve if the input value is NaN + or Infinity. + + No new tests because this doesn't change the behavior. + + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * runtime/UString.cpp: + (JSC::createRep): + (JSC::UString::UString): + (JSC::UString::from): Move the code to doubleToStringInJavaScriptFormat(). + * runtime/UString.h: + * wtf/dtoa.cpp: + (WTF::dtoa): Fix a bug about rve. + (WTF::append): A helper for doubleToStringInJavaScriptFormat(). + (WTF::doubleToStringInJavaScriptFormat): Move the code from UString::from(double). + * wtf/dtoa.h: + +2009-11-18 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Remove WTF_USE_JAVASCRIPTCORE_BINDINGS as it is no longer used + https://bugs.webkit.org/show_bug.cgi?id=31643 + + * JavaScriptCore.pro: + +2009-11-18 Nate Chapin <japhet@chromium.org> + + Reviewed by Darin Fisher. + + Remove Chromium's unnecessary dependency on wtf's tcmalloc files. + + https://bugs.webkit.org/show_bug.cgi?id=31648 + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2009-11-18 Thiago Macieira <thiago.macieira@nokia.com> + + Reviewed by Gavin Barraclough. + + [Qt] Implement symbol hiding for JSC's JIT functions. + + These functions are implemented directly in assembly, so they need the + proper directives to enable/disable visibility. On ELF systems, it's + .hidden, whereas on Mach-O systems (Mac) it's .private_extern. On + Windows, it's not necessary since you have to explicitly export. I + also implemented the AIX idiom, though it's unlikely anyone will + implement AIX/POWER JIT. + https://bugs.webkit.org/show_bug.cgi?id=30864 + + * jit/JITStubs.cpp: + +2009-11-18 Oliver Hunt <oliver@apple.com> + + Reviewed by Alexey Proskuryakov. + + Interpreter may do an out of range access when throwing an exception in the profiler. + https://bugs.webkit.org/show_bug.cgi?id=31635 + + Add bounds check. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): + +2009-11-18 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Darin Adler. + + Fix the clobber list of cacheFlush for ARM and Thumb2 on Linux + https://bugs.webkit.org/show_bug.cgi?id=31631 + + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::cacheFlush): + +2009-11-18 Harald Fernengel <harald.fernengel@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix detection of linux-g++ + + Never use "linux-g++*" to check for linux-g++, since this will break embedded + builds which use linux-arm-g++ and friends. Use 'linux*-g++*' to check for any + g++ on linux mkspec. + + * JavaScriptCore.pri: + +2009-11-17 Jon Honeycutt <jhoneycutt@apple.com> + + Add JSContextRefPrivate.h to list of copied files. + + Reviewed by Mark Rowe. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make: + +2009-11-17 Martin Robinson <martin.james.robinson@gmail.com> + + Reviewed by Adam Barth. + + [GTK] Style cleanup for GOwnPtr + https://bugs.webkit.org/show_bug.cgi?id=31506 + + Remove forward declaration in GOwnPtr and do some style cleanup. + + * wtf/GOwnPtr.cpp: + * wtf/GOwnPtr.h: + (WTF::GOwnPtr::GOwnPtr): + (WTF::GOwnPtr::~GOwnPtr): + (WTF::GOwnPtr::get): + (WTF::GOwnPtr::release): + (WTF::GOwnPtr::outPtr): + (WTF::GOwnPtr::set): + (WTF::GOwnPtr::clear): + (WTF::GOwnPtr::operator*): + (WTF::GOwnPtr::operator->): + (WTF::GOwnPtr::operator!): + (WTF::GOwnPtr::operator UnspecifiedBoolType): + (WTF::GOwnPtr::swap): + (WTF::swap): + (WTF::operator==): + (WTF::operator!=): + (WTF::getPtr): + (WTF::freeOwnedGPtr): + +2009-11-17 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Incorrect use of JavaScriptCore API in DumpRenderTree + https://bugs.webkit.org/show_bug.cgi?id=31577 + + Add assertions to the 'toJS' functions to catch mistakes like + this early. Restructure existing code which blindly passed potentially + null values to toJS when forwarding exceptions so that a null check is + performed first. + + * API/APICast.h: + (toJS): + (toJSForGC): + * API/JSCallbackObjectFunctions.h: + (JSC::::getOwnPropertySlot): + (JSC::::put): + (JSC::::deleteProperty): + (JSC::::construct): + (JSC::::hasInstance): + (JSC::::call): + (JSC::::toNumber): + (JSC::::toString): + (JSC::::staticValueGetter): + (JSC::::callbackGetter): + * API/tests/testapi.c: Fix errors in the API tester. + (MyObject_getProperty): + (MyObject_convertToType): + (EvilExceptionObject_convertToType): + +2009-11-16 Zoltan Herczeg <zherczeg@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + https://bugs.webkit.org/show_bug.cgi?id=31050 + + Minor fixes for JSVALUE32_64: branchConvertDoubleToInt32 + failed on a CortexA8 CPU, but not on a simulator; and + JITCall.cpp modifications was somehow not committed to mainline. + + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::fmrs_r): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::branchConvertDoubleToInt32): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + +2009-11-16 Joerg Bornemann <joerg.bornemann@trolltech.com> + + Reviewed by Simon Hausmann. + + Fix Qt build on Windows CE 6. + + * JavaScriptCore.pri: Add missing include path. + * wtf/Platform.h: Include ce_time.h for Windows CE 6. + +2009-11-13 Zoltan Herczeg <zherczeg@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + https://bugs.webkit.org/show_bug.cgi?id=31050 + + Adding optimization support for mode JSVALUE32_64 + on ARM systems. + + * jit/JIT.h: + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::emit_op_method_check): + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::emit_op_put_by_id): + +2009-11-14 Zoltan Herczeg <zherczeg@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + https://bugs.webkit.org/show_bug.cgi?id=31050 + + Adding JSVALUE32_64 support for ARM (but not turning it + on by default). All optimizations must be disabled, since + this patch is only the first of a series of patches. + + During the work, a lot of x86 specific code revealed and + made platform independent. + See revisions: 50531 50541 50593 50594 50595 + + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::): + (JSC::ARMAssembler::fdivd_r): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::lshift32): + (JSC::MacroAssemblerARM::neg32): + (JSC::MacroAssemblerARM::rshift32): + (JSC::MacroAssemblerARM::branchOr32): + (JSC::MacroAssemblerARM::set8): + (JSC::MacroAssemblerARM::setTest8): + (JSC::MacroAssemblerARM::loadDouble): + (JSC::MacroAssemblerARM::divDouble): + (JSC::MacroAssemblerARM::convertInt32ToDouble): + (JSC::MacroAssemblerARM::zeroDouble): + * jit/JIT.cpp: + * jit/JIT.h: + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + * jit/JITStubs.cpp: + * wtf/StdLibExtras.h: + +2009-11-13 Dominik Röttsches <dominik.roettsches@access-company.com> + + Reviewed by Eric Seidel. + + Unify TextBoundaries implementations by only relying on WTF Unicode abstractions + https://bugs.webkit.org/show_bug.cgi?id=31468 + + Adding isAlphanumeric abstraction, required + by TextBoundaries.cpp. + + * wtf/unicode/glib/UnicodeGLib.h: + (WTF::Unicode::isAlphanumeric): + * wtf/unicode/icu/UnicodeIcu.h: + (WTF::Unicode::isAlphanumeric): + +2009-11-13 Norbert Leser <norbert.leser&nokia.com> + + Reviewed by Eric Seidel. + + Added macros for USERINCLUDE paths within symbian blocks + to guarantee inclusion of respective header files from local path + first (to avoid clashes with same names of header files in system include path). + + * JavaScriptCore.pri: + +2009-11-13 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + JSValueProtect and JSValueUnprotect don't protect API wrapper values + https://bugs.webkit.org/show_bug.cgi?id=31485 + + Make JSValueProtect/Unprotect use a new 'toJS' function, 'toJSForGC' that + does not attempt to to strip out API wrapper objects. + + * API/APICast.h: + (toJSForGC): + * API/JSValueRef.cpp: + (JSValueProtect): + (JSValueUnprotect): + * API/tests/testapi.c: + (makeGlobalNumberValue): + (main): + +2009-11-13 İsmail Dönmez <ismail@namtrac.org> + + Reviewed by Antti Koivisto. + + Fix typo, ce_time.cpp should be ce_time.c + + * JavaScriptCore.pri: + +2009-11-12 Steve VanDeBogart <vandebo@chromium.org> + + Reviewed by Adam Barth. + + Calculate the time offset only if we were able to parse + the date string. This saves an IPC in Chromium for + invalid date strings. + https://bugs.webkit.org/show_bug.cgi?id=31416 + + * wtf/DateMath.cpp: + (WTF::parseDateFromNullTerminatedCharacters): + (JSC::parseDateFromNullTerminatedCharacters): + +2009-11-12 Oliver Hunt <oliver@apple.com> + + Rollout r50896 until i can work out why it causes failures. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitReturn): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + * parser/Nodes.cpp: + (JSC::EvalNode::emitBytecode): + +2009-11-12 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Stephanie Lewis. + + Remove LIBRARY directive from def file to fix Debug_All target. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2009-11-12 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Rubber-stamped by Holger Freyther. + + Revert r50204, since it makes DRT crash on 32 bits release builds + for GTK+. + + * wtf/FastMalloc.h: + +2009-11-12 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Start unifying entry logic for function and eval code. + + Eval now uses a ret instruction to end execution, and sets up + a callframe more in line with what we do for function entry. + + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitReturn): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + * parser/Nodes.cpp: + (JSC::EvalNode::emitBytecode): + +2009-11-12 Richard Moe Gustavsen <richard.gustavsen@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Disable pthread_setname_np. + + This allows Qt builds on Mac from 10.6 to run on earlier version + where this symbol is not present. + https://bugs.webkit.org/show_bug.cgi?id=31403 + + * wtf/Platform.h: + +2009-11-12 Thiago Macieira <thiago.macieira@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Qt] Fix linking on Linux 32-bit. + + It was missing the ".text" directive at the top of the file, + indicating that code would follow. Without it, the assembler created + "NOTYPE" symbols, which would result in linker errors. + https://bugs.webkit.org/show_bug.cgi?id=30863 + + * jit/JITStubs.cpp: + +2009-11-11 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Alexey Proskuryakov. + + Refactor multiple JavaScriptCore threads + https://bugs.webkit.org/show_bug.cgi?id=31328 + + Remove the id field from the PlatformThread structure + as it is not used. + + * runtime/Collector.cpp: + (JSC::getCurrentPlatformThread): + (JSC::suspendThread): + (JSC::resumeThread): + (JSC::getPlatformThreadRegisters): + +2009-11-10 Geoffrey Garen <ggaren@apple.com> + + Linux build fix: Added an #include for UINT_MAX. + + * runtime/WeakRandom.h: + +2009-11-10 Geoffrey Garen <ggaren@apple.com> + + JavaScriptGlue build fix: Marked a file 'private' instead of 'project'. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2009-11-10 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Gavin "avGni arBalroguch" Barraclough. + + Faster Math.random, based on GameRand. + + SunSpider says 1.4% faster. + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: Added the header to the project. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: Use an object to track random number generation + state, initialized to the current time. + + * runtime/MathObject.cpp: + (JSC::MathObject::MathObject): + (JSC::mathProtoFuncRandom): Use the new hotness. + + * runtime/WeakRandom.h: Added. + (JSC::WeakRandom::WeakRandom): + (JSC::WeakRandom::get): + (JSC::WeakRandom::advance): The new hotness. + +2009-11-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Imported the v8 DST cache. + + SunSpider says 1.5% faster. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::resetDateCache): Reset the DST cache when resetting + other date data. + + * runtime/JSGlobalData.h: + (JSC::DSTOffsetCache::DSTOffsetCache): + (JSC::DSTOffsetCache::reset): Added a struct for the DST cache. + + * wtf/DateMath.cpp: + (WTF::calculateDSTOffsetSimple): + (WTF::calculateDSTOffset): + (WTF::parseDateFromNullTerminatedCharacters): + (JSC::getDSTOffset): + (JSC::gregorianDateTimeToMS): + (JSC::msToGregorianDateTime): + (JSC::parseDateFromNullTerminatedCharacters): + * wtf/DateMath.h: The imported code for probing and updating the cache. + +2009-11-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Fixed an edge case that could cause the engine not to notice a timezone + change. + + No test because this case would require manual intervention to change + the timezone during the test. + + SunSpider reports no change. + + * runtime/DateInstanceCache.h: + (JSC::DateInstanceCache::DateInstanceCache): + (JSC::DateInstanceCache::reset): Added a helper function for resetting + this cache. Also, shrank the cache, since we'll be resetting it often. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::resetDateCache): Include resetting the DateInstanceCache + in resetting Date data. (Otherwise, a cache hit could bypass a necessary + timezone update check.) + +2009-11-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Some manual inlining and constant propogation in Date code. + + SunSpider reports a 0.4% speedup on date-*, no overall speedup. Shark + says some previously evident stalls are now gone. + + * runtime/DateConstructor.cpp: + (JSC::callDate): + * runtime/DateConversion.cpp: + (JSC::formatTime): + (JSC::formatTimeUTC): Split formatTime into UTC and non-UTC variants. + + * runtime/DateConversion.h: + * runtime/DateInstance.cpp: + (JSC::DateInstance::calculateGregorianDateTime): + (JSC::DateInstance::calculateGregorianDateTimeUTC): + * runtime/DateInstance.h: + (JSC::DateInstance::gregorianDateTime): + (JSC::DateInstance::gregorianDateTimeUTC): Split gregorianDateTime into + a UTC and non-UTC variant, and split each variant into a fast inline + case and a slow out-of-line case. + + * runtime/DatePrototype.cpp: + (JSC::formatLocaleDate): + (JSC::dateProtoFuncToString): + (JSC::dateProtoFuncToUTCString): + (JSC::dateProtoFuncToISOString): + (JSC::dateProtoFuncToDateString): + (JSC::dateProtoFuncToTimeString): + (JSC::dateProtoFuncGetFullYear): + (JSC::dateProtoFuncGetUTCFullYear): + (JSC::dateProtoFuncToGMTString): + (JSC::dateProtoFuncGetMonth): + (JSC::dateProtoFuncGetUTCMonth): + (JSC::dateProtoFuncGetDate): + (JSC::dateProtoFuncGetUTCDate): + (JSC::dateProtoFuncGetDay): + (JSC::dateProtoFuncGetUTCDay): + (JSC::dateProtoFuncGetHours): + (JSC::dateProtoFuncGetUTCHours): + (JSC::dateProtoFuncGetMinutes): + (JSC::dateProtoFuncGetUTCMinutes): + (JSC::dateProtoFuncGetSeconds): + (JSC::dateProtoFuncGetUTCSeconds): + (JSC::dateProtoFuncGetTimezoneOffset): + (JSC::setNewValueFromTimeArgs): + (JSC::setNewValueFromDateArgs): + (JSC::dateProtoFuncSetYear): + (JSC::dateProtoFuncGetYear): Updated for the gregorianDateTime change above. + +2009-11-09 Geoffrey Garen <ggaren@apple.com> + + Build fix: export a new symbol. + + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2009-11-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam "Home Wrecker" Weinig. + + Added a tiny cache for Date parsing. + + SunSpider says 1.2% faster. + + * runtime/DateConversion.cpp: + (JSC::parseDate): Try to reuse the last parsed Date, if present. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::resetDateCache): + * runtime/JSGlobalData.h: Added storage for last parsed Date. Refactored + this code to make resetting the date cache easier. + + * runtime/JSGlobalObject.h: + (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Updated for + refactoring. + + * wtf/DateMath.cpp: + (JSC::parseDateFromNullTerminatedCharacters): + * wtf/DateMath.h: Changed ExecState to be first parameter, as is the JSC custom. + +2009-11-09 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Can cache prototype lookups on uncacheable dictionaries. + https://bugs.webkit.org/show_bug.cgi?id=31198 + + Replace fromDictionaryTransition with flattenDictionaryObject and + flattenDictionaryStructure. This change is necessary as we need to + guarantee that our attempt to convert away from a dictionary structure + will definitely succeed, and in some cases this requires mutating the + object storage itself. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::tryCacheGetByID): + * jit/JITStubs.cpp: + (JSC::JITThunks::tryCacheGetByID): + (JSC::DEFINE_STUB_FUNCTION): + * runtime/BatchedTransitionOptimizer.h: + (JSC::BatchedTransitionOptimizer::~BatchedTransitionOptimizer): + * runtime/JSObject.h: + (JSC::JSObject::flattenDictionaryObject): + * runtime/Operations.h: + (JSC::normalizePrototypeChain): + * runtime/Structure.cpp: + (JSC::Structure::flattenDictionaryStructure): + (JSC::comparePropertyMapEntryIndices): + * runtime/Structure.h: + +2009-11-09 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Not reviewed, build fix. + + Remove extra character from r50701. + + * JavaScriptCore.pri: + +2009-11-09 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Not reviewed, build fix. + + Revert r50695 because it broke QtWebKit (clean builds). + + * JavaScriptCore.pri: + +2009-11-09 Norbert Leser <norbert.leser@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Prepended $$PWD to GENERATED_SOURCES_DIR to avoid potential ambiguities when included from WebCore.pro. + Some preprocessors consider this GENERATED_SOURCES_DIR relative to current invoking dir (e.g., ./WebCore), + and not the working dir of JavaCriptCore.pri (i.e., ../JavaScriptCore/). + + * JavaScriptCore.pri: + +2009-11-09 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Use explicit parentheses to silence gcc 4.4 -Wparentheses warnings + https://bugs.webkit.org/show_bug.cgi?id=31040 + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + +2009-11-08 David Levin <levin@chromium.org> + + Reviewed by NOBODY (speculative snow leopard and windows build fixes). + + * wtf/DateMath.cpp: + (WTF::parseDateFromNullTerminatedCharacters): + (JSC::gregorianDateTimeToMS): + (JSC::msToGregorianDateTime): + (JSC::parseDateFromNullTerminatedCharacters): + * wtf/DateMath.h: + (JSC::GregorianDateTime::GregorianDateTime): + +2009-11-08 David Levin <levin@chromium.org> + + Reviewed by NOBODY (chromium build fix). + + Hopefully, the last build fix. + + Create better separation in DateMath about the JSC + and non-JSC portions. Also, only expose the non-JSC + version in the exports. + + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * wtf/DateMath.cpp: + (WTF::parseDateFromNullTerminatedCharacters): + (JSC::getUTCOffset): + (JSC::gregorianDateTimeToMS): + (JSC::msToGregorianDateTime): + (JSC::parseDateFromNullTerminatedCharacters): + * wtf/DateMath.h: + (JSC::gmtoffset): + +2009-11-08 David Levin <levin@chromium.org> + + Reviewed by NOBODY (chromium build fix). + + For the change in DateMath. + + * config.h: + * wtf/DateMath.cpp: + +2009-11-06 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: export some symbols. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2009-11-06 Geoffrey Garen <ggaren@apple.com> + + Build fix: updated export file. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2009-11-06 Geoffrey Garen <ggaren@apple.com> + + Build fix: added some #includes. + + * wtf/CurrentTime.h: + * wtf/DateMath.h: + +2009-11-06 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=31197 + Implemented a timezone cache not based on Mac OS X's notify_check API. + + If the VM calculates the local timezone offset from UTC, it caches the + result until the end of the current VM invocation. (We don't want to cache + forever, because the user's timezone may change over time.) + + This removes notify_* overhead on Mac, and, more significantly, removes + OS time and date call overhead on non-Mac platforms. + + ~8% speedup on Date microbenchmark on Mac. SunSpider reports maybe a tiny + speedup on Mac. (Speedup on non-Mac platforms should be even more noticeable.) + + * JavaScriptCore.exp: + + * interpreter/CachedCall.h: + (JSC::CachedCall::CachedCall): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + * runtime/JSGlobalObject.h: + (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Made the + DynamicGlobalObjectScope constructor responsible for checking whether a + dynamicGlobalObject has already been set. This eliminated some duplicate + client code, and allowed me to avoid adding even more duplicate client + code. Made DynamicGlobalObjectScope responsible for resetting the + local timezone cache upon first entry to the VM. + + * runtime/DateConstructor.cpp: + (JSC::constructDate): + (JSC::callDate): + (JSC::dateParse): + (JSC::dateUTC): + * runtime/DateConversion.cpp: + (JSC::parseDate): + * runtime/DateConversion.h: + * runtime/DateInstance.cpp: + (JSC::DateInstance::gregorianDateTime): + * runtime/DateInstance.h: + * runtime/DateInstanceCache.h: + * runtime/DatePrototype.cpp: + (JSC::setNewValueFromTimeArgs): + (JSC::setNewValueFromDateArgs): + (JSC::dateProtoFuncSetYear): + * runtime/InitializeThreading.cpp: + (JSC::initializeThreadingOnce): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + * wtf/DateMath.cpp: + (WTF::getCurrentUTCTime): + (WTF::getCurrentUTCTimeWithMicroseconds): + (WTF::getLocalTime): + (JSC::getUTCOffset): Use the new cache. Also, see below. + (JSC::gregorianDateTimeToMS): + (JSC::msToGregorianDateTime): + (JSC::initializeDates): + (JSC::parseDateFromNullTerminatedCharacters): Simplified the way this function + accounts for the local timezone offset, to accomodate our new caching API, + and a (possibly misguided) caller in WebCore. Also, see below. + * wtf/DateMath.h: + (JSC::GregorianDateTime::GregorianDateTime): Moved most of the code in + DateMath.* into the JSC namespace. The code needed to move so it could + naturally interact with ExecState and JSGlobalData to support caching. + Logically, it seemed right to move it, too, since this code is not really + as low-level as the WTF namespace might imply -- it implements a set of + date parsing and conversion quirks that are finely tuned to the JavaScript + language. Also removed the Mac OS X notify_* infrastructure. + + * wtf/CurrentTime.h: + (WTF::currentTimeMS): + (WTF::getLocalTime): Moved the rest of the DateMath code here, and renamed + it to make it consistent with WTF's currentTime function. + +2009-11-06 Gabor Loki <loki@inf.u-szeged.hu> + + Unreviewed trivial buildfix after r50595. + + Rename the remaining rshiftPtr calls to rshift32 + + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_rshift): + * jit/JITInlineMethods.h: + (JSC::JIT::emitFastArithImmToInt): + +2009-11-06 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Tidy up the shift methods on the macro-assembler interface. + + Currently behaviour of shifts of a magnitude > 0x1f is undefined. + Instead defined that all shifts are masked to this range. This makes a lot of + practical sense, both since having undefined behaviour is not particularly + desirable, and because this behaviour is commonly required (particularly since + it is required bt ECMA-262 for shifts). + + Update the ARM assemblers to provide this behaviour. Remove (now) redundant + masks from JITArithmetic, and remove rshiftPtr (this was used in case that + could be rewritten in a simpler form using rshift32, only optimized JSVALUE32 + on x86-64, which uses JSVALUE64!) + + * assembler/MacroAssembler.h: + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::lshift32): + (JSC::MacroAssemblerARM::rshift32): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::lshift32): + (JSC::MacroAssemblerARMv7::rshift32): + * assembler/MacroAssemblerX86_64.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_lshift): + (JSC::JIT::emit_op_rshift): + +2009-11-05 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Oliver Hunt. + + Remove a magic number (1) from the JIT, instead compute the value with OBJECT_OFFSET. + + * jit/JITInlineMethods.h: + (JSC::JIT::emitPutJITStubArg): + (JSC::JIT::emitPutJITStubArgConstant): + (JSC::JIT::emitGetJITStubArg): + (JSC::JIT::emitPutJITStubArgFromVirtualRegister): + * jit/JITStubCall.h: + (JSC::JITStubCall::JITStubCall): + (JSC::JITStubCall::getArgument): + * jit/JITStubs.h: + +2009-11-05 Zoltan Herczeg <zherczeg@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + https://bugs.webkit.org/show_bug.cgi?id=31159 + Fix branchDouble behaviour on ARM THUMB2 JIT. + + The x86 branchDouble behaviour is reworked, and all JIT + ports should follow the x86 port. See bug 31104 and 31151 + + This patch contains a fix for the traditional ARM port + + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::): + (JSC::ARMAssembler::fmrs_r): + (JSC::ARMAssembler::ftosid_r): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::): + (JSC::MacroAssemblerARM::branchDouble): + (JSC::MacroAssemblerARM::branchConvertDoubleToInt32): + +2009-11-05 Chris Jerdonek <chris.jerdonek@gmail.com> + + Reviewed by Eric Seidel. + + Removed the "this is part of the KDE project" comments from + all *.h, *.cpp, *.idl, and *.pm files. + + https://bugs.webkit.org/show_bug.cgi?id=31167 + + The maintenance and architecture page in the project wiki lists + this as a task. + + This change includes no changes or additions to test cases + since the change affects only comments. + + * wtf/wince/FastMallocWince.h: + +2009-11-05 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + Use ARMv7 specific encoding for immediate constants on ARMv7 target + https://bugs.webkit.org/show_bug.cgi?id=31060 + + * assembler/ARMAssembler.cpp: + (JSC::ARMAssembler::getOp2): Use INVALID_IMM + (JSC::ARMAssembler::getImm): Use encodeComplexImm for complex immediate + (JSC::ARMAssembler::moveImm): Ditto. + (JSC::ARMAssembler::encodeComplexImm): Encode a constant by one or two + instructions or a PC relative load. + * assembler/ARMAssembler.h: Use INVALID_IMM if a constant cannot be + encoded as an immediate constant. + (JSC::ARMAssembler::): + (JSC::ARMAssembler::movw_r): 16-bit immediate load + (JSC::ARMAssembler::movt_r): High halfword 16-bit immediate load + (JSC::ARMAssembler::getImm16Op2): Encode immediate constant for + movw_r and mowt_r + +2009-11-04 Mark Mentovai <mark@chromium.org> + + Reviewed by Mark Rowe. + + Provide TARGETING_TIGER and TARGETING_LEOPARD as analogues to + BUILDING_ON_TIGER and BUILDING_ON_LEOPARD. The TARGETING_ macros + consider the deployment target; the BUILDING_ON_ macros consider the + headers being built against. + + * wtf/Platform.h: + +2009-11-04 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=31151 + Fix branchDouble behaviour on ARM THUMB2 JIT. + + The ARMv7 JIT is currently using ARMv7Assembler::ConditionEQ to branch + for DoubleEqualOrUnordered, however this is incorrect – ConditionEQ won't + branch on unordered operands. Similarly, DoubleLessThanOrUnordered & + DoubleLessThanOrEqualOrUnordered use ARMv7Assembler::ConditionLO & + ARMv7Assembler::ConditionLS, whereas they should be using + ARMv7Assembler::ConditionLT & ARMv7Assembler::ConditionLE. + + Fix these, and fill out the missing DoubleConditions. + + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::): + (JSC::MacroAssemblerARMv7::branchDouble): + +2009-11-04 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Oliver Hunt. + + Enable native call optimizations on ARMv7. (Existing ARM_TRADITIONAL + implementation was generic, worked perfectly, just needed turning on). + + * jit/JITOpcodes.cpp: + * wtf/Platform.h: + +2009-11-04 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Mark Rowe, Oliver Hunt, and Sam Weinig. + + Add a missing assert to the ARMv7 JIT. + + * assembler/ARMv7Assembler.h: + (JSC::ARMThumbImmediate::ARMThumbImmediate): + +2009-11-04 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Oliver Hunt. + + Remove bogus op_ prefix on dumped version of three opcodes. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + +2009-11-04 Mark Rowe <mrowe@apple.com> + + Reviewed by Sam Weinig. + + Fix dumping of constants in bytecode so that they aren't printed as large positive register numbers. + + We do this by having the registerName function return information about the constant if the register + number corresponds to a constant. This requires that registerName, and several functions that call it, + be converted to member functions of CodeBlock so that the constant value can be retrieved. The + ExecState also needs to be threaded down through these functions so that it can be passed on to + constantName when needed. + + * bytecode/CodeBlock.cpp: + (JSC::constantName): + (JSC::CodeBlock::registerName): + (JSC::CodeBlock::printUnaryOp): + (JSC::CodeBlock::printBinaryOp): + (JSC::CodeBlock::printConditionalJump): + (JSC::CodeBlock::printGetByIdOp): + (JSC::CodeBlock::printPutByIdOp): + (JSC::CodeBlock::dump): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::isConstantRegisterIndex): + +2009-11-04 Pavel Heimlich <tropikhajma@gmail.com> + + Reviewed by Alexey Proskuryakov. + + https://bugs.webkit.org/show_bug.cgi?id=30647 + Solaris build failure due to strnstr. + + * wtf/StringExtras.h: Enable strnstr on Solaris, too. + +2009-11-04 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=31104 + Refactor x86-specific behaviour out of the JIT. + + - Add explicit double branch conditions for ordered and unordered comparisons (presently the brehaviour is a mix). + - Refactor double to int conversion out into the MacroAssembler. + - Remove broken double to int conversion for !JSVALUE32_64 builds - this code was broken and slowing us down, fixing it showed it not to be an improvement. + - Remove exclusion of double to int conversion from (1 % X) cases in JSVALUE32_64 builds - if this was of benefit this is no longer the case; simplify. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::): + (JSC::MacroAssemblerX86Common::convertInt32ToDouble): + (JSC::MacroAssemblerX86Common::branchDouble): + (JSC::MacroAssemblerX86Common::branchConvertDoubleToInt32): + * jit/JITArithmetic.cpp: + (JSC::JIT::emitBinaryDoubleOp): + (JSC::JIT::emit_op_div): + (JSC::JIT::emitSlow_op_jnless): + (JSC::JIT::emitSlow_op_jnlesseq): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_jfalse): + +2009-11-04 Mark Mentovai <mark@chromium.org> + + Reviewed by Eric Seidel. + + Remove BUILDING_ON_LEOPARD from JavaScriptCore.gyp. This is supposed + to be set as needed only in wtf/Platform.h. + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2009-11-02 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + REGRESSION (r48573): JSC may incorrectly cache chain lookups with a dictionary at the head of the chain + https://bugs.webkit.org/show_bug.cgi?id=31045 + + Add guards to prevent caching of prototype chain lookups with dictionaries at the + head of the chain. Also add a few tighter assertions to cached prototype lookups + to catch this in future. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::tryCacheGetByID): + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::JITThunks::tryCacheGetByID): + +2009-11-02 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Darin Adler. + + PLATFORM(CF) should be set when building for Qt on Darwin + https://bugs.webkit.org/show_bug.cgi?id=23671 + + * wtf/Platform.h: Turn on CF support if both QT and DARWIN + platforms are defined. + +2009-11-02 Dmitry Titov <dimich@chromium.org> + + Reviewed by David Levin. + + Remove threadsafe refcounting from tasks used with WTF::MessageQueue. + https://bugs.webkit.org/show_bug.cgi?id=30612 + + * wtf/MessageQueue.h: + (WTF::MessageQueue::alwaysTruePredicate): + (WTF::MessageQueue::~MessageQueue): + (WTF::MessageQueue::append): + (WTF::MessageQueue::appendAndCheckEmpty): + (WTF::MessageQueue::prepend): + (WTF::MessageQueue::waitForMessage): + (WTF::MessageQueue::waitForMessageFilteredWithTimeout): + (WTF::MessageQueue::tryGetMessage): + (WTF::MessageQueue::removeIf): + The MessageQueue is changed to act as a queue of OwnPtr<DataType>. It takes ownership + of posted tasks and passes it to the new owner (in another thread) when the task is fetched. + All methods have arguments of type PassOwnPtr<DataType> and return the same type. + + * wtf/Threading.cpp: + (WTF::createThread): + Superficial change to trigger rebuild of JSC project on Windows, + workaround for https://bugs.webkit.org/show_bug.cgi?id=30890 + +2009-10-30 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Fixed failing layout test: restore a special case I accidentally deleted. + + * runtime/DatePrototype.cpp: + (JSC::setNewValueFromDateArgs): In the case of applying a change to a date + that is NaN, reset the date to 0 *and* then apply the change; don't just + reset the date to 0. + +2009-10-30 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: update for object-to-pointer change. + + * runtime/DatePrototype.cpp: + (JSC::formatLocaleDate): + +2009-10-29 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=30942 + Use pointers instead of copies to pass GregorianDateTime objects around. + + SunSpider reports a shocking 4.5% speedup on date-format-xparb, and 1.3% + speedup on date-format-tofte. + + * runtime/DateInstance.cpp: + (JSC::DateInstance::gregorianDateTime): + * runtime/DateInstance.h: + * runtime/DatePrototype.cpp: + (JSC::formatLocaleDate): + (JSC::dateProtoFuncToString): + (JSC::dateProtoFuncToUTCString): + (JSC::dateProtoFuncToISOString): + (JSC::dateProtoFuncToDateString): + (JSC::dateProtoFuncToTimeString): + (JSC::dateProtoFuncGetFullYear): + (JSC::dateProtoFuncGetUTCFullYear): + (JSC::dateProtoFuncToGMTString): + (JSC::dateProtoFuncGetMonth): + (JSC::dateProtoFuncGetUTCMonth): + (JSC::dateProtoFuncGetDate): + (JSC::dateProtoFuncGetUTCDate): + (JSC::dateProtoFuncGetDay): + (JSC::dateProtoFuncGetUTCDay): + (JSC::dateProtoFuncGetHours): + (JSC::dateProtoFuncGetUTCHours): + (JSC::dateProtoFuncGetMinutes): + (JSC::dateProtoFuncGetUTCMinutes): + (JSC::dateProtoFuncGetSeconds): + (JSC::dateProtoFuncGetUTCSeconds): + (JSC::dateProtoFuncGetTimezoneOffset): + (JSC::setNewValueFromTimeArgs): + (JSC::setNewValueFromDateArgs): + (JSC::dateProtoFuncSetYear): + (JSC::dateProtoFuncGetYear): Renamed getGregorianDateTime to gregorianDateTime, + since it no longer has an out parameter. Uses 0 to indicate invalid dates. + +2009-10-30 Zoltan Horvath <zoltan@webkit.org> + + Reviewed by Darin Adler. + + Allow custom memory allocation control for JavaScriptCore's ListHashSet + https://bugs.webkit.org/show_bug.cgi?id=30853 + + Inherits ListHashSet class from FastAllocBase because it is + instantiated by 'new' in WebCore/rendering/RenderBlock.cpp:1813. + + * wtf/ListHashSet.h: + +2009-10-30 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Regression: crash enumerating properties of an object with getters or setters + https://bugs.webkit.org/show_bug.cgi?id=30948 + + Add a guard to prevent us trying to cache property enumeration on + objects with getters or setters. + + * runtime/JSPropertyNameIterator.cpp: + (JSC::JSPropertyNameIterator::create): + +2009-10-30 Roland Steiner <rolandsteiner@chromium.org> + + Reviewed by Eric Seidel. + + Remove ENABLE_RUBY guards as discussed with Dave Hyatt and Maciej Stachowiak. + + Bug 28420 - Implement HTML5 <ruby> rendering + (https://bugs.webkit.org/show_bug.cgi?id=28420) + + No new tests (no functional change). + + * Configurations/FeatureDefines.xcconfig: + +2009-10-29 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + REGRESSION (r50218-r50262): E*TRADE accounts page is missing content + https://bugs.webkit.org/show_bug.cgi?id=30947 + <rdar://problem/7348833> + + The logic for flagging that a structure has non-enumerable properties + was in addPropertyWithoutTransition, rather than in the core Structure::put + method. Despite this I was unable to produce a testcase that caused + the failure that etrade was experiencing, but the new assertion in + getEnumerablePropertyNames triggers on numerous layout tests without + the fix, so in effecti all for..in enumeration in any test ends up + doing the required consistency check. + + * runtime/Structure.cpp: + (JSC::Structure::addPropertyWithoutTransition): + (JSC::Structure::put): + (JSC::Structure::getEnumerablePropertyNames): + (JSC::Structure::checkConsistency): + +2009-10-29 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + Add cacheFlush support for Thumb-2 on Linux + https://bugs.webkit.org/show_bug.cgi?id=30865 + + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::cacheFlush): + +2009-10-28 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + JSC JIT on ARMv7 cannot link jumps >16Mb range + https://bugs.webkit.org/show_bug.cgi?id=30891 + + Start planing all relative jumps as move-32-bit-immediate-to-register-BX. + In the cases where the jump would fall within a relative jump range, use a relative jump. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::~ARMv7Assembler): + (JSC::ARMv7Assembler::LinkRecord::LinkRecord): + (JSC::ARMv7Assembler::): + (JSC::ARMv7Assembler::executableCopy): + (JSC::ARMv7Assembler::linkJump): + (JSC::ARMv7Assembler::relinkJump): + (JSC::ARMv7Assembler::setInt32): + (JSC::ARMv7Assembler::isB): + (JSC::ARMv7Assembler::isBX): + (JSC::ARMv7Assembler::isMOV_imm_T3): + (JSC::ARMv7Assembler::isMOVT): + (JSC::ARMv7Assembler::isNOP_T1): + (JSC::ARMv7Assembler::isNOP_T2): + (JSC::ARMv7Assembler::linkJumpAbsolute): + (JSC::ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst): + (JSC::ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond): + (JSC::ARMv7Assembler::ARMInstructionFormatter::twoWordOp5i6Imm4Reg4EncodedImm): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::makeJump): + (JSC::MacroAssemblerARMv7::makeBranch): + * jit/JIT.h: + * wtf/Platform.h: + +2009-10-28 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + Improve for..in enumeration performance + https://bugs.webkit.org/show_bug.cgi?id=30887 + + Improve indexing of an object with a for..in iterator by + identifying cases where get_by_val is being used with a iterator + as the subscript and replace it with a new get_by_pname + bytecode. get_by_pname then optimizes lookups that directly access + the base object. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * bytecode/Opcode.h: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitGetByVal): + * bytecompiler/BytecodeGenerator.h: + (JSC::BytecodeGenerator::pushOptimisedForIn): + (JSC::BytecodeGenerator::popOptimisedForIn): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompileSlowCases): + * jit/JIT.h: + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetDirectOffset): + (JSC::JIT::emit_op_get_by_pname): + (JSC::JIT::emitSlow_op_get_by_pname): + * parser/Nodes.cpp: + (JSC::ForInNode::emitBytecode): + * runtime/JSObject.h: + * runtime/JSPropertyNameIterator.cpp: + (JSC::JSPropertyNameIterator::create): + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::getOffset): + (JSC::JSPropertyNameIterator::JSPropertyNameIterator): + * runtime/JSValue.h: + (JSC::JSValue::): + * runtime/Structure.cpp: + (JSC::Structure::addPropertyTransition): + (JSC::Structure::changePrototypeTransition): + (JSC::Structure::despecifyFunctionTransition): + (JSC::Structure::addAnonymousSlotsTransition): + (JSC::Structure::getterSetterTransition): + (JSC::Structure::toDictionaryTransition): + (JSC::Structure::addPropertyWithoutTransition): + Track the existence (or not) of non-enumerable properties. + * runtime/Structure.h: + (JSC::Structure::propertyStorageCapacity): + (JSC::Structure::propertyStorageSize): + (JSC::Structure::hasNonEnumerableProperties): + (JSC::Structure::hasAnonymousSlots): + +2009-10-28 Dmitry Titov <dimich@chromium.org> + + Not reviewed, attemp to fix Windows build. + + Touch the cpp file to cause recompile. + + * wtf/Threading.cpp: + (WTF::threadEntryPoint): + +2009-10-28 Dmitry Titov <dimich@chromium.org> + + Reviewed by David Levin. + + https://bugs.webkit.org/show_bug.cgi?id=30805 + Add MessageQueue::removeIf(Predicate&) to remove certain tasks without pulling them from the queue. + Existing Database tests cover this since Database removes tasks when it is stopped. + + * wtf/MessageQueue.h: + (WTF::::removeIf): + +2009-10-28 Afonso R. Costa Jr. <afonso.costa@openbossa.org> + + Reviewed by Oliver Hunt. + + [Qt] Enable YARR when YARR_JIT is enabled + https://bugs.webkit.org/show_bug.cgi?id=30730 + + When enabling or disabling JIT using JAVASCRIPTCORE_JIT, the ENABLE_YARR should + be toggled also. + + * JavaScriptCore.pri: + +2009-10-24 Martin Robinson <martin.james.robinson@gmail.com> + + Reviewed by Oliver Hunt. + + Fix strict aliasing warning by switching reinterpret_cast to bitwise_cast. + + strict-aliasing warnings in JSFunction.h + https://bugs.webkit.org/show_bug.cgi?id=27869 + + * runtime/JSFunction.h: + (JSC::JSFunction::nativeFunction): + (JSC::JSFunction::scopeChain): + (JSC::JSFunction::setScopeChain): + (JSC::JSFunction::setNativeFunction): + +2009-10-28 Jan-Arve Sæther <jan-arve.saether@nokia.com> + + Reviewed by Tor Arne Vestbø. + + Build-fix for 64-bit Windows + + * wtf/Platform.h: Make sure to use WTF_USE_JSVALUE64 + +2009-10-28 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix!). + + * jit/JIT.h: + +2009-10-26 Holger Hans Peter Freyther <zecke@selfish.org> + + Rubber-stamped by Darin Adler. + + Export fastMalloc, fastCalloc, fastRealloc and fastFree on GCC/Unix + https://bugs.webkit.org/show_bug.cgi?id=30769 + + When using -fvisibility=hidden to hide all internal symbols by default + the malloc symbols will be hidden as well. For memory instrumentation + it is needed to provide an instrumented version of these symbols and + override the normal routines and by changing the visibility back to + default this becomes possible. + + The only other solution would be to use system malloc instead of the + TCmalloc implementation but this will not allow to analyze memory + behavior with the default allocator. + + * wtf/FastMalloc.h: Define WTF_FAST_MALLOC_EXPORT for GCC and !darwin + +2009-10-27 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Samuel Q. Weinig. + + Make the asserts protecting the offsets in the JIT more descriptive. + + * jit/JIT.h: + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::emit_op_method_check): + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::emit_op_put_by_id): + +2009-10-27 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + A little bit of refactoring in the date code. + + * JavaScriptCore.exp: Don't export this unused symbol. + + * runtime/DateConstructor.cpp: + (JSC::constructDate): + + * runtime/DateInstance.cpp: + (JSC::DateInstance::DateInstance): + * runtime/DateInstance.h: Removed some unused functions. Changed the default + constructor to ensure that a DateInstance is always initialized. + + * runtime/DatePrototype.cpp: + (JSC::DatePrototype::DatePrototype): Pass an initializer to our constructor, + since it now requires one. + + * wtf/DateMath.cpp: + (WTF::msToGregorianDateTime): Only compute our offset from UTC if our + output will require it. Otherwise, our offset is 0. + +2009-10-27 Geoffrey Garen <ggaren@apple.com> + + Build fix: Mark DateInstaceCache.h private, so other frameworks can see it. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2009-10-27 Geoffrey Garen <ggaren@apple.com> + + Build fix: re-readded this file. + + * runtime/DateInstanceCache.h: Added. + (JSC::DateInstanceData::create): + (JSC::DateInstanceData::DateInstanceData): + (JSC::DateInstanceCache::DateInstanceCache): + (JSC::DateInstanceCache::add): + (JSC::DateInstanceCache::lookup): + +2009-10-27 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler and Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=30800 + Cache recently computed date data. + + SunSpider reports a ~0.5% speedup, mostly from date-format-tofte.js. + + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: Added new file. + + * runtime/DateInstance.cpp: + (JSC::DateInstance::DateInstance): + (JSC::DateInstance::getGregorianDateTime): Use the shared cache. + + * runtime/DateInstance.h: Renamed m_cache to m_data, to avoid the confusion + of a "cache cache". + + * runtime/DatePrototype.cpp: + (JSC::formatLocaleDate): + (JSC::dateProtoFuncToString): + (JSC::dateProtoFuncToUTCString): + (JSC::dateProtoFuncToISOString): + (JSC::dateProtoFuncToDateString): + (JSC::dateProtoFuncToTimeString): + (JSC::dateProtoFuncGetFullYear): + (JSC::dateProtoFuncGetUTCFullYear): + (JSC::dateProtoFuncToGMTString): + (JSC::dateProtoFuncGetMonth): + (JSC::dateProtoFuncGetUTCMonth): + (JSC::dateProtoFuncGetDate): + (JSC::dateProtoFuncGetUTCDate): + (JSC::dateProtoFuncGetDay): + (JSC::dateProtoFuncGetUTCDay): + (JSC::dateProtoFuncGetHours): + (JSC::dateProtoFuncGetUTCHours): + (JSC::dateProtoFuncGetMinutes): + (JSC::dateProtoFuncGetUTCMinutes): + (JSC::dateProtoFuncGetSeconds): + (JSC::dateProtoFuncGetUTCSeconds): + (JSC::dateProtoFuncGetTimezoneOffset): + (JSC::setNewValueFromTimeArgs): + (JSC::setNewValueFromDateArgs): + (JSC::dateProtoFuncSetYear): + (JSC::dateProtoFuncGetYear): Pass an ExecState to these functions, so they + can access the DateInstanceCache. + + * runtime/JSGlobalData.h: Keep a DateInstanceCache. + +2009-10-27 James Robinson <jamesr@chromium.org> + + Reviewed by Darin Fisher. + + Ensures that JavaScriptCore/wtf/CurrentTime.cpp is not built in PLATFORM(CHROMIUM) builds. + + Chromium uses a different method to calculate the current time than is used in + JavaScriptCore/wtf/CurrentTime.cpp. This can lead to time skew when calls to currentTime() and Chromium's time + function are mixed. In particular, timers can get scheduled in the past which leads to 100% CPU use. + See http://code.google.com/p/chromium/issues/detail?id=25892 for an example. + + https://bugs.webkit.org/show_bug.cgi?id=30833 + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + * wtf/CurrentTime.cpp: + +2009-10-27 Peter Varga <pvarga@inf.u-szeged.hu> + + Rubber-stamped by Tor Arne Vestbø. + + Fix typo in RegexInterpreter.cpp and RegexJIT.cpp alterantive to + alternative. + + * yarr/RegexInterpreter.cpp: + (JSC::Yarr::ByteCompiler::alternativeBodyDisjunction): + (JSC::Yarr::ByteCompiler::alternativeDisjunction): + (JSC::Yarr::ByteCompiler::emitDisjunction): + * yarr/RegexJIT.cpp: + (JSC::Yarr::RegexGenerator::generateDisjunction): + +2009-10-26 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Darin Adler. + + Make .rc files compile on Windows without depending on MFC headers + https://bugs.webkit.org/show_bug.cgi?id=30750 + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.rc: Use + winresrc.h because it exists even when MFC is not installed, and is + all that's needed here. + +2009-10-26 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + The thunkReturnAddress is on JITStackFrame on ARM JIT as well + https://bugs.webkit.org/show_bug.cgi?id=30782 + + Move the thunkReturnAddress from top of the stack into the JITStackFrame + structure. This is a requirement for JSValue32_64 support on ARM. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::ret): Return with link register + (JSC::MacroAssemblerARM::prepareCall): Store the return address in link register + * jit/JIT.h: Remove unused ctiReturnRegister + * jit/JITInlineMethods.h: Same as ARMv7 + (JSC::JIT::restoreArgumentReference): Ditto. + (JSC::JIT::restoreArgumentReferenceForTrampoline): Ditto. + * jit/JITOpcodes.cpp: Remove ctiReturnRegister related instruction + * jit/JITStubs.cpp: Store thunkReturnAddress on JITStackFrame. Use + small trampoline functions which handle return addresses for each + CTI_STUB_FUNCTION. + * jit/JITStubs.h: Store thunkReturnAddress on JITStackFrame + (JSC::JITStackFrame::returnAddressSlot): Return with the address of thunkReturnAddress + * yarr/RegexJIT.cpp: + (JSC::Yarr::RegexGenerator::generateEnter): Remove the unnecessary instruction + +2009-10-26 Steve Block <steveblock@google.com> + + Reviewed by Darin Adler. + + Adds ability to disable ReadWriteLock on platforms (eg Android) that use pthreads but do not support pthread_rwlock. + https://bugs.webkit.org/show_bug.cgi?id=30713 + + * wtf/Platform.h: Modified. Defines HAVE_PTHREAD_RWLOCK for all platforms currently using pthreads. + * wtf/Threading.h: Modified. Use pthread_rwlock_t only when HAVE_PTHREAD_RWLOCK is defined. + * wtf/ThreadingPthreads.cpp: Modified. Build ReadWriteLock methods only when HAVE_PTHREAD_RWLOCK is defined. + +2009-10-24 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Holger Freyther. + + [Qt] [Symbian] Set the capability and memory required to run QtWebKit for Symbian + https://bugs.webkit.org/show_bug.cgi?id=30476 + + Assign ReadUserData WriteUserData NetworkServices Symbian capabilities + to jsc.exe. + + * jsc.pro: + +2009-10-23 Steve Block <steveblock@google.com> + + Reviewed by Dmitry Titov. + + Fixes a leak in createThreadInternal on Android. + https://bugs.webkit.org/show_bug.cgi?id=30698 + + * wtf/ThreadingPthreads.cpp: Modified. + (WTF::createThreadInternal): Avoid leaking a ThreadData object on failure. + +2009-10-22 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Alexey Proskuryakov. + + Fixed ASSERT when opening Safari's Caches window while the Web Inspector + is open. + + * runtime/Collector.cpp: + (JSC::typeName): Added two new types to the type name list in the Collector. + These types have been around for a while, but nobody remembered to consider them here. + + * runtime/JSCell.h: + (JSC::JSCell::isPropertyNameIterator): + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::isPropertyNameIterator): Give the Collector + a way to tell if a cell is a JSPropertyNameIterator. + +2009-10-22 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Jon Honeycutt. + + https://bugs.webkit.org/show_bug.cgi?id=30686 + Remove debug-specific def file. + Only Debug_All target uses JavaScriptCore_debug.dll naming, and since + that target is only used internally, maintaining two files just to + suppress a single link warning isn't worthwhile. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: Removed. + +2009-10-21 Jon Honeycutt <jhoneycutt@apple.com> + + <rdar://problem/7270320> Screenshots of off-screen plug-ins are blank + <rdar://problem/7270314> After halting a transparent PluginView on + Windows, the transparency is applied twice + + Reviewed by Dan Bernstein. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + Export WTF::deleteOwnedPtr(HDC). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: + Ditto. + +2009-10-20 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: updated variable name. + + * runtime/DatePrototype.cpp: + (JSC::formatLocaleDate): + +2009-10-20 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Mark Rowe. + + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_next_pname): Slightly tweaked this #ifdef to match the + size of a JSValue because m_jsStrings is an array of JSValues. + +2009-10-20 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Mark Rowe. + + Fixed a 64-bit regression caused by the fix for + https://bugs.webkit.org/show_bug.cgi?id=30570. + + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_next_pname): Use TimesEight stepping on 64-bit, since + 64-bit pointers are eight bytes long. + +2009-10-20 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Refactored DateInstance::msToGregorianDateTime so that a DateInstance's + caller doesn't need to supply the DateInstance's own internal value to + the DateInstance. + + * runtime/DateInstance.cpp: + (JSC::DateInstance::getGregorianDateTime): Renamed from "msToGregorianDateTime". + + * runtime/DateInstance.h: + * runtime/DatePrototype.cpp: + (JSC::formatLocaleDate): + (JSC::dateProtoFuncToString): + (JSC::dateProtoFuncToUTCString): + (JSC::dateProtoFuncToISOString): + (JSC::dateProtoFuncToDateString): + (JSC::dateProtoFuncToTimeString): + (JSC::dateProtoFuncToLocaleString): + (JSC::dateProtoFuncToLocaleDateString): + (JSC::dateProtoFuncToLocaleTimeString): + (JSC::dateProtoFuncGetTime): + (JSC::dateProtoFuncGetFullYear): + (JSC::dateProtoFuncGetUTCFullYear): + (JSC::dateProtoFuncToGMTString): + (JSC::dateProtoFuncGetMonth): + (JSC::dateProtoFuncGetUTCMonth): + (JSC::dateProtoFuncGetDate): + (JSC::dateProtoFuncGetUTCDate): + (JSC::dateProtoFuncGetDay): + (JSC::dateProtoFuncGetUTCDay): + (JSC::dateProtoFuncGetHours): + (JSC::dateProtoFuncGetUTCHours): + (JSC::dateProtoFuncGetMinutes): + (JSC::dateProtoFuncGetUTCMinutes): + (JSC::dateProtoFuncGetSeconds): + (JSC::dateProtoFuncGetUTCSeconds): + (JSC::dateProtoFuncGetTimezoneOffset): + (JSC::setNewValueFromTimeArgs): + (JSC::setNewValueFromDateArgs): + (JSC::dateProtoFuncSetYear): + (JSC::dateProtoFuncGetYear): Also renamed "utc" to "outputIsUTC", for clarity. + +2009-10-20 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Geoffrey Garen. + + The op_next_pname should use 4 bytes addressing mode in case of JSValue32 + https://bugs.webkit.org/show_bug.cgi?id=30570 + + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_next_pname): + +2009-10-20 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Oliver Hunt. + + Move OverridesMarkChildren flag from DatePrototype to its parent class + https://bugs.webkit.org/show_bug.cgi?id=30372 + + * runtime/DateInstance.h: + (JSC::DateInstance::createStructure): + * runtime/DatePrototype.h: + +2009-10-19 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Tightened up some put_by_id_transition code generation. + https://bugs.webkit.org/show_bug.cgi?id=30539 + + * jit/JIT.h: + * jit/JITPropertyAccess.cpp: + (JSC::JIT::testPrototype): + (JSC::JIT::privateCompilePutByIdTransition): No need to do object type + checks or read Structures and prototypes from objects: they're all known + constants at compile time. + +2009-10-19 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Added a private API for getting a global context from a context, for + clients who want to preserve a context for a later callback. + + * API/APICast.h: + (toGlobalRef): Added an ASSERT, since this function is used more often + than before. + + * API/JSContextRef.cpp: + * API/JSContextRefPrivate.h: Added. The new API. + + * API/tests/testapi.c: + (print_callAsFunction): + (main): Test the new API. + + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: Build and export the new API. + +2009-10-17 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Tightened up some instanceof code generation. + https://bugs.webkit.org/show_bug.cgi?id=30488 + + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_instanceof): + (JSC::JIT::emitSlow_op_instanceof): No need to do object type checks - + cell type checks and ImplementsDefaultHasIntance checks implicitly + supersede object type checks. + +2009-10-18 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Darin Adler. + + Use _stricmp and _strnicmp instead of deprecated stricmp and strnicmp. + https://bugs.webkit.org/show_bug.cgi?id=30474 + + stricmp and strnicmp are deprecated beginning in Visual + C++ 2005. Use _stricmp and _strnicmp instead in StringExtras.h. + + * wtf/StringExtras.h: + (strncasecmp): + (strcasecmp): + +2009-10-16 Geoffrey Garen <ggaren@apple.com> + + Build fix: apparently we shouldn't export those symbols? + + * JavaScriptCore.exp: + +2009-10-16 Geoffrey Garen <ggaren@apple.com> + + Build fix: export some symbols. + + * JavaScriptCore.exp: + +2009-10-16 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + structure typeinfo flags should be inherited. + https://bugs.webkit.org/show_bug.cgi?id=30468 + + Add StructureFlag constant to the various JSC classes and use + it for the TypeInfo construction. This allows us to simply + accumulate flags by basing each classes StructureInfo on its parents. + + * API/JSCallbackConstructor.h: + (JSC::JSCallbackConstructor::createStructure): + * API/JSCallbackFunction.h: + (JSC::JSCallbackFunction::createStructure): + * API/JSCallbackObject.h: + (JSC::JSCallbackObject::createStructure): + * debugger/DebuggerActivation.h: + (JSC::DebuggerActivation::createStructure): + * runtime/Arguments.h: + (JSC::Arguments::createStructure): + * runtime/BooleanObject.h: + (JSC::BooleanObject::createStructure): + * runtime/DatePrototype.h: + (JSC::DatePrototype::createStructure): + * runtime/FunctionPrototype.h: + (JSC::FunctionPrototype::createStructure): + * runtime/GlobalEvalFunction.h: + (JSC::GlobalEvalFunction::createStructure): + * runtime/InternalFunction.h: + (JSC::InternalFunction::createStructure): + * runtime/JSActivation.h: + (JSC::JSActivation::createStructure): + * runtime/JSArray.h: + (JSC::JSArray::createStructure): + * runtime/JSByteArray.cpp: + (JSC::JSByteArray::createStructure): + * runtime/JSByteArray.h: + * runtime/JSFunction.h: + (JSC::JSFunction::createStructure): + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::createStructure): + * runtime/JSNotAnObject.h: + (JSC::JSNotAnObject::createStructure): + * runtime/JSONObject.h: + (JSC::JSONObject::createStructure): + * runtime/JSObject.h: + (JSC::JSObject::createStructure): + * runtime/JSStaticScopeObject.h: + (JSC::JSStaticScopeObject::createStructure): + * runtime/JSVariableObject.h: + (JSC::JSVariableObject::createStructure): + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::createStructure): + * runtime/MathObject.h: + (JSC::MathObject::createStructure): + * runtime/NumberConstructor.h: + (JSC::NumberConstructor::createStructure): + * runtime/NumberObject.h: + (JSC::NumberObject::createStructure): + * runtime/RegExpConstructor.h: + (JSC::RegExpConstructor::createStructure): + * runtime/RegExpObject.h: + (JSC::RegExpObject::createStructure): + * runtime/StringObject.h: + (JSC::StringObject::createStructure): + * runtime/StringObjectThatMasqueradesAsUndefined.h: + (JSC::StringObjectThatMasqueradesAsUndefined::createStructure): + +2009-10-16 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Fast for-in enumeration: Cache JSPropertyNameIterator; cache JSStrings + in JSPropertyNameIterator; inline more code. + + 1.024x as fast on SunSpider (fasta: 1.43x as fast). + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * bytecode/Opcode.h: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitGetPropertyNames): + (JSC::BytecodeGenerator::emitNextPropertyName): + * bytecompiler/BytecodeGenerator.h: Added a few extra operands to + op_get_pnames and op_next_pname so that we can track iteration state + in the register file instead of in the JSPropertyNameIterator. (To be + cacheable, the JSPropertyNameIterator must be stateless.) + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::tryCachePutByID): + (JSC::Interpreter::tryCacheGetByID): Updated for rename to + "normalizePrototypeChain" and removal of "isCacheable". + + (JSC::Interpreter::privateExecute): Updated for in-RegisterFile + iteration state tracking. + + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JIT.h: + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_get_pnames): Updated for in-RegisterFile + iteration state tracking. + + (JSC::JIT::emit_op_next_pname): Inlined code generation for op_next_pname. + + * jit/JITStubs.cpp: + (JSC::JITThunks::tryCachePutByID): + (JSC::JITThunks::tryCacheGetByID): Updated for rename to + "normalizePrototypeChain" and removal of "isCacheable". + + (JSC::DEFINE_STUB_FUNCTION): + * jit/JITStubs.h: + (JSC::): Added has_property and to_object stubs. Removed op_next_pname + stub, since has_property is all we need anymore. + + * parser/Nodes.cpp: + (JSC::ForInNode::emitBytecode): Updated for in-RegisterFile + iteration state tracking. + + * runtime/JSCell.h: + * runtime/JSObject.cpp: + (JSC::JSObject::getPropertyNames): Don't do caching at this layer + anymore, since we don't create a JSPropertyNameIterator at this layer. + + * runtime/JSPropertyNameIterator.cpp: + (JSC::JSPropertyNameIterator::create): Do do caching at this layer. + (JSC::JSPropertyNameIterator::get): Updated for in-RegisterFile + iteration state tracking. + (JSC::JSPropertyNameIterator::markChildren): Mark our JSStrings. + + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::size): + (JSC::JSPropertyNameIterator::setCachedStructure): + (JSC::JSPropertyNameIterator::cachedStructure): + (JSC::JSPropertyNameIterator::setCachedPrototypeChain): + (JSC::JSPropertyNameIterator::cachedPrototypeChain): + (JSC::JSPropertyNameIterator::JSPropertyNameIterator): + (JSC::Structure::setEnumerationCache): Don't store iteration state in + a JSPropertyNameIterator. Do cache a JSPropertyNameIterator in a + Structure. + + * runtime/JSValue.h: + (JSC::asCell): + * runtime/MarkStack.h: Make those mischievous #include gods happy. + + * runtime/ObjectConstructor.cpp: + + * runtime/Operations.h: + (JSC::normalizePrototypeChain): Renamed countPrototypeChainEntriesAndCheckForProxies + to normalizePrototypeChain, since it changes dictionary prototypes to + non-dictionary objects. + + * runtime/PropertyNameArray.cpp: + (JSC::PropertyNameArray::add): + * runtime/PropertyNameArray.h: + (JSC::PropertyNameArrayData::PropertyNameArrayData): + (JSC::PropertyNameArray::data): + (JSC::PropertyNameArray::size): + (JSC::PropertyNameArray::begin): + (JSC::PropertyNameArray::end): Simplified some code here to help with + current and future refactoring. + + * runtime/Protect.h: + * runtime/Structure.cpp: + (JSC::Structure::~Structure): + (JSC::Structure::addPropertyWithoutTransition): + (JSC::Structure::removePropertyWithoutTransition): No need to clear + the enumeration cache with adding / removing properties without + transition. It is an error to add / remove properties without transition + once an object has been observed, and we can ASSERT to catch that. + + * runtime/Structure.h: + (JSC::Structure::enumerationCache): Changed the enumeration cache to + hold a JSPropertyNameIterator. + + * runtime/StructureChain.cpp: + * runtime/StructureChain.h: + (JSC::StructureChain::head): Removed StructureChain::isCacheable because + it was wrong-headed in two ways: (1) It gave up when a prototype was a + dictionary, but instead we want un-dictionary heavily accessed + prototypes; (2) It folded a test for hasDefaultGetPropertyNames() into + a generic test for "cacheable-ness", but hasDefaultGetPropertyNames() + is only releavant to for-in caching. + +2009-10-16 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Adam Roben. + + Add a Debug_All configuration to build entire stack as debug. + Change Debug_Internal to: + - stop using _debug suffix for all WebKit/Safari binaries + - not use _debug as a DLL naming suffix + - use non-debug C runtime lib. + + * JavaScriptCore.vcproj/JavaScriptCore.make: Debug build in makefile should build Debug_All. + * JavaScriptCore.vcproj/JavaScriptCore.sln: Add Debug_All configuration. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: Add Debug_All configuration. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj: Renamed single configuration from "Release" to "all". + * JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln: Add Debug_All configuration. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: Add Debug_All configuration. + * JavaScriptCore.vcproj/jsc/jsc.vcproj: Add Debug_All configuration. + * JavaScriptCore.vcproj/testapi/testapi.vcproj: Add Debug_All configuration. + +2009-10-16 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Make typeinfo flags default to false + https://bugs.webkit.org/show_bug.cgi?id=30372 + + Last part -- replace HasDefaultGetPropertyNames with OverridesGetPropertyNames + flag. + + * API/JSCallbackConstructor.h: + (JSC::JSCallbackConstructor::createStructure): + * API/JSCallbackObject.h: + (JSC::JSCallbackObject::createStructure): + * debugger/DebuggerActivation.h: + (JSC::DebuggerActivation::createStructure): + * runtime/Arguments.h: + (JSC::Arguments::createStructure): + * runtime/BooleanObject.h: + (JSC::BooleanObject::createStructure): + * runtime/DatePrototype.h: + (JSC::DatePrototype::createStructure): + * runtime/FunctionPrototype.h: + (JSC::FunctionPrototype::createStructure): + * runtime/GlobalEvalFunction.h: + (JSC::GlobalEvalFunction::createStructure): + * runtime/JSAPIValueWrapper.h: + (JSC::JSAPIValueWrapper::createStructure): + * runtime/JSActivation.h: + (JSC::JSActivation::createStructure): + * runtime/JSArray.h: + (JSC::JSArray::createStructure): + * runtime/JSByteArray.cpp: + (JSC::JSByteArray::createStructure): + * runtime/JSFunction.h: + (JSC::JSFunction::createStructure): + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::createStructure): + * runtime/JSNotAnObject.h: + (JSC::JSNotAnObject::createStructure): + * runtime/JSONObject.h: + (JSC::JSONObject::createStructure): + * runtime/JSObject.cpp: + (JSC::JSObject::getPropertyNames): + * runtime/JSObject.h: + (JSC::JSObject::createStructure): + * runtime/JSStaticScopeObject.h: + (JSC::JSStaticScopeObject::createStructure): + * runtime/JSTypeInfo.h: + (JSC::TypeInfo::overridesGetPropertyNames): + * runtime/JSVariableObject.h: + (JSC::JSVariableObject::createStructure): + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::createStructure): + * runtime/MathObject.h: + (JSC::MathObject::createStructure): + * runtime/NumberConstructor.h: + (JSC::NumberConstructor::createStructure): + * runtime/NumberObject.h: + (JSC::NumberObject::createStructure): + * runtime/RegExpConstructor.h: + (JSC::RegExpConstructor::createStructure): + * runtime/RegExpObject.h: + (JSC::RegExpObject::createStructure): + * runtime/StringObject.h: + (JSC::StringObject::createStructure): + * runtime/StringObjectThatMasqueradesAsUndefined.h: + (JSC::StringObjectThatMasqueradesAsUndefined::createStructure): + * runtime/StructureChain.cpp: + (JSC::StructureChain::isCacheable): + +2009-10-16 Kevin Ollivier <kevino@theolliviers.com> + + wxMSW build fix, we can't use the simple hash there because the PlatformModuleVersion + structure differs. + + * wtf/Platform.h: + +2009-10-16 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Implement ExecutableAllocator for Symbian + https://bugs.webkit.org/show_bug.cgi?id=29946 + + Tested with YARR JIT enabled for Symbian; + This patch does not (yet) enable YARR JIT by default. + + * JavaScriptCore.pri: + * jit/ExecutableAllocator.h: + * jit/ExecutableAllocatorSymbian.cpp: Added. + (JSC::ExecutableAllocator::intializePageSize): + (JSC::ExecutablePool::systemAlloc): + (JSC::ExecutablePool::systemRelease): + +2009-10-15 Oliver Hunt <oliver@apple.com> + + Reviewed by Darin Adler. + + Make typeinfo flags default to false + https://bugs.webkit.org/show_bug.cgi?id=30372 + + Part 2 -- Reverse the TypeInfo HasDefaultMark flag to OverridesMarkChildren, etc + + * API/JSCallbackConstructor.h: + (JSC::JSCallbackConstructor::createStructure): + * API/JSCallbackFunction.h: + (JSC::JSCallbackFunction::createStructure): + * API/JSCallbackObject.h: + (JSC::JSCallbackObject::createStructure): + * debugger/DebuggerActivation.h: + (JSC::DebuggerActivation::createStructure): + * runtime/Arguments.h: + (JSC::Arguments::createStructure): + * runtime/BooleanObject.h: + (JSC::BooleanObject::createStructure): + * runtime/DatePrototype.h: + (JSC::DatePrototype::createStructure): + * runtime/FunctionPrototype.h: + (JSC::FunctionPrototype::createStructure): + * runtime/GetterSetter.h: + (JSC::GetterSetter::createStructure): + * runtime/GlobalEvalFunction.h: + (JSC::GlobalEvalFunction::createStructure): + * runtime/InternalFunction.h: + (JSC::InternalFunction::createStructure): + * runtime/JSAPIValueWrapper.h: + (JSC::JSAPIValueWrapper::createStructure): + * runtime/JSActivation.h: + (JSC::JSActivation::createStructure): + * runtime/JSArray.h: + (JSC::JSArray::createStructure): + (JSC::MarkStack::markChildren): + * runtime/JSByteArray.cpp: + (JSC::JSByteArray::createStructure): + * runtime/JSFunction.h: + (JSC::JSFunction::createStructure): + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::createStructure): + * runtime/JSNotAnObject.h: + (JSC::JSNotAnObject::createStructure): + * runtime/JSNumberCell.h: + (JSC::JSNumberCell::createStructure): + * runtime/JSONObject.h: + (JSC::JSONObject::createStructure): + * runtime/JSObject.h: + (JSC::JSObject::createStructure): + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::createStructure): + * runtime/JSStaticScopeObject.h: + (JSC::JSStaticScopeObject::createStructure): + * runtime/JSString.h: + (JSC::JSString::createStructure): + * runtime/JSTypeInfo.h: + (JSC::TypeInfo::overridesMarkChildren): + * runtime/JSVariableObject.h: + (JSC::JSVariableObject::createStructure): + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::createStructure): + * runtime/MathObject.h: + (JSC::MathObject::createStructure): + * runtime/NumberConstructor.h: + (JSC::NumberConstructor::createStructure): + * runtime/NumberObject.h: + (JSC::NumberObject::createStructure): + * runtime/RegExpConstructor.h: + (JSC::RegExpConstructor::createStructure): + * runtime/RegExpObject.h: + (JSC::RegExpObject::createStructure): + * runtime/StringObject.h: + (JSC::StringObject::createStructure): + * runtime/StringObjectThatMasqueradesAsUndefined.h: + (JSC::StringObjectThatMasqueradesAsUndefined::createStructure): + +2009-10-14 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + Make typeinfo flags default to false + https://bugs.webkit.org/show_bug.cgi?id=30372 + + Part 1. Reverse the HasStandardGetOwnPropertySlot flag. + + * API/JSCallbackConstructor.h: + (JSC::JSCallbackConstructor::createStructure): + * API/JSCallbackFunction.h: + (JSC::JSCallbackFunction::createStructure): + * API/JSCallbackObject.h: + (JSC::JSCallbackObject::createStructure): + * debugger/DebuggerActivation.h: + (JSC::DebuggerActivation::createStructure): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * runtime/Arguments.h: + (JSC::Arguments::createStructure): + * runtime/BooleanObject.h: + (JSC::BooleanObject::createStructure): + * runtime/DatePrototype.h: + (JSC::DatePrototype::createStructure): + * runtime/FunctionPrototype.h: + (JSC::FunctionPrototype::createStructure): + * runtime/GlobalEvalFunction.h: + (JSC::GlobalEvalFunction::createStructure): + * runtime/InternalFunction.h: + (JSC::InternalFunction::createStructure): + * runtime/JSActivation.h: + (JSC::JSActivation::createStructure): + * runtime/JSArray.h: + (JSC::JSArray::createStructure): + * runtime/JSByteArray.cpp: + (JSC::JSByteArray::createStructure): + * runtime/JSFunction.h: + (JSC::JSFunction::createStructure): + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::createStructure): + * runtime/JSNumberCell.h: + (JSC::JSNumberCell::createStructure): + * runtime/JSONObject.h: + (JSC::JSONObject::createStructure): + * runtime/JSObject.h: + (JSC::JSObject::createStructure): + (JSC::JSCell::fastGetOwnPropertySlot): + * runtime/JSStaticScopeObject.h: + (JSC::JSStaticScopeObject::createStructure): + * runtime/JSString.h: + (JSC::JSString::createStructure): + * runtime/JSTypeInfo.h: + (JSC::TypeInfo::overridesGetOwnPropertySlot): + * runtime/JSVariableObject.h: + (JSC::JSVariableObject::createStructure): + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::createStructure): + * runtime/MathObject.h: + (JSC::MathObject::createStructure): + * runtime/NumberConstructor.h: + (JSC::NumberConstructor::createStructure): + * runtime/NumberObject.h: + (JSC::NumberObject::createStructure): + * runtime/RegExpConstructor.h: + (JSC::RegExpConstructor::createStructure): + * runtime/RegExpObject.h: + (JSC::RegExpObject::createStructure): + * runtime/StringObject.h: + (JSC::StringObject::createStructure): + * runtime/StringObjectThatMasqueradesAsUndefined.h: + (JSC::StringObjectThatMasqueradesAsUndefined::createStructure): + +2009-10-14 Kevin Ollivier <kevino@theolliviers.com> +2009-10-14 Darin Adler <darin@apple.com> + + Additions so fix for https://bugs.webkit.org/show_bug.cgi?id=18994 + can build on Windows. + + * wtf/MathExtras.h: Added llround and llroundf for Windows. + +2009-10-14 Kevin Ollivier <kevino@theolliviers.com> + + wx build fix. Set ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH for plugins while we're still building stubs. + + * wtf/Platform.h: + +2009-10-13 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + Refactor ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH + https://bugs.webkit.org/show_bug.cgi?id=30278 + + Move the definition of ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH + from the make system into common code. + + * wtf/Platform.h: + +2009-10-13 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Darin Adler. + + ARM compiler does not understand reinterpret_cast<void*> + https://bugs.webkit.org/show_bug.cgi?id=29034 + + Change reinterpret_cast<void*> to regular C style (void*) cast + for the ARM RVCT compiler. + + * assembler/MacroAssemblerCodeRef.h: + (JSC::FunctionPtr::FunctionPtr): + * jit/JITOpcodes.cpp: Cast to FunctionPtr first + instead of directly casting to reinterpret_cast + * jit/JITStubCall.h: Ditto + change the type of m_stub + from void* to FunctionPtr. + (JSC::JITStubCall::JITStubCall): + (JSC::JITStubCall::call): + * jit/JITStubs.cpp: Ditto. + (JSC::DEFINE_STUB_FUNCTION(EncodedJSValue, op_throw)): + +2009-10-11 Oliver Hunt <oliver@apple.com> + + Re-enable the JIT. + + * wtf/Platform.h: + +2009-10-10 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Support for String.trim(), String.trimLeft() and String.trimRight() methods + https://bugs.webkit.org/show_bug.cgi?id=26590 + + Implement trim, trimLeft, and trimRight + + * runtime/StringPrototype.cpp: + (JSC::isTrimWhitespace): + Our normal string whitespace function does not include U+200B which + is needed for compatibility with mozilla's implementation of trim. + U+200B does not appear to be expected according to spec, however I am + choosing to be lax, and match mozilla behavior so have added this + exception. + (JSC::trimString): + +2009-10-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Eliminated some legacy bytecode weirdness. + + Use vPC[x] subscripting instead of ++vPC to access instruction operands. + This is simpler, and often more efficient. + + To support this, and to remove use of hard-coded offsets in bytecode and + JIT code generation and dumping, calculate jump offsets from the beginning + of an instruction, rather than the middle or end. + + Also, use OPCODE_LENGTH instead of hard-coded constants for the sizes of + opcodes. + + SunSpider reports no change in JIT mode, and a 1.01x speedup in Interpreter + mode. + + * bytecode/CodeBlock.cpp: + (JSC::printConditionalJump): + (JSC::CodeBlock::dump): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitJump): + (JSC::BytecodeGenerator::emitJumpIfTrue): + (JSC::BytecodeGenerator::emitJumpIfFalse): + (JSC::BytecodeGenerator::emitJumpIfNotFunctionCall): + (JSC::BytecodeGenerator::emitJumpIfNotFunctionApply): + (JSC::BytecodeGenerator::emitComplexJumpScopes): + (JSC::BytecodeGenerator::emitJumpScopes): + (JSC::BytecodeGenerator::emitNextPropertyName): + (JSC::BytecodeGenerator::emitCatch): + (JSC::BytecodeGenerator::emitJumpSubroutine): + (JSC::prepareJumpTableForImmediateSwitch): + (JSC::prepareJumpTableForCharacterSwitch): + (JSC::prepareJumpTableForStringSwitch): + (JSC::BytecodeGenerator::endSwitch): + * bytecompiler/Label.h: + (JSC::Label::setLocation): + (JSC::Label::bind): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::resolve): + (JSC::Interpreter::resolveSkip): + (JSC::Interpreter::resolveGlobal): + (JSC::Interpreter::resolveBase): + (JSC::Interpreter::resolveBaseAndProperty): + (JSC::Interpreter::createExceptionScope): + (JSC::Interpreter::privateExecute): + * interpreter/Interpreter.h: + * jit/JIT.cpp: + (JSC::JIT::privateCompile): + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_jnless): + (JSC::JIT::emitSlow_op_jnless): + (JSC::JIT::emit_op_jnlesseq): + (JSC::JIT::emitSlow_op_jnlesseq): + (JSC::JIT::emitBinaryDoubleOp): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_jmp): + (JSC::JIT::emit_op_loop): + (JSC::JIT::emit_op_loop_if_less): + (JSC::JIT::emitSlow_op_loop_if_less): + (JSC::JIT::emit_op_loop_if_lesseq): + (JSC::JIT::emitSlow_op_loop_if_lesseq): + (JSC::JIT::emit_op_loop_if_true): + (JSC::JIT::emitSlow_op_loop_if_true): + (JSC::JIT::emit_op_jfalse): + (JSC::JIT::emitSlow_op_jfalse): + (JSC::JIT::emit_op_jtrue): + (JSC::JIT::emitSlow_op_jtrue): + (JSC::JIT::emit_op_jeq_null): + (JSC::JIT::emit_op_jneq_null): + (JSC::JIT::emit_op_jneq_ptr): + (JSC::JIT::emit_op_jsr): + (JSC::JIT::emit_op_next_pname): + (JSC::JIT::emit_op_jmp_scopes): + +2009-10-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Migrated some code that didn't belong out of Structure. + + SunSpider says maybe 1.03x faster. + + * runtime/JSCell.h: Nixed Structure::markAggregate, and made marking of + a Structure's prototype the direct responsility of the object using it. + (Giving Structure a mark function was misleading because it implied that + all live structures get marked during GC, when they don't.) + + * runtime/JSGlobalObject.cpp: + (JSC::markIfNeeded): + (JSC::JSGlobalObject::markChildren): Added code to mark prototypes stored + on the global object. Maybe this wasn't necessary, but now we don't have + to wonder. + + * runtime/JSObject.cpp: + (JSC::JSObject::getPropertyNames): + (JSC::JSObject::getOwnPropertyNames): + (JSC::JSObject::getEnumerableNamesFromClassInfoTable): + * runtime/JSObject.h: + (JSC::JSObject::markChildrenDirect): + * runtime/PropertyNameArray.h: + * runtime/Structure.cpp: + * runtime/Structure.h: + (JSC::Structure::setEnumerationCache): + (JSC::Structure::enumerationCache): Moved property name gathering code + from Structure to JSObject because having a Structure iterate its JSObject + was a layering violation. A JSObject is implemented using a Structure; not + the other way around. + +2009-10-09 Mark Rowe <mrowe@apple.com> + + Attempt to fix the GTK release build. + + * GNUmakefile.am: Include Grammar.cpp in release builds now that + AllInOneFile.cpp is gone. + +2009-10-09 Gabor Loki <loki@inf.u-szeged.hu> + + Rubber-stamped by Eric Seidel. + + Add ARM JIT support for Gtk port (disabled by default) + https://bugs.webkit.org/show_bug.cgi?id=30228 + + * GNUmakefile.am: + +2009-10-08 Geoffrey Garen <ggaren@apple.com> + + Tiger build fix: added a few more variable initializations. + + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncReplace): + (JSC::stringProtoFuncSearch): + +2009-10-08 Geoffrey Garen <ggaren@apple.com> + + Qt build fix: added missing #include. + + * jsc.cpp: + +2009-10-08 Geoffrey Garen <ggaren@apple.com> + + Tiger build fix: initialize variable whose initialization the compiler + can't otherwise figure out. + + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::match): + +2009-10-08 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: updated exports. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: + +2009-10-08 Geoffrey Garen <ggaren@apple.com> + + Tiger build fix: fixed file name case. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2009-10-08 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Maciej Stachowiak. + + At long last, I pronounce the death of AllInOneFile.cpp. + + SunSpider reports a 1.01x speedup. + + * AllInOneFile.cpp: Removed. + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.xcodeproj/project.pbxproj: Added missing project files + to compilation stages. + + * parser/Grammar.y: + * parser/Lexer.cpp: + * parser/Lexer.h: + (JSC::jscyylex): + * runtime/ArrayConstructor.cpp: + (JSC::constructArrayWithSizeQuirk): + * runtime/Collector.h: + * runtime/JSCell.cpp: + (JSC::JSCell::operator new): + * runtime/JSCell.h: + (JSC::JSCell::operator new): + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::operator new): + * runtime/JSNumberCell.h: + (JSC::JSNumberCell::operator new): + * runtime/JSString.cpp: + * runtime/JSString.h: + (JSC::jsString): + (JSC::jsSubstring): + (JSC::jsOwnedString): + * runtime/RegExpConstructor.cpp: + * runtime/RegExpConstructor.h: + (JSC::RegExpConstructorPrivate::RegExpConstructorPrivate): + (JSC::RegExpConstructorPrivate::lastOvector): + (JSC::RegExpConstructorPrivate::tempOvector): + (JSC::RegExpConstructorPrivate::changeLastOvector): + (JSC::RegExpConstructor::performMatch): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncMatch): + * yarr/RegexJIT.cpp: + * yarr/RegexJIT.h: + (JSC::Yarr::executeRegex): Inlined a few things that Shark said + were hot, on the presumption that AllInOneFile.cpp used to inline them + automatically. + +2009-10-08 Zoltan Herczeg <zherczeg@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + Fix for JIT'ed op_call instructions (evals, constructs, etc.) + when !ENABLE(JIT_OPTIMIZE_CALL) && USE(JSVALUE32_64) + + https://bugs.webkit.org/show_bug.cgi?id=30201 + + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + +2009-10-07 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: removed no longer exported symbol. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: + +2009-10-07 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Fixed <rdar://problem/5751979> Database code takes JSLock on secondary + thread, permanently slowing down JavaScript + + Removed the optional lock from Heap::protect, Heap::unprotect, and friends, + since WebCore no longer uses it. + + * JavaScriptCore.exp: + * runtime/Collector.cpp: + (JSC::Heap::protect): + (JSC::Heap::unprotect): + (JSC::Heap::markProtectedObjects): + (JSC::Heap::protectedGlobalObjectCount): + (JSC::Heap::protectedObjectCount): + (JSC::Heap::protectedObjectTypeCounts): + * runtime/Collector.h: + +2009-10-07 Zoltan Horvath <zoltan@webkit.org> + + Reviewed by Darin Adler. + + Allow custom memory allocation control for JavaScriptCore's IdentifierArena + https://bugs.webkit.org/show_bug.cgi?id=30158 + + Inherits IdentifierArena class from FastAllocBase because it has been + instantiated by 'new' in JavaScriptCore/parser/ParserArena.cpp:36. + + * parser/ParserArena.h: + +2009-10-07 Adam Roben <aroben@apple.com> + + Export DateInstance::info in a way that works on Windows + + Fixes <http://webkit.org/b/30171> + fast/dom/Window/window-postmessage-clone.html fails on Windows + + Reviewed by Anders Carlsson. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: + Removed the export of DateInstance::info from here. + + * runtime/DateInstance.h: Use JS_EXPORTDATA to export + DateInstance::info, which is the required way of exporting data on + Windows. + +2009-10-07 Jørgen Lind <jorgen.lind@nokia.com> + + Reviewed by Simon Hausmann. + + When enabling or disabling the JIT through .qmake.cache, make sure + to also toggle ENABLE_YARR_JIT. + + * JavaScriptCore.pri: + +2009-10-06 Priit Laes <plaes@plaes.org> + + Reviewed by Gavin Barraclough. + + Linking fails with "relocation R_X86_64_PC32 against symbol + `cti_vm_throw'" + https://bugs.webkit.org/show_bug.cgi?id=28422 + + * jit/JITStubs.cpp: + Mark cti_vm_throw symbol as PLT-indirect symbol, so it doesn't end up + in text segment causing relocation errors on amd64 architecture. + Introduced new define SYMBOL_STRING_RELOCATION for such symbols. + +2009-10-06 Oliver Hunt <oliver@apple.com> + + Windows linking fix + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: + +2009-10-06 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (build fix). + + Windows build fix. + + * runtime/DateInstance.cpp: + +2009-10-05 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + It should be possible to post (clone) built-in JS objects to Workers + https://bugs.webkit.org/show_bug.cgi?id=22878 + + Expose helpers to throw correct exceptions during object graph walk + used for cloning and add a helper function to create Date instances + without going through the JS Date constructor function. + + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/DateInstance.cpp: + (JSC::DateInstance::DateInstance): + * runtime/DateInstance.h: + * runtime/ExceptionHelpers.cpp: + (JSC::createTypeError): + * runtime/ExceptionHelpers.h: + +2009-10-06 David Levin <levin@chromium.org> + + Reviewed by Oliver Hunt. + + StringImpl needs a method to get an instance for another thread which doesn't copy the underlying buffer. + https://bugs.webkit.org/show_bug.cgi?id=30095 + + * wtf/CrossThreadRefCounted.h: + Removed an unused function and assert improvement. + (WTF::CrossThreadRefCounted::isOwnedByCurrentThread): Moved out common code from asserts. + (WTF::CrossThreadRefCounted::ref): Changed assert to use the common method. + (WTF::CrossThreadRefCounted::deref): Changed assert to use the common method. + (WTF::CrossThreadRefCounted::crossThreadCopy): Since this includes a potentially + non-threadsafe operation, add an assert that the class is owned by the current thread. + +2009-10-05 Kevin Ollivier <kevino@theolliviers.com> + + wx build fix. Add Symbian files to the list of excludes. + + * wscript: + +2009-10-05 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Remove precompiled header from JavaScriptCore compilation to + prevent qmake warning during autonomous compilation. + https://bugs.webkit.org/show_bug.cgi?id=30069 + + * JavaScriptCore.pro: + 2009-10-02 Geoffrey Garen <ggaren@apple.com> Reviewed by Sam Weinig. @@ -88,6 +7495,62 @@ (JSC::JSValue::operator bool): Test for the empty value tag, instead of testing for the cell tag with a 0 payload. +2009-10-02 Steve Falkenburg <sfalken@apple.com> + + Reviewed by Mark Rowe. + + <https://bugs.webkit.org/show_bug.cgi?id=29989> + Safari version number shouldn't be exposed in WebKit code + + For a WebKit version of 532.3.4: + Product version is: 5.32.3.4 (was 4.0.3.0) + File version is: 5.32.3.4 (was 4.532.3.4) + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.rc: + +2009-10-02 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Rubber-stamped by Simon Hausmann. + + Fix the Qt on Mac OS X build. + + * wtf/FastMalloc.cpp: + +2009-10-02 Jørgen Lind <jorgen.lind@nokia.com> + + Reviewed by Simon Hausmann. + + Allow enabling and disabling of the JIT through a qmake variable. + + Qt's configure may set this variable through .qmake.cache if a + commandline option is given and/or the compile test for hwcap.h + failed/succeeded. + + * JavaScriptCore.pri: + +2009-10-01 Mark Rowe <mrowe@apple.com> + + Fix the Tiger build. Don't unconditionally enable 3D canvas as it is not supported on Tiger. + + * Configurations/FeatureDefines.xcconfig: + +2009-10-01 Yongjun Zhang <yongjun.zhang@nokia.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=29187 + + Don't inline ~ListRefPtr() to work around winscw compiler forward declaration + bug regarding templated classes. + + The compiler bug is reported at: + https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=9812 + + The change will be reverted when the above bug is fixed in winscw compiler. + + * wtf/ListRefPtr.h: + (WTF::::~ListRefPtr): + 2009-10-01 Zoltan Horvath <zoltan@webkit.org> Reviewed by Simon Hausmann. @@ -109,6 +7572,25 @@ (WTF::sleep): * wtf/FastMalloc.h: +2009-09-30 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by George Staikos. + + Defines two pseudo-platforms for ARM and Thumb-2 instruction set. + https://bugs.webkit.org/show_bug.cgi?id=29122 + + Introduces WTF_PLATFORM_ARM_TRADITIONAL and WTF_PLATFORM_ARM_THUMB2 + macros on ARM platforms. The PLATFORM(ARM_THUMB2) should be used + when Thumb-2 instruction set is the required target. The + PLATFORM(ARM_TRADITIONAL) is for generic ARM instruction set. In + case where the code is common the PLATFORM(ARM) have to be used. + + Modified by George Wright <gwright@rim.com> to correctly work + with the RVCT-defined __TARGET_ARCH_ARM and __TARGET_ARCH_THUMB + compiler macros, as well as adding readability changes. + + * wtf/Platform.h: + 2009-09-30 Oliver Hunt <oliver@apple.com> Reviewed by Geoff Garen. @@ -143,12 +7625,106 @@ Reviewed by Simon Hausmann. + Reduce heap size on Symbian from 64MB to 8MB. + + This is not a perfect fix, it requires more fine tuning. + But this makes it possible again to debug in the emulator, + which is more important in order to be able to fix other + run-time issues. + + * runtime/Collector.h: + +2009-09-30 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + Fix CRASH() macro for Symbian build. * wtf/Assertions.h: Added missing } 2009-09-29 Geoffrey Garen <ggaren@apple.com> + Reviewed by Gavin Barraclough. + + Inlined a few math operations. + + ~1% SunSpider speedup. + + * jit/JIT.h: + * jit/JITArithmetic.cpp: + (JSC::JIT::compileBinaryArithOpSlowCase): + (JSC::JIT::emitSlow_op_add): + (JSC::JIT::emitSlow_op_mul): + (JSC::JIT::emit_op_sub): + (JSC::JIT::emitSlow_op_sub): Don't take a stub call when operating on + a constant int and a double. + +2009-09-28 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Tidy up codeblock sampler + https://bugs.webkit.org/show_bug.cgi?id=29836 + + Some rather simple refactoring of codeblock sampler so that + it's easier for us to use it to find problems in non-jsc + environments + + * JavaScriptCore.exp: + * bytecode/SamplingTool.h: + * debugger/Debugger.cpp: + (JSC::evaluateInGlobalCallFrame): + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::evaluate): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::Interpreter): + (JSC::Interpreter::execute): + (JSC::Interpreter::privateExecute): + (JSC::Interpreter::enableSampler): + (JSC::Interpreter::dumpSampleData): + (JSC::Interpreter::startSampling): + (JSC::Interpreter::stopSampling): + * interpreter/Interpreter.h: + (JSC::Interpreter::sampler): + * jit/JIT.h: + * jsc.cpp: + (runWithScripts): + * runtime/Completion.cpp: + (JSC::checkSyntax): + (JSC::evaluate): + * runtime/Executable.h: + (JSC::EvalExecutable::EvalExecutable): + (JSC::ProgramExecutable::create): + (JSC::ProgramExecutable::ProgramExecutable): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::startSampling): + (JSC::JSGlobalData::stopSampling): + (JSC::JSGlobalData::dumpSampleData): + * runtime/JSGlobalData.h: + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncEval): + +2009-09-29 Jeremy Orlow <jorlow@chromium.org> + + Reviewed by Dimitri Glazkov. + + Add GYP generated files to svn:ignore + https://bugs.webkit.org/show_bug.cgi?id=29895 + + The following files are generated by JavaScriptCore's GYP file and should be ignored: + + pcre.mk + wtf.scons + wtf.mk + SConstruct + wtf_config.scons + wtf_config.mk + pcre.scons + + * JavaScriptCore.gyp: Changed property svn:ignore. + +2009-09-29 Geoffrey Garen <ggaren@apple.com> + Reviewed by Sam Weinig. Standardized an optimization for adding non-numbers. @@ -159,6 +7735,32 @@ (JSC::JIT::emit_op_add): (JSC::JIT::emitSlow_op_add): +2009-09-29 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: export a new symbol. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: + +2009-09-28 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Removed virtual destructor from JSGlobalObjectData to eliminate pointer + fix-ups when accessing JSGlobalObject::d. + + Replaced with an explicit destructor function pointer. + + 6% speedup on bench-alloc-nonretained.js. + + * JavaScriptCore.exp: + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::~JSGlobalObject): + (JSC::JSGlobalObject::destroyJSGlobalObjectData): + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData): + (JSC::JSGlobalObject::JSGlobalObject): + 2009-09-29 Janne Koskinen <janne.p.koskinen@digia.com> Reviewed by David Kilzer. @@ -187,6 +7789,12 @@ 2009-09-28 Mark Rowe <mrowe@apple.com> + Fix the PowerPC build. + + * JavaScriptCore.exp: + +2009-09-28 Mark Rowe <mrowe@apple.com> + Reviewed by Gavin Barraclough. <rdar://problem/7195704> JavaScriptCore fails to mark registers when built for x86_64 using LLVM GCC. @@ -195,22 +7803,175 @@ (JSC::Heap::markCurrentThreadConservatively): Force jmp_buf to use the appropriate alignment for a pointer to ensure that we correctly interpret the contents of registers during marking. -2009-09-29 Geoffrey Garen <ggaren@apple.com> +2009-09-28 Geoffrey Garen <ggaren@apple.com> - Reviewed by Gavin Barraclough. + Windows build fix: added new exports. - Inlined a few math operations. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: + +2009-09-28 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: removed exports that no longer exist. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: + +2009-09-28 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + NotNullPassRefPtr: smart pointer optimized for passing references that are not null + https://bugs.webkit.org/show_bug.cgi?id=29822 - ~1% SunSpider speedup. + Added NotNullPassRefPtr, and deployed it in all places that initialize + JavaScript objects. + + 2.2% speedup on bench-allocate-nonretained.js. - * jit/JIT.h: - * jit/JITArithmetic.cpp: - (JSC::JIT::compileBinaryArithOpSlowCase): - (JSC::JIT::emitSlow_op_add): - (JSC::JIT::emitSlow_op_mul): - (JSC::JIT::emit_op_sub): - (JSC::JIT::emitSlow_op_sub): Don't take a stub call when operating on - a constant int and a double. + * API/JSCallbackConstructor.cpp: + (JSC::JSCallbackConstructor::JSCallbackConstructor): + * API/JSCallbackConstructor.h: + * API/JSCallbackObject.h: + * API/JSCallbackObjectFunctions.h: + (JSC::JSCallbackObject::JSCallbackObject): + * JavaScriptCore.exp: + * bytecode/CodeBlock.h: + (JSC::CodeBlock::addFunctionDecl): + (JSC::CodeBlock::addFunctionExpr): + * runtime/ArrayConstructor.cpp: + (JSC::ArrayConstructor::ArrayConstructor): + * runtime/ArrayConstructor.h: + * runtime/ArrayPrototype.cpp: + (JSC::ArrayPrototype::ArrayPrototype): + * runtime/ArrayPrototype.h: + * runtime/BooleanConstructor.cpp: + (JSC::BooleanConstructor::BooleanConstructor): + * runtime/BooleanConstructor.h: + * runtime/BooleanObject.cpp: + (JSC::BooleanObject::BooleanObject): + * runtime/BooleanObject.h: + * runtime/BooleanPrototype.cpp: + (JSC::BooleanPrototype::BooleanPrototype): + * runtime/BooleanPrototype.h: + * runtime/DateConstructor.cpp: + (JSC::DateConstructor::DateConstructor): + * runtime/DateConstructor.h: + * runtime/DateInstance.cpp: + (JSC::DateInstance::DateInstance): + * runtime/DateInstance.h: + * runtime/DatePrototype.cpp: + (JSC::DatePrototype::DatePrototype): + * runtime/DatePrototype.h: + * runtime/ErrorConstructor.cpp: + (JSC::ErrorConstructor::ErrorConstructor): + * runtime/ErrorConstructor.h: + * runtime/ErrorInstance.cpp: + (JSC::ErrorInstance::ErrorInstance): + * runtime/ErrorInstance.h: + * runtime/ErrorPrototype.cpp: + (JSC::ErrorPrototype::ErrorPrototype): + * runtime/ErrorPrototype.h: + * runtime/FunctionConstructor.cpp: + (JSC::FunctionConstructor::FunctionConstructor): + * runtime/FunctionConstructor.h: + * runtime/FunctionPrototype.cpp: + (JSC::FunctionPrototype::FunctionPrototype): + * runtime/FunctionPrototype.h: + * runtime/GlobalEvalFunction.cpp: + (JSC::GlobalEvalFunction::GlobalEvalFunction): + * runtime/GlobalEvalFunction.h: + * runtime/InternalFunction.cpp: + (JSC::InternalFunction::InternalFunction): + * runtime/InternalFunction.h: + (JSC::InternalFunction::InternalFunction): + * runtime/JSActivation.cpp: + (JSC::JSActivation::JSActivation): + * runtime/JSActivation.h: + (JSC::JSActivation::JSActivationData::JSActivationData): + * runtime/JSArray.cpp: + (JSC::JSArray::JSArray): + * runtime/JSArray.h: + * runtime/JSByteArray.cpp: + (JSC::JSByteArray::JSByteArray): + * runtime/JSByteArray.h: + * runtime/JSFunction.cpp: + (JSC::JSFunction::JSFunction): + * runtime/JSFunction.h: + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::JSGlobalObject): + * runtime/JSONObject.h: + (JSC::JSONObject::JSONObject): + * runtime/JSObject.h: + (JSC::JSObject::JSObject): + (JSC::JSObject::setStructure): + * runtime/JSVariableObject.h: + (JSC::JSVariableObject::JSVariableObject): + * runtime/JSWrapperObject.h: + (JSC::JSWrapperObject::JSWrapperObject): + * runtime/MathObject.cpp: + (JSC::MathObject::MathObject): + * runtime/MathObject.h: + * runtime/NativeErrorConstructor.cpp: + (JSC::NativeErrorConstructor::NativeErrorConstructor): + * runtime/NativeErrorConstructor.h: + * runtime/NativeErrorPrototype.cpp: + (JSC::NativeErrorPrototype::NativeErrorPrototype): + * runtime/NativeErrorPrototype.h: + * runtime/NumberConstructor.cpp: + (JSC::NumberConstructor::NumberConstructor): + * runtime/NumberConstructor.h: + * runtime/NumberObject.cpp: + (JSC::NumberObject::NumberObject): + * runtime/NumberObject.h: + * runtime/NumberPrototype.cpp: + (JSC::NumberPrototype::NumberPrototype): + * runtime/NumberPrototype.h: + * runtime/ObjectConstructor.cpp: + (JSC::ObjectConstructor::ObjectConstructor): + * runtime/ObjectConstructor.h: + * runtime/ObjectPrototype.cpp: + (JSC::ObjectPrototype::ObjectPrototype): + * runtime/ObjectPrototype.h: + * runtime/PropertyNameArray.h: + (JSC::PropertyNameArrayData::setCachedPrototypeChain): + * runtime/PrototypeFunction.cpp: + (JSC::PrototypeFunction::PrototypeFunction): + * runtime/PrototypeFunction.h: + * runtime/RegExpConstructor.cpp: + (JSC::RegExpConstructor::RegExpConstructor): + * runtime/RegExpConstructor.h: + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::RegExpObject): + * runtime/RegExpObject.h: + (JSC::RegExpObject::RegExpObjectData::RegExpObjectData): + * runtime/RegExpPrototype.cpp: + (JSC::RegExpPrototype::RegExpPrototype): + * runtime/RegExpPrototype.h: + * runtime/StringConstructor.cpp: + (JSC::StringConstructor::StringConstructor): + * runtime/StringConstructor.h: + * runtime/StringObject.cpp: + (JSC::StringObject::StringObject): + * runtime/StringObject.h: + * runtime/StringObjectThatMasqueradesAsUndefined.h: + (JSC::StringObjectThatMasqueradesAsUndefined::StringObjectThatMasqueradesAsUndefined): + * runtime/StringPrototype.cpp: + (JSC::StringPrototype::StringPrototype): + * runtime/StringPrototype.h: + * wtf/PassRefPtr.h: + (WTF::NotNullPassRefPtr::NotNullPassRefPtr): + (WTF::NotNullPassRefPtr::~NotNullPassRefPtr): + (WTF::NotNullPassRefPtr::get): + (WTF::NotNullPassRefPtr::clear): + (WTF::NotNullPassRefPtr::releaseRef): + (WTF::NotNullPassRefPtr::operator*): + (WTF::NotNullPassRefPtr::operator->): + (WTF::NotNullPassRefPtr::operator!): + (WTF::NotNullPassRefPtr::operator UnspecifiedBoolType): + * wtf/RefPtr.h: + (WTF::RefPtr::RefPtr): + (WTF::operator==): 2009-09-28 Oliver Hunt <oliver@apple.com> @@ -249,28 +8010,6 @@ * wtf/Platform.h: Add a WTF_USE_QXMLQUERY #define. -2009-09-28 Yongjun Zhang <yongjun.zhang@nokia.com> - - Reviewed by Eric Seidel. - - https://bugs.webkit.org/show_bug.cgi?id=28054 - - Use derefInNotNull() to work around winscw compiler forward declaration bug - regarding templated classes. - - The compiler bug is reported at - https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=9812. - - The change should be reverted when the above bug is fixed in winscw compiler. - - Add parenthesis around (RefPtr::*UnspecifiedBoolType) to make winscw compiler - work with the default UnSpecifiedBoolType() operator, which removes the winscw hack. - - * wtf/RefPtr.h: - (WTF::RefPtr::~RefPtr): - (WTF::RefPtr::clear): - (WTF::RefPtr::operator UnspecifiedBoolType): - 2009-09-28 Gabor Loki <loki@inf.u-szeged.hu> Reviewed by Simon Hausmann. @@ -351,6 +8090,81 @@ * yarr/RegexJIT.cpp: (JSC::Yarr::RegexGenerator::generatePatternCharacterPair): +2009-09-25 Jeremy Orlow <jorlow@chromium.org> + + This is breaking Chromium try bots, so I'm counting this as a build fix. + + Add more svn:ignore exceptions. On different platforms, these files are + generated with different case for JavaScriptCore. Also there are some + wtf project files that get built apparently. + + * JavaScriptCore.gyp: Changed property svn:ignore. + +2009-09-25 Ada Chan <adachan@apple.com> + + Build fix. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore_debug.def: + +2009-09-25 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + Inlined some object creation code, including lexicalGlobalObject access + https://bugs.webkit.org/show_bug.cgi?id=29750 + + SunSpider says 0.5% faster. + + 0.8% speedup on bench-alloc-nonretained.js. + 2.5% speedup on v8-splay.js. + + * interpreter/CachedCall.h: + (JSC::CachedCall::CachedCall): + * interpreter/CallFrame.h: + (JSC::ExecState::lexicalGlobalObject): + (JSC::ExecState::globalThisValue): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::dumpRegisters): + (JSC::Interpreter::execute): + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * runtime/FunctionConstructor.cpp: + (JSC::constructFunction): + * runtime/ScopeChain.cpp: + (JSC::ScopeChainNode::print): + * runtime/ScopeChain.h: + (JSC::ScopeChainNode::ScopeChainNode): + (JSC::ScopeChainNode::~ScopeChainNode): + (JSC::ScopeChainNode::push): + (JSC::ScopeChain::ScopeChain): + (JSC::ScopeChain::globalObject): Added a globalObject data member to ScopeChainNode. + Replaced accessor function for globalObject() with data member. Replaced + globalThisObject() accessor with direct access to globalThis, to match. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::init): + * runtime/JSGlobalObject.h: Inlined array and object construction. + +2009-09-25 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Gavin Barraclough. + + Add ARM version detection rules for Symbian + https://bugs.webkit.org/show_bug.cgi?id=29715 + + * wtf/Platform.h: + +2009-09-24 Xan Lopez <xlopez@igalia.com> + + Reviewed by Mark "Do It!" Rowe. + + Some GCC versions don't like C++-style comments in preprocessor + directives, change to C-style to shut them up. + + * wtf/Platform.h: + 2009-09-24 Oliver Hunt <oliver@apple.com> Reviewed by Gavin Barraclough. @@ -375,6 +8189,33 @@ (JSC::JIT::emitLoadInt32ToDouble): (JSC::JIT::emitJumpSlowCaseIfNotImmediateNumber): +2009-09-24 Jeremy Orlow <jorlow@chromium.org> + + Reviewed by Dimitri Glazkov. + + Add GYP generated files to svn:ignore + https://bugs.webkit.org/show_bug.cgi?id=29724 + + Adding the following files to the svn:ignore list (all in the + JavaScriptCore/JavaScriptCore.gyp directory) + + JavaScriptCore.xcodeproj + JavaScriptCore.sln + JavaScriptCore.vcproj + JavaScriptCore_Debug.rules + JavaScriptCore_Release.rules + JavaScriptCore_Release - no tcmalloc.rules + JavaScriptCore_Purify.rules + JavaScriptCore.mk + JavaScriptCore_Debug_rules.mk + JavaScriptCore_Release_rules.mk + JavaScriptCore_Release - no tcmalloc_rules.mk + JavaScriptCore_Purify_rules.mk + JavaScriptCore.scons + JavaScriptCore_main.scons + + * JavaScriptCore.gyp: Changed property svn:ignore. + 2009-09-24 Yong Li <yong.li@torchmobile.com> Reviewed by Adam Barth. @@ -391,17 +8232,6 @@ 2009-09-24 Mark Rowe <mrowe@apple.com> - Reviewed by Gavin Barraclough. - - Fix FastMalloc to build with assertions enabled. - - * wtf/FastMalloc.cpp: - (WTF::TCMalloc_Central_FreeList::ReleaseToSpans): - * wtf/TCSpinLock.h: - (TCMalloc_SpinLock::IsHeld): - -2009-09-24 Mark Rowe <mrowe@apple.com> - Reviewed by Sam Weinig. <rdar://problem/7215058> FastMalloc scavenging thread should be named @@ -414,12 +8244,87 @@ 2009-09-24 Geoffrey Garen <ggaren@apple.com> + Reviewed by Sam Weinig. + + Renamed clear to removeAll, as suggested by Darin Adler. + + * wtf/HashCountedSet.h: + (WTF::::removeAll): + +2009-09-24 Mark Rowe <mrowe@apple.com> + + Reviewed by Gavin Barraclough. + + Fix FastMalloc to build with assertions enabled. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_Central_FreeList::ReleaseToSpans): + * wtf/TCSpinLock.h: + (TCMalloc_SpinLock::IsHeld): + +2009-09-24 Geoffrey Garen <ggaren@apple.com> + Suggested by Darin Adler. Removed some unnecessary parameter names. * wtf/HashCountedSet.h: +2009-09-24 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + On Windows JSChar is typedef'ed to wchar_t. + + When building with WINSCW for Symbian we need to do the + same typedef. + + * API/JSStringRef.h: + +2009-09-23 Geoffrey Garen <ggaren@apple.com> + + A piece of my last patch that I forgot. + + * wtf/HashCountedSet.h: + (WTF::::clear): Added HashCountedSet::clear. + +2009-09-24 Gabor Loki <loki@inf.u-szeged.hu> + + Reviewed by Gavin Barraclough. + + Avoid __clear_cache built-in function if DISABLE_BUILTIN_CLEAR_CACHE define is set + https://bugs.webkit.org/show_bug.cgi?id=28886 + + There are some GCC packages (for example GCC-2006q3 from CodeSourcery) + which contain __clear_cache built-in function only for C while the C++ + version of __clear_cache is missing on ARM architectures. + + Fixed a small bug in the inline assembly of cacheFlush function on + ARM_TRADITIONAL. + + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::cacheFlush): + +2009-09-23 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Added the ability to swap vectors with inline capacities, so you can + store a vector with inline capacity in a hash table. + + * wtf/Vector.h: + (WTF::swap): + (WTF::VectorBuffer::swap): + +2009-09-23 David Kilzer <ddkilzer@apple.com> + + Move definition of USE(PLUGIN_HOST_PROCESS) from WebKitPrefix.h to Platform.h + + Reviewed by Mark Rowe. + + * wtf/Platform.h: Define WTF_USE_PLUGIN_HOST_PROCESS to 1 when + building on 64-bit SnowLeopard. Define to 0 elsewhere. + 2009-09-22 Oliver Hunt <oliver@apple.com> Reviewed by Geoff Garen. @@ -474,71 +8379,84 @@ * wtf/Forward.h: Added PassOwnPtr. -2009-09-22 Simon Hausmann <simon.hausmann@nokia.com> +2009-09-22 Yaar Schnitman <yaar@chromium.org> - Unreviewed build fix for Windows CE < 5 + Reviewed by David Levin. - Define WINCEBASIC to disable the IsDebuggerPresent() code in - wtf/Assertions.cpp. + Ported chromium.org's javascriptcore.gyp for the webkit chromium port. - * JavaScriptCore.pri: + https://bugs.webkit.org/show_bug.cgi?id=29617 -2009-10-02 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + * JavaScriptCore.gyp/JavaScriptCore.gyp: Added. - Rubber-stamped by Simon Hausmann. +2009-09-22 Thiago Macieira <thiago.macieira@nokia.com> - Fix the Qt on Mac OS X build. + Reviewed by Simon Hausmann. - * wtf/FastMalloc.cpp: + Fix compilation with WINSCW: no varargs macros -2009-10-02 Jørgen Lind <jorgen.lind@nokia.com> + Disable variadic arguments for WINSCW just like we do + for MSVC7. + + * wtf/Assertions.h: + +2009-09-22 Kent Hansen <khansen@trolltech.com> Reviewed by Simon Hausmann. - Allow enabling and disabling of the JIT through a qmake variable. + Disable variadic macros on MSVC7. - Qt's configure may set this variable through .qmake.cache if a - commandline option is given and/or the compile test for hwcap.h - failed/succeeded. + This was originally added in r26589 but not extended + when LOG_DISABLED/ASSERT_DISABLED was introduced. + + * wtf/Assertions.h: + +2009-09-22 Simon Hausmann <simon.hausmann@nokia.com> + + Unreviewed build fix for Windows CE < 5 + + Define WINCEBASIC to disable the IsDebuggerPresent() code in + wtf/Assertions.cpp. * JavaScriptCore.pri: -2009-09-23 Geoffrey Garen <ggaren@apple.com> +2009-09-22 Joerg Bornemann <joerg.bornemann@nokia.com> - A piece of my last patch that I forgot. + Reviewed by Simon Hausmann. - * wtf/HashCountedSet.h: - (WTF::::clear): Added HashCountedSet::clear. + Fix major memory leak in JavaScriptCore RegisterFile on Windows CE -2009-09-24 Gabor Loki <loki@inf.u-szeged.hu> + https://bugs.webkit.org/show_bug.cgi?id=29367 - Reviewed by Gavin Barraclough. + On Widows CE we must decommit all committed pages before we release + them. See VirtualFree documentation. + Desktop Windows behaves much smoother in this situation. - Reduce heap size on Symbian from 64MB to 8MB. + * interpreter/RegisterFile.cpp: + (JSC::RegisterFile::~RegisterFile): - This is not a perfect fix, it requires more fine tuning. - But this makes it possible again to debug in the emulator, - which is more important in order to be able to fix other - run-time issues. +2009-09-21 Greg Bolsinga <bolsinga@apple.com> - * runtime/Collector.h: + Reviewed by Simon Fraser & Sam Weinig. -2009-09-30 Janne Koskinen <janne.p.koskinen@digia.com> + Add ENABLE(ORIENTATION_EVENTS) + https://bugs.webkit.org/show_bug.cgi?id=29508 - Reviewed by Simon Hausmann. + * wtf/Platform.h: Also sort PLATFORM(IPHONE) #defines. - Avoid __clear_cache built-in function if DISABLE_BUILTIN_CLEAR_CACHE define is set - https://bugs.webkit.org/show_bug.cgi?id=28886 +2009-09-21 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> - There are some GCC packages (for example GCC-2006q3 from CodeSourcery) - which contain __clear_cache built-in function only for C while the C++ - version of __clear_cache is missing on ARM architectures. + Reviewed by Eric Seidel. - Fixed a small bug in the inline assembly of cacheFlush function on - ARM_TRADITIONAL. + [Fix] SourceCode's uninitialized member + + Potential source of crashes and bugs was fixed. Default constructor + didn't initialized m_provider member. - * jit/ExecutableAllocator.h: - (JSC::ExecutableAllocator::cacheFlush): + https://bugs.webkit.org/show_bug.cgi?id=29364 + + * parser/SourceCode.h: + (JSC::SourceCode::SourceCode): 2009-09-21 Oliver Hunt <oliver@apple.com> diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/Info.plist b/src/3rdparty/javascriptcore/JavaScriptCore/Info.plist index 17949b0..77c9eb8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/Info.plist +++ b/src/3rdparty/javascriptcore/JavaScriptCore/Info.plist @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> @@ -7,7 +7,7 @@ <key>CFBundleExecutable</key> <string>${PRODUCT_NAME}</string> <key>CFBundleGetInfoString</key> - <string>${BUNDLE_VERSION}, Copyright 2003-2009 Apple Inc.; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2001 Peter Kelly <pmk@post.com>; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string> + <string>${BUNDLE_VERSION}, Copyright 2003-2010 Apple Inc.; Copyright 1999-2001 Harri Porten <porten@kde.org>; Copyright 2001 Peter Kelly <pmk@post.com>; Copyright 1997-2005 University of Cambridge; Copyright 1991, 2000, 2001 by Lucent Technologies.</string> <key>CFBundleIdentifier</key> <string>com.apple.${PRODUCT_NAME}</string> <key>CFBundleInfoDictionaryVersion</key> diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.gypi b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.gypi index 15a0c0f..24577da 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.gypi +++ b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.gypi @@ -1,7 +1,6 @@ { 'variables': { 'javascriptcore_files': [ - 'AllInOneFile.cpp', 'API/APICast.h', 'API/JavaScript.h', 'API/JavaScriptCore.h', @@ -19,6 +18,7 @@ 'API/JSClassRef.h', 'API/JSContextRef.cpp', 'API/JSContextRef.h', + 'API/JSContextRefPrivate.h', 'API/JSObjectRef.cpp', 'API/JSObjectRef.h', 'API/JSProfilerPrivate.cpp', @@ -64,6 +64,7 @@ 'bytecode/StructureStubInfo.h', 'bytecompiler/BytecodeGenerator.cpp', 'bytecompiler/BytecodeGenerator.h', + 'bytecompiler/NodesCodegen.cpp', 'bytecompiler/Label.h', 'bytecompiler/LabelScope.h', 'bytecompiler/RegisterID.h', @@ -148,8 +149,6 @@ 'pcre/ucpinternal.h', 'pcre/ucptable.cpp', 'profiler/CallIdentifier.h', - 'profiler/HeavyProfile.cpp', - 'profiler/HeavyProfile.h', 'profiler/Profile.cpp', 'profiler/Profile.h', 'profiler/ProfileGenerator.cpp', @@ -159,8 +158,6 @@ 'profiler/Profiler.cpp', 'profiler/Profiler.h', 'profiler/ProfilerServer.h', - 'profiler/TreeProfile.cpp', - 'profiler/TreeProfile.h', 'runtime/ArgList.cpp', 'runtime/ArgList.h', 'runtime/Arguments.cpp', @@ -194,6 +191,7 @@ 'runtime/DateConversion.h', 'runtime/DateInstance.cpp', 'runtime/DateInstance.h', + 'runtime/DateInstanceCache.h', 'runtime/DatePrototype.cpp', 'runtime/DatePrototype.h', 'runtime/Error.cpp', @@ -331,6 +329,7 @@ 'runtime/Tracing.h', 'runtime/UString.cpp', 'runtime/UString.h', + 'runtime/WeakRandom.h', 'wrec/CharacterClass.cpp', 'wrec/CharacterClass.h', 'wrec/CharacterClassConstructor.cpp', @@ -368,8 +367,8 @@ 'wtf/FastMalloc.h', 'wtf/Forward.h', 'wtf/GetPtr.h', - 'wtf/GOwnPtr.cpp', - 'wtf/GOwnPtr.h', + 'wtf/gtk/GOwnPtr.cpp', + 'wtf/gtk/GOwnPtr.h', 'wtf/gtk/MainThreadGtk.cpp', 'wtf/gtk/ThreadingGtk.cpp', 'wtf/HashCountedSet.h', @@ -399,8 +398,6 @@ 'wtf/PassRefPtr.h', 'wtf/Platform.h', 'wtf/PtrAndFlags.h', - 'wtf/qt/MainThreadQt.cpp', - 'wtf/qt/ThreadingQt.cpp', 'wtf/RandomNumber.cpp', 'wtf/RandomNumber.h', 'wtf/RandomNumberSeed.h', @@ -413,11 +410,16 @@ 'wtf/SegmentedVector.h', 'wtf/StdLibExtras.h', 'wtf/StringExtras.h', + 'wtf/StringHashFunctions.h', 'wtf/TCPackedCache.h', + 'wtf/qt/MainThreadQt.cpp', + 'wtf/qt/ThreadingQt.cpp', 'wtf/TCPageMap.h', 'wtf/TCSpinLock.h', 'wtf/TCSystemAlloc.cpp', 'wtf/TCSystemAlloc.h', + 'wtf/ThreadIdentifierDataPthreads.cpp', + 'wtf/ThreadIdentifierDataPthreads.h', 'wtf/Threading.cpp', 'wtf/Threading.h', 'wtf/ThreadingNone.cpp', diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.order b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.order index 3ae3ec6..d6f6caa 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.order +++ b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.order @@ -1625,7 +1625,6 @@ __ZN3JSC18EmptyStatementNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10Registe __ZN3JSCL27compareByStringPairForQSortEPKvS1_ __Z22jsc_pcre_ucp_othercasej __ZN3JSCL35objectProtoFuncPropertyIsEnumerableEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE -__ZNK3JSC8JSObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj __ZN3WTF7HashMapIjN3JSC7JSValueENS_7IntHashIjEENS_10HashTraitsIjEENS5_IS2_EEE3setERKjRKS2_ __ZN3WTF9HashTableIjSt4pairIjN3JSC7JSValueEENS_18PairFirstExtractorIS4_EENS_7IntHashIjEENS_14PairHashTraitsINS_10HashTraitsIjEE __ZN3JSC12RegisterFile21releaseExcessCapacityEv @@ -1841,7 +1840,6 @@ __ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE __ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE __ZN3JSCL27objectProtoFuncLookupSetterEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_7ArgListE __ZN3JSC8JSObject12lookupSetterEPNS_9ExecStateERKNS_10IdentifierE -__ZNK3JSC16JSVariableObject21getPropertyAttributesEPNS_9ExecStateERKNS_10IdentifierERj __ZN3JSC9ExecState22regExpConstructorTableEPS0_ __ZN3JSCL24regExpConstructorDollar7EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE __ZN3JSCL24regExpConstructorDollar8EPNS_9ExecStateERKNS_10IdentifierERKNS_12PropertySlotE diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri index a6fb2f8..75737ae 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri +++ b/src/3rdparty/javascriptcore/JavaScriptCore/JavaScriptCore.pri @@ -1,14 +1,23 @@ # JavaScriptCore - Qt4 build info VPATH += $$PWD +CONFIG(standalone_package) { + isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/generated +} else { + isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = generated +} + CONFIG(debug, debug|release) { - isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = generated$${QMAKE_DIR_SEP}debug OBJECTS_DIR = obj/debug } else { # Release - isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = generated$${QMAKE_DIR_SEP}release OBJECTS_DIR = obj/release } +symbian: { + # Need to guarantee this comes before system includes of /epoc32/include + MMP_RULES += "USERINCLUDE ../JavaScriptCore/profiler" +} + INCLUDEPATH = \ $$PWD \ $$PWD/.. \ @@ -19,6 +28,7 @@ INCLUDEPATH = \ $$PWD/interpreter \ $$PWD/jit \ $$PWD/parser \ + $$PWD/pcre \ $$PWD/profiler \ $$PWD/runtime \ $$PWD/wrec \ @@ -27,12 +37,11 @@ INCLUDEPATH = \ $$PWD/yarr \ $$PWD/API \ $$PWD/ForwardingHeaders \ - $$GENERATED_SOURCES_DIR \ + $$JSC_GENERATED_SOURCES_DIR \ $$INCLUDEPATH DEFINES += BUILDING_QT__ BUILDING_JavaScriptCore BUILDING_WTF -GENERATED_SOURCES_DIR_SLASH = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP} win32-* { LIBS += -lwinmm } @@ -47,11 +56,6 @@ contains(JAVASCRIPTCORE_JIT,no) { DEFINES+=ENABLE_YARR=0 } -# In debug mode JIT disabled until crash fixed -win32-* { - CONFIG(debug):!contains(DEFINES, ENABLE_JIT=1): DEFINES+=ENABLE_JIT=0 -} - # Rules when JIT enabled (not disabled) !contains(DEFINES, ENABLE_JIT=0) { linux*-g++*:greaterThan(QT_GCC_MAJOR_VERSION,3):greaterThan(QT_GCC_MINOR_VERSION,0) { @@ -68,33 +72,7 @@ wince* { include(pcre/pcre.pri) -LUT_FILES += \ - runtime/DatePrototype.cpp \ - runtime/JSONObject.cpp \ - runtime/NumberConstructor.cpp \ - runtime/StringPrototype.cpp \ - runtime/ArrayPrototype.cpp \ - runtime/MathObject.cpp \ - runtime/RegExpConstructor.cpp \ - runtime/RegExpObject.cpp - -KEYWORDLUT_FILES += \ - parser/Keywords.table - -JSCBISON += \ - parser/Grammar.y - SOURCES += \ - wtf/Assertions.cpp \ - wtf/ByteArray.cpp \ - wtf/HashTable.cpp \ - wtf/MainThread.cpp \ - wtf/RandomNumber.cpp \ - wtf/RefCountedLeakCounter.cpp \ - wtf/TypeTraits.cpp \ - wtf/unicode/CollatorDefault.cpp \ - wtf/unicode/icu/CollatorICU.cpp \ - wtf/unicode/UTF8.cpp \ API/JSBase.cpp \ API/JSCallbackConstructor.cpp \ API/JSCallbackFunction.cpp \ @@ -105,55 +83,39 @@ SOURCES += \ API/JSStringRef.cpp \ API/JSValueRef.cpp \ API/OpaqueJSString.cpp \ - runtime/InitializeThreading.cpp \ - runtime/JSGlobalData.cpp \ - runtime/JSGlobalObject.cpp \ - runtime/JSStaticScopeObject.cpp \ - runtime/JSVariableObject.cpp \ - runtime/JSActivation.cpp \ - runtime/JSNotAnObject.cpp \ - runtime/JSONObject.cpp \ - runtime/LiteralParser.cpp \ - runtime/MarkStack.cpp \ - runtime/TimeoutChecker.cpp \ - bytecode/CodeBlock.cpp \ - bytecode/StructureStubInfo.cpp \ - bytecode/JumpTable.cpp \ assembler/ARMAssembler.cpp \ assembler/MacroAssemblerARM.cpp \ - jit/JIT.cpp \ - jit/JITCall.cpp \ + bytecode/CodeBlock.cpp \ + bytecode/JumpTable.cpp \ + bytecode/Opcode.cpp \ + bytecode/SamplingTool.cpp \ + bytecode/StructureStubInfo.cpp \ + bytecompiler/BytecodeGenerator.cpp \ + bytecompiler/NodesCodegen.cpp \ + debugger/DebuggerActivation.cpp \ + debugger/DebuggerCallFrame.cpp \ + debugger/Debugger.cpp \ + interpreter/CallFrame.cpp \ + interpreter/Interpreter.cpp \ + interpreter/RegisterFile.cpp \ + jit/ExecutableAllocatorPosix.cpp \ + jit/ExecutableAllocatorSymbian.cpp \ + jit/ExecutableAllocatorWin.cpp \ + jit/ExecutableAllocator.cpp \ jit/JITArithmetic.cpp \ + jit/JITCall.cpp \ + jit/JIT.cpp \ jit/JITOpcodes.cpp \ jit/JITPropertyAccess.cpp \ - jit/ExecutableAllocator.cpp \ jit/JITStubs.cpp \ - bytecompiler/BytecodeGenerator.cpp \ - runtime/ExceptionHelpers.cpp \ - runtime/JSPropertyNameIterator.cpp \ - interpreter/Interpreter.cpp \ - bytecode/Opcode.cpp \ - bytecode/SamplingTool.cpp \ - yarr/RegexCompiler.cpp \ - yarr/RegexInterpreter.cpp \ - yarr/RegexJIT.cpp \ - interpreter/RegisterFile.cpp - -win32-*|wince* { - SOURCES += jit/ExecutableAllocatorWin.cpp \ - runtime/MarkStackWin.cpp -} else { - SOURCES += jit/ExecutableAllocatorPosix.cpp \ - runtime/MarkStackPosix.cpp -} - -!contains(DEFINES, USE_SYSTEM_MALLOC) { - SOURCES += wtf/TCSystemAlloc.cpp -} - -# AllInOneFile.cpp helps gcc analize and optimize code -# Other compilers may be able to do this at link time -SOURCES += \ + parser/Lexer.cpp \ + parser/Nodes.cpp \ + parser/ParserArena.cpp \ + parser/Parser.cpp \ + profiler/Profile.cpp \ + profiler/ProfileGenerator.cpp \ + profiler/ProfileNode.cpp \ + profiler/Profiler.cpp \ runtime/ArgList.cpp \ runtime/Arguments.cpp \ runtime/ArrayConstructor.cpp \ @@ -164,62 +126,67 @@ SOURCES += \ runtime/CallData.cpp \ runtime/Collector.cpp \ runtime/CommonIdentifiers.cpp \ + runtime/Completion.cpp \ runtime/ConstructData.cpp \ - wtf/CurrentTime.cpp \ runtime/DateConstructor.cpp \ runtime/DateConversion.cpp \ runtime/DateInstance.cpp \ runtime/DatePrototype.cpp \ - debugger/Debugger.cpp \ - debugger/DebuggerCallFrame.cpp \ - debugger/DebuggerActivation.cpp \ - wtf/dtoa.cpp \ - runtime/Error.cpp \ runtime/ErrorConstructor.cpp \ + runtime/Error.cpp \ runtime/ErrorInstance.cpp \ runtime/ErrorPrototype.cpp \ - interpreter/CallFrame.cpp \ + runtime/ExceptionHelpers.cpp \ runtime/Executable.cpp \ runtime/FunctionConstructor.cpp \ runtime/FunctionPrototype.cpp \ runtime/GetterSetter.cpp \ runtime/GlobalEvalFunction.cpp \ runtime/Identifier.cpp \ + runtime/InitializeThreading.cpp \ runtime/InternalFunction.cpp \ - runtime/Completion.cpp \ - runtime/JSArray.cpp \ + runtime/JSActivation.cpp \ runtime/JSAPIValueWrapper.cpp \ + runtime/JSArray.cpp \ runtime/JSByteArray.cpp \ runtime/JSCell.cpp \ runtime/JSFunction.cpp \ + runtime/JSGlobalData.cpp \ + runtime/JSGlobalObject.cpp \ runtime/JSGlobalObjectFunctions.cpp \ runtime/JSImmediate.cpp \ runtime/JSLock.cpp \ + runtime/JSNotAnObject.cpp \ runtime/JSNumberCell.cpp \ runtime/JSObject.cpp \ + runtime/JSONObject.cpp \ + runtime/JSPropertyNameIterator.cpp \ + runtime/JSStaticScopeObject.cpp \ runtime/JSString.cpp \ runtime/JSValue.cpp \ + runtime/JSVariableObject.cpp \ runtime/JSWrapperObject.cpp \ - parser/Lexer.cpp \ + runtime/LiteralParser.cpp \ runtime/Lookup.cpp \ + runtime/MarkStackPosix.cpp \ + runtime/MarkStackSymbian.cpp \ + runtime/MarkStackWin.cpp \ + runtime/MarkStack.cpp \ runtime/MathObject.cpp \ runtime/NativeErrorConstructor.cpp \ runtime/NativeErrorPrototype.cpp \ - parser/Nodes.cpp \ runtime/NumberConstructor.cpp \ runtime/NumberObject.cpp \ runtime/NumberPrototype.cpp \ runtime/ObjectConstructor.cpp \ runtime/ObjectPrototype.cpp \ runtime/Operations.cpp \ - parser/Parser.cpp \ - parser/ParserArena.cpp \ runtime/PropertyDescriptor.cpp \ runtime/PropertyNameArray.cpp \ runtime/PropertySlot.cpp \ runtime/PrototypeFunction.cpp \ - runtime/RegExp.cpp \ runtime/RegExpConstructor.cpp \ + runtime/RegExp.cpp \ runtime/RegExpObject.cpp \ runtime/RegExpPrototype.cpp \ runtime/ScopeChain.cpp \ @@ -227,50 +194,38 @@ SOURCES += \ runtime/StringConstructor.cpp \ runtime/StringObject.cpp \ runtime/StringPrototype.cpp \ - runtime/Structure.cpp \ runtime/StructureChain.cpp \ + runtime/Structure.cpp \ + runtime/TimeoutChecker.cpp \ runtime/UString.cpp \ - profiler/HeavyProfile.cpp \ - profiler/Profile.cpp \ - profiler/ProfileGenerator.cpp \ - profiler/ProfileNode.cpp \ - profiler/Profiler.cpp \ - profiler/TreeProfile.cpp \ + runtime/UStringImpl.cpp \ + wtf/Assertions.cpp \ + wtf/ByteArray.cpp \ + wtf/CurrentTime.cpp \ wtf/DateMath.cpp \ + wtf/dtoa.cpp \ wtf/FastMalloc.cpp \ + wtf/HashTable.cpp \ + wtf/MainThread.cpp \ + wtf/qt/MainThreadQt.cpp \ + wtf/qt/ThreadingQt.cpp \ + wtf/RandomNumber.cpp \ + wtf/RefCountedLeakCounter.cpp \ + wtf/ThreadingNone.cpp \ wtf/Threading.cpp \ - wtf/qt/MainThreadQt.cpp - -!contains(DEFINES, ENABLE_SINGLE_THREADED=1) { - SOURCES += wtf/qt/ThreadingQt.cpp -} else { - DEFINES += ENABLE_JSC_MULTIPLE_THREADS=0 - SOURCES += wtf/ThreadingNone.cpp -} - -# GENERATOR 1-A: LUT creator -lut.output = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.lut.h -lut.commands = perl $$PWD/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT} -lut.depend = ${QMAKE_FILE_NAME} -lut.input = LUT_FILES -lut.CONFIG += no_link -addExtraCompiler(lut) + wtf/TypeTraits.cpp \ + wtf/unicode/CollatorDefault.cpp \ + wtf/unicode/icu/CollatorICU.cpp \ + wtf/unicode/UTF8.cpp \ + yarr/RegexCompiler.cpp \ + yarr/RegexInterpreter.cpp \ + yarr/RegexJIT.cpp -# GENERATOR 1-B: particular LUT creator (for 1 file only) -keywordlut.output = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}Lexer.lut.h -keywordlut.commands = perl $$PWD/create_hash_table ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT} -keywordlut.depend = ${QMAKE_FILE_NAME} -keywordlut.input = KEYWORDLUT_FILES -keywordlut.CONFIG += no_link -addExtraCompiler(keywordlut) +# Generated files, simply list them for JavaScriptCore +SOURCES += \ + $${JSC_GENERATED_SOURCES_DIR}/Grammar.cpp -# GENERATOR 2: bison grammar -jscbison.output = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.cpp -jscbison.commands = bison -d -p jscyy ${QMAKE_FILE_NAME} -o $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c && $(MOVE) $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.c ${QMAKE_FILE_OUT} && $(MOVE) $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.tab.h $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}${QMAKE_FILE_BASE}.h -jscbison.depend = ${QMAKE_FILE_NAME} -jscbison.input = JSCBISON -jscbison.variable_out = GENERATED_SOURCES -jscbison.dependency_type = TYPE_C -jscbison.CONFIG = target_predeps -addExtraCompilerWithHeader(jscbison) +!contains(DEFINES, USE_SYSTEM_MALLOC) { + SOURCES += wtf/TCSystemAlloc.cpp +} diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMAssembler.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMAssembler.cpp index 1324586..6dd2b87 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMAssembler.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMAssembler.cpp @@ -26,7 +26,7 @@ #include "config.h" -#if ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL) +#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) #include "ARMAssembler.h" @@ -34,39 +34,6 @@ namespace JSC { // Patching helpers -ARMWord* ARMAssembler::getLdrImmAddress(ARMWord* insn, uint32_t* constPool) -{ - // Must be an ldr ..., [pc +/- imm] - ASSERT((*insn & 0x0f7f0000) == 0x051f0000); - - if (constPool && (*insn & 0x1)) - return reinterpret_cast<ARMWord*>(constPool + ((*insn & SDT_OFFSET_MASK) >> 1)); - - ARMWord addr = reinterpret_cast<ARMWord>(insn) + 2 * sizeof(ARMWord); - if (*insn & DT_UP) - return reinterpret_cast<ARMWord*>(addr + (*insn & SDT_OFFSET_MASK)); - else - return reinterpret_cast<ARMWord*>(addr - (*insn & SDT_OFFSET_MASK)); -} - -void ARMAssembler::linkBranch(void* code, JmpSrc from, void* to, int useConstantPool) -{ - ARMWord* insn = reinterpret_cast<ARMWord*>(code) + (from.m_offset / sizeof(ARMWord)); - - if (!useConstantPool) { - int diff = reinterpret_cast<ARMWord*>(to) - reinterpret_cast<ARMWord*>(insn + 2); - - if ((diff <= BOFFSET_MAX && diff >= BOFFSET_MIN)) { - *insn = B | getConditionalField(*insn) | (diff & BRANCH_MASK); - ExecutableAllocator::cacheFlush(insn, sizeof(ARMWord)); - return; - } - } - ARMWord* addr = getLdrImmAddress(insn); - *addr = reinterpret_cast<ARMWord>(to); - ExecutableAllocator::cacheFlush(addr, sizeof(ARMWord)); -} - void ARMAssembler::patchConstantPoolLoad(void* loadAddr, void* constPoolAddr) { ARMWord *ldr = reinterpret_cast<ARMWord*>(loadAddr); @@ -118,7 +85,7 @@ ARMWord ARMAssembler::getOp2(ARMWord imm) if ((imm & 0x00ffffff) == 0) return OP2_IMM | (imm >> 24) | (rol << 8); - return 0; + return INVALID_IMM; } int ARMAssembler::genInt(int reg, ARMWord imm, bool positive) @@ -236,25 +203,18 @@ ARMWord ARMAssembler::getImm(ARMWord imm, int tmpReg, bool invert) // Do it by 1 instruction tmp = getOp2(imm); - if (tmp) + if (tmp != INVALID_IMM) return tmp; tmp = getOp2(~imm); - if (tmp) { + if (tmp != INVALID_IMM) { if (invert) return tmp | OP2_INV_IMM; mvn_r(tmpReg, tmp); return tmpReg; } - // Do it by 2 instruction - if (genInt(tmpReg, imm, true)) - return tmpReg; - if (genInt(tmpReg, ~imm, false)) - return tmpReg; - - ldr_imm(tmpReg, imm); - return tmpReg; + return encodeComplexImm(imm, tmpReg); } void ARMAssembler::moveImm(ARMWord imm, int dest) @@ -263,24 +223,41 @@ void ARMAssembler::moveImm(ARMWord imm, int dest) // Do it by 1 instruction tmp = getOp2(imm); - if (tmp) { + if (tmp != INVALID_IMM) { mov_r(dest, tmp); return; } tmp = getOp2(~imm); - if (tmp) { + if (tmp != INVALID_IMM) { mvn_r(dest, tmp); return; } + encodeComplexImm(imm, dest); +} + +ARMWord ARMAssembler::encodeComplexImm(ARMWord imm, int dest) +{ +#if WTF_ARM_ARCH_AT_LEAST(7) + ARMWord tmp = getImm16Op2(imm); + if (tmp != INVALID_IMM) { + movw_r(dest, tmp); + return dest; + } + movw_r(dest, getImm16Op2(imm & 0xffff)); + movt_r(dest, getImm16Op2(imm >> 16)); + return dest; +#else // Do it by 2 instruction if (genInt(dest, imm, true)) - return; + return dest; if (genInt(dest, ~imm, false)) - return; + return dest; ldr_imm(dest, imm); + return dest; +#endif } // Memory load/store helpers @@ -378,10 +355,17 @@ void* ARMAssembler::executableCopy(ExecutablePool* allocator) // The last bit is set if the constant must be placed on constant pool. int pos = (*iter) & (~0x1); ARMWord* ldrAddr = reinterpret_cast<ARMWord*>(data + pos); - ARMWord offset = *getLdrImmAddress(ldrAddr); - if (offset != 0xffffffff) { - JmpSrc jmpSrc(pos); - linkBranch(data, jmpSrc, data + offset, ((*iter) & 1)); + ARMWord* addr = getLdrImmAddress(ldrAddr); + if (*addr != 0xffffffff) { + if (!(*iter & 1)) { + int diff = reinterpret_cast<ARMWord*>(data + *addr) - (ldrAddr + DefaultPrefetching); + + if ((diff <= BOFFSET_MAX && diff >= BOFFSET_MIN)) { + *ldrAddr = B | getConditionalField(*ldrAddr) | (diff & BRANCH_MASK); + continue; + } + } + *addr = reinterpret_cast<ARMWord>(data + *addr); } } @@ -390,4 +374,4 @@ void* ARMAssembler::executableCopy(ExecutablePool* allocator) } // namespace JSC -#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL) +#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMAssembler.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMAssembler.h index 9f9a450..6967b37 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMAssembler.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMAssembler.h @@ -29,7 +29,7 @@ #include <wtf/Platform.h> -#if ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL) +#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) #include "AssemblerBufferWithConstantPool.h" #include <wtf/Assertions.h> @@ -121,6 +121,7 @@ namespace JSC { MUL = 0x00000090, MULL = 0x00c00090, FADDD = 0x0e300b00, + FDIVD = 0x0e800b00, FSUBD = 0x0e300b40, FMULD = 0x0e200b00, FCMPD = 0x0eb40b40, @@ -133,12 +134,18 @@ namespace JSC { B = 0x0a000000, BL = 0x0b000000, FMSR = 0x0e000a10, + FMRS = 0x0e100a10, FSITOD = 0x0eb80bc0, + FTOSID = 0x0ebd0b40, FMSTAT = 0x0ef1fa10, -#if ARM_ARCH_VERSION >= 5 +#if WTF_ARM_ARCH_AT_LEAST(5) CLZ = 0x016f0f10, BKPT = 0xe120070, #endif +#if WTF_ARM_ARCH_AT_LEAST(7) + MOVW = 0x03000000, + MOVT = 0x03400000, +#endif }; enum { @@ -175,6 +182,9 @@ namespace JSC { padForAlign32 = 0xee120070, }; + static const ARMWord INVALID_IMM = 0xf0000000; + static const int DefaultPrefetching = 2; + class JmpSrc { friend class ARMAssembler; public: @@ -333,6 +343,20 @@ namespace JSC { emitInst(static_cast<ARMWord>(cc) | MOV, rd, ARMRegisters::r0, op2); } +#if WTF_ARM_ARCH_AT_LEAST(7) + void movw_r(int rd, ARMWord op2, Condition cc = AL) + { + ASSERT((op2 | 0xf0fff) == 0xf0fff); + m_buffer.putInt(static_cast<ARMWord>(cc) | MOVW | RD(rd) | op2); + } + + void movt_r(int rd, ARMWord op2, Condition cc = AL) + { + ASSERT((op2 | 0xf0fff) == 0xf0fff); + m_buffer.putInt(static_cast<ARMWord>(cc) | MOVT | RD(rd) | op2); + } +#endif + void movs_r(int rd, ARMWord op2, Condition cc = AL) { emitInst(static_cast<ARMWord>(cc) | MOV | SET_CC, rd, ARMRegisters::r0, op2); @@ -378,6 +402,11 @@ namespace JSC { emitInst(static_cast<ARMWord>(cc) | FADDD, dd, dn, dm); } + void fdivd_r(int dd, int dn, int dm, Condition cc = AL) + { + emitInst(static_cast<ARMWord>(cc) | FDIVD, dd, dn, dm); + } + void fsubd_r(int dd, int dn, int dm, Condition cc = AL) { emitInst(static_cast<ARMWord>(cc) | FSUBD, dd, dn, dm); @@ -482,17 +511,27 @@ namespace JSC { emitInst(static_cast<ARMWord>(cc) | FMSR, rn, dd, 0); } + void fmrs_r(int rd, int dn, Condition cc = AL) + { + emitInst(static_cast<ARMWord>(cc) | FMRS, rd, dn, 0); + } + void fsitod_r(int dd, int dm, Condition cc = AL) { emitInst(static_cast<ARMWord>(cc) | FSITOD, dd, 0, dm); } + void ftosid_r(int fd, int dm, Condition cc = AL) + { + emitInst(static_cast<ARMWord>(cc) | FTOSID, fd, 0, dm); + } + void fmstat(Condition cc = AL) { m_buffer.putInt(static_cast<ARMWord>(cc) | FMSTAT); } -#if ARM_ARCH_VERSION >= 5 +#if WTF_ARM_ARCH_AT_LEAST(5) void clz_r(int rd, int rm, Condition cc = AL) { m_buffer.putInt(static_cast<ARMWord>(cc) | CLZ | RD(rd) | RM(rm)); @@ -501,7 +540,7 @@ namespace JSC { void bkpt(ARMWord value) { -#if ARM_ARCH_VERSION >= 5 +#if WTF_ARM_ARCH_AT_LEAST(5) m_buffer.putInt(BKPT | ((value & 0xff0) << 4) | (value & 0xf)); #else // Cannot access to Zero memory address @@ -594,15 +633,32 @@ namespace JSC { // Patching helpers - static ARMWord* getLdrImmAddress(ARMWord* insn, uint32_t* constPool = 0); - static void linkBranch(void* code, JmpSrc from, void* to, int useConstantPool = 0); + static ARMWord* getLdrImmAddress(ARMWord* insn) + { + // Must be an ldr ..., [pc +/- imm] + ASSERT((*insn & 0x0f7f0000) == 0x051f0000); + + ARMWord addr = reinterpret_cast<ARMWord>(insn) + DefaultPrefetching * sizeof(ARMWord); + if (*insn & DT_UP) + return reinterpret_cast<ARMWord*>(addr + (*insn & SDT_OFFSET_MASK)); + return reinterpret_cast<ARMWord*>(addr - (*insn & SDT_OFFSET_MASK)); + } + + static ARMWord* getLdrImmAddressOnPool(ARMWord* insn, uint32_t* constPool) + { + // Must be an ldr ..., [pc +/- imm] + ASSERT((*insn & 0x0f7f0000) == 0x051f0000); + + if (*insn & 0x1) + return reinterpret_cast<ARMWord*>(constPool + ((*insn & SDT_OFFSET_MASK) >> 1)); + return getLdrImmAddress(insn); + } static void patchPointerInternal(intptr_t from, void* to) { ARMWord* insn = reinterpret_cast<ARMWord*>(from); ARMWord* addr = getLdrImmAddress(insn); *addr = reinterpret_cast<ARMWord>(to); - ExecutableAllocator::cacheFlush(addr, sizeof(ARMWord)); } static ARMWord patchConstantPoolLoad(ARMWord load, ARMWord value) @@ -647,12 +703,13 @@ namespace JSC { void linkJump(JmpSrc from, JmpDst to) { ARMWord* insn = reinterpret_cast<ARMWord*>(m_buffer.data()) + (from.m_offset / sizeof(ARMWord)); - *getLdrImmAddress(insn, m_buffer.poolAddress()) = static_cast<ARMWord>(to.m_offset); + ARMWord* addr = getLdrImmAddressOnPool(insn, m_buffer.poolAddress()); + *addr = static_cast<ARMWord>(to.m_offset); } static void linkJump(void* code, JmpSrc from, void* to) { - linkBranch(code, from, to); + patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to); } static void relinkJump(void* from, void* to) @@ -662,12 +719,12 @@ namespace JSC { static void linkCall(void* code, JmpSrc from, void* to) { - linkBranch(code, from, to, true); + patchPointerInternal(reinterpret_cast<intptr_t>(code) + from.m_offset, to); } static void relinkCall(void* from, void* to) { - relinkJump(from, to); + patchPointerInternal(reinterpret_cast<intptr_t>(from) - sizeof(ARMWord), to); } // Address operations @@ -708,8 +765,18 @@ namespace JSC { } static ARMWord getOp2(ARMWord imm); + +#if WTF_ARM_ARCH_AT_LEAST(7) + static ARMWord getImm16Op2(ARMWord imm) + { + if (imm <= 0xffff) + return (imm & 0xf000) << 4 | (imm & 0xfff); + return INVALID_IMM; + } +#endif ARMWord getImm(ARMWord imm, int tmpReg, bool invert = false); void moveImm(ARMWord imm, int dest); + ARMWord encodeComplexImm(ARMWord imm, int dest); // Memory load/store helpers @@ -764,6 +831,6 @@ namespace JSC { } // namespace JSC -#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL) +#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) #endif // ARMAssembler_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMv7Assembler.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMv7Assembler.h index 078de44..6cde63b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/ARMv7Assembler.h @@ -28,7 +28,7 @@ #include <wtf/Platform.h> -#if ENABLE(ASSEMBLER) && PLATFORM(ARM_THUMB2) +#if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2) #include "AssemblerBuffer.h" #include <wtf/Assertions.h> @@ -236,6 +236,11 @@ class ARMThumbImmediate { ARMThumbImmediate(ThumbImmediateType type, uint16_t value) : m_type(TypeUInt16) { + // Make sure this constructor is only reached with type TypeUInt16; + // this extra parameter makes the code a little clearer by making it + // explicit at call sites which type is being constructed + ASSERT_UNUSED(type, type == TypeUInt16); + m_value.asInt = value; } @@ -407,6 +412,11 @@ register writeback class ARMv7Assembler { public: + ~ARMv7Assembler() + { + ASSERT(m_jumpsToLink.isEmpty()); + } + typedef ARMRegisters::RegisterID RegisterID; typedef ARMRegisters::FPRegisterID FPRegisterID; @@ -477,6 +487,17 @@ public: private: + struct LinkRecord { + LinkRecord(intptr_t from, intptr_t to) + : from(from) + , to(to) + { + } + + intptr_t from; + intptr_t to; + }; + // ARMv7, Appx-A.6.3 bool BadReg(RegisterID reg) { @@ -574,6 +595,7 @@ private: OP_SUB_SP_imm_T1 = 0xB080, OP_BKPT = 0xBE00, OP_IT = 0xBF00, + OP_NOP_T1 = 0xBF00, } OpcodeID; typedef enum { @@ -608,6 +630,7 @@ private: OP_MOV_imm_T3 = 0xF240, OP_SUB_imm_T4 = 0xF2A0, OP_MOVT = 0xF2C0, + OP_NOP_T2a = 0xF3AF, OP_LDRH_reg_T2 = 0xF830, OP_LDRH_imm_T3 = 0xF830, OP_STR_imm_T4 = 0xF840, @@ -626,6 +649,7 @@ private: typedef enum { OP_B_T4b = 0x9000, + OP_NOP_T2b = 0x8000, } OpcodeID2; struct FourFours { @@ -1481,6 +1505,15 @@ public: void* executableCopy(ExecutablePool* allocator) { void* copy = m_formatter.executableCopy(allocator); + + unsigned jumpCount = m_jumpsToLink.size(); + for (unsigned i = 0; i < jumpCount; ++i) { + uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].from); + uint16_t* target = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(copy) + m_jumpsToLink[i].to); + linkJumpAbsolute(location, target); + } + m_jumpsToLink.clear(); + ASSERT(copy); return copy; } @@ -1503,11 +1536,7 @@ public: { ASSERT(to.m_offset != -1); ASSERT(from.m_offset != -1); - - uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(m_formatter.data()) + from.m_offset); - intptr_t relative = to.m_offset - from.m_offset; - - linkWithOffset(location, relative); + m_jumpsToLink.append(LinkRecord(from.m_offset, to.m_offset)); } static void linkJump(void* code, JmpSrc from, void* to) @@ -1515,9 +1544,7 @@ public: ASSERT(from.m_offset != -1); uint16_t* location = reinterpret_cast<uint16_t*>(reinterpret_cast<intptr_t>(code) + from.m_offset); - intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(location); - - linkWithOffset(location, relative); + linkJumpAbsolute(location, to); } // bah, this mathod should really be static, since it is used by the LinkBuffer. @@ -1541,10 +1568,9 @@ public: ASSERT(!(reinterpret_cast<intptr_t>(from) & 1)); ASSERT(!(reinterpret_cast<intptr_t>(to) & 1)); - intptr_t relative = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from); - linkWithOffset(reinterpret_cast<uint16_t*>(from), relative); + linkJumpAbsolute(reinterpret_cast<uint16_t*>(from), to); - ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 2, 2 * sizeof(uint16_t)); + ExecutableAllocator::cacheFlush(reinterpret_cast<uint16_t*>(from) - 5, 5 * sizeof(uint16_t)); } static void relinkCall(void* from, void* to) @@ -1613,14 +1639,14 @@ private: static void setInt32(void* code, uint32_t value) { uint16_t* location = reinterpret_cast<uint16_t*>(code); + ASSERT(isMOV_imm_T3(location - 4) && isMOVT(location - 2)); - uint16_t lo16 = value; - uint16_t hi16 = value >> 16; - - spliceHi5(location - 4, lo16); - spliceLo11(location - 3, lo16); - spliceHi5(location - 2, hi16); - spliceLo11(location - 1, hi16); + ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value)); + ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(value >> 16)); + location[-4] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); + location[-3] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-3] >> 8) & 0xf, lo16); + location[-2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); + location[-1] = twoWordOp5i6Imm4Reg4EncodedImmSecond((location[-1] >> 8) & 0xf, hi16); ExecutableAllocator::cacheFlush(location - 4, 4 * sizeof(uint16_t)); } @@ -1630,41 +1656,89 @@ private: setInt32(code, reinterpret_cast<uint32_t>(value)); } - // Linking & patching: - // This method assumes that the JmpSrc being linked is a T4 b instruction. - static void linkWithOffset(uint16_t* instruction, intptr_t relative) - { - // Currently branches > 16m = mostly deathy. - if (((relative << 7) >> 7) != relative) { - // FIXME: This CRASH means we cannot turn the JIT on by default on arm-v7. - fprintf(stderr, "Error: Cannot link T4b.\n"); - CRASH(); - } - - // ARM encoding for the top two bits below the sign bit is 'peculiar'. - if (relative >= 0) - relative ^= 0xC00000; + static bool isB(void* address) + { + uint16_t* instruction = static_cast<uint16_t*>(address); + return ((instruction[0] & 0xf800) == OP_B_T4a) && ((instruction[1] & 0xd000) == OP_B_T4b); + } - // All branch offsets should be an even distance. - ASSERT(!(relative & 1)); + static bool isBX(void* address) + { + uint16_t* instruction = static_cast<uint16_t*>(address); + return (instruction[0] & 0xff87) == OP_BX; + } - int word1 = ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); - int word2 = ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); + static bool isMOV_imm_T3(void* address) + { + uint16_t* instruction = static_cast<uint16_t*>(address); + return ((instruction[0] & 0xFBF0) == OP_MOV_imm_T3) && ((instruction[1] & 0x8000) == 0); + } - instruction[-2] = OP_B_T4a | word1; - instruction[-1] = OP_B_T4b | word2; + static bool isMOVT(void* address) + { + uint16_t* instruction = static_cast<uint16_t*>(address); + return ((instruction[0] & 0xFBF0) == OP_MOVT) && ((instruction[1] & 0x8000) == 0); } - // These functions can be used to splice 16-bit immediates back into previously generated instructions. - static void spliceHi5(uint16_t* where, uint16_t what) + static bool isNOP_T1(void* address) { - uint16_t pattern = (what >> 12) | ((what & 0x0800) >> 1); - *where = (*where & 0xFBF0) | pattern; + uint16_t* instruction = static_cast<uint16_t*>(address); + return instruction[0] == OP_NOP_T1; } - static void spliceLo11(uint16_t* where, uint16_t what) + + static bool isNOP_T2(void* address) { - uint16_t pattern = ((what & 0x0700) << 4) | (what & 0x00FF); - *where = (*where & 0x8F00) | pattern; + uint16_t* instruction = static_cast<uint16_t*>(address); + return (instruction[0] == OP_NOP_T2a) && (instruction[1] == OP_NOP_T2b); + } + + static void linkJumpAbsolute(uint16_t* instruction, void* target) + { + // FIMXE: this should be up in the MacroAssembler layer. :-( + const uint16_t JUMP_TEMPORARY_REGISTER = ARMRegisters::ip; + + ASSERT(!(reinterpret_cast<intptr_t>(instruction) & 1)); + ASSERT(!(reinterpret_cast<intptr_t>(target) & 1)); + + ASSERT( (isMOV_imm_T3(instruction - 5) && isMOVT(instruction - 3) && isBX(instruction - 1)) + || (isNOP_T1(instruction - 5) && isNOP_T2(instruction - 4) && isB(instruction - 2)) ); + + intptr_t relative = reinterpret_cast<intptr_t>(target) - (reinterpret_cast<intptr_t>(instruction)); + if (((relative << 7) >> 7) == relative) { + // ARM encoding for the top two bits below the sign bit is 'peculiar'. + if (relative >= 0) + relative ^= 0xC00000; + + // All branch offsets should be an even distance. + ASSERT(!(relative & 1)); + // There may be a better way to fix this, but right now put the NOPs first, since in the + // case of an conditional branch this will be coming after an ITTT predicating *three* + // instructions! Looking backwards to modify the ITTT to an IT is not easy, due to + // variable wdith encoding - the previous instruction might *look* like an ITTT but + // actually be the second half of a 2-word op. + instruction[-5] = OP_NOP_T1; + instruction[-4] = OP_NOP_T2a; + instruction[-3] = OP_NOP_T2b; + instruction[-2] = OP_B_T4a | ((relative & 0x1000000) >> 14) | ((relative & 0x3ff000) >> 12); + instruction[-1] = OP_B_T4b | ((relative & 0x800000) >> 10) | ((relative & 0x400000) >> 11) | ((relative & 0xffe) >> 1); + } else { + ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) + 1)); + ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast<uint16_t>(reinterpret_cast<uint32_t>(target) >> 16)); + instruction[-5] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); + instruction[-4] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, lo16); + instruction[-3] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); + instruction[-2] = twoWordOp5i6Imm4Reg4EncodedImmSecond(JUMP_TEMPORARY_REGISTER, hi16); + instruction[-1] = OP_BX | (JUMP_TEMPORARY_REGISTER << 3); + } + } + + static uint16_t twoWordOp5i6Imm4Reg4EncodedImmFirst(uint16_t op, ARMThumbImmediate imm) + { + return op | (imm.m_value.i << 10) | imm.m_value.imm4; + } + static uint16_t twoWordOp5i6Imm4Reg4EncodedImmSecond(uint16_t rd, ARMThumbImmediate imm) + { + return (imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8; } class ARMInstructionFormatter { @@ -1723,8 +1797,11 @@ private: void twoWordOp5i6Imm4Reg4EncodedImm(OpcodeID1 op, int imm4, RegisterID rd, ARMThumbImmediate imm) { - m_buffer.putShort(op | (imm.m_value.i << 10) | imm4); - m_buffer.putShort((imm.m_value.imm3 << 12) | (rd << 8) | imm.m_value.imm8); + ARMThumbImmediate newImm = imm; + newImm.m_value.imm4 = imm4; + + m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmFirst(op, newImm)); + m_buffer.putShort(ARMv7Assembler::twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, newImm)); } void twoWordOp12Reg4Reg4Imm12(OpcodeID1 op, RegisterID reg1, RegisterID reg2, uint16_t imm) @@ -1749,10 +1826,12 @@ private: private: AssemblerBuffer m_buffer; } m_formatter; + + Vector<LinkRecord> m_jumpsToLink; }; } // namespace JSC -#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM_THUMB2) +#endif // ENABLE(ASSEMBLER) && CPU(ARM_THUMB2) #endif // ARMAssembler_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/AbstractMacroAssembler.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/AbstractMacroAssembler.h index 525fe98..198e8d1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -173,16 +173,16 @@ public: struct Imm32 { explicit Imm32(int32_t value) : m_value(value) -#if PLATFORM(ARM) +#if CPU(ARM) , m_isPointer(false) #endif { } -#if !PLATFORM(X86_64) +#if !CPU(X86_64) explicit Imm32(ImmPtr ptr) : m_value(ptr.asIntptr()) -#if PLATFORM(ARM) +#if CPU(ARM) , m_isPointer(true) #endif { @@ -190,7 +190,7 @@ public: #endif int32_t m_value; -#if PLATFORM(ARM) +#if CPU(ARM) // We rely on being able to regenerate code to recover exception handling // information. Since ARMv7 supports 16-bit immediates there is a danger // that if pointer values change the layout of the generated code will change. diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssembler.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssembler.h index 2743ab4..76bd205 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssembler.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssembler.h @@ -30,19 +30,19 @@ #if ENABLE(ASSEMBLER) -#if PLATFORM(ARM_THUMB2) +#if CPU(ARM_THUMB2) #include "MacroAssemblerARMv7.h" namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; }; -#elif PLATFORM(ARM_TRADITIONAL) +#elif CPU(ARM_TRADITIONAL) #include "MacroAssemblerARM.h" namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; }; -#elif PLATFORM(X86) +#elif CPU(X86) #include "MacroAssemblerX86.h" namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; }; -#elif PLATFORM(X86_64) +#elif CPU(X86_64) #include "MacroAssemblerX86_64.h" namespace JSC { typedef MacroAssemblerX86_64 MacroAssemblerBase; }; @@ -60,7 +60,7 @@ public: using MacroAssemblerBase::jump; using MacroAssemblerBase::branch32; using MacroAssemblerBase::branch16; -#if PLATFORM(X86_64) +#if CPU(X86_64) using MacroAssemblerBase::branchPtr; using MacroAssemblerBase::branchTestPtr; #endif @@ -133,7 +133,8 @@ public: // Ptr methods // On 32-bit platforms (i.e. x86), these methods directly map onto their 32-bit equivalents. -#if !PLATFORM(X86_64) + // FIXME: should this use a test for 32-bitness instead of this specific exception? +#if !CPU(X86_64) void addPtr(RegisterID src, RegisterID dest) { add32(src, dest); @@ -179,16 +180,6 @@ public: or32(imm, dest); } - void rshiftPtr(RegisterID shift_amount, RegisterID dest) - { - rshift32(shift_amount, dest); - } - - void rshiftPtr(Imm32 imm, RegisterID dest) - { - rshift32(imm, dest); - } - void subPtr(RegisterID src, RegisterID dest) { sub32(src, dest); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARM.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARM.cpp index d726ecd..b5b20fa 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARM.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARM.cpp @@ -26,11 +26,11 @@ #include "config.h" -#if ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL) +#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) #include "MacroAssemblerARM.h" -#if PLATFORM(LINUX) +#if OS(LINUX) #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -43,7 +43,7 @@ namespace JSC { static bool isVFPPresent() { -#if PLATFORM(LINUX) +#if OS(LINUX) int fd = open("/proc/self/auxv", O_RDONLY); if (fd > 0) { Elf32_auxv_t aux; @@ -62,7 +62,8 @@ static bool isVFPPresent() const bool MacroAssemblerARM::s_isVFPPresent = isVFPPresent(); -#if defined(ARM_REQUIRE_NATURAL_ALIGNMENT) && ARM_REQUIRE_NATURAL_ALIGNMENT +#if CPU(ARMV5_OR_LOWER) +/* On ARMv5 and below, natural alignment is required. */ void MacroAssemblerARM::load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) { ARMWord op2; @@ -91,4 +92,4 @@ void MacroAssemblerARM::load32WithUnalignedHalfWords(BaseIndex address, Register } -#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL) +#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARM.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARM.h index aa8cbb0..21b8de8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -30,7 +30,7 @@ #include <wtf/Platform.h> -#if ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL) +#if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) #include "ARMAssembler.h" #include "AbstractMacroAssembler.h" @@ -38,6 +38,9 @@ namespace JSC { class MacroAssemblerARM : public AbstractMacroAssembler<ARMAssembler> { + static const int DoubleConditionMask = 0x0f; + static const int DoubleConditionBitSpecial = 0x10; + COMPILE_ASSERT(!(DoubleConditionBitSpecial & DoubleConditionMask), DoubleConditionBitSpecial_should_not_interfere_with_ARMAssembler_Condition_codes); public: enum Condition { Equal = ARMAssembler::EQ, @@ -57,14 +60,24 @@ public: }; enum DoubleCondition { + // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN. DoubleEqual = ARMAssembler::EQ, + DoubleNotEqual = ARMAssembler::NE | DoubleConditionBitSpecial, DoubleGreaterThan = ARMAssembler::GT, DoubleGreaterThanOrEqual = ARMAssembler::GE, - DoubleLessThan = ARMAssembler::LT, - DoubleLessThanOrEqual = ARMAssembler::LE, + DoubleLessThan = ARMAssembler::CC, + DoubleLessThanOrEqual = ARMAssembler::LS, + // If either operand is NaN, these conditions always evaluate to true. + DoubleEqualOrUnordered = ARMAssembler::EQ | DoubleConditionBitSpecial, + DoubleNotEqualOrUnordered = ARMAssembler::NE, + DoubleGreaterThanOrUnordered = ARMAssembler::HI, + DoubleGreaterThanOrEqualOrUnordered = ARMAssembler::CS, + DoubleLessThanOrUnordered = ARMAssembler::LT, + DoubleLessThanOrEqualOrUnordered = ARMAssembler::LE, }; static const RegisterID stackPointerRegister = ARMRegisters::sp; + static const RegisterID linkRegister = ARMRegisters::lr; static const Scale ScalePtr = TimesFour; @@ -105,14 +118,18 @@ public: m_assembler.ands_r(dest, dest, w); } - void lshift32(Imm32 imm, RegisterID dest) + void lshift32(RegisterID shift_amount, RegisterID dest) { - m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f)); + ARMWord w = ARMAssembler::getOp2(0x1f); + ASSERT(w != ARMAssembler::INVALID_IMM); + m_assembler.and_r(ARMRegisters::S0, shift_amount, w); + + m_assembler.movs_r(dest, m_assembler.lsl_r(dest, ARMRegisters::S0)); } - void lshift32(RegisterID shift_amount, RegisterID dest) + void lshift32(Imm32 imm, RegisterID dest) { - m_assembler.movs_r(dest, m_assembler.lsl_r(dest, shift_amount)); + m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f)); } void mul32(RegisterID src, RegisterID dest) @@ -130,6 +147,11 @@ public: m_assembler.muls_r(dest, src, ARMRegisters::S0); } + void neg32(RegisterID srcDest) + { + m_assembler.rsbs_r(srcDest, srcDest, ARMAssembler::getOp2(0)); + } + void not32(RegisterID dest) { m_assembler.mvns_r(dest, dest); @@ -147,7 +169,11 @@ public: void rshift32(RegisterID shift_amount, RegisterID dest) { - m_assembler.movs_r(dest, m_assembler.asr_r(dest, shift_amount)); + ARMWord w = ARMAssembler::getOp2(0x1f); + ASSERT(w != ARMAssembler::INVALID_IMM); + m_assembler.and_r(ARMRegisters::S0, shift_amount, w); + + m_assembler.movs_r(dest, m_assembler.asr_r(dest, ARMRegisters::S0)); } void rshift32(Imm32 imm, RegisterID dest) @@ -198,7 +224,7 @@ public: m_assembler.baseIndexTransfer32(true, dest, address.base, address.index, static_cast<int>(address.scale), address.offset); } -#if defined(ARM_REQUIRE_NATURAL_ALIGNMENT) && ARM_REQUIRE_NATURAL_ALIGNMENT +#if CPU(ARMV5_OR_LOWER) void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest); #else void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) @@ -504,6 +530,13 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } + Jump branchOr32(Condition cond, RegisterID src, RegisterID dest) + { + ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); + or32(src, dest); + return Jump(m_assembler.jmp(ARMCondition(cond))); + } + void breakpoint() { m_assembler.bkpt(0); @@ -530,7 +563,7 @@ public: void ret() { - pop(ARMRegisters::pc); + m_assembler.mov_r(ARMRegisters::pc, linkRegister); } void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest) @@ -547,6 +580,25 @@ public: m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond)); } + void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest) + { + // ARM doesn't have byte registers + set32(cond, left, right, dest); + } + + void set8(Condition cond, Address left, RegisterID right, RegisterID dest) + { + // ARM doesn't have byte registers + load32(left, ARMRegisters::S1); + set32(cond, ARMRegisters::S1, right, dest); + } + + void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + { + // ARM doesn't have byte registers + set32(cond, left, right, dest); + } + void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest) { load32(address, ARMRegisters::S1); @@ -558,6 +610,12 @@ public: m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond)); } + void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest) + { + // ARM doesn't have byte registers + setTest32(cond, address, mask, dest); + } + void add32(Imm32 imm, RegisterID src, RegisterID dest) { m_assembler.add_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); @@ -665,6 +723,12 @@ public: m_assembler.doubleTransfer(true, dest, address.base, address.offset); } + void loadDouble(void* address, FPRegisterID dest) + { + m_assembler.ldr_un_imm(ARMRegisters::S0, (ARMWord)address); + m_assembler.fdtr_u(true, dest, ARMRegisters::S0, 0); + } + void storeDouble(FPRegisterID src, ImplicitAddress address) { m_assembler.doubleTransfer(false, src, address.base, address.offset); @@ -681,6 +745,18 @@ public: addDouble(ARMRegisters::SD0, dest); } + void divDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.fdivd_r(dest, dest, src); + } + + void divDouble(Address src, FPRegisterID dest) + { + ASSERT_NOT_REACHED(); // Untested + loadDouble(src, ARMRegisters::SD0); + divDouble(ARMRegisters::SD0, dest); + } + void subDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.fsubd_r(dest, dest, src); @@ -709,11 +785,30 @@ public: m_assembler.fsitod_r(dest, dest); } + void convertInt32ToDouble(Address src, FPRegisterID dest) + { + ASSERT_NOT_REACHED(); // Untested + // flds does not worth the effort here + load32(src, ARMRegisters::S1); + convertInt32ToDouble(ARMRegisters::S1, dest); + } + + void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest) + { + ASSERT_NOT_REACHED(); // Untested + // flds does not worth the effort here + m_assembler.ldr_un_imm(ARMRegisters::S1, (ARMWord)src.m_ptr); + m_assembler.dtr_u(true, ARMRegisters::S1, ARMRegisters::S1, 0); + convertInt32ToDouble(ARMRegisters::S1, dest); + } + Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) { m_assembler.fcmpd_r(left, right); m_assembler.fmstat(); - return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond))); + if (cond & DoubleConditionBitSpecial) + m_assembler.cmp_r(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::VS); + return Jump(m_assembler.jmp(static_cast<ARMAssembler::Condition>(cond & ~DoubleConditionMask))); } // Truncates 'src' to an integer, and places the resulting 'dest'. @@ -728,6 +823,29 @@ public: return jump(); } + // Convert 'src' to an integer, and places the resulting 'dest'. + // If the result is not representable as a 32 bit value, branch. + // May also branch for some values that are representable in 32 bits + // (specifically, in this case, 0). + void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp) + { + m_assembler.ftosid_r(ARMRegisters::SD0, src); + m_assembler.fmrs_r(dest, ARMRegisters::SD0); + + // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump. + m_assembler.fsitod_r(ARMRegisters::SD0, ARMRegisters::SD0); + failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, ARMRegisters::SD0)); + + // If the result is zero, it might have been -0.0, and 0.0 equals to -0.0 + failureCases.append(branchTest32(Zero, dest)); + } + + void zeroDouble(FPRegisterID srcDest) + { + m_assembler.mov_r(ARMRegisters::S0, ARMAssembler::getOp2(0)); + convertInt32ToDouble(ARMRegisters::S0, srcDest); + } + protected: ARMAssembler::Condition ARMCondition(Condition cond) { @@ -746,11 +864,9 @@ protected: void prepareCall() { - ensureSpace(3 * sizeof(ARMWord), sizeof(ARMWord)); + ensureSpace(2 * sizeof(ARMWord), sizeof(ARMWord)); - // S0 might be used for parameter passing - m_assembler.add_r(ARMRegisters::S1, ARMRegisters::pc, ARMAssembler::OP2_IMM | 0x4); - m_assembler.push_r(ARMRegisters::S1); + m_assembler.mov_r(linkRegister, ARMRegisters::pc); } void call32(RegisterID base, int32_t offset) @@ -812,6 +928,6 @@ private: } -#endif // ENABLE(ASSEMBLER) && PLATFORM(ARM_TRADITIONAL) +#endif // ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) #endif // MacroAssemblerARM_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARMv7.h index a549604..532a9cf 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -93,13 +93,21 @@ public: Zero = ARMv7Assembler::ConditionEQ, NonZero = ARMv7Assembler::ConditionNE }; - enum DoubleCondition { + // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN. DoubleEqual = ARMv7Assembler::ConditionEQ, + DoubleNotEqual = ARMv7Assembler::ConditionVC, // Not the right flag! check for this & handle differently. DoubleGreaterThan = ARMv7Assembler::ConditionGT, DoubleGreaterThanOrEqual = ARMv7Assembler::ConditionGE, DoubleLessThan = ARMv7Assembler::ConditionLO, DoubleLessThanOrEqual = ARMv7Assembler::ConditionLS, + // If either operand is NaN, these conditions always evaluate to true. + DoubleEqualOrUnordered = ARMv7Assembler::ConditionVS, // Not the right flag! check for this & handle differently. + DoubleNotEqualOrUnordered = ARMv7Assembler::ConditionNE, + DoubleGreaterThanOrUnordered = ARMv7Assembler::ConditionHI, + DoubleGreaterThanOrEqualOrUnordered = ARMv7Assembler::ConditionHS, + DoubleLessThanOrUnordered = ARMv7Assembler::ConditionLT, + DoubleLessThanOrEqualOrUnordered = ARMv7Assembler::ConditionLE, }; static const RegisterID stackPointerRegister = ARMRegisters::sp; @@ -189,14 +197,19 @@ public: } } - void lshift32(Imm32 imm, RegisterID dest) + void lshift32(RegisterID shift_amount, RegisterID dest) { - m_assembler.lsl(dest, dest, imm.m_value); + // Clamp the shift to the range 0..31 + ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f); + ASSERT(armImm.isValid()); + m_assembler.ARM_and(dataTempRegister, shift_amount, armImm); + + m_assembler.lsl(dest, dest, dataTempRegister); } - void lshift32(RegisterID shift_amount, RegisterID dest) + void lshift32(Imm32 imm, RegisterID dest) { - m_assembler.lsl(dest, dest, shift_amount); + m_assembler.lsl(dest, dest, imm.m_value & 0x1f); } void mul32(RegisterID src, RegisterID dest) @@ -233,12 +246,17 @@ public: void rshift32(RegisterID shift_amount, RegisterID dest) { - m_assembler.asr(dest, dest, shift_amount); + // Clamp the shift to the range 0..31 + ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f); + ASSERT(armImm.isValid()); + m_assembler.ARM_and(dataTempRegister, shift_amount, armImm); + + m_assembler.asr(dest, dest, dataTempRegister); } void rshift32(Imm32 imm, RegisterID dest) { - m_assembler.asr(dest, dest, imm.m_value); + m_assembler.asr(dest, dest, imm.m_value & 0x1f); } void sub32(RegisterID src, RegisterID dest) @@ -531,6 +549,23 @@ public: { m_assembler.vcmp_F64(left, right); m_assembler.vmrs_APSR_nzcv_FPSCR(); + + if (cond == DoubleNotEqual) { + // ConditionNE jumps if NotEqual *or* unordered - force the unordered cases not to jump. + Jump unordered = makeBranch(ARMv7Assembler::ConditionVS); + Jump result = makeBranch(ARMv7Assembler::ConditionNE); + unordered.link(this); + return result; + } + if (cond == DoubleEqualOrUnordered) { + Jump unordered = makeBranch(ARMv7Assembler::ConditionVS); + Jump notEqual = makeBranch(ARMv7Assembler::ConditionNE); + unordered.link(this); + // We get here if either unordered, or equal. + Jump result = makeJump(); + notEqual.link(this); + return result; + } return makeBranch(cond); } @@ -990,13 +1025,15 @@ public: protected: ARMv7Assembler::JmpSrc makeJump() { - return m_assembler.b(); + moveFixedWidthEncoding(Imm32(0), dataTempRegister); + return m_assembler.bx(dataTempRegister); } ARMv7Assembler::JmpSrc makeBranch(ARMv7Assembler::Condition cond) { - m_assembler.it(cond); - return m_assembler.b(); + m_assembler.it(cond, true, true); + moveFixedWidthEncoding(Imm32(0), dataTempRegister); + return m_assembler.bx(dataTempRegister); } ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); } ARMv7Assembler::JmpSrc makeBranch(DoubleCondition cond) { return makeBranch(armV7Condition(cond)); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerCodeRef.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerCodeRef.h index 568260a..cae8bf6 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerCodeRef.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerCodeRef.h @@ -37,7 +37,7 @@ // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid // instruction address on the platform (for example, check any alignment requirements). -#if PLATFORM(ARM_THUMB2) +#if CPU(ARM_THUMB2) // ARM/thumb instructions must be 16-bit aligned, but all code pointers to be loaded // into the processor are decorated with the bottom bit set, indicating that this is // thumb code (as oposed to 32-bit traditional ARM). The first test checks for both @@ -69,7 +69,13 @@ public: template<typename FunctionType> explicit FunctionPtr(FunctionType* value) +#if COMPILER(RVCT) + // RVTC compiler needs C-style cast as it fails with the following error + // Error: #694: reinterpret_cast cannot cast away const or other type qualifiers + : m_value((void*)(value)) +#else : m_value(reinterpret_cast<void*>(value)) +#endif { ASSERT_VALID_CODE_POINTER(m_value); } @@ -124,7 +130,7 @@ public: } explicit MacroAssemblerCodePtr(void* value) -#if PLATFORM(ARM_THUMB2) +#if CPU(ARM_THUMB2) // Decorate the pointer as a thumb code pointer. : m_value(reinterpret_cast<char*>(value) + 1) #else @@ -141,7 +147,7 @@ public: } void* executableAddress() const { return m_value; } -#if PLATFORM(ARM_THUMB2) +#if CPU(ARM_THUMB2) // To use this pointer as a data address remove the decoration. void* dataLocation() const { ASSERT_VALID_CODE_POINTER(m_value); return reinterpret_cast<char*>(m_value) - 1; } #else diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86.h index 6e96240..ca7c31a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86.h @@ -28,7 +28,7 @@ #include <wtf/Platform.h> -#if ENABLE(ASSEMBLER) && PLATFORM(X86) +#if ENABLE(ASSEMBLER) && CPU(X86) #include "MacroAssemblerX86Common.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86Common.h index 5ebefa7..449df86 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -36,6 +36,10 @@ namespace JSC { class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> { + static const int DoubleConditionBitInvert = 0x10; + static const int DoubleConditionBitSpecial = 0x20; + static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial; + public: enum Condition { @@ -56,13 +60,24 @@ public: }; enum DoubleCondition { - DoubleEqual = X86Assembler::ConditionE, + // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN. + DoubleEqual = X86Assembler::ConditionE | DoubleConditionBitSpecial, DoubleNotEqual = X86Assembler::ConditionNE, DoubleGreaterThan = X86Assembler::ConditionA, DoubleGreaterThanOrEqual = X86Assembler::ConditionAE, - DoubleLessThan = X86Assembler::ConditionB, - DoubleLessThanOrEqual = X86Assembler::ConditionBE, + DoubleLessThan = X86Assembler::ConditionA | DoubleConditionBitInvert, + DoubleLessThanOrEqual = X86Assembler::ConditionAE | DoubleConditionBitInvert, + // If either operand is NaN, these conditions always evaluate to true. + DoubleEqualOrUnordered = X86Assembler::ConditionE, + DoubleNotEqualOrUnordered = X86Assembler::ConditionNE | DoubleConditionBitSpecial, + DoubleGreaterThanOrUnordered = X86Assembler::ConditionB | DoubleConditionBitInvert, + DoubleGreaterThanOrEqualOrUnordered = X86Assembler::ConditionBE | DoubleConditionBitInvert, + DoubleLessThanOrUnordered = X86Assembler::ConditionB, + DoubleLessThanOrEqualOrUnordered = X86Assembler::ConditionBE, }; + COMPILE_ASSERT( + !((X86Assembler::ConditionE | X86Assembler::ConditionNE | X86Assembler::ConditionA | X86Assembler::ConditionAE | X86Assembler::ConditionB | X86Assembler::ConditionBE) & DoubleConditionBits), + DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes); static const RegisterID stackPointerRegister = X86Registers::esp; @@ -416,20 +431,35 @@ public: void convertInt32ToDouble(Address src, FPRegisterID dest) { + ASSERT(isSSE2Present()); m_assembler.cvtsi2sd_mr(src.offset, src.base, dest); } Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) { ASSERT(isSSE2Present()); - m_assembler.ucomisd_rr(right, left); - return Jump(m_assembler.jCC(x86Condition(cond))); - } - Jump branchDouble(DoubleCondition cond, FPRegisterID left, Address right) - { - m_assembler.ucomisd_mr(right.offset, right.base, left); - return Jump(m_assembler.jCC(x86Condition(cond))); + if (cond & DoubleConditionBitInvert) + m_assembler.ucomisd_rr(left, right); + else + m_assembler.ucomisd_rr(right, left); + + if (cond == DoubleEqual) { + Jump isUnordered(m_assembler.jp()); + Jump result = Jump(m_assembler.je()); + isUnordered.link(this); + return result; + } else if (cond == DoubleNotEqualOrUnordered) { + Jump isUnordered(m_assembler.jp()); + Jump isEqual(m_assembler.je()); + isUnordered.link(this); + Jump result = jump(); + isEqual.link(this); + return result; + } + + ASSERT(!(cond & DoubleConditionBitSpecial)); + return Jump(m_assembler.jCC(static_cast<X86Assembler::Condition>(cond & ~DoubleConditionBits))); } // Truncates 'src' to an integer, and places the resulting 'dest'. @@ -443,6 +473,25 @@ public: return branch32(Equal, dest, Imm32(0x80000000)); } + // Convert 'src' to an integer, and places the resulting 'dest'. + // If the result is not representable as a 32 bit value, branch. + // May also branch for some values that are representable in 32 bits + // (specifically, in this case, 0). + void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp) + { + ASSERT(isSSE2Present()); + m_assembler.cvttsd2si_rr(src, dest); + + // If the result is zero, it might have been -0.0, and the double comparison won't catch this! + failureCases.append(branchTest32(Zero, dest)); + + // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump. + convertInt32ToDouble(dest, fpTemp); + m_assembler.ucomisd_rr(fpTemp, src); + failureCases.append(m_assembler.jp()); + failureCases.append(m_assembler.jne()); + } + void zeroDouble(FPRegisterID srcDest) { ASSERT(isSSE2Present()); @@ -493,7 +542,7 @@ public: m_assembler.movl_i32r(imm.m_value, dest); } -#if PLATFORM(X86_64) +#if CPU(X86_64) void move(RegisterID src, RegisterID dest) { // Note: on 64-bit this is is a full register move; perhaps it would be @@ -509,7 +558,8 @@ public: void swap(RegisterID reg1, RegisterID reg2) { - m_assembler.xchgq_rr(reg1, reg2); + if (reg1 != reg2) + m_assembler.xchgq_rr(reg1, reg2); } void signExtend32ToPtr(RegisterID src, RegisterID dest) @@ -889,18 +939,13 @@ protected: return static_cast<X86Assembler::Condition>(cond); } - X86Assembler::Condition x86Condition(DoubleCondition cond) - { - return static_cast<X86Assembler::Condition>(cond); - } - private: // Only MacroAssemblerX86 should be using the following method; SSE2 is always available on // x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'. friend class MacroAssemblerX86; -#if PLATFORM(X86) -#if PLATFORM(MAC) +#if CPU(X86) +#if OS(MAC_OS_X) // All X86 Macs are guaranteed to support at least SSE2, static bool isSSE2Present() @@ -908,7 +953,7 @@ private: return true; } -#else // PLATFORM(MAC) +#else // OS(MAC_OS_X) enum SSE2CheckState { NotCheckedSSE2, @@ -951,8 +996,8 @@ private: static SSE2CheckState s_sse2CheckState; -#endif // PLATFORM(MAC) -#elif !defined(NDEBUG) // PLATFORM(X86) +#endif // OS(MAC_OS_X) +#elif !defined(NDEBUG) // CPU(X86) // On x86-64 we should never be checking for SSE2 in a non-debug build, // but non debug add this method to keep the asserts above happy. diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86_64.h index 0f95fe6..ec93f8c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -28,7 +28,7 @@ #include <wtf/Platform.h> -#if ENABLE(ASSEMBLER) && PLATFORM(X86_64) +#if ENABLE(ASSEMBLER) && CPU(X86_64) #include "MacroAssemblerX86Common.h" @@ -192,33 +192,6 @@ public: m_assembler.orq_ir(imm.m_value, dest); } - void rshiftPtr(RegisterID shift_amount, RegisterID dest) - { - // On x86 we can only shift by ecx; if asked to shift by another register we'll - // need rejig the shift amount into ecx first, and restore the registers afterwards. - if (shift_amount != X86Registers::ecx) { - swap(shift_amount, X86Registers::ecx); - - // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx" - if (dest == shift_amount) - m_assembler.sarq_CLr(X86Registers::ecx); - // E.g. transform "shll %eax, %ecx" -> "xchgl %eax, %ecx; shll %ecx, %eax; xchgl %eax, %ecx" - else if (dest == X86Registers::ecx) - m_assembler.sarq_CLr(shift_amount); - // E.g. transform "shll %eax, %ebx" -> "xchgl %eax, %ecx; shll %ecx, %ebx; xchgl %eax, %ecx" - else - m_assembler.sarq_CLr(dest); - - swap(shift_amount, X86Registers::ecx); - } else - m_assembler.sarq_CLr(dest); - } - - void rshiftPtr(Imm32 imm, RegisterID dest) - { - m_assembler.sarq_i8r(imm.m_value, dest); - } - void subPtr(RegisterID src, RegisterID dest) { m_assembler.subq_rr(src, dest); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/X86Assembler.h b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/X86Assembler.h index cbbaaa5..ab3d05f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/assembler/X86Assembler.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/assembler/X86Assembler.h @@ -28,7 +28,7 @@ #include <wtf/Platform.h> -#if ENABLE(ASSEMBLER) && (PLATFORM(X86) || PLATFORM(X86_64)) +#if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64)) #include "AssemblerBuffer.h" #include <stdint.h> @@ -50,7 +50,7 @@ namespace X86Registers { esi, edi, -#if PLATFORM(X86_64) +#if CPU(X86_64) r8, r9, r10, @@ -118,12 +118,12 @@ private: OP_XOR_GvEv = 0x33, OP_CMP_EvGv = 0x39, OP_CMP_GvEv = 0x3B, -#if PLATFORM(X86_64) +#if CPU(X86_64) PRE_REX = 0x40, #endif OP_PUSH_EAX = 0x50, OP_POP_EAX = 0x58, -#if PLATFORM(X86_64) +#if CPU(X86_64) OP_MOVSXD_GvEv = 0x63, #endif PRE_OPERAND_SIZE = 0x66, @@ -296,7 +296,7 @@ public: // Arithmetic operations: -#if !PLATFORM(X86_64) +#if !CPU(X86_64) void adcl_im(int imm, void* addr) { if (CAN_SIGN_EXTEND_8_32(imm)) { @@ -346,7 +346,7 @@ public: } } -#if PLATFORM(X86_64) +#if CPU(X86_64) void addq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst); @@ -423,7 +423,7 @@ public: } } -#if PLATFORM(X86_64) +#if CPU(X86_64) void andq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_AND_EvGv, src, dst); @@ -509,7 +509,7 @@ public: } } -#if PLATFORM(X86_64) +#if CPU(X86_64) void orq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_OR_EvGv, src, dst); @@ -575,7 +575,7 @@ public: } } -#if PLATFORM(X86_64) +#if CPU(X86_64) void subq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_SUB_EvGv, src, dst); @@ -641,7 +641,7 @@ public: } } -#if PLATFORM(X86_64) +#if CPU(X86_64) void xorq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst); @@ -689,7 +689,7 @@ public: m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst); } -#if PLATFORM(X86_64) +#if CPU(X86_64) void sarq_CLr(RegisterID dst) { m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst); @@ -789,7 +789,7 @@ public: m_formatter.immediate32(imm); } -#if PLATFORM(X86_64) +#if CPU(X86_64) void cmpq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_CMP_EvGv, src, dst); @@ -897,7 +897,7 @@ public: m_formatter.immediate32(imm); } -#if PLATFORM(X86_64) +#if CPU(X86_64) void testq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst); @@ -971,7 +971,7 @@ public: m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst); } -#if PLATFORM(X86_64) +#if CPU(X86_64) void xchgq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst); @@ -1001,7 +1001,7 @@ public: void movl_mEAX(void* addr) { m_formatter.oneByteOp(OP_MOV_EAXOv); -#if PLATFORM(X86_64) +#if CPU(X86_64) m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); #else m_formatter.immediate32(reinterpret_cast<int>(addr)); @@ -1038,14 +1038,14 @@ public: void movl_EAXm(void* addr) { m_formatter.oneByteOp(OP_MOV_OvEAX); -#if PLATFORM(X86_64) +#if CPU(X86_64) m_formatter.immediate64(reinterpret_cast<int64_t>(addr)); #else m_formatter.immediate32(reinterpret_cast<int>(addr)); #endif } -#if PLATFORM(X86_64) +#if CPU(X86_64) void movq_rr(RegisterID src, RegisterID dst) { m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst); @@ -1157,7 +1157,7 @@ public: { m_formatter.oneByteOp(OP_LEA, dst, base, offset); } -#if PLATFORM(X86_64) +#if CPU(X86_64) void leaq_mr(int offset, RegisterID base, RegisterID dst) { m_formatter.oneByteOp64(OP_LEA, dst, base, offset); @@ -1323,7 +1323,7 @@ public: m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, base, offset); } -#if !PLATFORM(X86_64) +#if !CPU(X86_64) void cvtsi2sd_mr(void* address, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F2); @@ -1343,7 +1343,7 @@ public: m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst); } -#if PLATFORM(X86_64) +#if CPU(X86_64) void movq_rr(XMMRegisterID src, RegisterID dst) { m_formatter.prefix(PRE_SSE_66); @@ -1369,7 +1369,7 @@ public: m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset); } -#if !PLATFORM(X86_64) +#if !CPU(X86_64) void movsd_mr(void* address, XMMRegisterID dst) { m_formatter.prefix(PRE_SSE_F2); @@ -1535,7 +1535,7 @@ public: static void repatchLoadPtrToLEA(void* where) { -#if PLATFORM(X86_64) +#if CPU(X86_64) // On x86-64 pointer memory accesses require a 64-bit operand, and as such a REX prefix. // Skip over the prefix byte. where = reinterpret_cast<char*>(where) + 1; @@ -1679,7 +1679,7 @@ private: memoryModRM(reg, base, index, scale, offset); } -#if !PLATFORM(X86_64) +#if !CPU(X86_64) void oneByteOp(OneByteOpcodeID opcode, int reg, void* address) { m_buffer.ensureSpace(maxInstructionSize); @@ -1722,7 +1722,7 @@ private: memoryModRM(reg, base, index, scale, offset); } -#if !PLATFORM(X86_64) +#if !CPU(X86_64) void twoByteOp(TwoByteOpcodeID opcode, int reg, void* address) { m_buffer.ensureSpace(maxInstructionSize); @@ -1732,7 +1732,7 @@ private: } #endif -#if PLATFORM(X86_64) +#if CPU(X86_64) // Quad-word-sized operands: // // Used to format 64-bit operantions, planting a REX.w prefix. @@ -1891,7 +1891,7 @@ private: static const RegisterID noBase = X86Registers::ebp; static const RegisterID hasSib = X86Registers::esp; static const RegisterID noIndex = X86Registers::esp; -#if PLATFORM(X86_64) +#if CPU(X86_64) static const RegisterID noBase2 = X86Registers::r13; static const RegisterID hasSib2 = X86Registers::r12; @@ -1967,7 +1967,7 @@ private: void memoryModRM(int reg, RegisterID base, int offset) { // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. -#if PLATFORM(X86_64) +#if CPU(X86_64) if ((base == hasSib) || (base == hasSib2)) { #else if (base == hasSib) { @@ -1982,7 +1982,7 @@ private: m_buffer.putIntUnchecked(offset); } } else { -#if PLATFORM(X86_64) +#if CPU(X86_64) if (!offset && (base != noBase) && (base != noBase2)) #else if (!offset && (base != noBase)) @@ -2001,7 +2001,7 @@ private: void memoryModRM_disp32(int reg, RegisterID base, int offset) { // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there. -#if PLATFORM(X86_64) +#if CPU(X86_64) if ((base == hasSib) || (base == hasSib2)) { #else if (base == hasSib) { @@ -2018,7 +2018,7 @@ private: { ASSERT(index != noIndex); -#if PLATFORM(X86_64) +#if CPU(X86_64) if (!offset && (base != noBase) && (base != noBase2)) #else if (!offset && (base != noBase)) @@ -2033,7 +2033,7 @@ private: } } -#if !PLATFORM(X86_64) +#if !CPU(X86_64) void memoryModRM(int reg, void* address) { // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32! @@ -2048,6 +2048,6 @@ private: } // namespace JSC -#endif // ENABLE(ASSEMBLER) && PLATFORM(X86) +#endif // ENABLE(ASSEMBLER) && CPU(X86) #endif // X86Assembler_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/CodeBlock.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/CodeBlock.cpp index 7e5f6cf..2256583 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/CodeBlock.cpp @@ -51,7 +51,7 @@ static UString escapeQuotes(const UString& str) UString result = str; int pos = 0; while ((pos = result.find('\"', pos)) >= 0) { - result = result.substr(0, pos) + "\"\\\"\"" + result.substr(pos + 1); + result = makeString(result.substr(0, pos), "\"\\\"\"", result.substr(pos + 1)); pos += 4; } return result; @@ -62,49 +62,50 @@ static UString valueToSourceString(ExecState* exec, JSValue val) if (!val) return "0"; - if (val.isString()) { - UString result("\""); - result += escapeQuotes(val.toString(exec)) + "\""; - return result; - } + if (val.isString()) + return makeString("\"", escapeQuotes(val.toString(exec)), "\""); return val.toString(exec); } -static CString registerName(int r) +static CString constantName(ExecState* exec, int k, JSValue value) { - if (r == missingThisObjectMarker()) - return "<null>"; - - return (UString("r") + UString::from(r)).UTF8String(); + return makeString(valueToSourceString(exec, value), "(@k", UString::from(k - FirstConstantRegisterIndex), ")").UTF8String(); } -static CString constantName(ExecState* exec, int k, JSValue value) +static CString idName(int id0, const Identifier& ident) { - return (valueToSourceString(exec, value) + "(@k" + UString::from(k) + ")").UTF8String(); + return makeString(ident.ustring(), "(@id", UString::from(id0), ")").UTF8String(); } -static CString idName(int id0, const Identifier& ident) +CString CodeBlock::registerName(ExecState* exec, int r) const { - return (ident.ustring() + "(@id" + UString::from(id0) +")").UTF8String(); + if (r == missingThisObjectMarker()) + return "<null>"; + + if (isConstantRegisterIndex(r)) + return constantName(exec, r, getConstant(r)); + + return makeString("r", UString::from(r)).UTF8String(); } static UString regexpToSourceString(RegExp* regExp) { - UString pattern = UString("/") + regExp->pattern() + "/"; + char postfix[5] = { '/', 0, 0, 0, 0 }; + int index = 1; if (regExp->global()) - pattern += "g"; + postfix[index++] = 'g'; if (regExp->ignoreCase()) - pattern += "i"; + postfix[index++] = 'i'; if (regExp->multiline()) - pattern += "m"; + postfix[index] = 'm'; - return pattern; + return makeString("/", regExp->pattern(), postfix); } static CString regexpName(int re, RegExp* regexp) { - return (regexpToSourceString(regexp) + "(@re" + UString::from(re) + ")").UTF8String(); + return makeString(regexpToSourceString(regexp), "(@re", UString::from(re), ")").UTF8String(); } static UString pointerToSourceString(void* p) @@ -135,49 +136,44 @@ NEVER_INLINE static const char* debugHookName(int debugHookID) return ""; } -static int locationForOffset(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int offset) -{ - return it - begin + offset; -} - -static void printUnaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op) +void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str()); + printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).c_str(), registerName(exec, r1).c_str()); } -static void printBinaryOp(int location, Vector<Instruction>::const_iterator& it, const char* op) +void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str()); } -static void printConditionalJump(const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it, int location, const char* op) +void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op) const { int r0 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(r0).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).c_str(), offset, location + offset); } -static void printGetByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op) +void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); it += 4; } -static void printPutByIdOp(int location, Vector<Instruction>::const_iterator& it, const Vector<Identifier>& m_identifiers, const char* op) +void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str()); it += 4; } @@ -362,7 +358,7 @@ void CodeBlock::dump(ExecState* exec) const unsigned registerIndex = m_numVars; size_t i = 0; do { - printf(" r%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).ascii()); + printf(" k%u = %s\n", registerIndex, valueToSourceString(exec, m_constantRegisters[i].jsValue()).ascii()); ++i; ++registerIndex; } while (i < m_constantRegisters.size()); @@ -486,7 +482,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_enter_with_activation: { int r0 = (++it)->u.operand; - printf("[%4d] enter_with_activation %s\n", location, registerName(r0).c_str()); + printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).c_str()); break; } case op_create_arguments: { @@ -499,148 +495,148 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_convert_this: { int r0 = (++it)->u.operand; - printf("[%4d] convert_this %s\n", location, registerName(r0).c_str()); + printf("[%4d] convert_this %s\n", location, registerName(exec, r0).c_str()); break; } case op_new_object: { int r0 = (++it)->u.operand; - printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] new_object\t %s\n", location, registerName(exec, r0).c_str()); break; } case op_new_array: { int dst = (++it)->u.operand; int argv = (++it)->u.operand; int argc = (++it)->u.operand; - printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(dst).c_str(), registerName(argv).c_str(), argc); + printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).c_str(), registerName(exec, argv).c_str(), argc); break; } case op_new_regexp: { int r0 = (++it)->u.operand; int re0 = (++it)->u.operand; - printf("[%4d] new_regexp\t %s, %s\n", location, registerName(r0).c_str(), regexpName(re0, regexp(re0)).c_str()); + printf("[%4d] new_regexp\t %s, %s\n", location, registerName(exec, r0).c_str(), regexpName(re0, regexp(re0)).c_str()); break; } case op_mov: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] mov\t\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + printf("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str()); break; } case op_not: { - printUnaryOp(location, it, "not"); + printUnaryOp(exec, location, it, "not"); break; } case op_eq: { - printBinaryOp(location, it, "eq"); + printBinaryOp(exec, location, it, "eq"); break; } case op_eq_null: { - printUnaryOp(location, it, "eq_null"); + printUnaryOp(exec, location, it, "eq_null"); break; } case op_neq: { - printBinaryOp(location, it, "neq"); + printBinaryOp(exec, location, it, "neq"); break; } case op_neq_null: { - printUnaryOp(location, it, "neq_null"); + printUnaryOp(exec, location, it, "neq_null"); break; } case op_stricteq: { - printBinaryOp(location, it, "stricteq"); + printBinaryOp(exec, location, it, "stricteq"); break; } case op_nstricteq: { - printBinaryOp(location, it, "nstricteq"); + printBinaryOp(exec, location, it, "nstricteq"); break; } case op_less: { - printBinaryOp(location, it, "less"); + printBinaryOp(exec, location, it, "less"); break; } case op_lesseq: { - printBinaryOp(location, it, "lesseq"); + printBinaryOp(exec, location, it, "lesseq"); break; } case op_pre_inc: { int r0 = (++it)->u.operand; - printf("[%4d] pre_inc\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).c_str()); break; } case op_pre_dec: { int r0 = (++it)->u.operand; - printf("[%4d] pre_dec\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).c_str()); break; } case op_post_inc: { - printUnaryOp(location, it, "post_inc"); + printUnaryOp(exec, location, it, "post_inc"); break; } case op_post_dec: { - printUnaryOp(location, it, "post_dec"); + printUnaryOp(exec, location, it, "post_dec"); break; } case op_to_jsnumber: { - printUnaryOp(location, it, "to_jsnumber"); + printUnaryOp(exec, location, it, "to_jsnumber"); break; } case op_negate: { - printUnaryOp(location, it, "negate"); + printUnaryOp(exec, location, it, "negate"); break; } case op_add: { - printBinaryOp(location, it, "add"); + printBinaryOp(exec, location, it, "add"); ++it; break; } case op_mul: { - printBinaryOp(location, it, "mul"); + printBinaryOp(exec, location, it, "mul"); ++it; break; } case op_div: { - printBinaryOp(location, it, "div"); + printBinaryOp(exec, location, it, "div"); ++it; break; } case op_mod: { - printBinaryOp(location, it, "mod"); + printBinaryOp(exec, location, it, "mod"); break; } case op_sub: { - printBinaryOp(location, it, "sub"); + printBinaryOp(exec, location, it, "sub"); ++it; break; } case op_lshift: { - printBinaryOp(location, it, "lshift"); + printBinaryOp(exec, location, it, "lshift"); break; } case op_rshift: { - printBinaryOp(location, it, "rshift"); + printBinaryOp(exec, location, it, "rshift"); break; } case op_urshift: { - printBinaryOp(location, it, "urshift"); + printBinaryOp(exec, location, it, "urshift"); break; } case op_bitand: { - printBinaryOp(location, it, "bitand"); + printBinaryOp(exec, location, it, "bitand"); ++it; break; } case op_bitxor: { - printBinaryOp(location, it, "bitxor"); + printBinaryOp(exec, location, it, "bitxor"); ++it; break; } case op_bitor: { - printBinaryOp(location, it, "bitor"); + printBinaryOp(exec, location, it, "bitor"); ++it; break; } case op_bitnot: { - printUnaryOp(location, it, "bitnot"); + printUnaryOp(exec, location, it, "bitnot"); break; } case op_instanceof: { @@ -648,59 +644,59 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; int r3 = (++it)->u.operand; - printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str(), registerName(r3).c_str()); + printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str(), registerName(exec, r3).c_str()); break; } case op_typeof: { - printUnaryOp(location, it, "typeof"); + printUnaryOp(exec, location, it, "typeof"); break; } case op_is_undefined: { - printUnaryOp(location, it, "is_undefined"); + printUnaryOp(exec, location, it, "is_undefined"); break; } case op_is_boolean: { - printUnaryOp(location, it, "is_boolean"); + printUnaryOp(exec, location, it, "is_boolean"); break; } case op_is_number: { - printUnaryOp(location, it, "is_number"); + printUnaryOp(exec, location, it, "is_number"); break; } case op_is_string: { - printUnaryOp(location, it, "is_string"); + printUnaryOp(exec, location, it, "is_string"); break; } case op_is_object: { - printUnaryOp(location, it, "is_object"); + printUnaryOp(exec, location, it, "is_object"); break; } case op_is_function: { - printUnaryOp(location, it, "is_function"); + printUnaryOp(exec, location, it, "is_function"); break; } case op_in: { - printBinaryOp(location, it, "in"); + printBinaryOp(exec, location, it, "in"); break; } case op_resolve: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] resolve\t\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); break; } case op_resolve_skip: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int skipLevels = (++it)->u.operand; - printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels); + printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels); break; } case op_resolve_global: { int r0 = (++it)->u.operand; JSValue scope = JSValue((++it)->u.jsCell); int id0 = (++it)->u.operand; - printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve_global\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).c_str()); it += 2; break; } @@ -708,244 +704,265 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int index = (++it)->u.operand; int skipLevels = (++it)->u.operand; - printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(r0).c_str(), index, skipLevels); + printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).c_str(), index, skipLevels); break; } case op_put_scoped_var: { int index = (++it)->u.operand; int skipLevels = (++it)->u.operand; int r0 = (++it)->u.operand; - printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(r0).c_str()); + printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(exec, r0).c_str()); break; } case op_get_global_var: { int r0 = (++it)->u.operand; JSValue scope = JSValue((++it)->u.jsCell); int index = (++it)->u.operand; - printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(r0).c_str(), valueToSourceString(exec, scope).ascii(), index); + printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(exec, r0).c_str(), valueToSourceString(exec, scope).ascii(), index); break; } case op_put_global_var: { JSValue scope = JSValue((++it)->u.jsCell); int index = (++it)->u.operand; int r0 = (++it)->u.operand; - printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(r0).c_str()); + printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(exec, r0).c_str()); break; } case op_resolve_base: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] resolve_base\t %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve_base\t %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); break; } case op_resolve_with_base: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); break; } case op_get_by_id: { - printGetByIdOp(location, it, m_identifiers, "get_by_id"); + printGetByIdOp(exec, location, it, "get_by_id"); break; } case op_get_by_id_self: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_self"); + printGetByIdOp(exec, location, it, "get_by_id_self"); break; } case op_get_by_id_self_list: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_self_list"); + printGetByIdOp(exec, location, it, "get_by_id_self_list"); break; } case op_get_by_id_proto: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_proto"); + printGetByIdOp(exec, location, it, "get_by_id_proto"); break; } case op_get_by_id_proto_list: { - printGetByIdOp(location, it, m_identifiers, "op_get_by_id_proto_list"); + printGetByIdOp(exec, location, it, "op_get_by_id_proto_list"); break; } case op_get_by_id_chain: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_chain"); + printGetByIdOp(exec, location, it, "get_by_id_chain"); break; } case op_get_by_id_generic: { - printGetByIdOp(location, it, m_identifiers, "get_by_id_generic"); + printGetByIdOp(exec, location, it, "get_by_id_generic"); break; } case op_get_array_length: { - printGetByIdOp(location, it, m_identifiers, "get_array_length"); + printGetByIdOp(exec, location, it, "get_array_length"); break; } case op_get_string_length: { - printGetByIdOp(location, it, m_identifiers, "get_string_length"); + printGetByIdOp(exec, location, it, "get_string_length"); break; } case op_put_by_id: { - printPutByIdOp(location, it, m_identifiers, "put_by_id"); + printPutByIdOp(exec, location, it, "put_by_id"); break; } case op_put_by_id_replace: { - printPutByIdOp(location, it, m_identifiers, "put_by_id_replace"); + printPutByIdOp(exec, location, it, "put_by_id_replace"); break; } case op_put_by_id_transition: { - printPutByIdOp(location, it, m_identifiers, "put_by_id_transition"); + printPutByIdOp(exec, location, it, "put_by_id_transition"); break; } case op_put_by_id_generic: { - printPutByIdOp(location, it, m_identifiers, "put_by_id_generic"); + printPutByIdOp(exec, location, it, "put_by_id_generic"); break; } case op_put_getter: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str()); break; } case op_put_setter: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str()); break; } case op_method_check: { - printf("[%4d] op_method_check\n", location); + printf("[%4d] method_check\n", location); break; } case op_del_by_id: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); break; } case op_get_by_val: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str()); + break; + } + case op_get_by_pname: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int r2 = (++it)->u.operand; + int r3 = (++it)->u.operand; + int r4 = (++it)->u.operand; + int r5 = (++it)->u.operand; + printf("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str(), registerName(exec, r3).c_str(), registerName(exec, r4).c_str(), registerName(exec, r5).c_str()); break; } case op_put_by_val: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str()); break; } case op_del_by_val: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int r2 = (++it)->u.operand; - printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), registerName(r2).c_str()); + printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str()); break; } case op_put_by_index: { int r0 = (++it)->u.operand; unsigned n0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(r0).c_str(), n0, registerName(r1).c_str()); + printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(exec, r0).c_str(), n0, registerName(exec, r1).c_str()); break; } case op_jmp: { int offset = (++it)->u.operand; - printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset)); + printf("[%4d] jmp\t\t %d(->%d)\n", location, offset, location + offset); break; } case op_loop: { int offset = (++it)->u.operand; - printf("[%4d] loop\t\t %d(->%d)\n", location, offset, locationForOffset(begin, it, offset)); + printf("[%4d] loop\t\t %d(->%d)\n", location, offset, location + offset); break; } case op_jtrue: { - printConditionalJump(begin, it, location, "jtrue"); + printConditionalJump(exec, begin, it, location, "jtrue"); break; } case op_loop_if_true: { - printConditionalJump(begin, it, location, "loop_if_true"); + printConditionalJump(exec, begin, it, location, "loop_if_true"); + break; + } + case op_loop_if_false: { + printConditionalJump(exec, begin, it, location, "loop_if_false"); break; } case op_jfalse: { - printConditionalJump(begin, it, location, "jfalse"); + printConditionalJump(exec, begin, it, location, "jfalse"); break; } case op_jeq_null: { - printConditionalJump(begin, it, location, "jeq_null"); + printConditionalJump(exec, begin, it, location, "jeq_null"); break; } case op_jneq_null: { - printConditionalJump(begin, it, location, "jneq_null"); + printConditionalJump(exec, begin, it, location, "jneq_null"); break; } case op_jneq_ptr: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); break; } case op_jnless: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); break; } case op_jnlesseq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); break; } case op_loop_if_less: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); + break; + } + case op_jless: { + int r0 = (++it)->u.operand; + int r1 = (++it)->u.operand; + int offset = (++it)->u.operand; + printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); break; } case op_loop_if_lesseq: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(r0).c_str(), registerName(r1).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); break; } case op_switch_imm: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); + printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).c_str()); break; } case op_switch_char: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); + printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).c_str()); break; } case op_switch_string: { int tableIndex = (++it)->u.operand; int defaultTarget = (++it)->u.operand; int scrutineeRegister = (++it)->u.operand; - printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, locationForOffset(begin, it, defaultTarget), registerName(scrutineeRegister).c_str()); + printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).c_str()); break; } case op_new_func: { int r0 = (++it)->u.operand; int f0 = (++it)->u.operand; - printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(r0).c_str(), f0); + printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(exec, r0).c_str(), f0); break; } case op_new_func_exp: { int r0 = (++it)->u.operand; int f0 = (++it)->u.operand; - printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(r0).c_str(), f0); + printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(exec, r0).c_str(), f0); break; } case op_call: { @@ -953,7 +970,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int func = (++it)->u.operand; int argCount = (++it)->u.operand; int registerOffset = (++it)->u.operand; - printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset); + printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(exec, dst).c_str(), registerName(exec, func).c_str(), argCount, registerOffset); break; } case op_call_eval: { @@ -961,7 +978,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int func = (++it)->u.operand; int argCount = (++it)->u.operand; int registerOffset = (++it)->u.operand; - printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset); + printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(exec, dst).c_str(), registerName(exec, func).c_str(), argCount, registerOffset); break; } case op_call_varargs: { @@ -969,16 +986,16 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int func = (++it)->u.operand; int argCount = (++it)->u.operand; int registerOffset = (++it)->u.operand; - printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(dst).c_str(), registerName(func).c_str(), registerName(argCount).c_str(), registerOffset); + printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(exec, dst).c_str(), registerName(exec, func).c_str(), registerName(exec, argCount).c_str(), registerOffset); break; } case op_load_varargs: { - printUnaryOp(location, it, "load_varargs"); + printUnaryOp(exec, location, it, "load_varargs"); break; } case op_tear_off_activation: { int r0 = (++it)->u.operand; - printf("[%4d] tear_off_activation\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] tear_off_activation\t %s\n", location, registerName(exec, r0).c_str()); break; } case op_tear_off_arguments: { @@ -987,7 +1004,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_ret: { int r0 = (++it)->u.operand; - printf("[%4d] ret\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] ret\t\t %s\n", location, registerName(exec, r0).c_str()); break; } case op_construct: { @@ -997,44 +1014,49 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int registerOffset = (++it)->u.operand; int proto = (++it)->u.operand; int thisRegister = (++it)->u.operand; - printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(dst).c_str(), registerName(func).c_str(), argCount, registerOffset, registerName(proto).c_str(), registerName(thisRegister).c_str()); + printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(exec, dst).c_str(), registerName(exec, func).c_str(), argCount, registerOffset, registerName(exec, proto).c_str(), registerName(exec, thisRegister).c_str()); break; } case op_construct_verify: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] construct_verify\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + printf("[%4d] construct_verify\t %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str()); break; } case op_strcat: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int count = (++it)->u.operand; - printf("[%4d] op_strcat\t %s, %s, %d\n", location, registerName(r0).c_str(), registerName(r1).c_str(), count); + printf("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), count); break; } case op_to_primitive: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] op_to_primitive\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + printf("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str()); break; } case op_get_pnames: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - printf("[%4d] get_pnames\t %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str()); + int r0 = it[1].u.operand; + int r1 = it[2].u.operand; + int r2 = it[3].u.operand; + int r3 = it[4].u.operand; + int offset = it[5].u.operand; + printf("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str(), registerName(exec, r3).c_str(), offset, location + offset); + it += OPCODE_LENGTH(op_get_pnames) - 1; break; } case op_next_pname: { - int dest = (++it)->u.operand; - int iter = (++it)->u.operand; - int offset = (++it)->u.operand; - printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(dest).c_str(), registerName(iter).c_str(), offset, locationForOffset(begin, it, offset)); + int dest = it[1].u.operand; + int iter = it[4].u.operand; + int offset = it[5].u.operand; + printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(exec, dest).c_str(), registerName(exec, iter).c_str(), offset, location + offset); + it += OPCODE_LENGTH(op_next_pname) - 1; break; } case op_push_scope: { int r0 = (++it)->u.operand; - printf("[%4d] push_scope\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] push_scope\t %s\n", location, registerName(exec, r0).c_str()); break; } case op_pop_scope: { @@ -1045,64 +1067,63 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(r1).c_str()); + printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str()); break; } case op_jmp_scopes: { int scopeDelta = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, locationForOffset(begin, it, offset)); + printf("[%4d] jmp_scopes\t^%d, %d(->%d)\n", location, scopeDelta, offset, location + offset); break; } case op_catch: { int r0 = (++it)->u.operand; - printf("[%4d] catch\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] catch\t\t %s\n", location, registerName(exec, r0).c_str()); break; } case op_throw: { int r0 = (++it)->u.operand; - printf("[%4d] throw\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] throw\t\t %s\n", location, registerName(exec, r0).c_str()); break; } case op_new_error: { int r0 = (++it)->u.operand; int errorType = (++it)->u.operand; int k0 = (++it)->u.operand; - printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, getConstant(k0)).c_str()); + printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(exec, r0).c_str(), errorType, constantName(exec, k0, getConstant(k0)).c_str()); break; } case op_jsr: { int retAddrDst = (++it)->u.operand; int offset = (++it)->u.operand; - printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(retAddrDst).c_str(), offset, locationForOffset(begin, it, offset)); + printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(exec, retAddrDst).c_str(), offset, location + offset); break; } case op_sret: { int retAddrSrc = (++it)->u.operand; - printf("[%4d] sret\t\t %s\n", location, registerName(retAddrSrc).c_str()); + printf("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).c_str()); break; } case op_debug: { int debugHookID = (++it)->u.operand; int firstLine = (++it)->u.operand; int lastLine = (++it)->u.operand; - int column = (++it)->u.operand; - printf("[%4d] debug\t\t %s, %d, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine, column); + printf("[%4d] debug\t\t %s, %d, %d\n", location, debugHookName(debugHookID), firstLine, lastLine); break; } case op_profile_will_call: { int function = (++it)->u.operand; - printf("[%4d] profile_will_call %s\n", location, registerName(function).c_str()); + printf("[%4d] profile_will_call %s\n", location, registerName(exec, function).c_str()); break; } case op_profile_did_call: { int function = (++it)->u.operand; - printf("[%4d] profile_did_call\t %s\n", location, registerName(function).c_str()); + printf("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).c_str()); break; } case op_end: { int r0 = (++it)->u.operand; - printf("[%4d] end\t\t %s\n", location, registerName(r0).c_str()); + printf("[%4d] end\t\t %s\n", location, registerName(exec, r0).c_str()); break; } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/CodeBlock.h b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/CodeBlock.h index 0163540..eb874cc 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/CodeBlock.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/CodeBlock.h @@ -438,13 +438,13 @@ namespace JSC { size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); } void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); } Register& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; } - ALWAYS_INLINE bool isConstantRegisterIndex(int index) { return index >= FirstConstantRegisterIndex; } + ALWAYS_INLINE bool isConstantRegisterIndex(int index) const { return index >= FirstConstantRegisterIndex; } ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); } - unsigned addFunctionDecl(PassRefPtr<FunctionExecutable> n) { unsigned size = m_functionDecls.size(); m_functionDecls.append(n); return size; } + unsigned addFunctionDecl(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionDecls.size(); m_functionDecls.append(n); return size; } FunctionExecutable* functionDecl(int index) { return m_functionDecls[index].get(); } int numberOfFunctionDecls() { return m_functionDecls.size(); } - unsigned addFunctionExpr(PassRefPtr<FunctionExecutable> n) { unsigned size = m_functionExprs.size(); m_functionExprs.append(n); return size; } + unsigned addFunctionExpr(NonNullPassRefPtr<FunctionExecutable> n) { unsigned size = m_functionExprs.size(); m_functionExprs.append(n); return size; } FunctionExecutable* functionExpr(int index) { return m_functionExprs[index].get(); } unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; } @@ -482,6 +482,13 @@ namespace JSC { private: #if !defined(NDEBUG) || ENABLE(OPCODE_SAMPLING) void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const; + + CString registerName(ExecState*, int r) const; + void printUnaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const; + void printBinaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const; + void printConditionalJump(ExecState*, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator&, int location, const char* op) const; + void printGetByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const; + void printPutByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const; #endif void reparseForExceptionInfoIfNecessary(CallFrame*); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/Opcode.h b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/Opcode.h index cf50442..d9b2153 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/Opcode.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/Opcode.h @@ -113,6 +113,7 @@ namespace JSC { macro(op_put_by_id_generic, 8) \ macro(op_del_by_id, 4) \ macro(op_get_by_val, 4) \ + macro(op_get_by_pname, 7) \ macro(op_put_by_val, 4) \ macro(op_del_by_val, 4) \ macro(op_put_by_index, 4) \ @@ -127,9 +128,11 @@ namespace JSC { macro(op_jneq_ptr, 4) \ macro(op_jnless, 4) \ macro(op_jnlesseq, 4) \ + macro(op_jless, 4) \ macro(op_jmp_scopes, 3) \ macro(op_loop, 2) \ macro(op_loop_if_true, 3) \ + macro(op_loop_if_false, 3) \ macro(op_loop_if_less, 4) \ macro(op_loop_if_lesseq, 4) \ macro(op_switch_imm, 4) \ @@ -152,8 +155,8 @@ namespace JSC { macro(op_strcat, 4) \ macro(op_to_primitive, 3) \ \ - macro(op_get_pnames, 3) \ - macro(op_next_pname, 4) \ + macro(op_get_pnames, 6) \ + macro(op_next_pname, 7) \ \ macro(op_push_scope, 2) \ macro(op_pop_scope, 1) \ @@ -166,7 +169,7 @@ namespace JSC { macro(op_jsr, 3) \ macro(op_sret, 2) \ \ - macro(op_debug, 5) \ + macro(op_debug, 4) \ macro(op_profile_will_call, 2) \ macro(op_profile_did_call, 2) \ \ @@ -193,8 +196,12 @@ namespace JSC { #undef VERIFY_OPCODE_ID #if HAVE(COMPUTED_GOTO) +#if COMPILER(RVCT) typedef void* Opcode; #else + typedef const void* Opcode; +#endif +#else typedef OpcodeID Opcode; #endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/SamplingTool.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/SamplingTool.cpp index 865c919..3f0babc 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/SamplingTool.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/SamplingTool.cpp @@ -33,7 +33,7 @@ #include "Interpreter.h" #include "Opcode.h" -#if !PLATFORM(WIN_OS) +#if !OS(WINDOWS) #include <unistd.h> #endif @@ -91,7 +91,7 @@ void SamplingFlags::stop() {} uint32_t SamplingFlags::s_flags = 1 << 15; -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) static void sleepForMicroseconds(unsigned us) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/SamplingTool.h b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/SamplingTool.h index 711b086..c3e6247 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/SamplingTool.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/bytecode/SamplingTool.h @@ -113,7 +113,11 @@ namespace JSC { void sample(CodeBlock*, Instruction*); +#if COMPILER(WINSCW) || COMPILER(ACC) ScriptExecutable* m_executable; +#else + RefPtr<ScriptExecutable> m_executable; +#endif CodeBlock* m_codeBlock; int m_sampleCount; int m_opcodeSampleCount; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 10a1136..b0a0877 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -534,7 +534,7 @@ PassRefPtr<LabelScope> BytecodeGenerator::newLabelScope(LabelScope::Type type, c m_labelScopes.removeLast(); // Allocate new label scope. - LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>(0)); // Only loops have continue targets. + LabelScope scope(type, name, scopeDepth(), newLabel(), type == LabelScope::Loop ? newLabel() : PassRefPtr<Label>()); // Only loops have continue targets. m_labelScopes.append(scope); return &m_labelScopes.last(); } @@ -608,14 +608,15 @@ void ALWAYS_INLINE BytecodeGenerator::rewindUnaryOp() PassRefPtr<Label> BytecodeGenerator::emitJump(Label* target) { + size_t begin = instructions().size(); emitOpcode(target->isForward() ? op_jmp : op_loop); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* target) { - if (m_lastOpcodeID == op_less && !target->isForward()) { + if (m_lastOpcodeID == op_less) { int dstIndex; int src1Index; int src2Index; @@ -624,10 +625,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindBinaryOp(); - emitOpcode(op_loop_if_less); + + size_t begin = instructions().size(); + emitOpcode(target->isForward() ? op_jless : op_loop_if_less); instructions().append(src1Index); instructions().append(src2Index); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } } else if (m_lastOpcodeID == op_lesseq && !target->isForward()) { @@ -639,10 +642,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindBinaryOp(); + + size_t begin = instructions().size(); emitOpcode(op_loop_if_lesseq); instructions().append(src1Index); instructions().append(src2Index); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } } else if (m_lastOpcodeID == op_eq_null && target->isForward()) { @@ -653,9 +658,11 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); + + size_t begin = instructions().size(); emitOpcode(op_jeq_null); instructions().append(srcIndex); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } } else if (m_lastOpcodeID == op_neq_null && target->isForward()) { @@ -666,24 +673,26 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfTrue(RegisterID* cond, Label* tar if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); + + size_t begin = instructions().size(); emitOpcode(op_jneq_null); instructions().append(srcIndex); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } } + size_t begin = instructions().size(); + emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true); instructions().append(cond->index()); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* target) { - ASSERT(target->isForward()); - - if (m_lastOpcodeID == op_less) { + if (m_lastOpcodeID == op_less && target->isForward()) { int dstIndex; int src1Index; int src2Index; @@ -692,13 +701,15 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindBinaryOp(); + + size_t begin = instructions().size(); emitOpcode(op_jnless); instructions().append(src1Index); instructions().append(src2Index); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } - } else if (m_lastOpcodeID == op_lesseq) { + } else if (m_lastOpcodeID == op_lesseq && target->isForward()) { int dstIndex; int src1Index; int src2Index; @@ -707,10 +718,12 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindBinaryOp(); + + size_t begin = instructions().size(); emitOpcode(op_jnlesseq); instructions().append(src1Index); instructions().append(src2Index); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } } else if (m_lastOpcodeID == op_not) { @@ -721,12 +734,14 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); - emitOpcode(op_jtrue); + + size_t begin = instructions().size(); + emitOpcode(target->isForward() ? op_jtrue : op_loop_if_true); instructions().append(srcIndex); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } - } else if (m_lastOpcodeID == op_eq_null) { + } else if (m_lastOpcodeID == op_eq_null && target->isForward()) { int dstIndex; int srcIndex; @@ -734,12 +749,14 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); + + size_t begin = instructions().size(); emitOpcode(op_jneq_null); instructions().append(srcIndex); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } - } else if (m_lastOpcodeID == op_neq_null) { + } else if (m_lastOpcodeID == op_neq_null && target->isForward()) { int dstIndex; int srcIndex; @@ -747,34 +764,41 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfFalse(RegisterID* cond, Label* ta if (cond->index() == dstIndex && cond->isTemporary() && !cond->refCount()) { rewindUnaryOp(); + + size_t begin = instructions().size(); emitOpcode(op_jeq_null); instructions().append(srcIndex); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } } - emitOpcode(op_jfalse); + size_t begin = instructions().size(); + emitOpcode(target->isForward() ? op_jfalse : op_loop_if_false); instructions().append(cond->index()); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionCall(RegisterID* cond, Label* target) { + size_t begin = instructions().size(); + emitOpcode(op_jneq_ptr); instructions().append(cond->index()); instructions().append(m_scopeChain->globalObject()->d()->callFunction); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond, Label* target) { + size_t begin = instructions().size(); + emitOpcode(op_jneq_ptr); instructions().append(cond->index()); instructions().append(m_scopeChain->globalObject()->d()->applyFunction); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } @@ -880,7 +904,7 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst && src1->isTemporary() && m_codeBlock->isConstantRegisterIndex(src2->index()) && m_codeBlock->constantRegister(src2->index()).jsValue().isString()) { - const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->value(); + const UString& value = asString(m_codeBlock->constantRegister(src2->index()).jsValue())->tryGetValue(); if (value == "undefined") { rewindUnaryOp(); emitOpcode(op_is_undefined); @@ -1255,6 +1279,19 @@ RegisterID* BytecodeGenerator::emitDeleteById(RegisterID* dst, RegisterID* base, RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property) { + for (size_t i = m_forInContextStack.size(); i > 0; i--) { + ForInContext& context = m_forInContextStack[i - 1]; + if (context.propertyRegister == property) { + emitOpcode(op_get_by_pname); + instructions().append(dst->index()); + instructions().append(base->index()); + instructions().append(property->index()); + instructions().append(context.expectedSubscriptRegister->index()); + instructions().append(context.iterRegister->index()); + instructions().append(context.indexRegister->index()); + return dst; + } + } emitOpcode(op_get_by_val); instructions().append(dst->index()); instructions().append(base->index()); @@ -1598,7 +1635,7 @@ void BytecodeGenerator::emitPopScope() m_dynamicScopeDepth--; } -void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine, int column) +void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, int lastLine) { if (!m_shouldEmitDebugHooks) return; @@ -1606,7 +1643,6 @@ void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, in instructions().append(debugHookID); instructions().append(firstLine); instructions().append(lastLine); - instructions().append(column); } void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst) @@ -1719,6 +1755,8 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro } if (nNormalScopes) { + size_t begin = instructions().size(); + // We need to remove a number of dynamic scopes to get to the next // finally block emitOpcode(op_jmp_scopes); @@ -1727,14 +1765,14 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro // If topScope == bottomScope then there isn't actually a finally block // left to emit, so make the jmp_scopes jump directly to the target label if (topScope == bottomScope) { - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } // Otherwise we just use jmp_scopes to pop a group of scopes and go // to the next instruction RefPtr<Label> nextInsn = newLabel(); - instructions().append(nextInsn->offsetFrom(instructions().size())); + instructions().append(nextInsn->bind(begin, instructions().size())); emitLabel(nextInsn.get()); } @@ -1759,27 +1797,47 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpScopes(Label* target, int targetSco if (m_finallyDepth) return emitComplexJumpScopes(target, &m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta); + size_t begin = instructions().size(); + emitOpcode(op_jmp_scopes); instructions().append(scopeDelta); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return target; } -RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target) +RegisterID* BytecodeGenerator::emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget) +{ + size_t begin = instructions().size(); + + emitOpcode(op_get_pnames); + instructions().append(dst->index()); + instructions().append(base->index()); + instructions().append(i->index()); + instructions().append(size->index()); + instructions().append(breakTarget->bind(begin, instructions().size())); + return dst; +} + +RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target) { + size_t begin = instructions().size(); + emitOpcode(op_next_pname); instructions().append(dst->index()); + instructions().append(base->index()); + instructions().append(i->index()); + instructions().append(size->index()); instructions().append(iter->index()); - instructions().append(target->offsetFrom(instructions().size())); + instructions().append(target->bind(begin, instructions().size())); return dst; } RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end) { #if ENABLE(JIT) - HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() }; + HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth, CodeLocationLabel() }; #else - HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth }; + HandlerInfo info = { start->bind(0, 0), end->bind(0, 0), instructions().size(), m_dynamicScopeDepth + m_baseScopeDepth }; #endif m_codeBlock->addExceptionHandler(info); @@ -1799,9 +1857,11 @@ RegisterID* BytecodeGenerator::emitNewError(RegisterID* dst, ErrorType type, JSV PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally) { + size_t begin = instructions().size(); + emitOpcode(op_jsr); instructions().append(retAddrDst->index()); - instructions().append(finally->offsetFrom(instructions().size())); + instructions().append(finally->bind(begin, instructions().size())); emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it. return finally; } @@ -1871,7 +1931,7 @@ static void prepareJumpTableForImmediateSwitch(SimpleJumpTable& jumpTable, int32 // We're emitting this after the clause labels should have been fixed, so // the labels should not be "forward" references ASSERT(!labels[i]->isForward()); - jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); + jumpTable.add(keyForImmediateSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3)); } } @@ -1897,7 +1957,7 @@ static void prepareJumpTableForCharacterSwitch(SimpleJumpTable& jumpTable, int32 // We're emitting this after the clause labels should have been fixed, so // the labels should not be "forward" references ASSERT(!labels[i]->isForward()); - jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->offsetFrom(switchAddress)); + jumpTable.add(keyForCharacterSwitch(nodes[i], min, max), labels[i]->bind(switchAddress, switchAddress + 3)); } } @@ -1911,7 +1971,7 @@ static void prepareJumpTableForStringSwitch(StringJumpTable& jumpTable, int32_t ASSERT(nodes[i]->isString()); UString::Rep* clause = static_cast<StringNode*>(nodes[i])->value().ustring().rep(); OffsetLocation location; - location.branchOffset = labels[i]->offsetFrom(switchAddress); + location.branchOffset = labels[i]->bind(switchAddress, switchAddress + 3); jumpTable.offsetTable.add(clause, location); } } @@ -1922,23 +1982,23 @@ void BytecodeGenerator::endSwitch(uint32_t clauseCount, RefPtr<Label>* labels, E m_switchContextStack.removeLast(); if (switchInfo.switchType == SwitchInfo::SwitchImmediate) { instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfImmediateSwitchJumpTables(); - instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3); + instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3); SimpleJumpTable& jumpTable = m_codeBlock->addImmediateSwitchJumpTable(); - prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max); + prepareJumpTableForImmediateSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max); } else if (switchInfo.switchType == SwitchInfo::SwitchCharacter) { instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfCharacterSwitchJumpTables(); - instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3); + instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3); SimpleJumpTable& jumpTable = m_codeBlock->addCharacterSwitchJumpTable(); - prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes, min, max); + prepareJumpTableForCharacterSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes, min, max); } else { ASSERT(switchInfo.switchType == SwitchInfo::SwitchString); instructions()[switchInfo.bytecodeOffset + 1] = m_codeBlock->numberOfStringSwitchJumpTables(); - instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->offsetFrom(switchInfo.bytecodeOffset + 3); + instructions()[switchInfo.bytecodeOffset + 2] = defaultLabel->bind(switchInfo.bytecodeOffset, switchInfo.bytecodeOffset + 3); StringJumpTable& jumpTable = m_codeBlock->addStringSwitchJumpTable(); - prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset + 3, clauseCount, labels, nodes); + prepareJumpTableForStringSwitch(jumpTable, switchInfo.bytecodeOffset, clauseCount, labels, nodes); } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/BytecodeGenerator.h index f614f0b..8b6a425 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -61,6 +61,13 @@ namespace JSC { FinallyContext finallyContext; }; + struct ForInContext { + RefPtr<RegisterID> expectedSubscriptRegister; + RefPtr<RegisterID> iterRegister; + RefPtr<RegisterID> indexRegister; + RefPtr<RegisterID> propertyRegister; + }; + class BytecodeGenerator : public FastAllocBase { public: typedef DeclarationStacks::VarStack VarStack; @@ -185,6 +192,19 @@ namespace JSC { return emitNode(0, n); } + void emitNodeInConditionContext(ExpressionNode* n, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue) + { + if (!m_codeBlock->numberOfLineInfos() || m_codeBlock->lastLineInfo().lineNumber != n->lineNo()) { + LineInfo info = { instructions().size(), n->lineNo() }; + m_codeBlock->addLineInfo(info); + } + if (m_emitNodeDepth >= s_maxEmitNodeDepth) + emitThrowExpressionTooDeepException(); + ++m_emitNodeDepth; + n->emitBytecodeInConditionContext(*this, trueTarget, falseTarget, fallThroughMeansTrue); + --m_emitNodeDepth; + } + void emitExpressionInfo(unsigned divot, unsigned startOffset, unsigned endOffset) { divot -= m_codeBlock->sourceOffset(); @@ -312,8 +332,8 @@ namespace JSC { PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*); void emitSubroutineReturn(RegisterID* retAddrSrc); - RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base) { return emitUnaryOp(op_get_pnames, dst, base); } - RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* iter, Label* target); + RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget); + RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target); RegisterID* emitCatch(RegisterID*, Label* start, Label* end); void emitThrow(RegisterID* exc) { emitUnaryNoDstOp(op_throw, exc); } @@ -323,7 +343,7 @@ namespace JSC { RegisterID* emitPushScope(RegisterID* scope); void emitPopScope(); - void emitDebugHook(DebugHookID, int firstLine, int lastLine, int column ); + void emitDebugHook(DebugHookID, int firstLine, int lastLine); int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; } bool hasFinaliser() { return m_finallyDepth != 0; } @@ -331,6 +351,17 @@ namespace JSC { void pushFinallyContext(Label* target, RegisterID* returnAddrDst); void popFinallyContext(); + void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister) + { + ForInContext context = { expectedBase, iter, index, propertyRegister }; + m_forInContextStack.append(context); + } + + void popOptimisedForIn() + { + m_forInContextStack.removeLast(); + } + LabelScope* breakTarget(const Identifier&); LabelScope* continueTarget(const Identifier&); @@ -467,6 +498,7 @@ namespace JSC { Vector<ControlFlowContext> m_scopeContextStack; Vector<SwitchInfo> m_switchContextStack; + Vector<ForInContext> m_forInContextStack; int m_nextGlobalIndex; int m_nextParameterIndex; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/Label.h b/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/Label.h index 0b3d038..8cab1db 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/Label.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/Label.h @@ -51,19 +51,17 @@ namespace JSC { m_location = location; unsigned size = m_unresolvedJumps.size(); - for (unsigned i = 0; i < size; ++i) { - unsigned j = m_unresolvedJumps[i]; - m_codeBlock->instructions()[j].u.operand = m_location - j; - } + for (unsigned i = 0; i < size; ++i) + m_codeBlock->instructions()[m_unresolvedJumps[i].second].u.operand = m_location - m_unresolvedJumps[i].first; } - int offsetFrom(int location) const + int bind(int opcode, int offset) const { if (m_location == invalidLocation) { - m_unresolvedJumps.append(location); + m_unresolvedJumps.append(std::make_pair(opcode, offset)); return 0; } - return m_location - location; + return m_location - opcode; } void ref() { ++m_refCount; } @@ -77,7 +75,7 @@ namespace JSC { bool isForward() const { return m_location == invalidLocation; } private: - typedef Vector<int, 8> JumpVector; + typedef Vector<std::pair<int, int>, 8> JumpVector; static const unsigned invalidLocation = UINT_MAX; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/NodesCodegen.cpp new file mode 100644 index 0000000..64b059d --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -0,0 +1,2012 @@ +/* +* Copyright (C) 1999-2002 Harri Porten (porten@kde.org) +* Copyright (C) 2001 Peter Kelly (pmk@post.com) +* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. +* Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) +* Copyright (C) 2007 Maks Orlovich +* Copyright (C) 2007 Eric Seidel <eric@webkit.org> +* +* This library is free software; you can redistribute it and/or +* modify it under the terms of the GNU Library General Public +* License as published by the Free Software Foundation; either +* version 2 of the License, or (at your option) any later version. +* +* This library is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +* Library General Public License for more details. +* +* You should have received a copy of the GNU Library General Public License +* along with this library; see the file COPYING.LIB. If not, write to +* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +* Boston, MA 02110-1301, USA. +* +*/ + +#include "config.h" +#include "Nodes.h" +#include "NodeConstructors.h" + +#include "BytecodeGenerator.h" +#include "CallFrame.h" +#include "Debugger.h" +#include "JIT.h" +#include "JSFunction.h" +#include "JSGlobalObject.h" +#include "JSStaticScopeObject.h" +#include "LabelScope.h" +#include "Lexer.h" +#include "Operations.h" +#include "Parser.h" +#include "PropertyNameArray.h" +#include "RegExpObject.h" +#include "SamplingTool.h" +#include <wtf/Assertions.h> +#include <wtf/RefCountedLeakCounter.h> +#include <wtf/Threading.h> + +using namespace WTF; + +namespace JSC { + +/* + Details of the emitBytecode function. + + Return value: The register holding the production's value. + dst: An optional parameter specifying the most efficient destination at + which to store the production's value. The callee must honor dst. + + The dst argument provides for a crude form of copy propagation. For example, + + x = 1 + + becomes + + load r[x], 1 + + instead of + + load r0, 1 + mov r[x], r0 + + because the assignment node, "x =", passes r[x] as dst to the number node, "1". +*/ + +// ------------------------------ ThrowableExpressionData -------------------------------- + +static void substitute(UString& string, const UString& substring) +{ + int position = string.find("%s"); + ASSERT(position != -1); + string = makeString(string.substr(0, position), substring, string.substr(position + 2)); +} + +RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* message) +{ + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message)); + generator.emitThrow(exception); + return exception; +} + +RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label) +{ + UString message = messageTemplate; + substitute(message, label); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message)); + generator.emitThrow(exception); + return exception; +} + +inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label) +{ + return emitThrowError(generator, type, messageTemplate, label.ustring()); +} + +// ------------------------------ NullNode ------------------------------------- + +RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (dst == generator.ignoredResult()) + return 0; + return generator.emitLoad(dst, jsNull()); +} + +// ------------------------------ BooleanNode ---------------------------------- + +RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (dst == generator.ignoredResult()) + return 0; + return generator.emitLoad(dst, m_value); +} + +// ------------------------------ NumberNode ----------------------------------- + +RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (dst == generator.ignoredResult()) + return 0; + return generator.emitLoad(dst, m_value); +} + +// ------------------------------ StringNode ----------------------------------- + +RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (dst == generator.ignoredResult()) + return 0; + return generator.emitLoad(dst, m_value); +} + +// ------------------------------ RegExpNode ----------------------------------- + +RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring()); + if (!regExp->isValid()) + return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage()); + if (dst == generator.ignoredResult()) + return 0; + return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get()); +} + +// ------------------------------ ThisNode ------------------------------------- + +RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (dst == generator.ignoredResult()) + return 0; + return generator.moveToDestinationIfNeeded(dst, generator.thisRegister()); +} + +// ------------------------------ ResolveNode ---------------------------------- + +bool ResolveNode::isPure(BytecodeGenerator& generator) const +{ + return generator.isLocal(m_ident); +} + +RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (RegisterID* local = generator.registerFor(m_ident)) { + if (dst == generator.ignoredResult()) + return 0; + return generator.moveToDestinationIfNeeded(dst, local); + } + + generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0); + return generator.emitResolve(generator.finalDestination(dst), m_ident); +} + +// ------------------------------ ArrayNode ------------------------------------ + +RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + // FIXME: Should we put all of this code into emitNewArray? + + unsigned length = 0; + ElementNode* firstPutElement; + for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) { + if (firstPutElement->elision()) + break; + ++length; + } + + if (!firstPutElement && !m_elision) + return generator.emitNewArray(generator.finalDestination(dst), m_element); + + RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element); + + for (ElementNode* n = firstPutElement; n; n = n->next()) { + RegisterID* value = generator.emitNode(n->value()); + length += n->elision(); + generator.emitPutByIndex(array.get(), length++, value); + } + + if (m_elision) { + RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length)); + generator.emitPutById(array.get(), generator.propertyNames().length, value); + } + + return generator.moveToDestinationIfNeeded(dst, array.get()); +} + +bool ArrayNode::isSimpleArray() const +{ + if (m_elision || m_optional) + return false; + for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) { + if (ptr->elision()) + return false; + } + return true; +} + +ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const +{ + ASSERT(!m_elision && !m_optional); + ElementNode* ptr = m_element; + if (!ptr) + return 0; + ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value()); + ArgumentListNode* tail = head; + ptr = ptr->next(); + for (; ptr; ptr = ptr->next()) { + ASSERT(!ptr->elision()); + tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value()); + } + return head; +} + +// ------------------------------ ObjectLiteralNode ---------------------------- + +RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (!m_list) { + if (dst == generator.ignoredResult()) + return 0; + return generator.emitNewObject(generator.finalDestination(dst)); + } + return generator.emitNode(dst, m_list); +} + +// ------------------------------ PropertyListNode ----------------------------- + +RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> newObj = generator.tempDestination(dst); + + generator.emitNewObject(newObj.get()); + + for (PropertyListNode* p = this; p; p = p->m_next) { + RegisterID* value = generator.emitNode(p->m_node->m_assign); + + switch (p->m_node->m_type) { + case PropertyNode::Constant: { + generator.emitPutById(newObj.get(), p->m_node->name(), value); + break; + } + case PropertyNode::Getter: { + generator.emitPutGetter(newObj.get(), p->m_node->name(), value); + break; + } + case PropertyNode::Setter: { + generator.emitPutSetter(newObj.get(), p->m_node->name(), value); + break; + } + default: + ASSERT_NOT_REACHED(); + } + } + + return generator.moveToDestinationIfNeeded(dst, newObj.get()); +} + +// ------------------------------ BracketAccessorNode -------------------------------- + +RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator)); + RegisterID* property = generator.emitNode(m_subscript); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); +} + +// ------------------------------ DotAccessorNode -------------------------------- + +RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RegisterID* base = generator.emitNode(m_base); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + return generator.emitGetById(generator.finalDestination(dst), base, m_ident); +} + +// ------------------------------ ArgumentListNode ----------------------------- + +RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + ASSERT(m_expr); + return generator.emitNode(dst, m_expr); +} + +// ------------------------------ NewExprNode ---------------------------------- + +RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> func = generator.emitNode(m_expr); + return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset()); +} + +// ------------------------------ EvalFunctionCallNode ---------------------------------- + +RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> func = generator.tempDestination(dst); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0); + generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval); + return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); +} + +// ------------------------------ FunctionCallValueNode ---------------------------------- + +RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> func = generator.emitNode(m_expr); + RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); +} + +// ------------------------------ FunctionCallResolveNode ---------------------------------- + +RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { + RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); + return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + } + + int index = 0; + size_t depth = 0; + JSObject* globalObject = 0; + if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { + RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); + RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + } + + RefPtr<RegisterID> func = generator.newTemporary(); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + int identifierStart = divot() - startOffset(); + generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0); + generator.emitResolveWithBase(thisRegister.get(), func.get(), m_ident); + return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); +} + +// ------------------------------ FunctionCallBracketNode ---------------------------------- + +RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNode(m_base); + RegisterID* property = generator.emitNode(m_subscript); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); +} + +// ------------------------------ FunctionCallDotNode ---------------------------------- + +RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> function = generator.tempDestination(dst); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + generator.emitNode(thisRegister.get(), m_base); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + generator.emitMethodCheck(); + generator.emitGetById(function.get(), thisRegister.get(), m_ident); + return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); +} + +RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<Label> realCall = generator.newLabel(); + RefPtr<Label> end = generator.newLabel(); + RefPtr<RegisterID> base = generator.emitNode(m_base); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); + RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get()); + generator.emitJumpIfNotFunctionCall(function.get(), realCall.get()); + { + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + ArgumentListNode* oldList = m_args->m_listNode; + if (m_args->m_listNode && m_args->m_listNode->m_expr) { + generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + m_args->m_listNode = m_args->m_listNode->m_next; + } else + generator.emitLoad(thisRegister.get(), jsNull()); + + generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + generator.emitJump(end.get()); + m_args->m_listNode = oldList; + } + generator.emitLabel(realCall.get()); + { + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + } + generator.emitLabel(end.get()); + return finalDestination.get(); +} + +static bool areTrivialApplyArguments(ArgumentsNode* args) +{ + return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next + || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray()); +} + +RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + // A few simple cases can be trivially handled as ordinary function calls. + // function.apply(), function.apply(arg) -> identical to function.call + // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation + bool mayBeCall = areTrivialApplyArguments(m_args); + + RefPtr<Label> realCall = generator.newLabel(); + RefPtr<Label> end = generator.newLabel(); + RefPtr<RegisterID> base = generator.emitNode(m_base); + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); + RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get()); + generator.emitJumpIfNotFunctionApply(function.get(), realCall.get()); + { + if (mayBeCall) { + RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + ArgumentListNode* oldList = m_args->m_listNode; + if (m_args->m_listNode && m_args->m_listNode->m_expr) { + generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + m_args->m_listNode = m_args->m_listNode->m_next; + if (m_args->m_listNode) { + ASSERT(m_args->m_listNode->m_expr->isSimpleArray()); + ASSERT(!m_args->m_listNode->m_next); + m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData()); + } + } else + generator.emitLoad(thisRegister.get(), jsNull()); + generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + m_args->m_listNode = oldList; + } else { + ASSERT(m_args->m_listNode && m_args->m_listNode->m_next); + RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get()); + RefPtr<RegisterID> argsCountRegister = generator.newTemporary(); + RefPtr<RegisterID> thisRegister = generator.newTemporary(); + RefPtr<RegisterID> argsRegister = generator.newTemporary(); + generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); + ArgumentListNode* args = m_args->m_listNode->m_next; + bool isArgumentsApply = false; + if (args->m_expr->isResolveNode()) { + ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr); + isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier()); + if (isArgumentsApply) + generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments()); + } + if (!isArgumentsApply) + generator.emitNode(argsRegister.get(), args->m_expr); + while ((args = args->m_next)) + generator.emitNode(args->m_expr); + + generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get()); + generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset()); + } + generator.emitJump(end.get()); + } + generator.emitLabel(realCall.get()); + { + RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); + generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); + } + generator.emitLabel(end.get()); + return finalDestination.get(); +} + +// ------------------------------ PostfixResolveNode ---------------------------------- + +static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper) +{ + return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst); +} + +static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper) +{ + if (srcDst == dst) + return generator.emitToJSNumber(dst, srcDst); + return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst); +} + +RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (RegisterID* local = generator.registerFor(m_ident)) { + if (generator.isLocalConstant(m_ident)) { + if (dst == generator.ignoredResult()) + return 0; + return generator.emitToJSNumber(generator.finalDestination(dst), local); + } + + if (dst == generator.ignoredResult()) + return emitPreIncOrDec(generator, local, m_operator); + return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator); + } + + int index = 0; + size_t depth = 0; + JSObject* globalObject = 0; + if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { + RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); + RegisterID* oldValue; + if (dst == generator.ignoredResult()) { + oldValue = 0; + emitPreIncOrDec(generator, value.get(), m_operator); + } else { + oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); + } + generator.emitPutScopedVar(depth, index, value.get(), globalObject); + return oldValue; + } + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + RefPtr<RegisterID> value = generator.newTemporary(); + RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident); + RegisterID* oldValue; + if (dst == generator.ignoredResult()) { + oldValue = 0; + emitPreIncOrDec(generator, value.get(), m_operator); + } else { + oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); + } + generator.emitPutById(base.get(), m_ident, value.get()); + return oldValue; +} + +// ------------------------------ PostfixBracketNode ---------------------------------- + +RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNode(m_base); + RefPtr<RegisterID> property = generator.emitNode(m_subscript); + + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get()); + RegisterID* oldValue; + if (dst == generator.ignoredResult()) { + oldValue = 0; + if (m_operator == OpPlusPlus) + generator.emitPreInc(value.get()); + else + generator.emitPreDec(value.get()); + } else { + oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); + } + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitPutByVal(base.get(), property.get(), value.get()); + return oldValue; +} + +// ------------------------------ PostfixDotNode ---------------------------------- + +RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNode(m_base); + + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); + RegisterID* oldValue; + if (dst == generator.ignoredResult()) { + oldValue = 0; + if (m_operator == OpPlusPlus) + generator.emitPreInc(value.get()); + else + generator.emitPreDec(value.get()); + } else { + oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); + } + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitPutById(base.get(), m_ident, value.get()); + return oldValue; +} + +// ------------------------------ PostfixErrorNode ----------------------------------- + +RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus + ? "Postfix ++ operator applied to value that is not a reference." + : "Postfix -- operator applied to value that is not a reference."); +} + +// ------------------------------ DeleteResolveNode ----------------------------------- + +RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (generator.registerFor(m_ident)) + return generator.emitLoad(generator.finalDestination(dst), false); + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident); + return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident); +} + +// ------------------------------ DeleteBracketNode ----------------------------------- + +RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> r0 = generator.emitNode(m_base); + RegisterID* r1 = generator.emitNode(m_subscript); + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1); +} + +// ------------------------------ DeleteDotNode ----------------------------------- + +RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RegisterID* r0 = generator.emitNode(m_base); + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident); +} + +// ------------------------------ DeleteValueNode ----------------------------------- + +RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitNode(generator.ignoredResult(), m_expr); + + // delete on a non-location expression ignores the value and returns true + return generator.emitLoad(generator.finalDestination(dst), true); +} + +// ------------------------------ VoidNode ------------------------------------- + +RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (dst == generator.ignoredResult()) { + generator.emitNode(generator.ignoredResult(), m_expr); + return 0; + } + RefPtr<RegisterID> r0 = generator.emitNode(m_expr); + return generator.emitLoad(dst, jsUndefined()); +} + +// ------------------------------ TypeOfValueNode ----------------------------------- + +RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (RegisterID* local = generator.registerFor(m_ident)) { + if (dst == generator.ignoredResult()) + return 0; + return generator.emitTypeOf(generator.finalDestination(dst), local); + } + + RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident); + generator.emitGetById(scratch.get(), scratch.get(), m_ident); + if (dst == generator.ignoredResult()) + return 0; + return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get()); +} + +// ------------------------------ TypeOfValueNode ----------------------------------- + +RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (dst == generator.ignoredResult()) { + generator.emitNode(generator.ignoredResult(), m_expr); + return 0; + } + RefPtr<RegisterID> src = generator.emitNode(m_expr); + return generator.emitTypeOf(generator.finalDestination(dst), src.get()); +} + +// ------------------------------ PrefixResolveNode ---------------------------------- + +RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (RegisterID* local = generator.registerFor(m_ident)) { + if (generator.isLocalConstant(m_ident)) { + if (dst == generator.ignoredResult()) + return 0; + RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0); + return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes()); + } + + emitPreIncOrDec(generator, local, m_operator); + return generator.moveToDestinationIfNeeded(dst, local); + } + + int index = 0; + size_t depth = 0; + JSObject* globalObject = 0; + if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { + RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); + emitPreIncOrDec(generator, propDst.get(), m_operator); + generator.emitPutScopedVar(depth, index, propDst.get(), globalObject); + return generator.moveToDestinationIfNeeded(dst, propDst.get()); + } + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + RefPtr<RegisterID> propDst = generator.tempDestination(dst); + RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident); + emitPreIncOrDec(generator, propDst.get(), m_operator); + generator.emitPutById(base.get(), m_ident, propDst.get()); + return generator.moveToDestinationIfNeeded(dst, propDst.get()); +} + +// ------------------------------ PrefixBracketNode ---------------------------------- + +RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNode(m_base); + RefPtr<RegisterID> property = generator.emitNode(m_subscript); + RefPtr<RegisterID> propDst = generator.tempDestination(dst); + + generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); + RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get()); + if (m_operator == OpPlusPlus) + generator.emitPreInc(value); + else + generator.emitPreDec(value); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitPutByVal(base.get(), property.get(), value); + return generator.moveToDestinationIfNeeded(dst, propDst.get()); +} + +// ------------------------------ PrefixDotNode ---------------------------------- + +RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNode(m_base); + RefPtr<RegisterID> propDst = generator.tempDestination(dst); + + generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); + RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident); + if (m_operator == OpPlusPlus) + generator.emitPreInc(value); + else + generator.emitPreDec(value); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitPutById(base.get(), m_ident, value); + return generator.moveToDestinationIfNeeded(dst, propDst.get()); +} + +// ------------------------------ PrefixErrorNode ----------------------------------- + +RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus + ? "Prefix ++ operator applied to value that is not a reference." + : "Prefix -- operator applied to value that is not a reference."); +} + +// ------------------------------ Unary Operation Nodes ----------------------------------- + +RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RegisterID* src = generator.emitNode(m_expr); + return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); +} + + +// ------------------------------ LogicalNotNode ----------------------------------- + +void LogicalNotNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue) +{ + ASSERT(expr()->hasConditionContextCodegen()); + + // reverse the true and false targets + generator.emitNodeInConditionContext(expr(), falseTarget, trueTarget, !fallThroughMeansTrue); +} + + +// ------------------------------ Binary Operation Nodes ----------------------------------- + +// BinaryOpNode::emitStrcat: +// +// This node generates an op_strcat operation. This opcode can handle concatenation of three or +// more values, where we can determine a set of separate op_add operations would be operating on +// string values. +// +// This function expects to be operating on a graph of AST nodes looking something like this: +// +// (a)... (b) +// \ / +// (+) (c) +// \ / +// [d] ((+)) +// \ / +// [+=] +// +// The assignment operation is optional, if it exists the register holding the value on the +// lefthand side of the assignment should be passing as the optional 'lhs' argument. +// +// The method should be called on the node at the root of the tree of regular binary add +// operations (marked in the diagram with a double set of parentheses). This node must +// be performing a string concatenation (determined by statically detecting that at least +// one child must be a string). +// +// Since the minimum number of values being concatenated together is expected to be 3, if +// a lhs to a concatenating assignment is not provided then the root add should have at +// least one left child that is also an add that can be determined to be operating on strings. +// +RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe) +{ + ASSERT(isAdd()); + ASSERT(resultDescriptor().definitelyIsString()); + + // Create a list of expressions for all the adds in the tree of nodes we can convert into + // a string concatenation. The rightmost node (c) is added first. The rightmost node is + // added first, and the leftmost child is never added, so the vector produced for the + // example above will be [ c, b ]. + Vector<ExpressionNode*, 16> reverseExpressionList; + reverseExpressionList.append(m_expr2); + + // Examine the left child of the add. So long as this is a string add, add its right-child + // to the list, and keep processing along the left fork. + ExpressionNode* leftMostAddChild = m_expr1; + while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) { + reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2); + leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1; + } + + Vector<RefPtr<RegisterID>, 16> temporaryRegisters; + + // If there is an assignment, allocate a temporary to hold the lhs after conversion. + // We could possibly avoid this (the lhs is converted last anyway, we could let the + // op_strcat node handle its conversion if required). + if (lhs) + temporaryRegisters.append(generator.newTemporary()); + + // Emit code for the leftmost node ((a) in the example). + temporaryRegisters.append(generator.newTemporary()); + RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get(); + generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild); + + // Note on ordering of conversions: + // + // We maintain the same ordering of conversions as we would see if the concatenations + // was performed as a sequence of adds (otherwise this optimization could change + // behaviour should an object have been provided a valueOf or toString method). + // + // Considering the above example, the sequnce of execution is: + // * evaluate operand (a) + // * evaluate operand (b) + // * convert (a) to primitive <- (this would be triggered by the first add) + // * convert (b) to primitive <- (ditto) + // * evaluate operand (c) + // * convert (c) to primitive <- (this would be triggered by the second add) + // And optionally, if there is an assignment: + // * convert (d) to primitive <- (this would be triggered by the assigning addition) + // + // As such we do not plant an op to convert the leftmost child now. Instead, use + // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion + // once the second node has been generated. However, if the leftmost child is an + // immediate we can trivially determine that no conversion will be required. + // If this is the case + if (leftMostAddChild->isString()) + leftMostAddChildTempRegister = 0; + + while (reverseExpressionList.size()) { + ExpressionNode* node = reverseExpressionList.last(); + reverseExpressionList.removeLast(); + + // Emit the code for the current node. + temporaryRegisters.append(generator.newTemporary()); + generator.emitNode(temporaryRegisters.last().get(), node); + + // On the first iteration of this loop, when we first reach this point we have just + // generated the second node, which means it is time to convert the leftmost operand. + if (leftMostAddChildTempRegister) { + generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister); + leftMostAddChildTempRegister = 0; // Only do this once. + } + // Plant a conversion for this node, if necessary. + if (!node->isString()) + generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get()); + } + ASSERT(temporaryRegisters.size() >= 3); + + // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. + // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. + if (emitExpressionInfoForMe) + generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); + + // If there is an assignment convert the lhs now. This will also copy lhs to + // the temporary register we allocated for it. + if (lhs) + generator.emitToPrimitive(temporaryRegisters[0].get(), lhs); + + return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size()); +} + +RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + OpcodeID opcodeID = this->opcodeID(); + + if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) + return emitStrcat(generator, dst); + + if (opcodeID == op_neq) { + if (m_expr1->isNull() || m_expr2->isNull()) { + RefPtr<RegisterID> src = generator.tempDestination(dst); + generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); + return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get()); + } + } + + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); + return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); +} + +RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (m_expr1->isNull() || m_expr2->isNull()) { + RefPtr<RegisterID> src = generator.tempDestination(dst); + generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); + return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get()); + } + + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); + return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2); +} + +RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); + return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2); +} + +RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); + return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor())); +} + +RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RegisterID* src2 = generator.emitNode(m_expr2); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); +} + +RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); + RefPtr<RegisterID> src2 = generator.emitNode(m_expr2); + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitGetByIdExceptionInfo(op_instanceof); + RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype); + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype); +} + +// ------------------------------ LogicalOpNode ---------------------------- + +RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> temp = generator.tempDestination(dst); + RefPtr<Label> target = generator.newLabel(); + + generator.emitNode(temp.get(), m_expr1); + if (m_operator == OpLogicalAnd) + generator.emitJumpIfFalse(temp.get(), target.get()); + else + generator.emitJumpIfTrue(temp.get(), target.get()); + generator.emitNode(temp.get(), m_expr2); + generator.emitLabel(target.get()); + + return generator.moveToDestinationIfNeeded(dst, temp.get()); +} + +void LogicalOpNode::emitBytecodeInConditionContext(BytecodeGenerator& generator, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue) +{ + if (m_expr1->hasConditionContextCodegen()) { + RefPtr<Label> afterExpr1 = generator.newLabel(); + if (m_operator == OpLogicalAnd) + generator.emitNodeInConditionContext(m_expr1, afterExpr1.get(), falseTarget, true); + else + generator.emitNodeInConditionContext(m_expr1, trueTarget, afterExpr1.get(), false); + generator.emitLabel(afterExpr1.get()); + } else { + RegisterID* temp = generator.emitNode(m_expr1); + if (m_operator == OpLogicalAnd) + generator.emitJumpIfFalse(temp, falseTarget); + else + generator.emitJumpIfTrue(temp, trueTarget); + } + + if (m_expr2->hasConditionContextCodegen()) + generator.emitNodeInConditionContext(m_expr2, trueTarget, falseTarget, fallThroughMeansTrue); + else { + RegisterID* temp = generator.emitNode(m_expr2); + if (fallThroughMeansTrue) + generator.emitJumpIfFalse(temp, falseTarget); + else + generator.emitJumpIfTrue(temp, trueTarget); + } +} + +// ------------------------------ ConditionalNode ------------------------------ + +RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> newDst = generator.finalDestination(dst); + RefPtr<Label> beforeElse = generator.newLabel(); + RefPtr<Label> afterElse = generator.newLabel(); + + if (m_logical->hasConditionContextCodegen()) { + RefPtr<Label> beforeThen = generator.newLabel(); + generator.emitNodeInConditionContext(m_logical, beforeThen.get(), beforeElse.get(), true); + generator.emitLabel(beforeThen.get()); + } else { + RegisterID* cond = generator.emitNode(m_logical); + generator.emitJumpIfFalse(cond, beforeElse.get()); + } + + generator.emitNode(newDst.get(), m_expr1); + generator.emitJump(afterElse.get()); + + generator.emitLabel(beforeElse.get()); + generator.emitNode(newDst.get(), m_expr2); + + generator.emitLabel(afterElse.get()); + + return newDst.get(); +} + +// ------------------------------ ReadModifyResolveNode ----------------------------------- + +// FIXME: should this be moved to be a method on BytecodeGenerator? +static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0) +{ + OpcodeID opcodeID; + switch (oper) { + case OpMultEq: + opcodeID = op_mul; + break; + case OpDivEq: + opcodeID = op_div; + break; + case OpPlusEq: + if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString()) + return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe); + opcodeID = op_add; + break; + case OpMinusEq: + opcodeID = op_sub; + break; + case OpLShift: + opcodeID = op_lshift; + break; + case OpRShift: + opcodeID = op_rshift; + break; + case OpURShift: + opcodeID = op_urshift; + break; + case OpAndEq: + opcodeID = op_bitand; + break; + case OpXOrEq: + opcodeID = op_bitxor; + break; + case OpOrEq: + opcodeID = op_bitor; + break; + case OpModEq: + opcodeID = op_mod; + break; + default: + ASSERT_NOT_REACHED(); + return dst; + } + + RegisterID* src2 = generator.emitNode(m_right); + + // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. + // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. + if (emitExpressionInfoForMe) + generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); + + return generator.emitBinaryOp(opcodeID, dst, src1, src2, types); +} + +RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (RegisterID* local = generator.registerFor(m_ident)) { + if (generator.isLocalConstant(m_ident)) { + return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + } + + if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { + RefPtr<RegisterID> result = generator.newTemporary(); + generator.emitMove(result.get(), local); + emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + generator.emitMove(local, result.get()); + return generator.moveToDestinationIfNeeded(dst, result.get()); + } + + RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + return generator.moveToDestinationIfNeeded(dst, result); + } + + int index = 0; + size_t depth = 0; + JSObject* globalObject = 0; + if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { + RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); + RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + generator.emitPutScopedVar(depth, index, result, globalObject); + return result; + } + + RefPtr<RegisterID> src1 = generator.tempDestination(dst); + generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0); + RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident); + RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); + return generator.emitPutById(base.get(), m_ident, result); +} + +// ------------------------------ AssignResolveNode ----------------------------------- + +RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (RegisterID* local = generator.registerFor(m_ident)) { + if (generator.isLocalConstant(m_ident)) + return generator.emitNode(dst, m_right); + + RegisterID* result = generator.emitNode(local, m_right); + return generator.moveToDestinationIfNeeded(dst, result); + } + + int index = 0; + size_t depth = 0; + JSObject* globalObject = 0; + if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { + if (dst == generator.ignoredResult()) + dst = 0; + RegisterID* value = generator.emitNode(dst, m_right); + generator.emitPutScopedVar(depth, index, value, globalObject); + return value; + } + + RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); + if (dst == generator.ignoredResult()) + dst = 0; + RegisterID* value = generator.emitNode(dst, m_right); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + return generator.emitPutById(base.get(), m_ident, value); +} + +// ------------------------------ AssignDotNode ----------------------------------- + +RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); + RegisterID* result = generator.emitNode(value.get(), m_right); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitPutById(base.get(), m_ident, result); + return generator.moveToDestinationIfNeeded(dst, result); +} + +// ------------------------------ ReadModifyDotNode ----------------------------------- + +RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); + + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); + RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + return generator.emitPutById(base.get(), m_ident, updatedValue); +} + +// ------------------------------ AssignErrorNode ----------------------------------- + +RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference."); +} + +// ------------------------------ AssignBracketNode ----------------------------------- + +RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); + RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); + RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); + RegisterID* result = generator.emitNode(value.get(), m_right); + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitPutByVal(base.get(), property.get(), result); + return generator.moveToDestinationIfNeeded(dst, result); +} + +// ------------------------------ ReadModifyBracketNode ----------------------------------- + +RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); + RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); + + generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); + RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); + RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitPutByVal(base.get(), property.get(), updatedValue); + + return updatedValue; +} + +// ------------------------------ CommaNode ------------------------------------ + +RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + ASSERT(m_expressions.size() > 1); + for (size_t i = 0; i < m_expressions.size() - 1; i++) + generator.emitNode(generator.ignoredResult(), m_expressions[i]); + return generator.emitNode(dst, m_expressions.last()); +} + +// ------------------------------ ConstDeclNode ------------------------------------ + +RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) +{ + if (RegisterID* local = generator.constRegisterFor(m_ident)) { + if (!m_init) + return local; + + return generator.emitNode(local, m_init); + } + + if (generator.codeType() != EvalCode) { + if (m_init) + return generator.emitNode(m_init); + else + return generator.emitResolve(generator.newTemporary(), m_ident); + } + // FIXME: While this code should only be hit in eval code, it will potentially + // assign to the wrong base if m_ident exists in an intervening dynamic scope. + RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); + RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined()); + return generator.emitPutById(base.get(), m_ident, value); +} + +RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + RegisterID* result = 0; + for (ConstDeclNode* n = this; n; n = n->m_next) + result = n->emitCodeSingle(generator); + + return result; +} + +// ------------------------------ ConstStatementNode ----------------------------- + +RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + return generator.emitNode(m_next); +} + +// ------------------------------ SourceElements ------------------------------- + + +inline StatementNode* SourceElements::lastStatement() const +{ + size_t size = m_statements.size(); + return size ? m_statements[size - 1] : 0; +} + +inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + size_t size = m_statements.size(); + for (size_t i = 0; i < size; ++i) + generator.emitNode(dst, m_statements[i]); +} + +// ------------------------------ BlockNode ------------------------------------ + +inline StatementNode* BlockNode::lastStatement() const +{ + return m_statements ? m_statements->lastStatement() : 0; +} + +RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (m_statements) + m_statements->emitBytecode(generator, dst); + return 0; +} + +// ------------------------------ EmptyStatementNode --------------------------- + +RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + return dst; +} + +// ------------------------------ DebuggerStatementNode --------------------------- + +RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine()); + return dst; +} + +// ------------------------------ ExprStatementNode ---------------------------- + +RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + ASSERT(m_expr); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + return generator.emitNode(dst, m_expr); +} + +// ------------------------------ VarStatementNode ---------------------------- + +RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + ASSERT(m_expr); + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + return generator.emitNode(m_expr); +} + +// ------------------------------ IfNode --------------------------------------- + +RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + RefPtr<Label> afterThen = generator.newLabel(); + + if (m_condition->hasConditionContextCodegen()) { + RefPtr<Label> beforeThen = generator.newLabel(); + generator.emitNodeInConditionContext(m_condition, beforeThen.get(), afterThen.get(), true); + generator.emitLabel(beforeThen.get()); + } else { + RegisterID* cond = generator.emitNode(m_condition); + generator.emitJumpIfFalse(cond, afterThen.get()); + } + + generator.emitNode(dst, m_ifBlock); + generator.emitLabel(afterThen.get()); + + // FIXME: This should return the last statement executed so that it can be returned as a Completion. + return 0; +} + +// ------------------------------ IfElseNode --------------------------------------- + +RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + RefPtr<Label> beforeElse = generator.newLabel(); + RefPtr<Label> afterElse = generator.newLabel(); + + if (m_condition->hasConditionContextCodegen()) { + RefPtr<Label> beforeThen = generator.newLabel(); + generator.emitNodeInConditionContext(m_condition, beforeThen.get(), beforeElse.get(), true); + generator.emitLabel(beforeThen.get()); + } else { + RegisterID* cond = generator.emitNode(m_condition); + generator.emitJumpIfFalse(cond, beforeElse.get()); + } + + generator.emitNode(dst, m_ifBlock); + generator.emitJump(afterElse.get()); + + generator.emitLabel(beforeElse.get()); + + generator.emitNode(dst, m_elseBlock); + + generator.emitLabel(afterElse.get()); + + // FIXME: This should return the last statement executed so that it can be returned as a Completion. + return 0; +} + +// ------------------------------ DoWhileNode ---------------------------------- + +RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); + + RefPtr<Label> topOfLoop = generator.newLabel(); + generator.emitLabel(topOfLoop.get()); + + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); + + generator.emitLabel(scope->continueTarget()); +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); +#endif + if (m_expr->hasConditionContextCodegen()) + generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false); + else { + RegisterID* cond = generator.emitNode(m_expr); + generator.emitJumpIfTrue(cond, topOfLoop.get()); + } + + generator.emitLabel(scope->breakTarget()); + return result.get(); +} + +// ------------------------------ WhileNode ------------------------------------ + +RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); + +#ifdef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); +#endif + generator.emitJump(scope->continueTarget()); + + RefPtr<Label> topOfLoop = generator.newLabel(); + generator.emitLabel(topOfLoop.get()); + + generator.emitNode(dst, m_statement); + + generator.emitLabel(scope->continueTarget()); +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo()); +#endif + + if (m_expr->hasConditionContextCodegen()) + generator.emitNodeInConditionContext(m_expr, topOfLoop.get(), scope->breakTarget(), false); + else { + RegisterID* cond = generator.emitNode(m_expr); + generator.emitJumpIfTrue(cond, topOfLoop.get()); + } + + generator.emitLabel(scope->breakTarget()); + + // FIXME: This should return the last statement executed so that it can be returned as a Completion + return 0; +} + +// ------------------------------ ForNode -------------------------------------- + +RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); + + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + if (m_expr1) + generator.emitNode(generator.ignoredResult(), m_expr1); + + RefPtr<Label> condition = generator.newLabel(); + generator.emitJump(condition.get()); + + RefPtr<Label> topOfLoop = generator.newLabel(); + generator.emitLabel(topOfLoop.get()); + + RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); + + generator.emitLabel(scope->continueTarget()); +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); +#endif + if (m_expr3) + generator.emitNode(generator.ignoredResult(), m_expr3); + + generator.emitLabel(condition.get()); + if (m_expr2) { + if (m_expr2->hasConditionContextCodegen()) + generator.emitNodeInConditionContext(m_expr2, topOfLoop.get(), scope->breakTarget(), false); + else { + RegisterID* cond = generator.emitNode(m_expr2); + generator.emitJumpIfTrue(cond, topOfLoop.get()); + } + } else + generator.emitJump(topOfLoop.get()); + + generator.emitLabel(scope->breakTarget()); + return result.get(); +} + +// ------------------------------ ForInNode ------------------------------------ + +RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); + + if (!m_lexpr->isLocation()) + return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference."); + + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + if (m_init) + generator.emitNode(generator.ignoredResult(), m_init); + + RefPtr<RegisterID> base = generator.newTemporary(); + generator.emitNode(base.get(), m_expr); + RefPtr<RegisterID> i = generator.newTemporary(); + RefPtr<RegisterID> size = generator.newTemporary(); + RefPtr<RegisterID> expectedSubscript; + RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget()); + generator.emitJump(scope->continueTarget()); + + RefPtr<Label> loopStart = generator.newLabel(); + generator.emitLabel(loopStart.get()); + + RegisterID* propertyName; + bool optimizedForinAccess = false; + if (m_lexpr->isResolveNode()) { + const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); + propertyName = generator.registerFor(ident); + if (!propertyName) { + propertyName = generator.newTemporary(); + RefPtr<RegisterID> protect = propertyName; + RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident); + + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitPutById(base, ident, propertyName); + } else { + expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName); + generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName); + optimizedForinAccess = true; + } + } else if (m_lexpr->isDotAccessorNode()) { + DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr); + const Identifier& ident = assignNode->identifier(); + propertyName = generator.newTemporary(); + RefPtr<RegisterID> protect = propertyName; + RegisterID* base = generator.emitNode(assignNode->base()); + + generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset()); + generator.emitPutById(base, ident, propertyName); + } else { + ASSERT(m_lexpr->isBracketAccessorNode()); + BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr); + propertyName = generator.newTemporary(); + RefPtr<RegisterID> protect = propertyName; + RefPtr<RegisterID> base = generator.emitNode(assignNode->base()); + RegisterID* subscript = generator.emitNode(assignNode->subscript()); + + generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset()); + generator.emitPutByVal(base.get(), subscript, propertyName); + } + + generator.emitNode(dst, m_statement); + + if (optimizedForinAccess) + generator.popOptimisedForIn(); + + generator.emitLabel(scope->continueTarget()); + generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get()); +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); +#endif + generator.emitLabel(scope->breakTarget()); + return dst; +} + +// ------------------------------ ContinueNode --------------------------------- + +// ECMA 12.7 +RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + LabelScope* scope = generator.continueTarget(m_ident); + + if (!scope) + return m_ident.isEmpty() + ? emitThrowError(generator, SyntaxError, "Invalid continue statement.") + : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident); + + generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth()); + return dst; +} + +// ------------------------------ BreakNode ------------------------------------ + +// ECMA 12.8 +RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + LabelScope* scope = generator.breakTarget(m_ident); + + if (!scope) + return m_ident.isEmpty() + ? emitThrowError(generator, SyntaxError, "Invalid break statement.") + : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident); + + generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth()); + return dst; +} + +// ------------------------------ ReturnNode ----------------------------------- + +RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + if (generator.codeType() != FunctionCode) + return emitThrowError(generator, SyntaxError, "Invalid return statement."); + + if (dst == generator.ignoredResult()) + dst = 0; + RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined()); + RefPtr<RegisterID> returnRegister; + if (generator.scopeDepth()) { + RefPtr<Label> l0 = generator.newLabel(); + if (generator.hasFinaliser() && !r0->isTemporary()) { + returnRegister = generator.emitMove(generator.newTemporary(), r0); + r0 = returnRegister.get(); + } + generator.emitJumpScopes(l0.get(), 0); + generator.emitLabel(l0.get()); + } + generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); + return generator.emitReturn(r0); +} + +// ------------------------------ WithNode ------------------------------------- + +RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + RefPtr<RegisterID> scope = generator.newTemporary(); + generator.emitNode(scope.get(), m_expr); // scope must be protected until popped + generator.emitExpressionInfo(m_divot, m_expressionLength, 0); + generator.emitPushScope(scope.get()); + RegisterID* result = generator.emitNode(dst, m_statement); + generator.emitPopScope(); + return result; +} + +// ------------------------------ CaseClauseNode -------------------------------- + +inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (m_statements) + m_statements->emitBytecode(generator, dst); +} + +// ------------------------------ CaseBlockNode -------------------------------- + +enum SwitchKind { + SwitchUnset = 0, + SwitchNumber = 1, + SwitchString = 2, + SwitchNeither = 3 +}; + +static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num) +{ + for (; list; list = list->getNext()) { + ExpressionNode* clauseExpression = list->getClause()->expr(); + literalVector.append(clauseExpression); + if (clauseExpression->isNumber()) { + double value = static_cast<NumberNode*>(clauseExpression)->value(); + int32_t intVal = static_cast<int32_t>(value); + if ((typeForTable & ~SwitchNumber) || (intVal != value)) { + typeForTable = SwitchNeither; + break; + } + if (intVal < min_num) + min_num = intVal; + if (intVal > max_num) + max_num = intVal; + typeForTable = SwitchNumber; + continue; + } + if (clauseExpression->isString()) { + if (typeForTable & ~SwitchString) { + typeForTable = SwitchNeither; + break; + } + const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring(); + if (singleCharacterSwitch &= value.size() == 1) { + int32_t intVal = value.rep()->data()[0]; + if (intVal < min_num) + min_num = intVal; + if (intVal > max_num) + max_num = intVal; + } + typeForTable = SwitchString; + continue; + } + typeForTable = SwitchNeither; + break; + } +} + +SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num) +{ + SwitchKind typeForTable = SwitchUnset; + bool singleCharacterSwitch = true; + + processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); + processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); + + if (typeForTable == SwitchUnset || typeForTable == SwitchNeither) + return SwitchInfo::SwitchNone; + + if (typeForTable == SwitchNumber) { + int32_t range = max_num - min_num; + if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) + return SwitchInfo::SwitchImmediate; + return SwitchInfo::SwitchNone; + } + + ASSERT(typeForTable == SwitchString); + + if (singleCharacterSwitch) { + int32_t range = max_num - min_num; + if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) + return SwitchInfo::SwitchCharacter; + } + + return SwitchInfo::SwitchString; +} + +RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst) +{ + RefPtr<Label> defaultLabel; + Vector<RefPtr<Label>, 8> labelVector; + Vector<ExpressionNode*, 8> literalVector; + int32_t min_num = std::numeric_limits<int32_t>::max(); + int32_t max_num = std::numeric_limits<int32_t>::min(); + SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num); + + if (switchType != SwitchInfo::SwitchNone) { + // Prepare the various labels + for (uint32_t i = 0; i < literalVector.size(); i++) + labelVector.append(generator.newLabel()); + defaultLabel = generator.newLabel(); + generator.beginSwitch(switchExpression, switchType); + } else { + // Setup jumps + for (ClauseListNode* list = m_list1; list; list = list->getNext()) { + RefPtr<RegisterID> clauseVal = generator.newTemporary(); + generator.emitNode(clauseVal.get(), list->getClause()->expr()); + generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); + labelVector.append(generator.newLabel()); + generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); + } + + for (ClauseListNode* list = m_list2; list; list = list->getNext()) { + RefPtr<RegisterID> clauseVal = generator.newTemporary(); + generator.emitNode(clauseVal.get(), list->getClause()->expr()); + generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); + labelVector.append(generator.newLabel()); + generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); + } + defaultLabel = generator.newLabel(); + generator.emitJump(defaultLabel.get()); + } + + RegisterID* result = 0; + + size_t i = 0; + for (ClauseListNode* list = m_list1; list; list = list->getNext()) { + generator.emitLabel(labelVector[i++].get()); + list->getClause()->emitBytecode(generator, dst); + } + + if (m_defaultClause) { + generator.emitLabel(defaultLabel.get()); + m_defaultClause->emitBytecode(generator, dst); + } + + for (ClauseListNode* list = m_list2; list; list = list->getNext()) { + generator.emitLabel(labelVector[i++].get()); + list->getClause()->emitBytecode(generator, dst); + } + if (!m_defaultClause) + generator.emitLabel(defaultLabel.get()); + + ASSERT(i == labelVector.size()); + if (switchType != SwitchInfo::SwitchNone) { + ASSERT(labelVector.size() == literalVector.size()); + generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num); + } + return result; +} + +// ------------------------------ SwitchNode ----------------------------------- + +RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch); + + RefPtr<RegisterID> r0 = generator.emitNode(m_expr); + RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst); + + generator.emitLabel(scope->breakTarget()); + return r1; +} + +// ------------------------------ LabelNode ------------------------------------ + +RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + if (generator.breakTarget(m_name)) + return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name); + + RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name); + RegisterID* r0 = generator.emitNode(dst, m_statement); + + generator.emitLabel(scope->breakTarget()); + return r0; +} + +// ------------------------------ ThrowNode ------------------------------------ + +RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); + + if (dst == generator.ignoredResult()) + dst = 0; + RefPtr<RegisterID> expr = generator.emitNode(m_expr); + generator.emitExpressionInfo(divot(), startOffset(), endOffset()); + generator.emitThrow(expr.get()); + return 0; +} + +// ------------------------------ TryNode -------------------------------------- + +RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + // NOTE: The catch and finally blocks must be labeled explicitly, so the + // optimizer knows they may be jumped to from anywhere. + +#ifndef QT_BUILD_SCRIPT_LIB + generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); +#endif + + RefPtr<Label> tryStartLabel = generator.newLabel(); + RefPtr<Label> finallyStart; + RefPtr<RegisterID> finallyReturnAddr; + if (m_finallyBlock) { + finallyStart = generator.newLabel(); + finallyReturnAddr = generator.newTemporary(); + generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get()); + } + + generator.emitLabel(tryStartLabel.get()); + generator.emitNode(dst, m_tryBlock); + + if (m_catchBlock) { + RefPtr<Label> catchEndLabel = generator.newLabel(); + + // Normal path: jump over the catch block. + generator.emitJump(catchEndLabel.get()); + + // Uncaught exception path: the catch block. + RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); + RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get()); + if (m_catchHasEval) { + RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary()); + generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get()); + generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get()); + generator.emitPushScope(exceptionRegister.get()); + } else + generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); + generator.emitNode(dst, m_catchBlock); + generator.emitPopScope(); + generator.emitLabel(catchEndLabel.get()); + } + + if (m_finallyBlock) { + generator.popFinallyContext(); + // there may be important registers live at the time we jump + // to a finally block (such as for a return or throw) so we + // ref the highest register ever used as a conservative + // approach to not clobbering anything important + RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister(); + RefPtr<Label> finallyEndLabel = generator.newLabel(); + + // Normal path: invoke the finally block, then jump over it. + generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); + generator.emitJump(finallyEndLabel.get()); + + // Uncaught exception path: invoke the finally block, then re-throw the exception. + RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); + RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get()); + generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); + generator.emitThrow(tempExceptionRegister.get()); + + // The finally block. + generator.emitLabel(finallyStart.get()); + generator.emitNode(dst, m_finallyBlock); + generator.emitSubroutineReturn(finallyReturnAddr.get()); + + generator.emitLabel(finallyEndLabel.get()); + } + + return dst; +} + +// ------------------------------ ScopeNode ----------------------------- + +inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (m_data->m_statements) + m_data->m_statements->emitBytecode(generator, dst); +} + +// ------------------------------ ProgramNode ----------------------------- + +RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); + + RefPtr<RegisterID> dstRegister = generator.newTemporary(); + generator.emitLoad(dstRegister.get(), jsUndefined()); + emitStatementsBytecode(generator, dstRegister.get()); + + generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); + generator.emitEnd(dstRegister.get()); + return 0; +} + +// ------------------------------ EvalNode ----------------------------- + +RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine()); + + RefPtr<RegisterID> dstRegister = generator.newTemporary(); + generator.emitLoad(dstRegister.get(), jsUndefined()); + emitStatementsBytecode(generator, dstRegister.get()); + + generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine()); + generator.emitEnd(dstRegister.get()); + return 0; +} + +// ------------------------------ FunctionBodyNode ----------------------------- + +RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) +{ + generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine()); + emitStatementsBytecode(generator, generator.ignoredResult()); + StatementNode* singleStatement = this->singleStatement(); + if (singleStatement && singleStatement->isBlock()) { + StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement(); + if (lastStatementInBlock && lastStatementInBlock->isReturnNode()) + return 0; + } + + RegisterID* r0 = generator.emitLoad(0, jsUndefined()); + generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine()); + generator.emitReturn(r0); + return 0; +} + +// ------------------------------ FuncDeclNode --------------------------------- + +RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + if (dst == generator.ignoredResult()) + dst = 0; + return dst; +} + +// ------------------------------ FuncExprNode --------------------------------- + +RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) +{ + return generator.emitNewFunctionExpression(generator.finalDestination(dst), this); +} + +} // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/config.h b/src/3rdparty/javascriptcore/JavaScriptCore/config.h index 5e70265..d5fdfe9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/config.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/config.h @@ -25,26 +25,26 @@ #include <wtf/Platform.h> -#if !defined(JS_EXPORTDATA) -#if PLATFORM(WIN_OS) && !defined(BUILDING_WX__) && !COMPILER(GCC) +#if OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC) #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) #define JS_EXPORTDATA __declspec(dllexport) #else #define JS_EXPORTDATA __declspec(dllimport) #endif +#define JS_EXPORTCLASS JS_EXPORTDATA #else #define JS_EXPORTDATA -#endif +#define JS_EXPORTCLASS #endif -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) // If we don't define these, they get defined in windef.h. // We want to use std::min and std::max #define max max #define min min -#if !COMPILER(MSVC7) && !PLATFORM(WINCE) +#if !COMPILER(MSVC7) && !OS(WINCE) // We need to define this before the first #include of stdlib.h or it won't contain rand_s. #ifndef _CRT_RAND_S #define _CRT_RAND_S @@ -53,13 +53,12 @@ #endif -#if PLATFORM(FREEBSD) || PLATFORM(OPENBSD) +#if OS(FREEBSD) || OS(OPENBSD) #define HAVE_PTHREAD_NP_H 1 #endif /* FIXME: if all platforms have these, do they really need #defines? */ #define HAVE_STDINT_H 1 -#define HAVE_STRING_H 1 #define WTF_CHANGES 1 @@ -76,3 +75,15 @@ #include <wtf/DisallowCType.h> #endif +#if PLATFORM(CHROMIUM) +#if !defined(WTF_USE_V8) +#define WTF_USE_V8 1 +#endif +#endif /* PLATFORM(CHROMIUM) */ + +#if !defined(WTF_USE_V8) +#define WTF_USE_V8 0 +#endif /* !defined(WTF_USE_V8) */ + +/* Using V8 implies not using JSC and vice versa */ +#define WTF_USE_JSC !WTF_USE_V8 diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/Debugger.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/Debugger.cpp index db02329..1d2e4fb 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/Debugger.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/Debugger.cpp @@ -67,8 +67,9 @@ void Debugger::recompileAllJSFunctions(JSGlobalData* globalData) FunctionExecutableSet functionExecutables; SourceProviderMap sourceProviders; - Heap::iterator heapEnd = globalData->heap.primaryHeapEnd(); - for (Heap::iterator it = globalData->heap.primaryHeapBegin(); it != heapEnd; ++it) { + LiveObjectIterator it = globalData->heap.primaryHeapBegin(); + LiveObjectIterator heapEnd = globalData->heap.primaryHeapEnd(); + for ( ; it != heapEnd; ++it) { if (!(*it)->inherits(&JSFunction::info)) continue; @@ -100,12 +101,12 @@ JSValue evaluateInGlobalCallFrame(const UString& script, JSValue& exception, JSG { CallFrame* globalCallFrame = globalObject->globalExec(); - EvalExecutable eval(globalCallFrame, makeSource(script)); - JSObject* error = eval.compile(globalCallFrame, globalCallFrame->scopeChain()); + RefPtr<EvalExecutable> eval = EvalExecutable::create(globalCallFrame, makeSource(script)); + JSObject* error = eval->compile(globalCallFrame, globalCallFrame->scopeChain()); if (error) return error; - return globalObject->globalData()->interpreter->execute(&eval, globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception); + return globalObject->globalData()->interpreter->execute(eval.get(), globalCallFrame, globalObject, globalCallFrame->scopeChain(), &exception); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/Debugger.h b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/Debugger.h index 811818d..3725478 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/Debugger.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/Debugger.h @@ -47,8 +47,7 @@ namespace JSC { { UNUSED_PARAM(id); }; - virtual void scriptLoad(QT_PREPEND_NAMESPACE(qint64) id, - const UString &program, + virtual void scriptLoad(QT_PREPEND_NAMESPACE(qint64) id, const UString &program, const UString &fileName, int baseLineNumber) { UNUSED_PARAM(id); @@ -90,14 +89,14 @@ namespace JSC { #endif virtual void sourceParsed(ExecState*, const SourceCode&, int errorLineNumber, const UString& errorMessage) = 0; - virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; - virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber, int column) = 0; + virtual void exception(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber, bool hasHandler) = 0; + virtual void atStatement(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; virtual void callEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; virtual void returnEvent(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; virtual void willExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; virtual void didExecuteProgram(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; - virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber, int column) = 0; + virtual void didReachBreakpoint(const DebuggerCallFrame&, intptr_t sourceID, int lineNumber) = 0; void recompileAllJSFunctions(JSGlobalData*); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerActivation.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerActivation.cpp index fa41374..0444d23 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerActivation.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerActivation.cpp @@ -66,19 +66,19 @@ void DebuggerActivation::putWithAttributes(ExecState* exec, const Identifier& pr m_activation->putWithAttributes(exec, propertyName, value, attributes); } -bool DebuggerActivation::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) +bool DebuggerActivation::deleteProperty(ExecState* exec, const Identifier& propertyName) { - return m_activation->deleteProperty(exec, propertyName, checkDontDelete); + return m_activation->deleteProperty(exec, propertyName); } -void DebuggerActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) +void DebuggerActivation::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - m_activation->getPropertyNames(exec, propertyNames); + m_activation->getPropertyNames(exec, propertyNames, mode); } -bool DebuggerActivation::getPropertyAttributes(JSC::ExecState* exec, const Identifier& propertyName, unsigned& attributes) const +bool DebuggerActivation::getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { - return m_activation->getPropertyAttributes(exec, propertyName, attributes); + return m_activation->getOwnPropertyDescriptor(exec, propertyName, descriptor); } void DebuggerActivation::defineGetter(ExecState* exec, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerActivation.h b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerActivation.h index 9bb1acd..354fcb8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerActivation.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerActivation.h @@ -41,9 +41,9 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void putWithAttributes(ExecState*, const Identifier& propertyName, JSValue, unsigned attributes); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); - virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); - virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); + virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void defineGetter(ExecState*, const Identifier& propertyName, JSObject* getterFunction, unsigned attributes); virtual void defineSetter(ExecState*, const Identifier& propertyName, JSObject* setterFunction, unsigned attributes); virtual JSValue lookupGetter(ExecState*, const Identifier& propertyName); @@ -51,9 +51,12 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultGetPropertyNames)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | JSObject::StructureFlags; + private: JSActivation* m_activation; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerCallFrame.cpp index 88b14e6..c6b4223 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerCallFrame.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/debugger/DebuggerCallFrame.cpp @@ -44,7 +44,7 @@ const UString* DebuggerCallFrame::functionName() const JSFunction* function = asFunction(m_callFrame->callee()); if (!function) return 0; - return &function->name(&m_callFrame->globalData()); + return &function->name(m_callFrame); } UString DebuggerCallFrame::calculatedFunctionName() const @@ -55,7 +55,7 @@ UString DebuggerCallFrame::calculatedFunctionName() const JSFunction* function = asFunction(m_callFrame->callee()); if (!function) return 0; - return function->calculatedDisplayName(&m_callFrame->globalData()); + return function->calculatedDisplayName(m_callFrame); } DebuggerCallFrame::Type DebuggerCallFrame::type() const @@ -79,12 +79,12 @@ JSValue DebuggerCallFrame::evaluate(const UString& script, JSValue& exception) c if (!m_callFrame->codeBlock()) return JSValue(); - EvalExecutable eval(m_callFrame, makeSource(script)); - JSObject* error = eval.compile(m_callFrame, m_callFrame->scopeChain()); + RefPtr<EvalExecutable> eval = EvalExecutable::create(m_callFrame, makeSource(script)); + JSObject* error = eval->compile(m_callFrame, m_callFrame->scopeChain()); if (error) return error; - return m_callFrame->scopeChain()->globalData->interpreter->execute(&eval, m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception); + return m_callFrame->scopeChain()->globalData->interpreter->execute(eval.get(), m_callFrame, thisObject(), m_callFrame->scopeChain(), &exception); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/ArrayPrototype.lut.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/ArrayPrototype.lut.h index 5732add..860176e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/ArrayPrototype.lut.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/ArrayPrototype.lut.h @@ -1,4 +1,4 @@ -// Automatically generated from ../runtime/ArrayPrototype.cpp using JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from runtime/ArrayPrototype.cpp using /home/khansen/dev/qtwebkit-qtscript-integration/JavaScriptCore/create_hash_table. DO NOT EDIT! #include "Lookup.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/DatePrototype.lut.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/DatePrototype.lut.h index 8b1c735..395669a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/DatePrototype.lut.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/DatePrototype.lut.h @@ -1,4 +1,4 @@ -// Automatically generated from ../runtime/DatePrototype.cpp using JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from runtime/DatePrototype.cpp using /home/khansen/dev/qtwebkit-qtscript-integration/JavaScriptCore/create_hash_table. DO NOT EDIT! #include "Lookup.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/GeneratedJITStubs_RVCT.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/GeneratedJITStubs_RVCT.h new file mode 100644 index 0000000..ef77e19 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/GeneratedJITStubs_RVCT.h @@ -0,0 +1,1199 @@ +extern "C" EncodedJSValue JITStubThunked_op_convert_this(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_convert_this(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_convert_this + str lr, [sp, #32] + bl JITStubThunked_op_convert_this + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_end(STUB_ARGS_DECLARATION); +__asm void cti_op_end(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_end + str lr, [sp, #32] + bl JITStubThunked_op_end + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_add(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_add(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_add + str lr, [sp, #32] + bl JITStubThunked_op_add + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_pre_inc(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_pre_inc(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_pre_inc + str lr, [sp, #32] + bl JITStubThunked_op_pre_inc + ldr lr, [sp, #32] + bx lr +} + +extern "C" int JITStubThunked_timeout_check(STUB_ARGS_DECLARATION); +__asm int cti_timeout_check(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_timeout_check + str lr, [sp, #32] + bl JITStubThunked_timeout_check + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_register_file_check(STUB_ARGS_DECLARATION); +__asm void cti_register_file_check(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_register_file_check + str lr, [sp, #32] + bl JITStubThunked_register_file_check + ldr lr, [sp, #32] + bx lr +} + +extern "C" int JITStubThunked_op_loop_if_lesseq(STUB_ARGS_DECLARATION); +__asm int cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_loop_if_lesseq + str lr, [sp, #32] + bl JITStubThunked_op_loop_if_lesseq + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_new_object(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_new_object(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_new_object + str lr, [sp, #32] + bl JITStubThunked_op_new_object + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_put_by_id_generic(STUB_ARGS_DECLARATION); +__asm void cti_op_put_by_id_generic(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_put_by_id_generic + str lr, [sp, #32] + bl JITStubThunked_op_put_by_id_generic + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_id_generic(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_id_generic(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_id_generic + str lr, [sp, #32] + bl JITStubThunked_op_get_by_id_generic + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_put_by_id(STUB_ARGS_DECLARATION); +__asm void cti_op_put_by_id(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_put_by_id + str lr, [sp, #32] + bl JITStubThunked_op_put_by_id + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_put_by_id_fail(STUB_ARGS_DECLARATION); +__asm void cti_op_put_by_id_fail(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_put_by_id_fail + str lr, [sp, #32] + bl JITStubThunked_op_put_by_id_fail + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_put_by_id_transition_realloc(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_put_by_id_transition_realloc(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_put_by_id_transition_realloc + str lr, [sp, #32] + bl JITStubThunked_op_put_by_id_transition_realloc + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_id_method_check(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_id_method_check + str lr, [sp, #32] + bl JITStubThunked_op_get_by_id_method_check + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_id(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_id(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_id + str lr, [sp, #32] + bl JITStubThunked_op_get_by_id + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_id_self_fail(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_id_self_fail + str lr, [sp, #32] + bl JITStubThunked_op_get_by_id_self_fail + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_id_proto_list(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_id_proto_list + str lr, [sp, #32] + bl JITStubThunked_op_get_by_id_proto_list + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_id_proto_list_full + str lr, [sp, #32] + bl JITStubThunked_op_get_by_id_proto_list_full + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_id_proto_fail + str lr, [sp, #32] + bl JITStubThunked_op_get_by_id_proto_fail + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_id_array_fail(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_id_array_fail + str lr, [sp, #32] + bl JITStubThunked_op_get_by_id_array_fail + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_id_string_fail(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_id_string_fail + str lr, [sp, #32] + bl JITStubThunked_op_get_by_id_string_fail + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_instanceof(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_instanceof(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_instanceof + str lr, [sp, #32] + bl JITStubThunked_op_instanceof + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_del_by_id(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_del_by_id(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_del_by_id + str lr, [sp, #32] + bl JITStubThunked_op_del_by_id + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_mul(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_mul(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_mul + str lr, [sp, #32] + bl JITStubThunked_op_mul + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_new_func(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_new_func(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_new_func + str lr, [sp, #32] + bl JITStubThunked_op_new_func + ldr lr, [sp, #32] + bx lr +} + +extern "C" void* JITStubThunked_op_call_JSFunction(STUB_ARGS_DECLARATION); +__asm void* cti_op_call_JSFunction(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_call_JSFunction + str lr, [sp, #32] + bl JITStubThunked_op_call_JSFunction + ldr lr, [sp, #32] + bx lr +} + +extern "C" VoidPtrPair JITStubThunked_op_call_arityCheck(STUB_ARGS_DECLARATION); +__asm VoidPtrPair cti_op_call_arityCheck(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_call_arityCheck + str lr, [sp, #32] + bl JITStubThunked_op_call_arityCheck + ldr lr, [sp, #32] + bx lr +} + +extern "C" void* JITStubThunked_vm_lazyLinkCall(STUB_ARGS_DECLARATION); +__asm void* cti_vm_lazyLinkCall(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_vm_lazyLinkCall + str lr, [sp, #32] + bl JITStubThunked_vm_lazyLinkCall + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_push_activation(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_push_activation(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_push_activation + str lr, [sp, #32] + bl JITStubThunked_op_push_activation + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_call_NotJSFunction(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_call_NotJSFunction(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_call_NotJSFunction + str lr, [sp, #32] + bl JITStubThunked_op_call_NotJSFunction + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_create_arguments(STUB_ARGS_DECLARATION); +__asm void cti_op_create_arguments(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_create_arguments + str lr, [sp, #32] + bl JITStubThunked_op_create_arguments + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_create_arguments_no_params(STUB_ARGS_DECLARATION); +__asm void cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_create_arguments_no_params + str lr, [sp, #32] + bl JITStubThunked_op_create_arguments_no_params + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_tear_off_activation(STUB_ARGS_DECLARATION); +__asm void cti_op_tear_off_activation(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_tear_off_activation + str lr, [sp, #32] + bl JITStubThunked_op_tear_off_activation + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_tear_off_arguments(STUB_ARGS_DECLARATION); +__asm void cti_op_tear_off_arguments(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_tear_off_arguments + str lr, [sp, #32] + bl JITStubThunked_op_tear_off_arguments + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_profile_will_call(STUB_ARGS_DECLARATION); +__asm void cti_op_profile_will_call(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_profile_will_call + str lr, [sp, #32] + bl JITStubThunked_op_profile_will_call + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_profile_did_call(STUB_ARGS_DECLARATION); +__asm void cti_op_profile_did_call(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_profile_did_call + str lr, [sp, #32] + bl JITStubThunked_op_profile_did_call + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_ret_scopeChain(STUB_ARGS_DECLARATION); +__asm void cti_op_ret_scopeChain(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_ret_scopeChain + str lr, [sp, #32] + bl JITStubThunked_op_ret_scopeChain + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_new_array(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_new_array(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_new_array + str lr, [sp, #32] + bl JITStubThunked_op_new_array + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_resolve(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_resolve(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_resolve + str lr, [sp, #32] + bl JITStubThunked_op_resolve + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_construct_JSConstruct(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_construct_JSConstruct(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_construct_JSConstruct + str lr, [sp, #32] + bl JITStubThunked_op_construct_JSConstruct + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_construct_NotJSConstruct(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_construct_NotJSConstruct + str lr, [sp, #32] + bl JITStubThunked_op_construct_NotJSConstruct + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_val(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_val(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_val + str lr, [sp, #32] + bl JITStubThunked_op_get_by_val + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_val_string(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_val_string(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_val_string + str lr, [sp, #32] + bl JITStubThunked_op_get_by_val_string + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_get_by_val_byte_array(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_get_by_val_byte_array(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_by_val_byte_array + str lr, [sp, #32] + bl JITStubThunked_op_get_by_val_byte_array + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_sub(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_sub(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_sub + str lr, [sp, #32] + bl JITStubThunked_op_sub + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_put_by_val(STUB_ARGS_DECLARATION); +__asm void cti_op_put_by_val(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_put_by_val + str lr, [sp, #32] + bl JITStubThunked_op_put_by_val + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_put_by_val_byte_array(STUB_ARGS_DECLARATION); +__asm void cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_put_by_val_byte_array + str lr, [sp, #32] + bl JITStubThunked_op_put_by_val_byte_array + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_lesseq(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_lesseq(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_lesseq + str lr, [sp, #32] + bl JITStubThunked_op_lesseq + ldr lr, [sp, #32] + bx lr +} + +extern "C" int JITStubThunked_op_load_varargs(STUB_ARGS_DECLARATION); +__asm int cti_op_load_varargs(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_load_varargs + str lr, [sp, #32] + bl JITStubThunked_op_load_varargs + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_negate(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_negate(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_negate + str lr, [sp, #32] + bl JITStubThunked_op_negate + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_resolve_base(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_resolve_base(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_resolve_base + str lr, [sp, #32] + bl JITStubThunked_op_resolve_base + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_resolve_skip(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_resolve_skip(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_resolve_skip + str lr, [sp, #32] + bl JITStubThunked_op_resolve_skip + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_resolve_global(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_resolve_global(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_resolve_global + str lr, [sp, #32] + bl JITStubThunked_op_resolve_global + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_div(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_div(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_div + str lr, [sp, #32] + bl JITStubThunked_op_div + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_pre_dec(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_pre_dec(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_pre_dec + str lr, [sp, #32] + bl JITStubThunked_op_pre_dec + ldr lr, [sp, #32] + bx lr +} + +extern "C" int JITStubThunked_op_jless(STUB_ARGS_DECLARATION); +__asm int cti_op_jless(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_jless + str lr, [sp, #32] + bl JITStubThunked_op_jless + ldr lr, [sp, #32] + bx lr +} + +extern "C" int JITStubThunked_op_jlesseq(STUB_ARGS_DECLARATION); +__asm int cti_op_jlesseq(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_jlesseq + str lr, [sp, #32] + bl JITStubThunked_op_jlesseq + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_not(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_not(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_not + str lr, [sp, #32] + bl JITStubThunked_op_not + ldr lr, [sp, #32] + bx lr +} + +extern "C" int JITStubThunked_op_jtrue(STUB_ARGS_DECLARATION); +__asm int cti_op_jtrue(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_jtrue + str lr, [sp, #32] + bl JITStubThunked_op_jtrue + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_post_inc(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_post_inc(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_post_inc + str lr, [sp, #32] + bl JITStubThunked_op_post_inc + ldr lr, [sp, #32] + bx lr +} + +extern "C" int JITStubThunked_op_eq(STUB_ARGS_DECLARATION); +__asm int cti_op_eq(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_eq + str lr, [sp, #32] + bl JITStubThunked_op_eq + ldr lr, [sp, #32] + bx lr +} + +extern "C" int JITStubThunked_op_eq_strings(STUB_ARGS_DECLARATION); +__asm int cti_op_eq_strings(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_eq_strings + str lr, [sp, #32] + bl JITStubThunked_op_eq_strings + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_lshift(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_lshift(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_lshift + str lr, [sp, #32] + bl JITStubThunked_op_lshift + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_bitand(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_bitand(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_bitand + str lr, [sp, #32] + bl JITStubThunked_op_bitand + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_rshift(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_rshift(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_rshift + str lr, [sp, #32] + bl JITStubThunked_op_rshift + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_bitnot(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_bitnot(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_bitnot + str lr, [sp, #32] + bl JITStubThunked_op_bitnot + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_resolve_with_base(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_resolve_with_base(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_resolve_with_base + str lr, [sp, #32] + bl JITStubThunked_op_resolve_with_base + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_new_func_exp(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_new_func_exp(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_new_func_exp + str lr, [sp, #32] + bl JITStubThunked_op_new_func_exp + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_mod(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_mod(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_mod + str lr, [sp, #32] + bl JITStubThunked_op_mod + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_less(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_less(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_less + str lr, [sp, #32] + bl JITStubThunked_op_less + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_post_dec(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_post_dec(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_post_dec + str lr, [sp, #32] + bl JITStubThunked_op_post_dec + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_urshift(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_urshift(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_urshift + str lr, [sp, #32] + bl JITStubThunked_op_urshift + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_bitxor(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_bitxor(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_bitxor + str lr, [sp, #32] + bl JITStubThunked_op_bitxor + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_new_regexp(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_new_regexp(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_new_regexp + str lr, [sp, #32] + bl JITStubThunked_op_new_regexp + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_bitor(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_bitor(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_bitor + str lr, [sp, #32] + bl JITStubThunked_op_bitor + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_call_eval(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_call_eval(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_call_eval + str lr, [sp, #32] + bl JITStubThunked_op_call_eval + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_throw(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_throw(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_throw + str lr, [sp, #32] + bl JITStubThunked_op_throw + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSPropertyNameIterator* JITStubThunked_op_get_pnames(STUB_ARGS_DECLARATION); +__asm JSPropertyNameIterator* cti_op_get_pnames(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_get_pnames + str lr, [sp, #32] + bl JITStubThunked_op_get_pnames + ldr lr, [sp, #32] + bx lr +} + +extern "C" int JITStubThunked_has_property(STUB_ARGS_DECLARATION); +__asm int cti_has_property(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_has_property + str lr, [sp, #32] + bl JITStubThunked_has_property + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_push_scope(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_push_scope(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_push_scope + str lr, [sp, #32] + bl JITStubThunked_op_push_scope + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_pop_scope(STUB_ARGS_DECLARATION); +__asm void cti_op_pop_scope(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_pop_scope + str lr, [sp, #32] + bl JITStubThunked_op_pop_scope + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_typeof(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_typeof(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_typeof + str lr, [sp, #32] + bl JITStubThunked_op_typeof + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_is_undefined(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_is_undefined(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_is_undefined + str lr, [sp, #32] + bl JITStubThunked_op_is_undefined + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_is_boolean(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_is_boolean(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_is_boolean + str lr, [sp, #32] + bl JITStubThunked_op_is_boolean + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_is_number(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_is_number(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_is_number + str lr, [sp, #32] + bl JITStubThunked_op_is_number + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_is_string(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_is_string(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_is_string + str lr, [sp, #32] + bl JITStubThunked_op_is_string + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_is_object(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_is_object(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_is_object + str lr, [sp, #32] + bl JITStubThunked_op_is_object + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_is_function(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_is_function(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_is_function + str lr, [sp, #32] + bl JITStubThunked_op_is_function + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_stricteq(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_stricteq(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_stricteq + str lr, [sp, #32] + bl JITStubThunked_op_stricteq + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_to_primitive(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_to_primitive(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_to_primitive + str lr, [sp, #32] + bl JITStubThunked_op_to_primitive + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_strcat(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_strcat(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_strcat + str lr, [sp, #32] + bl JITStubThunked_op_strcat + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_nstricteq(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_nstricteq(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_nstricteq + str lr, [sp, #32] + bl JITStubThunked_op_nstricteq + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_to_jsnumber(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_to_jsnumber(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_to_jsnumber + str lr, [sp, #32] + bl JITStubThunked_op_to_jsnumber + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_in(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_in(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_in + str lr, [sp, #32] + bl JITStubThunked_op_in + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_push_new_scope(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_push_new_scope(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_push_new_scope + str lr, [sp, #32] + bl JITStubThunked_op_push_new_scope + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_jmp_scopes(STUB_ARGS_DECLARATION); +__asm void cti_op_jmp_scopes(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_jmp_scopes + str lr, [sp, #32] + bl JITStubThunked_op_jmp_scopes + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_put_by_index(STUB_ARGS_DECLARATION); +__asm void cti_op_put_by_index(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_put_by_index + str lr, [sp, #32] + bl JITStubThunked_op_put_by_index + ldr lr, [sp, #32] + bx lr +} + +extern "C" void* JITStubThunked_op_switch_imm(STUB_ARGS_DECLARATION); +__asm void* cti_op_switch_imm(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_switch_imm + str lr, [sp, #32] + bl JITStubThunked_op_switch_imm + ldr lr, [sp, #32] + bx lr +} + +extern "C" void* JITStubThunked_op_switch_char(STUB_ARGS_DECLARATION); +__asm void* cti_op_switch_char(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_switch_char + str lr, [sp, #32] + bl JITStubThunked_op_switch_char + ldr lr, [sp, #32] + bx lr +} + +extern "C" void* JITStubThunked_op_switch_string(STUB_ARGS_DECLARATION); +__asm void* cti_op_switch_string(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_switch_string + str lr, [sp, #32] + bl JITStubThunked_op_switch_string + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_op_del_by_val(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_op_del_by_val(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_del_by_val + str lr, [sp, #32] + bl JITStubThunked_op_del_by_val + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_put_getter(STUB_ARGS_DECLARATION); +__asm void cti_op_put_getter(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_put_getter + str lr, [sp, #32] + bl JITStubThunked_op_put_getter + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_put_setter(STUB_ARGS_DECLARATION); +__asm void cti_op_put_setter(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_put_setter + str lr, [sp, #32] + bl JITStubThunked_op_put_setter + ldr lr, [sp, #32] + bx lr +} + +extern "C" JSObject* JITStubThunked_op_new_error(STUB_ARGS_DECLARATION); +__asm JSObject* cti_op_new_error(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_new_error + str lr, [sp, #32] + bl JITStubThunked_op_new_error + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_debug(STUB_ARGS_DECLARATION); +__asm void cti_op_debug(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_debug + str lr, [sp, #32] + bl JITStubThunked_op_debug + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_debug_catch(STUB_ARGS_DECLARATION); +__asm void cti_op_debug_catch(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_debug_catch + str lr, [sp, #32] + bl JITStubThunked_op_debug_catch + ldr lr, [sp, #32] + bx lr +} + +extern "C" void JITStubThunked_op_debug_return(STUB_ARGS_DECLARATION); +__asm void cti_op_debug_return(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_op_debug_return + str lr, [sp, #32] + bl JITStubThunked_op_debug_return + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_vm_throw(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_vm_throw(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_vm_throw + str lr, [sp, #32] + bl JITStubThunked_vm_throw + ldr lr, [sp, #32] + bx lr +} + +extern "C" EncodedJSValue JITStubThunked_to_object(STUB_ARGS_DECLARATION); +__asm EncodedJSValue cti_to_object(STUB_ARGS_DECLARATION) +{ + ARM + IMPORT JITStubThunked_to_object + str lr, [sp, #32] + bl JITStubThunked_to_object + ldr lr, [sp, #32] + bx lr +} + diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/Grammar.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/generated/Grammar.cpp index f1fa708..6ac1b9b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/Grammar.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/Grammar.cpp @@ -208,7 +208,7 @@ /* Copy the first part of user declarations. */ -#line 3 "../parser/Grammar.y" +#line 3 "parser/Grammar.y" /* @@ -236,6 +236,7 @@ #include "JSObject.h" #include "JSString.h" +#include "Lexer.h" #include "NodeConstructors.h" #include "NodeInfo.h" #include <stdlib.h> @@ -251,13 +252,12 @@ // Default values for bison. #define YYDEBUG 0 // Set to 1 to debug a parse error. #define jscyydebug 0 // Set to 1 to debug a parse error. -#if !PLATFORM(DARWIN) +#if !OS(DARWIN) // Avoid triggering warnings in older bison by not setting this on the Darwin platform. // FIXME: Is this still needed? #define YYERROR_VERBOSE #endif -int jscyylex(void* lvalp, void* llocp, void* globalPtr); int jscyyerror(const char*); static inline bool allowAutomaticSemicolon(JSC::Lexer&, int); @@ -372,7 +372,7 @@ static inline void appendToVarDeclarationList(JSGlobalData* globalData, ParserAr #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -#line 146 "../parser/Grammar.y" +#line 146 "parser/Grammar.y" { int intValue; double doubleValue; @@ -405,7 +405,7 @@ typedef union YYSTYPE Operator op; } /* Line 187 of yacc.c. */ -#line 409 "JavaScriptCore/tmp/../generated/Grammar.tab.c" +#line 409 "generated/Grammar.tab.c" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 @@ -427,12 +427,12 @@ typedef struct YYLTYPE /* Copy the second part of user declarations. */ -#line 178 "../parser/Grammar.y" +#line 178 "parser/Grammar.y" template <typename T> inline void setStatementLocation(StatementNode* statement, const T& start, const T& end) { - statement->setLoc(start.first_line, end.last_line, start.first_column); + statement->setLoc(start.first_line, end.last_line); } static inline void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end) @@ -443,7 +443,7 @@ static inline void setExceptionLocation(ThrowableExpressionData* node, unsigned /* Line 216 of yacc.c. */ -#line 447 "JavaScriptCore/tmp/../generated/Grammar.tab.c" +#line 447 "generated/Grammar.tab.c" #ifdef short # undef short @@ -3010,32 +3010,32 @@ yyreduce: switch (yyn) { case 2: -#line 293 "../parser/Grammar.y" +#line 293 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NullNode(GLOBAL_DATA), 0, 1); ;} break; case 3: -#line 294 "../parser/Grammar.y" +#line 294 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BooleanNode(GLOBAL_DATA, true), 0, 1); ;} break; case 4: -#line 295 "../parser/Grammar.y" +#line 295 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BooleanNode(GLOBAL_DATA, false), 0, 1); ;} break; case 5: -#line 296 "../parser/Grammar.y" +#line 296 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeNumberNode(GLOBAL_DATA, (yyvsp[(1) - (1)].doubleValue)), 0, 1); ;} break; case 6: -#line 297 "../parser/Grammar.y" +#line 297 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StringNode(GLOBAL_DATA, *(yyvsp[(1) - (1)].ident)), 0, 1); ;} break; case 7: -#line 298 "../parser/Grammar.y" +#line 298 "parser/Grammar.y" { Lexer& l = *GLOBAL_DATA->lexer; const Identifier* pattern; @@ -3050,7 +3050,7 @@ yyreduce: break; case 8: -#line 309 "../parser/Grammar.y" +#line 309 "parser/Grammar.y" { Lexer& l = *GLOBAL_DATA->lexer; const Identifier* pattern; @@ -3065,27 +3065,27 @@ yyreduce: break; case 9: -#line 323 "../parser/Grammar.y" +#line 323 "parser/Grammar.y" { (yyval.propertyNode) = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *(yyvsp[(1) - (3)].ident), (yyvsp[(3) - (3)].expressionNode).m_node, PropertyNode::Constant), (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 10: -#line 324 "../parser/Grammar.y" +#line 324 "parser/Grammar.y" { (yyval.propertyNode) = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, *(yyvsp[(1) - (3)].ident), (yyvsp[(3) - (3)].expressionNode).m_node, PropertyNode::Constant), (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 11: -#line 325 "../parser/Grammar.y" +#line 325 "parser/Grammar.y" { (yyval.propertyNode) = createNodeInfo<PropertyNode*>(new (GLOBAL_DATA) PropertyNode(GLOBAL_DATA, (yyvsp[(1) - (3)].doubleValue), (yyvsp[(3) - (3)].expressionNode).m_node, PropertyNode::Constant), (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 12: -#line 326 "../parser/Grammar.y" +#line 326 "parser/Grammar.y" { (yyval.propertyNode) = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(GLOBAL_DATA, *(yyvsp[(1) - (7)].ident), *(yyvsp[(2) - (7)].ident), 0, (yyvsp[(6) - (7)].functionBodyNode), GLOBAL_DATA->lexer->sourceCode((yyvsp[(5) - (7)].intValue), (yyvsp[(7) - (7)].intValue), (yylsp[(5) - (7)]).first_line)), ClosureFeature, 0); setStatementLocation((yyvsp[(6) - (7)].functionBodyNode), (yylsp[(5) - (7)]), (yylsp[(7) - (7)])); if (!(yyval.propertyNode).m_node) YYABORT; ;} break; case 13: -#line 328 "../parser/Grammar.y" +#line 328 "parser/Grammar.y" { (yyval.propertyNode) = createNodeInfo<PropertyNode*>(makeGetterOrSetterPropertyNode(GLOBAL_DATA, *(yyvsp[(1) - (8)].ident), *(yyvsp[(2) - (8)].ident), (yyvsp[(4) - (8)].parameterList).m_node.head, (yyvsp[(7) - (8)].functionBodyNode), GLOBAL_DATA->lexer->sourceCode((yyvsp[(6) - (8)].intValue), (yyvsp[(8) - (8)].intValue), (yylsp[(6) - (8)]).first_line)), (yyvsp[(4) - (8)].parameterList).m_features | ClosureFeature, 0); if ((yyvsp[(4) - (8)].parameterList).m_features & ArgumentsFeature) @@ -3097,7 +3097,7 @@ yyreduce: break; case 14: -#line 339 "../parser/Grammar.y" +#line 339 "parser/Grammar.y" { (yyval.propertyList).m_node.head = new (GLOBAL_DATA) PropertyListNode(GLOBAL_DATA, (yyvsp[(1) - (1)].propertyNode).m_node); (yyval.propertyList).m_node.tail = (yyval.propertyList).m_node.head; (yyval.propertyList).m_features = (yyvsp[(1) - (1)].propertyNode).m_features; @@ -3105,7 +3105,7 @@ yyreduce: break; case 15: -#line 343 "../parser/Grammar.y" +#line 343 "parser/Grammar.y" { (yyval.propertyList).m_node.head = (yyvsp[(1) - (3)].propertyList).m_node.head; (yyval.propertyList).m_node.tail = new (GLOBAL_DATA) PropertyListNode(GLOBAL_DATA, (yyvsp[(3) - (3)].propertyNode).m_node, (yyvsp[(1) - (3)].propertyList).m_node.tail); (yyval.propertyList).m_features = (yyvsp[(1) - (3)].propertyList).m_features | (yyvsp[(3) - (3)].propertyNode).m_features; @@ -3113,52 +3113,52 @@ yyreduce: break; case 17: -#line 351 "../parser/Grammar.y" +#line 351 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA), 0, 0); ;} break; case 18: -#line 352 "../parser/Grammar.y" +#line 352 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA, (yyvsp[(2) - (3)].propertyList).m_node.head), (yyvsp[(2) - (3)].propertyList).m_features, (yyvsp[(2) - (3)].propertyList).m_numConstants); ;} break; case 19: -#line 354 "../parser/Grammar.y" +#line 354 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ObjectLiteralNode(GLOBAL_DATA, (yyvsp[(2) - (4)].propertyList).m_node.head), (yyvsp[(2) - (4)].propertyList).m_features, (yyvsp[(2) - (4)].propertyList).m_numConstants); ;} break; case 20: -#line 358 "../parser/Grammar.y" +#line 358 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ThisNode(GLOBAL_DATA), ThisFeature, 0); ;} break; case 23: -#line 361 "../parser/Grammar.y" +#line 361 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ResolveNode(GLOBAL_DATA, *(yyvsp[(1) - (1)].ident), (yylsp[(1) - (1)]).first_column), (*(yyvsp[(1) - (1)].ident) == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); ;} break; case 24: -#line 362 "../parser/Grammar.y" +#line 362 "parser/Grammar.y" { (yyval.expressionNode) = (yyvsp[(2) - (3)].expressionNode); ;} break; case 25: -#line 366 "../parser/Grammar.y" +#line 366 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, (yyvsp[(2) - (3)].intValue)), 0, (yyvsp[(2) - (3)].intValue) ? 1 : 0); ;} break; case 26: -#line 367 "../parser/Grammar.y" +#line 367 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, (yyvsp[(2) - (3)].elementList).m_node.head), (yyvsp[(2) - (3)].elementList).m_features, (yyvsp[(2) - (3)].elementList).m_numConstants); ;} break; case 27: -#line 368 "../parser/Grammar.y" +#line 368 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ArrayNode(GLOBAL_DATA, (yyvsp[(4) - (5)].intValue), (yyvsp[(2) - (5)].elementList).m_node.head), (yyvsp[(2) - (5)].elementList).m_features, (yyvsp[(4) - (5)].intValue) ? (yyvsp[(2) - (5)].elementList).m_numConstants + 1 : (yyvsp[(2) - (5)].elementList).m_numConstants); ;} break; case 28: -#line 372 "../parser/Grammar.y" +#line 372 "parser/Grammar.y" { (yyval.elementList).m_node.head = new (GLOBAL_DATA) ElementNode(GLOBAL_DATA, (yyvsp[(1) - (2)].intValue), (yyvsp[(2) - (2)].expressionNode).m_node); (yyval.elementList).m_node.tail = (yyval.elementList).m_node.head; (yyval.elementList).m_features = (yyvsp[(2) - (2)].expressionNode).m_features; @@ -3166,7 +3166,7 @@ yyreduce: break; case 29: -#line 377 "../parser/Grammar.y" +#line 377 "parser/Grammar.y" { (yyval.elementList).m_node.head = (yyvsp[(1) - (4)].elementList).m_node.head; (yyval.elementList).m_node.tail = new (GLOBAL_DATA) ElementNode(GLOBAL_DATA, (yyvsp[(1) - (4)].elementList).m_node.tail, (yyvsp[(3) - (4)].intValue), (yyvsp[(4) - (4)].expressionNode).m_node); (yyval.elementList).m_features = (yyvsp[(1) - (4)].elementList).m_features | (yyvsp[(4) - (4)].expressionNode).m_features; @@ -3174,27 +3174,27 @@ yyreduce: break; case 30: -#line 384 "../parser/Grammar.y" +#line 384 "parser/Grammar.y" { (yyval.intValue) = 0; ;} break; case 32: -#line 389 "../parser/Grammar.y" +#line 389 "parser/Grammar.y" { (yyval.intValue) = 1; ;} break; case 33: -#line 390 "../parser/Grammar.y" +#line 390 "parser/Grammar.y" { (yyval.intValue) = (yyvsp[(1) - (2)].intValue) + 1; ;} break; case 35: -#line 395 "../parser/Grammar.y" +#line 395 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>((yyvsp[(1) - (1)].funcExprNode).m_node, (yyvsp[(1) - (1)].funcExprNode).m_features, (yyvsp[(1) - (1)].funcExprNode).m_numConstants); ;} break; case 36: -#line 396 "../parser/Grammar.y" +#line 396 "parser/Grammar.y" { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, (yyvsp[(1) - (4)].expressionNode).m_node, (yyvsp[(3) - (4)].expressionNode).m_node, (yyvsp[(3) - (4)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (4)]).first_column, (yylsp[(1) - (4)]).last_column, (yylsp[(4) - (4)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (4)].expressionNode).m_features | (yyvsp[(3) - (4)].expressionNode).m_features, (yyvsp[(1) - (4)].expressionNode).m_numConstants + (yyvsp[(3) - (4)].expressionNode).m_numConstants); @@ -3202,7 +3202,7 @@ yyreduce: break; case 37: -#line 400 "../parser/Grammar.y" +#line 400 "parser/Grammar.y" { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, *(yyvsp[(3) - (3)].ident)); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(1) - (3)]).last_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants); @@ -3210,7 +3210,7 @@ yyreduce: break; case 38: -#line 404 "../parser/Grammar.y" +#line 404 "parser/Grammar.y" { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, (yyvsp[(2) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].argumentsNode).m_node); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(2) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].argumentsNode).m_features, (yyvsp[(2) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].argumentsNode).m_numConstants); @@ -3218,7 +3218,7 @@ yyreduce: break; case 40: -#line 412 "../parser/Grammar.y" +#line 412 "parser/Grammar.y" { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, (yyvsp[(1) - (4)].expressionNode).m_node, (yyvsp[(3) - (4)].expressionNode).m_node, (yyvsp[(3) - (4)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (4)]).first_column, (yylsp[(1) - (4)]).last_column, (yylsp[(4) - (4)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (4)].expressionNode).m_features | (yyvsp[(3) - (4)].expressionNode).m_features, (yyvsp[(1) - (4)].expressionNode).m_numConstants + (yyvsp[(3) - (4)].expressionNode).m_numConstants); @@ -3226,7 +3226,7 @@ yyreduce: break; case 41: -#line 416 "../parser/Grammar.y" +#line 416 "parser/Grammar.y" { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, *(yyvsp[(3) - (3)].ident)); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(1) - (3)]).last_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants); @@ -3234,7 +3234,7 @@ yyreduce: break; case 42: -#line 420 "../parser/Grammar.y" +#line 420 "parser/Grammar.y" { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, (yyvsp[(2) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].argumentsNode).m_node); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(2) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].argumentsNode).m_features, (yyvsp[(2) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].argumentsNode).m_numConstants); @@ -3242,7 +3242,7 @@ yyreduce: break; case 44: -#line 428 "../parser/Grammar.y" +#line 428 "parser/Grammar.y" { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(2) - (2)]).last_column, (yylsp[(2) - (2)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants); @@ -3250,7 +3250,7 @@ yyreduce: break; case 46: -#line 436 "../parser/Grammar.y" +#line 436 "parser/Grammar.y" { NewExprNode* node = new (GLOBAL_DATA) NewExprNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(2) - (2)]).last_column, (yylsp[(2) - (2)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants); @@ -3258,17 +3258,17 @@ yyreduce: break; case 47: -#line 443 "../parser/Grammar.y" +#line 443 "parser/Grammar.y" { (yyval.expressionNode) = makeFunctionCallNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode), (yyvsp[(2) - (2)].argumentsNode), (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(2) - (2)]).last_column); ;} break; case 48: -#line 444 "../parser/Grammar.y" +#line 444 "parser/Grammar.y" { (yyval.expressionNode) = makeFunctionCallNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode), (yyvsp[(2) - (2)].argumentsNode), (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(2) - (2)]).last_column); ;} break; case 49: -#line 445 "../parser/Grammar.y" +#line 445 "parser/Grammar.y" { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, (yyvsp[(1) - (4)].expressionNode).m_node, (yyvsp[(3) - (4)].expressionNode).m_node, (yyvsp[(3) - (4)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (4)]).first_column, (yylsp[(1) - (4)]).last_column, (yylsp[(4) - (4)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (4)].expressionNode).m_features | (yyvsp[(3) - (4)].expressionNode).m_features, (yyvsp[(1) - (4)].expressionNode).m_numConstants + (yyvsp[(3) - (4)].expressionNode).m_numConstants); @@ -3276,24 +3276,24 @@ yyreduce: break; case 50: -#line 449 "../parser/Grammar.y" +#line 449 "parser/Grammar.y" { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, *(yyvsp[(3) - (3)].ident)); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(1) - (3)]).last_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants); ;} break; case 51: -#line 455 "../parser/Grammar.y" +#line 455 "parser/Grammar.y" { (yyval.expressionNode) = makeFunctionCallNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode), (yyvsp[(2) - (2)].argumentsNode), (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(2) - (2)]).last_column); ;} break; case 52: -#line 456 "../parser/Grammar.y" +#line 456 "parser/Grammar.y" { (yyval.expressionNode) = makeFunctionCallNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode), (yyvsp[(2) - (2)].argumentsNode), (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(2) - (2)]).last_column); ;} break; case 53: -#line 457 "../parser/Grammar.y" +#line 457 "parser/Grammar.y" { BracketAccessorNode* node = new (GLOBAL_DATA) BracketAccessorNode(GLOBAL_DATA, (yyvsp[(1) - (4)].expressionNode).m_node, (yyvsp[(3) - (4)].expressionNode).m_node, (yyvsp[(3) - (4)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (4)]).first_column, (yylsp[(1) - (4)]).last_column, (yylsp[(4) - (4)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (4)].expressionNode).m_features | (yyvsp[(3) - (4)].expressionNode).m_features, (yyvsp[(1) - (4)].expressionNode).m_numConstants + (yyvsp[(3) - (4)].expressionNode).m_numConstants); @@ -3301,7 +3301,7 @@ yyreduce: break; case 54: -#line 461 "../parser/Grammar.y" +#line 461 "parser/Grammar.y" { DotAccessorNode* node = new (GLOBAL_DATA) DotAccessorNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, *(yyvsp[(3) - (3)].ident)); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(1) - (3)]).last_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants); @@ -3309,17 +3309,17 @@ yyreduce: break; case 55: -#line 468 "../parser/Grammar.y" +#line 468 "parser/Grammar.y" { (yyval.argumentsNode) = createNodeInfo<ArgumentsNode*>(new (GLOBAL_DATA) ArgumentsNode(GLOBAL_DATA), 0, 0); ;} break; case 56: -#line 469 "../parser/Grammar.y" +#line 469 "parser/Grammar.y" { (yyval.argumentsNode) = createNodeInfo<ArgumentsNode*>(new (GLOBAL_DATA) ArgumentsNode(GLOBAL_DATA, (yyvsp[(2) - (3)].argumentList).m_node.head), (yyvsp[(2) - (3)].argumentList).m_features, (yyvsp[(2) - (3)].argumentList).m_numConstants); ;} break; case 57: -#line 473 "../parser/Grammar.y" +#line 473 "parser/Grammar.y" { (yyval.argumentList).m_node.head = new (GLOBAL_DATA) ArgumentListNode(GLOBAL_DATA, (yyvsp[(1) - (1)].expressionNode).m_node); (yyval.argumentList).m_node.tail = (yyval.argumentList).m_node.head; (yyval.argumentList).m_features = (yyvsp[(1) - (1)].expressionNode).m_features; @@ -3327,7 +3327,7 @@ yyreduce: break; case 58: -#line 477 "../parser/Grammar.y" +#line 477 "parser/Grammar.y" { (yyval.argumentList).m_node.head = (yyvsp[(1) - (3)].argumentList).m_node.head; (yyval.argumentList).m_node.tail = new (GLOBAL_DATA) ArgumentListNode(GLOBAL_DATA, (yyvsp[(1) - (3)].argumentList).m_node.tail, (yyvsp[(3) - (3)].expressionNode).m_node); (yyval.argumentList).m_features = (yyvsp[(1) - (3)].argumentList).m_features | (yyvsp[(3) - (3)].expressionNode).m_features; @@ -3335,528 +3335,528 @@ yyreduce: break; case 64: -#line 495 "../parser/Grammar.y" +#line 495 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode).m_node, OpPlusPlus, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(2) - (2)]).last_column), (yyvsp[(1) - (2)].expressionNode).m_features | AssignFeature, (yyvsp[(1) - (2)].expressionNode).m_numConstants); ;} break; case 65: -#line 496 "../parser/Grammar.y" +#line 496 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode).m_node, OpMinusMinus, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(2) - (2)]).last_column), (yyvsp[(1) - (2)].expressionNode).m_features | AssignFeature, (yyvsp[(1) - (2)].expressionNode).m_numConstants); ;} break; case 67: -#line 501 "../parser/Grammar.y" +#line 501 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode).m_node, OpPlusPlus, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(2) - (2)]).last_column), (yyvsp[(1) - (2)].expressionNode).m_features | AssignFeature, (yyvsp[(1) - (2)].expressionNode).m_numConstants); ;} break; case 68: -#line 502 "../parser/Grammar.y" +#line 502 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makePostfixNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode).m_node, OpMinusMinus, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(2) - (2)]).last_column), (yyvsp[(1) - (2)].expressionNode).m_features | AssignFeature, (yyvsp[(1) - (2)].expressionNode).m_numConstants); ;} break; case 69: -#line 506 "../parser/Grammar.y" +#line 506 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeDeleteNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node, (yylsp[(1) - (2)]).first_column, (yylsp[(2) - (2)]).last_column, (yylsp[(2) - (2)]).last_column), (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 70: -#line 507 "../parser/Grammar.y" +#line 507 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) VoidNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node), (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants + 1); ;} break; case 71: -#line 508 "../parser/Grammar.y" +#line 508 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeTypeOfNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node), (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 72: -#line 509 "../parser/Grammar.y" +#line 509 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node, OpPlusPlus, (yylsp[(1) - (2)]).first_column, (yylsp[(2) - (2)]).first_column + 1, (yylsp[(2) - (2)]).last_column), (yyvsp[(2) - (2)].expressionNode).m_features | AssignFeature, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 73: -#line 510 "../parser/Grammar.y" +#line 510 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node, OpPlusPlus, (yylsp[(1) - (2)]).first_column, (yylsp[(2) - (2)]).first_column + 1, (yylsp[(2) - (2)]).last_column), (yyvsp[(2) - (2)].expressionNode).m_features | AssignFeature, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 74: -#line 511 "../parser/Grammar.y" +#line 511 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node, OpMinusMinus, (yylsp[(1) - (2)]).first_column, (yylsp[(2) - (2)]).first_column + 1, (yylsp[(2) - (2)]).last_column), (yyvsp[(2) - (2)].expressionNode).m_features | AssignFeature, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 75: -#line 512 "../parser/Grammar.y" +#line 512 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makePrefixNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node, OpMinusMinus, (yylsp[(1) - (2)]).first_column, (yylsp[(2) - (2)]).first_column + 1, (yylsp[(2) - (2)]).last_column), (yyvsp[(2) - (2)].expressionNode).m_features | AssignFeature, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 76: -#line 513 "../parser/Grammar.y" +#line 513 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) UnaryPlusNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node), (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 77: -#line 514 "../parser/Grammar.y" +#line 514 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeNegateNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node), (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 78: -#line 515 "../parser/Grammar.y" +#line 515 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeBitwiseNotNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node), (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 79: -#line 516 "../parser/Grammar.y" +#line 516 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalNotNode(GLOBAL_DATA, (yyvsp[(2) - (2)].expressionNode).m_node), (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 85: -#line 530 "../parser/Grammar.y" +#line 530 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 86: -#line 531 "../parser/Grammar.y" +#line 531 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 87: -#line 532 "../parser/Grammar.y" +#line 532 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ModNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 89: -#line 538 "../parser/Grammar.y" +#line 538 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeMultNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 90: -#line 540 "../parser/Grammar.y" +#line 540 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeDivNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 91: -#line 542 "../parser/Grammar.y" +#line 542 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ModNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 93: -#line 547 "../parser/Grammar.y" +#line 547 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 94: -#line 548 "../parser/Grammar.y" +#line 548 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 96: -#line 554 "../parser/Grammar.y" +#line 554 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeAddNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 97: -#line 556 "../parser/Grammar.y" +#line 556 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeSubNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 99: -#line 561 "../parser/Grammar.y" +#line 561 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 100: -#line 562 "../parser/Grammar.y" +#line 562 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 101: -#line 563 "../parser/Grammar.y" +#line 563 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) UnsignedRightShiftNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 103: -#line 568 "../parser/Grammar.y" +#line 568 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeLeftShiftNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 104: -#line 569 "../parser/Grammar.y" +#line 569 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeRightShiftNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 105: -#line 570 "../parser/Grammar.y" +#line 570 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) UnsignedRightShiftNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 107: -#line 575 "../parser/Grammar.y" +#line 575 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 108: -#line 576 "../parser/Grammar.y" +#line 576 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 109: -#line 577 "../parser/Grammar.y" +#line 577 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 110: -#line 578 "../parser/Grammar.y" +#line 578 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 111: -#line 579 "../parser/Grammar.y" +#line 579 "parser/Grammar.y" { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(3) - (3)]).first_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 112: -#line 582 "../parser/Grammar.y" +#line 582 "parser/Grammar.y" { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(3) - (3)]).first_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 114: -#line 589 "../parser/Grammar.y" +#line 589 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 115: -#line 590 "../parser/Grammar.y" +#line 590 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 116: -#line 591 "../parser/Grammar.y" +#line 591 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 117: -#line 592 "../parser/Grammar.y" +#line 592 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 118: -#line 594 "../parser/Grammar.y" +#line 594 "parser/Grammar.y" { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(3) - (3)]).first_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 120: -#line 601 "../parser/Grammar.y" +#line 601 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 121: -#line 602 "../parser/Grammar.y" +#line 602 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 122: -#line 603 "../parser/Grammar.y" +#line 603 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LessEqNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 123: -#line 604 "../parser/Grammar.y" +#line 604 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) GreaterEqNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 124: -#line 606 "../parser/Grammar.y" +#line 606 "parser/Grammar.y" { InstanceOfNode* node = new (GLOBAL_DATA) InstanceOfNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(3) - (3)]).first_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 125: -#line 610 "../parser/Grammar.y" +#line 610 "parser/Grammar.y" { InNode* node = new (GLOBAL_DATA) InNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(3) - (3)]).first_column, (yylsp[(3) - (3)]).last_column); (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(node, (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 127: -#line 617 "../parser/Grammar.y" +#line 617 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 128: -#line 618 "../parser/Grammar.y" +#line 618 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotEqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 129: -#line 619 "../parser/Grammar.y" +#line 619 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StrictEqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 130: -#line 620 "../parser/Grammar.y" +#line 620 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotStrictEqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 132: -#line 626 "../parser/Grammar.y" +#line 626 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 133: -#line 628 "../parser/Grammar.y" +#line 628 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotEqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 134: -#line 630 "../parser/Grammar.y" +#line 630 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StrictEqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 135: -#line 632 "../parser/Grammar.y" +#line 632 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotStrictEqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 137: -#line 638 "../parser/Grammar.y" +#line 638 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) EqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 138: -#line 639 "../parser/Grammar.y" +#line 639 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotEqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 139: -#line 641 "../parser/Grammar.y" +#line 641 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) StrictEqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 140: -#line 643 "../parser/Grammar.y" +#line 643 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) NotStrictEqualNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 142: -#line 648 "../parser/Grammar.y" +#line 648 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitAndNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 144: -#line 654 "../parser/Grammar.y" +#line 654 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitAndNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 146: -#line 659 "../parser/Grammar.y" +#line 659 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitAndNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 148: -#line 664 "../parser/Grammar.y" +#line 664 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitXOrNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 150: -#line 670 "../parser/Grammar.y" +#line 670 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitXOrNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 152: -#line 676 "../parser/Grammar.y" +#line 676 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitXOrNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 154: -#line 681 "../parser/Grammar.y" +#line 681 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitOrNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 156: -#line 687 "../parser/Grammar.y" +#line 687 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitOrNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 158: -#line 693 "../parser/Grammar.y" +#line 693 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) BitOrNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 160: -#line 698 "../parser/Grammar.y" +#line 698 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, OpLogicalAnd), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 162: -#line 704 "../parser/Grammar.y" +#line 704 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, OpLogicalAnd), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 164: -#line 710 "../parser/Grammar.y" +#line 710 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, OpLogicalAnd), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 166: -#line 715 "../parser/Grammar.y" +#line 715 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, OpLogicalOr), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 168: -#line 721 "../parser/Grammar.y" +#line 721 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, OpLogicalOr), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 170: -#line 726 "../parser/Grammar.y" +#line 726 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) LogicalOpNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node, OpLogicalOr), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 172: -#line 732 "../parser/Grammar.y" +#line 732 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ConditionalNode(GLOBAL_DATA, (yyvsp[(1) - (5)].expressionNode).m_node, (yyvsp[(3) - (5)].expressionNode).m_node, (yyvsp[(5) - (5)].expressionNode).m_node), (yyvsp[(1) - (5)].expressionNode).m_features | (yyvsp[(3) - (5)].expressionNode).m_features | (yyvsp[(5) - (5)].expressionNode).m_features, (yyvsp[(1) - (5)].expressionNode).m_numConstants + (yyvsp[(3) - (5)].expressionNode).m_numConstants + (yyvsp[(5) - (5)].expressionNode).m_numConstants); ;} break; case 174: -#line 738 "../parser/Grammar.y" +#line 738 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ConditionalNode(GLOBAL_DATA, (yyvsp[(1) - (5)].expressionNode).m_node, (yyvsp[(3) - (5)].expressionNode).m_node, (yyvsp[(5) - (5)].expressionNode).m_node), (yyvsp[(1) - (5)].expressionNode).m_features | (yyvsp[(3) - (5)].expressionNode).m_features | (yyvsp[(5) - (5)].expressionNode).m_features, (yyvsp[(1) - (5)].expressionNode).m_numConstants + (yyvsp[(3) - (5)].expressionNode).m_numConstants + (yyvsp[(5) - (5)].expressionNode).m_numConstants); ;} break; case 176: -#line 744 "../parser/Grammar.y" +#line 744 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(new (GLOBAL_DATA) ConditionalNode(GLOBAL_DATA, (yyvsp[(1) - (5)].expressionNode).m_node, (yyvsp[(3) - (5)].expressionNode).m_node, (yyvsp[(5) - (5)].expressionNode).m_node), (yyvsp[(1) - (5)].expressionNode).m_features | (yyvsp[(3) - (5)].expressionNode).m_features | (yyvsp[(5) - (5)].expressionNode).m_features, (yyvsp[(1) - (5)].expressionNode).m_numConstants + (yyvsp[(3) - (5)].expressionNode).m_numConstants + (yyvsp[(5) - (5)].expressionNode).m_numConstants); ;} break; case 178: -#line 750 "../parser/Grammar.y" +#line 750 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(2) - (3)].op), (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(1) - (3)].expressionNode).m_features & AssignFeature, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).first_column + 1, (yylsp[(3) - (3)]).last_column), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features | AssignFeature, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 180: -#line 758 "../parser/Grammar.y" +#line 758 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(2) - (3)].op), (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(1) - (3)].expressionNode).m_features & AssignFeature, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).first_column + 1, (yylsp[(3) - (3)]).last_column), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features | AssignFeature, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 182: -#line 766 "../parser/Grammar.y" +#line 766 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(makeAssignNode(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(2) - (3)].op), (yyvsp[(3) - (3)].expressionNode).m_node, (yyvsp[(1) - (3)].expressionNode).m_features & AssignFeature, (yyvsp[(3) - (3)].expressionNode).m_features & AssignFeature, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).first_column + 1, (yylsp[(3) - (3)]).last_column), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features | AssignFeature, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 183: -#line 772 "../parser/Grammar.y" +#line 772 "parser/Grammar.y" { (yyval.op) = OpEqual; ;} break; case 184: -#line 773 "../parser/Grammar.y" +#line 773 "parser/Grammar.y" { (yyval.op) = OpPlusEq; ;} break; case 185: -#line 774 "../parser/Grammar.y" +#line 774 "parser/Grammar.y" { (yyval.op) = OpMinusEq; ;} break; case 186: -#line 775 "../parser/Grammar.y" +#line 775 "parser/Grammar.y" { (yyval.op) = OpMultEq; ;} break; case 187: -#line 776 "../parser/Grammar.y" +#line 776 "parser/Grammar.y" { (yyval.op) = OpDivEq; ;} break; case 188: -#line 777 "../parser/Grammar.y" +#line 777 "parser/Grammar.y" { (yyval.op) = OpLShift; ;} break; case 189: -#line 778 "../parser/Grammar.y" +#line 778 "parser/Grammar.y" { (yyval.op) = OpRShift; ;} break; case 190: -#line 779 "../parser/Grammar.y" +#line 779 "parser/Grammar.y" { (yyval.op) = OpURShift; ;} break; case 191: -#line 780 "../parser/Grammar.y" +#line 780 "parser/Grammar.y" { (yyval.op) = OpAndEq; ;} break; case 192: -#line 781 "../parser/Grammar.y" +#line 781 "parser/Grammar.y" { (yyval.op) = OpXOrEq; ;} break; case 193: -#line 782 "../parser/Grammar.y" +#line 782 "parser/Grammar.y" { (yyval.op) = OpOrEq; ;} break; case 194: -#line 783 "../parser/Grammar.y" +#line 783 "parser/Grammar.y" { (yyval.op) = OpModEq; ;} break; case 196: -#line 788 "../parser/Grammar.y" +#line 788 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(combineCommaNodes(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 198: -#line 793 "../parser/Grammar.y" +#line 793 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(combineCommaNodes(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 200: -#line 798 "../parser/Grammar.y" +#line 798 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(combineCommaNodes(GLOBAL_DATA, (yyvsp[(1) - (3)].expressionNode).m_node, (yyvsp[(3) - (3)].expressionNode).m_node), (yyvsp[(1) - (3)].expressionNode).m_features | (yyvsp[(3) - (3)].expressionNode).m_features, (yyvsp[(1) - (3)].expressionNode).m_numConstants + (yyvsp[(3) - (3)].expressionNode).m_numConstants); ;} break; case 218: -#line 822 "../parser/Grammar.y" +#line 822 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, 0), 0, 0, 0, 0); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (2)]), (yylsp[(2) - (2)])); ;} break; case 219: -#line 824 "../parser/Grammar.y" +#line 824 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BlockNode(GLOBAL_DATA, (yyvsp[(2) - (3)].sourceElements).m_node), (yyvsp[(2) - (3)].sourceElements).m_varDeclarations, (yyvsp[(2) - (3)].sourceElements).m_funcDeclarations, (yyvsp[(2) - (3)].sourceElements).m_features, (yyvsp[(2) - (3)].sourceElements).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(3) - (3)])); ;} break; case 220: -#line 829 "../parser/Grammar.y" +#line 829 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, (yyvsp[(2) - (3)].varDeclList).m_node), (yyvsp[(2) - (3)].varDeclList).m_varDeclarations, (yyvsp[(2) - (3)].varDeclList).m_funcDeclarations, (yyvsp[(2) - (3)].varDeclList).m_features, (yyvsp[(2) - (3)].varDeclList).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(3) - (3)])); ;} break; case 221: -#line 831 "../parser/Grammar.y" +#line 831 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(makeVarStatementNode(GLOBAL_DATA, (yyvsp[(2) - (3)].varDeclList).m_node), (yyvsp[(2) - (3)].varDeclList).m_varDeclarations, (yyvsp[(2) - (3)].varDeclList).m_funcDeclarations, (yyvsp[(2) - (3)].varDeclList).m_features, (yyvsp[(2) - (3)].varDeclList).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(2) - (3)])); AUTO_SEMICOLON; ;} break; case 222: -#line 837 "../parser/Grammar.y" +#line 837 "parser/Grammar.y" { (yyval.varDeclList).m_node = 0; (yyval.varDeclList).m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>; appendToVarDeclarationList(GLOBAL_DATA, (yyval.varDeclList).m_varDeclarations, *(yyvsp[(1) - (1)].ident), 0); @@ -3867,7 +3867,7 @@ yyreduce: break; case 223: -#line 844 "../parser/Grammar.y" +#line 844 "parser/Grammar.y" { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *(yyvsp[(1) - (2)].ident), (yyvsp[(2) - (2)].expressionNode).m_node, (yyvsp[(2) - (2)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(2) - (2)]).first_column + 1, (yylsp[(2) - (2)]).last_column); (yyval.varDeclList).m_node = node; @@ -3880,7 +3880,7 @@ yyreduce: break; case 224: -#line 854 "../parser/Grammar.y" +#line 854 "parser/Grammar.y" { (yyval.varDeclList).m_node = (yyvsp[(1) - (3)].varDeclList).m_node; (yyval.varDeclList).m_varDeclarations = (yyvsp[(1) - (3)].varDeclList).m_varDeclarations; appendToVarDeclarationList(GLOBAL_DATA, (yyval.varDeclList).m_varDeclarations, *(yyvsp[(3) - (3)].ident), 0); @@ -3891,7 +3891,7 @@ yyreduce: break; case 225: -#line 862 "../parser/Grammar.y" +#line 862 "parser/Grammar.y" { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *(yyvsp[(3) - (4)].ident), (yyvsp[(4) - (4)].expressionNode).m_node, (yyvsp[(4) - (4)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(3) - (4)]).first_column, (yylsp[(4) - (4)]).first_column + 1, (yylsp[(4) - (4)]).last_column); (yyval.varDeclList).m_node = combineCommaNodes(GLOBAL_DATA, (yyvsp[(1) - (4)].varDeclList).m_node, node); @@ -3904,7 +3904,7 @@ yyreduce: break; case 226: -#line 874 "../parser/Grammar.y" +#line 874 "parser/Grammar.y" { (yyval.varDeclList).m_node = 0; (yyval.varDeclList).m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>; appendToVarDeclarationList(GLOBAL_DATA, (yyval.varDeclList).m_varDeclarations, *(yyvsp[(1) - (1)].ident), 0); @@ -3915,7 +3915,7 @@ yyreduce: break; case 227: -#line 881 "../parser/Grammar.y" +#line 881 "parser/Grammar.y" { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *(yyvsp[(1) - (2)].ident), (yyvsp[(2) - (2)].expressionNode).m_node, (yyvsp[(2) - (2)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(2) - (2)]).first_column + 1, (yylsp[(2) - (2)]).last_column); (yyval.varDeclList).m_node = node; @@ -3928,7 +3928,7 @@ yyreduce: break; case 228: -#line 891 "../parser/Grammar.y" +#line 891 "parser/Grammar.y" { (yyval.varDeclList).m_node = (yyvsp[(1) - (3)].varDeclList).m_node; (yyval.varDeclList).m_varDeclarations = (yyvsp[(1) - (3)].varDeclList).m_varDeclarations; appendToVarDeclarationList(GLOBAL_DATA, (yyval.varDeclList).m_varDeclarations, *(yyvsp[(3) - (3)].ident), 0); @@ -3939,7 +3939,7 @@ yyreduce: break; case 229: -#line 899 "../parser/Grammar.y" +#line 899 "parser/Grammar.y" { AssignResolveNode* node = new (GLOBAL_DATA) AssignResolveNode(GLOBAL_DATA, *(yyvsp[(3) - (4)].ident), (yyvsp[(4) - (4)].expressionNode).m_node, (yyvsp[(4) - (4)].expressionNode).m_features & AssignFeature); setExceptionLocation(node, (yylsp[(3) - (4)]).first_column, (yylsp[(4) - (4)]).first_column + 1, (yylsp[(4) - (4)]).last_column); (yyval.varDeclList).m_node = combineCommaNodes(GLOBAL_DATA, (yyvsp[(1) - (4)].varDeclList).m_node, node); @@ -3952,19 +3952,19 @@ yyreduce: break; case 230: -#line 911 "../parser/Grammar.y" +#line 911 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, (yyvsp[(2) - (3)].constDeclList).m_node.head), (yyvsp[(2) - (3)].constDeclList).m_varDeclarations, (yyvsp[(2) - (3)].constDeclList).m_funcDeclarations, (yyvsp[(2) - (3)].constDeclList).m_features, (yyvsp[(2) - (3)].constDeclList).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(3) - (3)])); ;} break; case 231: -#line 914 "../parser/Grammar.y" +#line 914 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ConstStatementNode(GLOBAL_DATA, (yyvsp[(2) - (3)].constDeclList).m_node.head), (yyvsp[(2) - (3)].constDeclList).m_varDeclarations, (yyvsp[(2) - (3)].constDeclList).m_funcDeclarations, (yyvsp[(2) - (3)].constDeclList).m_features, (yyvsp[(2) - (3)].constDeclList).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(2) - (3)])); AUTO_SEMICOLON; ;} break; case 232: -#line 919 "../parser/Grammar.y" +#line 919 "parser/Grammar.y" { (yyval.constDeclList).m_node.head = (yyvsp[(1) - (1)].constDeclNode).m_node; (yyval.constDeclList).m_node.tail = (yyval.constDeclList).m_node.head; (yyval.constDeclList).m_varDeclarations = new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::VarStack>; @@ -3976,7 +3976,7 @@ yyreduce: break; case 233: -#line 928 "../parser/Grammar.y" +#line 928 "parser/Grammar.y" { (yyval.constDeclList).m_node.head = (yyvsp[(1) - (3)].constDeclList).m_node.head; (yyvsp[(1) - (3)].constDeclList).m_node.tail->m_next = (yyvsp[(3) - (3)].constDeclNode).m_node; (yyval.constDeclList).m_node.tail = (yyvsp[(3) - (3)].constDeclNode).m_node; @@ -3988,50 +3988,50 @@ yyreduce: break; case 234: -#line 939 "../parser/Grammar.y" +#line 939 "parser/Grammar.y" { (yyval.constDeclNode) = createNodeInfo<ConstDeclNode*>(new (GLOBAL_DATA) ConstDeclNode(GLOBAL_DATA, *(yyvsp[(1) - (1)].ident), 0), (*(yyvsp[(1) - (1)].ident) == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0, 0); ;} break; case 235: -#line 940 "../parser/Grammar.y" +#line 940 "parser/Grammar.y" { (yyval.constDeclNode) = createNodeInfo<ConstDeclNode*>(new (GLOBAL_DATA) ConstDeclNode(GLOBAL_DATA, *(yyvsp[(1) - (2)].ident), (yyvsp[(2) - (2)].expressionNode).m_node), ((*(yyvsp[(1) - (2)].ident) == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | (yyvsp[(2) - (2)].expressionNode).m_features, (yyvsp[(2) - (2)].expressionNode).m_numConstants); ;} break; case 236: -#line 944 "../parser/Grammar.y" +#line 944 "parser/Grammar.y" { (yyval.expressionNode) = (yyvsp[(2) - (2)].expressionNode); ;} break; case 237: -#line 948 "../parser/Grammar.y" +#line 948 "parser/Grammar.y" { (yyval.expressionNode) = (yyvsp[(2) - (2)].expressionNode); ;} break; case 238: -#line 952 "../parser/Grammar.y" +#line 952 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) EmptyStatementNode(GLOBAL_DATA), 0, 0, 0, 0); ;} break; case 239: -#line 956 "../parser/Grammar.y" +#line 956 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode).m_node), 0, 0, (yyvsp[(1) - (2)].expressionNode).m_features, (yyvsp[(1) - (2)].expressionNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (2)]), (yylsp[(2) - (2)])); ;} break; case 240: -#line 958 "../parser/Grammar.y" +#line 958 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ExprStatementNode(GLOBAL_DATA, (yyvsp[(1) - (2)].expressionNode).m_node), 0, 0, (yyvsp[(1) - (2)].expressionNode).m_features, (yyvsp[(1) - (2)].expressionNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (2)]), (yylsp[(1) - (2)])); AUTO_SEMICOLON; ;} break; case 241: -#line 964 "../parser/Grammar.y" +#line 964 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfNode(GLOBAL_DATA, (yyvsp[(3) - (5)].expressionNode).m_node, (yyvsp[(5) - (5)].statementNode).m_node), (yyvsp[(5) - (5)].statementNode).m_varDeclarations, (yyvsp[(5) - (5)].statementNode).m_funcDeclarations, (yyvsp[(3) - (5)].expressionNode).m_features | (yyvsp[(5) - (5)].statementNode).m_features, (yyvsp[(3) - (5)].expressionNode).m_numConstants + (yyvsp[(5) - (5)].statementNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (5)]), (yylsp[(4) - (5)])); ;} break; case 242: -#line 967 "../parser/Grammar.y" +#line 967 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) IfElseNode(GLOBAL_DATA, (yyvsp[(3) - (7)].expressionNode).m_node, (yyvsp[(5) - (7)].statementNode).m_node, (yyvsp[(7) - (7)].statementNode).m_node), mergeDeclarationLists((yyvsp[(5) - (7)].statementNode).m_varDeclarations, (yyvsp[(7) - (7)].statementNode).m_varDeclarations), mergeDeclarationLists((yyvsp[(5) - (7)].statementNode).m_funcDeclarations, (yyvsp[(7) - (7)].statementNode).m_funcDeclarations), @@ -4041,25 +4041,25 @@ yyreduce: break; case 243: -#line 976 "../parser/Grammar.y" +#line 976 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, (yyvsp[(2) - (7)].statementNode).m_node, (yyvsp[(5) - (7)].expressionNode).m_node), (yyvsp[(2) - (7)].statementNode).m_varDeclarations, (yyvsp[(2) - (7)].statementNode).m_funcDeclarations, (yyvsp[(2) - (7)].statementNode).m_features | (yyvsp[(5) - (7)].expressionNode).m_features, (yyvsp[(2) - (7)].statementNode).m_numConstants + (yyvsp[(5) - (7)].expressionNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (7)]), (yylsp[(3) - (7)])); ;} break; case 244: -#line 978 "../parser/Grammar.y" +#line 978 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DoWhileNode(GLOBAL_DATA, (yyvsp[(2) - (7)].statementNode).m_node, (yyvsp[(5) - (7)].expressionNode).m_node), (yyvsp[(2) - (7)].statementNode).m_varDeclarations, (yyvsp[(2) - (7)].statementNode).m_funcDeclarations, (yyvsp[(2) - (7)].statementNode).m_features | (yyvsp[(5) - (7)].expressionNode).m_features, (yyvsp[(2) - (7)].statementNode).m_numConstants + (yyvsp[(5) - (7)].expressionNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (7)]), (yylsp[(3) - (7)])); ;} break; case 245: -#line 980 "../parser/Grammar.y" +#line 980 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WhileNode(GLOBAL_DATA, (yyvsp[(3) - (5)].expressionNode).m_node, (yyvsp[(5) - (5)].statementNode).m_node), (yyvsp[(5) - (5)].statementNode).m_varDeclarations, (yyvsp[(5) - (5)].statementNode).m_funcDeclarations, (yyvsp[(3) - (5)].expressionNode).m_features | (yyvsp[(5) - (5)].statementNode).m_features, (yyvsp[(3) - (5)].expressionNode).m_numConstants + (yyvsp[(5) - (5)].statementNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (5)]), (yylsp[(4) - (5)])); ;} break; case 246: -#line 983 "../parser/Grammar.y" +#line 983 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, (yyvsp[(3) - (9)].expressionNode).m_node, (yyvsp[(5) - (9)].expressionNode).m_node, (yyvsp[(7) - (9)].expressionNode).m_node, (yyvsp[(9) - (9)].statementNode).m_node, false), (yyvsp[(9) - (9)].statementNode).m_varDeclarations, (yyvsp[(9) - (9)].statementNode).m_funcDeclarations, (yyvsp[(3) - (9)].expressionNode).m_features | (yyvsp[(5) - (9)].expressionNode).m_features | (yyvsp[(7) - (9)].expressionNode).m_features | (yyvsp[(9) - (9)].statementNode).m_features, (yyvsp[(3) - (9)].expressionNode).m_numConstants + (yyvsp[(5) - (9)].expressionNode).m_numConstants + (yyvsp[(7) - (9)].expressionNode).m_numConstants + (yyvsp[(9) - (9)].statementNode).m_numConstants); @@ -4068,7 +4068,7 @@ yyreduce: break; case 247: -#line 989 "../parser/Grammar.y" +#line 989 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) ForNode(GLOBAL_DATA, (yyvsp[(4) - (10)].varDeclList).m_node, (yyvsp[(6) - (10)].expressionNode).m_node, (yyvsp[(8) - (10)].expressionNode).m_node, (yyvsp[(10) - (10)].statementNode).m_node, true), mergeDeclarationLists((yyvsp[(4) - (10)].varDeclList).m_varDeclarations, (yyvsp[(10) - (10)].statementNode).m_varDeclarations), mergeDeclarationLists((yyvsp[(4) - (10)].varDeclList).m_funcDeclarations, (yyvsp[(10) - (10)].statementNode).m_funcDeclarations), @@ -4078,7 +4078,7 @@ yyreduce: break; case 248: -#line 996 "../parser/Grammar.y" +#line 996 "parser/Grammar.y" { ForInNode* node = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, (yyvsp[(3) - (7)].expressionNode).m_node, (yyvsp[(5) - (7)].expressionNode).m_node, (yyvsp[(7) - (7)].statementNode).m_node); setExceptionLocation(node, (yylsp[(3) - (7)]).first_column, (yylsp[(3) - (7)]).last_column, (yylsp[(5) - (7)]).last_column); @@ -4090,7 +4090,7 @@ yyreduce: break; case 249: -#line 1005 "../parser/Grammar.y" +#line 1005 "parser/Grammar.y" { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *(yyvsp[(4) - (8)].ident), 0, (yyvsp[(6) - (8)].expressionNode).m_node, (yyvsp[(8) - (8)].statementNode).m_node, (yylsp[(5) - (8)]).first_column, (yylsp[(5) - (8)]).first_column - (yylsp[(4) - (8)]).first_column, (yylsp[(6) - (8)]).last_column - (yylsp[(5) - (8)]).first_column); setExceptionLocation(forIn, (yylsp[(4) - (8)]).first_column, (yylsp[(5) - (8)]).first_column + 1, (yylsp[(6) - (8)]).last_column); appendToVarDeclarationList(GLOBAL_DATA, (yyvsp[(8) - (8)].statementNode).m_varDeclarations, *(yyvsp[(4) - (8)].ident), DeclarationStacks::HasInitializer); @@ -4099,7 +4099,7 @@ yyreduce: break; case 250: -#line 1011 "../parser/Grammar.y" +#line 1011 "parser/Grammar.y" { ForInNode *forIn = new (GLOBAL_DATA) ForInNode(GLOBAL_DATA, *(yyvsp[(4) - (9)].ident), (yyvsp[(5) - (9)].expressionNode).m_node, (yyvsp[(7) - (9)].expressionNode).m_node, (yyvsp[(9) - (9)].statementNode).m_node, (yylsp[(5) - (9)]).first_column, (yylsp[(5) - (9)]).first_column - (yylsp[(4) - (9)]).first_column, (yylsp[(5) - (9)]).last_column - (yylsp[(5) - (9)]).first_column); setExceptionLocation(forIn, (yylsp[(4) - (9)]).first_column, (yylsp[(6) - (9)]).first_column + 1, (yylsp[(7) - (9)]).last_column); appendToVarDeclarationList(GLOBAL_DATA, (yyvsp[(9) - (9)].statementNode).m_varDeclarations, *(yyvsp[(4) - (9)].ident), DeclarationStacks::HasInitializer); @@ -4110,17 +4110,17 @@ yyreduce: break; case 251: -#line 1021 "../parser/Grammar.y" +#line 1021 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(0, 0, 0); ;} break; case 253: -#line 1026 "../parser/Grammar.y" +#line 1026 "parser/Grammar.y" { (yyval.expressionNode) = createNodeInfo<ExpressionNode*>(0, 0, 0); ;} break; case 255: -#line 1031 "../parser/Grammar.y" +#line 1031 "parser/Grammar.y" { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(1) - (2)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); @@ -4128,7 +4128,7 @@ yyreduce: break; case 256: -#line 1035 "../parser/Grammar.y" +#line 1035 "parser/Grammar.y" { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(1) - (2)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); @@ -4136,7 +4136,7 @@ yyreduce: break; case 257: -#line 1039 "../parser/Grammar.y" +#line 1039 "parser/Grammar.y" { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *(yyvsp[(2) - (3)].ident)); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(2) - (3)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); @@ -4144,7 +4144,7 @@ yyreduce: break; case 258: -#line 1043 "../parser/Grammar.y" +#line 1043 "parser/Grammar.y" { ContinueNode* node = new (GLOBAL_DATA) ContinueNode(GLOBAL_DATA, *(yyvsp[(2) - (3)].ident)); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(2) - (3)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); @@ -4152,82 +4152,82 @@ yyreduce: break; case 259: -#line 1050 "../parser/Grammar.y" +#line 1050 "parser/Grammar.y" { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(1) - (2)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (2)]), (yylsp[(2) - (2)])); ;} break; case 260: -#line 1053 "../parser/Grammar.y" +#line 1053 "parser/Grammar.y" { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(1) - (2)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA), 0, 0, 0, 0); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (2)]), (yylsp[(1) - (2)])); AUTO_SEMICOLON; ;} break; case 261: -#line 1056 "../parser/Grammar.y" +#line 1056 "parser/Grammar.y" { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *(yyvsp[(2) - (3)].ident)); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(2) - (3)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(3) - (3)])); ;} break; case 262: -#line 1059 "../parser/Grammar.y" +#line 1059 "parser/Grammar.y" { BreakNode* node = new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *(yyvsp[(2) - (3)].ident)); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(2) - (3)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) BreakNode(GLOBAL_DATA, *(yyvsp[(2) - (3)].ident)), 0, 0, 0, 0); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(2) - (3)])); AUTO_SEMICOLON; ;} break; case 263: -#line 1065 "../parser/Grammar.y" +#line 1065 "parser/Grammar.y" { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(1) - (2)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (2)]), (yylsp[(2) - (2)])); ;} break; case 264: -#line 1068 "../parser/Grammar.y" +#line 1068 "parser/Grammar.y" { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, 0); setExceptionLocation(node, (yylsp[(1) - (2)]).first_column, (yylsp[(1) - (2)]).last_column, (yylsp[(1) - (2)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, 0, 0); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (2)]), (yylsp[(1) - (2)])); AUTO_SEMICOLON; ;} break; case 265: -#line 1071 "../parser/Grammar.y" +#line 1071 "parser/Grammar.y" { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, (yyvsp[(2) - (3)].expressionNode).m_node); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(2) - (3)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, (yyvsp[(2) - (3)].expressionNode).m_features, (yyvsp[(2) - (3)].expressionNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(3) - (3)])); ;} break; case 266: -#line 1074 "../parser/Grammar.y" +#line 1074 "parser/Grammar.y" { ReturnNode* node = new (GLOBAL_DATA) ReturnNode(GLOBAL_DATA, (yyvsp[(2) - (3)].expressionNode).m_node); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(2) - (3)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, (yyvsp[(2) - (3)].expressionNode).m_features, (yyvsp[(2) - (3)].expressionNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(2) - (3)])); AUTO_SEMICOLON; ;} break; case 267: -#line 1080 "../parser/Grammar.y" +#line 1080 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) WithNode(GLOBAL_DATA, (yyvsp[(3) - (5)].expressionNode).m_node, (yyvsp[(5) - (5)].statementNode).m_node, (yylsp[(3) - (5)]).last_column, (yylsp[(3) - (5)]).last_column - (yylsp[(3) - (5)]).first_column), (yyvsp[(5) - (5)].statementNode).m_varDeclarations, (yyvsp[(5) - (5)].statementNode).m_funcDeclarations, (yyvsp[(3) - (5)].expressionNode).m_features | (yyvsp[(5) - (5)].statementNode).m_features | WithFeature, (yyvsp[(3) - (5)].expressionNode).m_numConstants + (yyvsp[(5) - (5)].statementNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (5)]), (yylsp[(4) - (5)])); ;} break; case 268: -#line 1086 "../parser/Grammar.y" +#line 1086 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) SwitchNode(GLOBAL_DATA, (yyvsp[(3) - (5)].expressionNode).m_node, (yyvsp[(5) - (5)].caseBlockNode).m_node), (yyvsp[(5) - (5)].caseBlockNode).m_varDeclarations, (yyvsp[(5) - (5)].caseBlockNode).m_funcDeclarations, (yyvsp[(3) - (5)].expressionNode).m_features | (yyvsp[(5) - (5)].caseBlockNode).m_features, (yyvsp[(3) - (5)].expressionNode).m_numConstants + (yyvsp[(5) - (5)].caseBlockNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (5)]), (yylsp[(4) - (5)])); ;} break; case 269: -#line 1092 "../parser/Grammar.y" +#line 1092 "parser/Grammar.y" { (yyval.caseBlockNode) = createNodeDeclarationInfo<CaseBlockNode*>(new (GLOBAL_DATA) CaseBlockNode(GLOBAL_DATA, (yyvsp[(2) - (3)].clauseList).m_node.head, 0, 0), (yyvsp[(2) - (3)].clauseList).m_varDeclarations, (yyvsp[(2) - (3)].clauseList).m_funcDeclarations, (yyvsp[(2) - (3)].clauseList).m_features, (yyvsp[(2) - (3)].clauseList).m_numConstants); ;} break; case 270: -#line 1094 "../parser/Grammar.y" +#line 1094 "parser/Grammar.y" { (yyval.caseBlockNode) = createNodeDeclarationInfo<CaseBlockNode*>(new (GLOBAL_DATA) CaseBlockNode(GLOBAL_DATA, (yyvsp[(2) - (5)].clauseList).m_node.head, (yyvsp[(3) - (5)].caseClauseNode).m_node, (yyvsp[(4) - (5)].clauseList).m_node.head), mergeDeclarationLists(mergeDeclarationLists((yyvsp[(2) - (5)].clauseList).m_varDeclarations, (yyvsp[(3) - (5)].caseClauseNode).m_varDeclarations), (yyvsp[(4) - (5)].clauseList).m_varDeclarations), mergeDeclarationLists(mergeDeclarationLists((yyvsp[(2) - (5)].clauseList).m_funcDeclarations, (yyvsp[(3) - (5)].caseClauseNode).m_funcDeclarations), (yyvsp[(4) - (5)].clauseList).m_funcDeclarations), @@ -4236,12 +4236,12 @@ yyreduce: break; case 271: -#line 1102 "../parser/Grammar.y" +#line 1102 "parser/Grammar.y" { (yyval.clauseList).m_node.head = 0; (yyval.clauseList).m_node.tail = 0; (yyval.clauseList).m_varDeclarations = 0; (yyval.clauseList).m_funcDeclarations = 0; (yyval.clauseList).m_features = 0; (yyval.clauseList).m_numConstants = 0; ;} break; case 273: -#line 1107 "../parser/Grammar.y" +#line 1107 "parser/Grammar.y" { (yyval.clauseList).m_node.head = new (GLOBAL_DATA) ClauseListNode(GLOBAL_DATA, (yyvsp[(1) - (1)].caseClauseNode).m_node); (yyval.clauseList).m_node.tail = (yyval.clauseList).m_node.head; (yyval.clauseList).m_varDeclarations = (yyvsp[(1) - (1)].caseClauseNode).m_varDeclarations; @@ -4251,7 +4251,7 @@ yyreduce: break; case 274: -#line 1113 "../parser/Grammar.y" +#line 1113 "parser/Grammar.y" { (yyval.clauseList).m_node.head = (yyvsp[(1) - (2)].clauseList).m_node.head; (yyval.clauseList).m_node.tail = new (GLOBAL_DATA) ClauseListNode(GLOBAL_DATA, (yyvsp[(1) - (2)].clauseList).m_node.tail, (yyvsp[(2) - (2)].caseClauseNode).m_node); (yyval.clauseList).m_varDeclarations = mergeDeclarationLists((yyvsp[(1) - (2)].clauseList).m_varDeclarations, (yyvsp[(2) - (2)].caseClauseNode).m_varDeclarations); @@ -4262,34 +4262,34 @@ yyreduce: break; case 275: -#line 1123 "../parser/Grammar.y" +#line 1123 "parser/Grammar.y" { (yyval.caseClauseNode) = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, (yyvsp[(2) - (3)].expressionNode).m_node), 0, 0, (yyvsp[(2) - (3)].expressionNode).m_features, (yyvsp[(2) - (3)].expressionNode).m_numConstants); ;} break; case 276: -#line 1124 "../parser/Grammar.y" +#line 1124 "parser/Grammar.y" { (yyval.caseClauseNode) = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, (yyvsp[(2) - (4)].expressionNode).m_node, (yyvsp[(4) - (4)].sourceElements).m_node), (yyvsp[(4) - (4)].sourceElements).m_varDeclarations, (yyvsp[(4) - (4)].sourceElements).m_funcDeclarations, (yyvsp[(2) - (4)].expressionNode).m_features | (yyvsp[(4) - (4)].sourceElements).m_features, (yyvsp[(2) - (4)].expressionNode).m_numConstants + (yyvsp[(4) - (4)].sourceElements).m_numConstants); ;} break; case 277: -#line 1128 "../parser/Grammar.y" +#line 1128 "parser/Grammar.y" { (yyval.caseClauseNode) = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, 0), 0, 0, 0, 0); ;} break; case 278: -#line 1129 "../parser/Grammar.y" +#line 1129 "parser/Grammar.y" { (yyval.caseClauseNode) = createNodeDeclarationInfo<CaseClauseNode*>(new (GLOBAL_DATA) CaseClauseNode(GLOBAL_DATA, 0, (yyvsp[(3) - (3)].sourceElements).m_node), (yyvsp[(3) - (3)].sourceElements).m_varDeclarations, (yyvsp[(3) - (3)].sourceElements).m_funcDeclarations, (yyvsp[(3) - (3)].sourceElements).m_features, (yyvsp[(3) - (3)].sourceElements).m_numConstants); ;} break; case 279: -#line 1133 "../parser/Grammar.y" +#line 1133 "parser/Grammar.y" { LabelNode* node = new (GLOBAL_DATA) LabelNode(GLOBAL_DATA, *(yyvsp[(1) - (3)].ident), (yyvsp[(3) - (3)].statementNode).m_node); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(2) - (3)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, (yyvsp[(3) - (3)].statementNode).m_varDeclarations, (yyvsp[(3) - (3)].statementNode).m_funcDeclarations, (yyvsp[(3) - (3)].statementNode).m_features, (yyvsp[(3) - (3)].statementNode).m_numConstants); ;} break; case 280: -#line 1139 "../parser/Grammar.y" +#line 1139 "parser/Grammar.y" { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, (yyvsp[(2) - (3)].expressionNode).m_node); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(2) - (3)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, (yyvsp[(2) - (3)].expressionNode).m_features, (yyvsp[(2) - (3)].expressionNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(2) - (3)])); @@ -4297,7 +4297,7 @@ yyreduce: break; case 281: -#line 1143 "../parser/Grammar.y" +#line 1143 "parser/Grammar.y" { ThrowNode* node = new (GLOBAL_DATA) ThrowNode(GLOBAL_DATA, (yyvsp[(2) - (3)].expressionNode).m_node); setExceptionLocation(node, (yylsp[(1) - (3)]).first_column, (yylsp[(2) - (3)]).last_column, (yylsp[(2) - (3)]).last_column); (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(node, 0, 0, (yyvsp[(2) - (3)].expressionNode).m_features, (yyvsp[(2) - (3)].expressionNode).m_numConstants); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (3)]), (yylsp[(2) - (3)])); AUTO_SEMICOLON; @@ -4305,7 +4305,7 @@ yyreduce: break; case 282: -#line 1150 "../parser/Grammar.y" +#line 1150 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, (yyvsp[(2) - (4)].statementNode).m_node, GLOBAL_DATA->propertyNames->nullIdentifier, false, 0, (yyvsp[(4) - (4)].statementNode).m_node), mergeDeclarationLists((yyvsp[(2) - (4)].statementNode).m_varDeclarations, (yyvsp[(4) - (4)].statementNode).m_varDeclarations), mergeDeclarationLists((yyvsp[(2) - (4)].statementNode).m_funcDeclarations, (yyvsp[(4) - (4)].statementNode).m_funcDeclarations), @@ -4315,7 +4315,7 @@ yyreduce: break; case 283: -#line 1156 "../parser/Grammar.y" +#line 1156 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, (yyvsp[(2) - (7)].statementNode).m_node, *(yyvsp[(5) - (7)].ident), ((yyvsp[(7) - (7)].statementNode).m_features & EvalFeature) != 0, (yyvsp[(7) - (7)].statementNode).m_node, 0), mergeDeclarationLists((yyvsp[(2) - (7)].statementNode).m_varDeclarations, (yyvsp[(7) - (7)].statementNode).m_varDeclarations), mergeDeclarationLists((yyvsp[(2) - (7)].statementNode).m_funcDeclarations, (yyvsp[(7) - (7)].statementNode).m_funcDeclarations), @@ -4325,7 +4325,7 @@ yyreduce: break; case 284: -#line 1163 "../parser/Grammar.y" +#line 1163 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, (yyvsp[(2) - (9)].statementNode).m_node, *(yyvsp[(5) - (9)].ident), ((yyvsp[(7) - (9)].statementNode).m_features & EvalFeature) != 0, (yyvsp[(7) - (9)].statementNode).m_node, (yyvsp[(9) - (9)].statementNode).m_node), mergeDeclarationLists(mergeDeclarationLists((yyvsp[(2) - (9)].statementNode).m_varDeclarations, (yyvsp[(7) - (9)].statementNode).m_varDeclarations), (yyvsp[(9) - (9)].statementNode).m_varDeclarations), mergeDeclarationLists(mergeDeclarationLists((yyvsp[(2) - (9)].statementNode).m_funcDeclarations, (yyvsp[(7) - (9)].statementNode).m_funcDeclarations), (yyvsp[(9) - (9)].statementNode).m_funcDeclarations), @@ -4335,24 +4335,24 @@ yyreduce: break; case 285: -#line 1172 "../parser/Grammar.y" +#line 1172 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (2)]), (yylsp[(2) - (2)])); ;} break; case 286: -#line 1174 "../parser/Grammar.y" +#line 1174 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) DebuggerStatementNode(GLOBAL_DATA), 0, 0, 0, 0); setStatementLocation((yyval.statementNode).m_node, (yylsp[(1) - (2)]), (yylsp[(1) - (2)])); AUTO_SEMICOLON; ;} break; case 287: -#line 1179 "../parser/Grammar.y" +#line 1179 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) FuncDeclNode(GLOBAL_DATA, *(yyvsp[(2) - (7)].ident), (yyvsp[(6) - (7)].functionBodyNode), GLOBAL_DATA->lexer->sourceCode((yyvsp[(5) - (7)].intValue), (yyvsp[(7) - (7)].intValue), (yylsp[(5) - (7)]).first_line)), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*(yyvsp[(2) - (7)].ident) == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | ClosureFeature, 0); setStatementLocation((yyvsp[(6) - (7)].functionBodyNode), (yylsp[(5) - (7)]), (yylsp[(7) - (7)])); (yyval.statementNode).m_funcDeclarations->data.append(static_cast<FuncDeclNode*>((yyval.statementNode).m_node)->body()); ;} break; case 288: -#line 1181 "../parser/Grammar.y" +#line 1181 "parser/Grammar.y" { (yyval.statementNode) = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) FuncDeclNode(GLOBAL_DATA, *(yyvsp[(2) - (8)].ident), (yyvsp[(7) - (8)].functionBodyNode), GLOBAL_DATA->lexer->sourceCode((yyvsp[(6) - (8)].intValue), (yyvsp[(8) - (8)].intValue), (yylsp[(6) - (8)]).first_line), (yyvsp[(4) - (8)].parameterList).m_node.head), 0, new (GLOBAL_DATA) ParserArenaData<DeclarationStacks::FunctionStack>, ((*(yyvsp[(2) - (8)].ident) == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0) | (yyvsp[(4) - (8)].parameterList).m_features | ClosureFeature, 0); if ((yyvsp[(4) - (8)].parameterList).m_features & ArgumentsFeature) @@ -4363,12 +4363,12 @@ yyreduce: break; case 289: -#line 1191 "../parser/Grammar.y" +#line 1191 "parser/Grammar.y" { (yyval.funcExprNode) = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, (yyvsp[(5) - (6)].functionBodyNode), GLOBAL_DATA->lexer->sourceCode((yyvsp[(4) - (6)].intValue), (yyvsp[(6) - (6)].intValue), (yylsp[(4) - (6)]).first_line)), ClosureFeature, 0); setStatementLocation((yyvsp[(5) - (6)].functionBodyNode), (yylsp[(4) - (6)]), (yylsp[(6) - (6)])); ;} break; case 290: -#line 1193 "../parser/Grammar.y" +#line 1193 "parser/Grammar.y" { (yyval.funcExprNode) = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, (yyvsp[(6) - (7)].functionBodyNode), GLOBAL_DATA->lexer->sourceCode((yyvsp[(5) - (7)].intValue), (yyvsp[(7) - (7)].intValue), (yylsp[(5) - (7)]).first_line), (yyvsp[(3) - (7)].parameterList).m_node.head), (yyvsp[(3) - (7)].parameterList).m_features | ClosureFeature, 0); if ((yyvsp[(3) - (7)].parameterList).m_features & ArgumentsFeature) @@ -4378,12 +4378,12 @@ yyreduce: break; case 291: -#line 1199 "../parser/Grammar.y" +#line 1199 "parser/Grammar.y" { (yyval.funcExprNode) = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, *(yyvsp[(2) - (7)].ident), (yyvsp[(6) - (7)].functionBodyNode), GLOBAL_DATA->lexer->sourceCode((yyvsp[(5) - (7)].intValue), (yyvsp[(7) - (7)].intValue), (yylsp[(5) - (7)]).first_line)), ClosureFeature, 0); setStatementLocation((yyvsp[(6) - (7)].functionBodyNode), (yylsp[(5) - (7)]), (yylsp[(7) - (7)])); ;} break; case 292: -#line 1201 "../parser/Grammar.y" +#line 1201 "parser/Grammar.y" { (yyval.funcExprNode) = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, *(yyvsp[(2) - (8)].ident), (yyvsp[(7) - (8)].functionBodyNode), GLOBAL_DATA->lexer->sourceCode((yyvsp[(6) - (8)].intValue), (yyvsp[(8) - (8)].intValue), (yylsp[(6) - (8)]).first_line), (yyvsp[(4) - (8)].parameterList).m_node.head), (yyvsp[(4) - (8)].parameterList).m_features | ClosureFeature, 0); if ((yyvsp[(4) - (8)].parameterList).m_features & ArgumentsFeature) @@ -4393,42 +4393,42 @@ yyreduce: break; case 293: -#line 1210 "../parser/Grammar.y" +#line 1210 "parser/Grammar.y" { (yyval.parameterList).m_node.head = new (GLOBAL_DATA) ParameterNode(GLOBAL_DATA, *(yyvsp[(1) - (1)].ident)); (yyval.parameterList).m_features = (*(yyvsp[(1) - (1)].ident) == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0; (yyval.parameterList).m_node.tail = (yyval.parameterList).m_node.head; ;} break; case 294: -#line 1213 "../parser/Grammar.y" +#line 1213 "parser/Grammar.y" { (yyval.parameterList).m_node.head = (yyvsp[(1) - (3)].parameterList).m_node.head; (yyval.parameterList).m_features = (yyvsp[(1) - (3)].parameterList).m_features | ((*(yyvsp[(3) - (3)].ident) == GLOBAL_DATA->propertyNames->arguments) ? ArgumentsFeature : 0); (yyval.parameterList).m_node.tail = new (GLOBAL_DATA) ParameterNode(GLOBAL_DATA, (yyvsp[(1) - (3)].parameterList).m_node.tail, *(yyvsp[(3) - (3)].ident)); ;} break; case 295: -#line 1219 "../parser/Grammar.y" +#line 1219 "parser/Grammar.y" { (yyval.functionBodyNode) = FunctionBodyNode::create(GLOBAL_DATA); ;} break; case 296: -#line 1220 "../parser/Grammar.y" +#line 1220 "parser/Grammar.y" { (yyval.functionBodyNode) = FunctionBodyNode::create(GLOBAL_DATA); ;} break; case 297: -#line 1224 "../parser/Grammar.y" +#line 1224 "parser/Grammar.y" { GLOBAL_DATA->parser->didFinishParsing(new (GLOBAL_DATA) SourceElements(GLOBAL_DATA), 0, 0, NoFeatures, (yylsp[(0) - (0)]).last_line, 0); ;} break; case 298: -#line 1225 "../parser/Grammar.y" +#line 1225 "parser/Grammar.y" { GLOBAL_DATA->parser->didFinishParsing((yyvsp[(1) - (1)].sourceElements).m_node, (yyvsp[(1) - (1)].sourceElements).m_varDeclarations, (yyvsp[(1) - (1)].sourceElements).m_funcDeclarations, (yyvsp[(1) - (1)].sourceElements).m_features, (yylsp[(1) - (1)]).last_line, (yyvsp[(1) - (1)].sourceElements).m_numConstants); ;} break; case 299: -#line 1230 "../parser/Grammar.y" +#line 1230 "parser/Grammar.y" { (yyval.sourceElements).m_node = new (GLOBAL_DATA) SourceElements(GLOBAL_DATA); (yyval.sourceElements).m_node->append((yyvsp[(1) - (1)].statementNode).m_node); (yyval.sourceElements).m_varDeclarations = (yyvsp[(1) - (1)].statementNode).m_varDeclarations; @@ -4439,7 +4439,7 @@ yyreduce: break; case 300: -#line 1237 "../parser/Grammar.y" +#line 1237 "parser/Grammar.y" { (yyval.sourceElements).m_node->append((yyvsp[(2) - (2)].statementNode).m_node); (yyval.sourceElements).m_varDeclarations = mergeDeclarationLists((yyvsp[(1) - (2)].sourceElements).m_varDeclarations, (yyvsp[(2) - (2)].statementNode).m_varDeclarations); (yyval.sourceElements).m_funcDeclarations = mergeDeclarationLists((yyvsp[(1) - (2)].sourceElements).m_funcDeclarations, (yyvsp[(2) - (2)].statementNode).m_funcDeclarations); @@ -4449,188 +4449,188 @@ yyreduce: break; case 304: -#line 1251 "../parser/Grammar.y" +#line 1251 "parser/Grammar.y" { ;} break; case 305: -#line 1252 "../parser/Grammar.y" +#line 1252 "parser/Grammar.y" { ;} break; case 306: -#line 1253 "../parser/Grammar.y" +#line 1253 "parser/Grammar.y" { if (!GLOBAL_DATA->lexer->skipRegExp()) YYABORT; ;} break; case 307: -#line 1254 "../parser/Grammar.y" +#line 1254 "parser/Grammar.y" { if (!GLOBAL_DATA->lexer->skipRegExp()) YYABORT; ;} break; case 308: -#line 1258 "../parser/Grammar.y" +#line 1258 "parser/Grammar.y" { ;} break; case 309: -#line 1259 "../parser/Grammar.y" +#line 1259 "parser/Grammar.y" { ;} break; case 310: -#line 1260 "../parser/Grammar.y" +#line 1260 "parser/Grammar.y" { ;} break; case 311: -#line 1261 "../parser/Grammar.y" +#line 1261 "parser/Grammar.y" { if (*(yyvsp[(1) - (7)].ident) != "get" && *(yyvsp[(1) - (7)].ident) != "set") YYABORT; ;} break; case 312: -#line 1262 "../parser/Grammar.y" +#line 1262 "parser/Grammar.y" { if (*(yyvsp[(1) - (8)].ident) != "get" && *(yyvsp[(1) - (8)].ident) != "set") YYABORT; ;} break; case 316: -#line 1272 "../parser/Grammar.y" +#line 1272 "parser/Grammar.y" { ;} break; case 317: -#line 1273 "../parser/Grammar.y" +#line 1273 "parser/Grammar.y" { ;} break; case 318: -#line 1275 "../parser/Grammar.y" +#line 1275 "parser/Grammar.y" { ;} break; case 322: -#line 1282 "../parser/Grammar.y" +#line 1282 "parser/Grammar.y" { ;} break; case 517: -#line 1650 "../parser/Grammar.y" +#line 1650 "parser/Grammar.y" { ;} break; case 518: -#line 1651 "../parser/Grammar.y" +#line 1651 "parser/Grammar.y" { ;} break; case 520: -#line 1656 "../parser/Grammar.y" +#line 1656 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 521: -#line 1660 "../parser/Grammar.y" +#line 1660 "parser/Grammar.y" { ;} break; case 522: -#line 1661 "../parser/Grammar.y" +#line 1661 "parser/Grammar.y" { ;} break; case 525: -#line 1667 "../parser/Grammar.y" +#line 1667 "parser/Grammar.y" { ;} break; case 526: -#line 1668 "../parser/Grammar.y" +#line 1668 "parser/Grammar.y" { ;} break; case 530: -#line 1675 "../parser/Grammar.y" +#line 1675 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 533: -#line 1684 "../parser/Grammar.y" +#line 1684 "parser/Grammar.y" { ;} break; case 534: -#line 1685 "../parser/Grammar.y" +#line 1685 "parser/Grammar.y" { ;} break; case 539: -#line 1702 "../parser/Grammar.y" +#line 1702 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 555: -#line 1733 "../parser/Grammar.y" +#line 1733 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 557: -#line 1735 "../parser/Grammar.y" +#line 1735 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 559: -#line 1740 "../parser/Grammar.y" +#line 1740 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 561: -#line 1742 "../parser/Grammar.y" +#line 1742 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 563: -#line 1747 "../parser/Grammar.y" +#line 1747 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 565: -#line 1749 "../parser/Grammar.y" +#line 1749 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 568: -#line 1761 "../parser/Grammar.y" +#line 1761 "parser/Grammar.y" { ;} break; case 569: -#line 1762 "../parser/Grammar.y" +#line 1762 "parser/Grammar.y" { ;} break; case 578: -#line 1786 "../parser/Grammar.y" +#line 1786 "parser/Grammar.y" { ;} break; case 580: -#line 1791 "../parser/Grammar.y" +#line 1791 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 585: -#line 1802 "../parser/Grammar.y" +#line 1802 "parser/Grammar.y" { AUTO_SEMICOLON; ;} break; case 592: -#line 1818 "../parser/Grammar.y" +#line 1818 "parser/Grammar.y" { ;} break; /* Line 1267 of yacc.c. */ -#line 4634 "JavaScriptCore/tmp/../generated/Grammar.tab.c" +#line 4634 "generated/Grammar.tab.c" default: break; } YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); @@ -4850,7 +4850,7 @@ yyreturn: } -#line 1834 "../parser/Grammar.y" +#line 1834 "parser/Grammar.y" #undef GLOBAL_DATA diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/Grammar.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/Grammar.h index 1fdb035..43a605a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/Grammar.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/Grammar.h @@ -174,7 +174,7 @@ #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED typedef union YYSTYPE -#line 146 "../parser/Grammar.y" +#line 146 "parser/Grammar.y" { int intValue; double doubleValue; @@ -207,7 +207,7 @@ typedef union YYSTYPE Operator op; } /* Line 1489 of yacc.c. */ -#line 211 "JavaScriptCore/tmp/../generated/Grammar.tab.h" +#line 211 "generated/Grammar.tab.h" YYSTYPE; # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/JSONObject.lut.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/JSONObject.lut.h index a9b1631..f1a8210 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/JSONObject.lut.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/JSONObject.lut.h @@ -1,4 +1,4 @@ -// Automatically generated from ../runtime/JSONObject.cpp using JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from runtime/JSONObject.cpp using /home/khansen/dev/qtwebkit-qtscript-integration/JavaScriptCore/create_hash_table. DO NOT EDIT! #include "Lookup.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/Lexer.lut.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/Lexer.lut.h index 95c33b6..107d98a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/Lexer.lut.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/Lexer.lut.h @@ -1,4 +1,4 @@ -// Automatically generated from ../parser/Keywords.table using JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from parser/Keywords.table using /home/khansen/dev/qtwebkit-qtscript-integration/JavaScriptCore/create_hash_table. DO NOT EDIT! #include "Lookup.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/MathObject.lut.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/MathObject.lut.h index 9cb0ee2..becbb8c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/MathObject.lut.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/MathObject.lut.h @@ -1,4 +1,4 @@ -// Automatically generated from ../runtime/MathObject.cpp using JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from runtime/MathObject.cpp using /home/khansen/dev/qtwebkit-qtscript-integration/JavaScriptCore/create_hash_table. DO NOT EDIT! #include "Lookup.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/NumberConstructor.lut.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/NumberConstructor.lut.h index 6285d62..9d754c7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/NumberConstructor.lut.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/NumberConstructor.lut.h @@ -1,4 +1,4 @@ -// Automatically generated from ../runtime/NumberConstructor.cpp using JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from runtime/NumberConstructor.cpp using /home/khansen/dev/qtwebkit-qtscript-integration/JavaScriptCore/create_hash_table. DO NOT EDIT! #include "Lookup.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/RegExpConstructor.lut.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/RegExpConstructor.lut.h index a3f15b3..c5fe7ad 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/RegExpConstructor.lut.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/RegExpConstructor.lut.h @@ -1,4 +1,4 @@ -// Automatically generated from ../runtime/RegExpConstructor.cpp using JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from runtime/RegExpConstructor.cpp using /home/khansen/dev/qtwebkit-qtscript-integration/JavaScriptCore/create_hash_table. DO NOT EDIT! #include "Lookup.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/RegExpObject.lut.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/RegExpObject.lut.h index 8c87f16..2d684ae 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/RegExpObject.lut.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/RegExpObject.lut.h @@ -1,4 +1,4 @@ -// Automatically generated from ../runtime/RegExpObject.cpp using JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from runtime/RegExpObject.cpp using /home/khansen/dev/qtwebkit-qtscript-integration/JavaScriptCore/create_hash_table. DO NOT EDIT! #include "Lookup.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/generated/StringPrototype.lut.h b/src/3rdparty/javascriptcore/JavaScriptCore/generated/StringPrototype.lut.h index f912298..c5dd4f0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/generated/StringPrototype.lut.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/generated/StringPrototype.lut.h @@ -1,10 +1,10 @@ -// Automatically generated from ../runtime/StringPrototype.cpp using JavaScriptCore/create_hash_table. DO NOT EDIT! +// Automatically generated from runtime/StringPrototype.cpp using /home/khansen/dev/qtwebkit-qtscript-integration/JavaScriptCore/create_hash_table. DO NOT EDIT! #include "Lookup.h" namespace JSC { -static const struct HashTableValue stringTableValues[33] = { +static const struct HashTableValue stringTableValues[36] = { { "toString", DontEnum|Function, (intptr_t)stringProtoFuncToString, (intptr_t)0 }, { "valueOf", DontEnum|Function, (intptr_t)stringProtoFuncToString, (intptr_t)0 }, { "charAt", DontEnum|Function, (intptr_t)stringProtoFuncCharAt, (intptr_t)1 }, @@ -37,9 +37,12 @@ static const struct HashTableValue stringTableValues[33] = { { "fontsize", DontEnum|Function, (intptr_t)stringProtoFuncFontsize, (intptr_t)1 }, { "anchor", DontEnum|Function, (intptr_t)stringProtoFuncAnchor, (intptr_t)1 }, { "link", DontEnum|Function, (intptr_t)stringProtoFuncLink, (intptr_t)1 }, + { "trim", DontEnum|Function, (intptr_t)stringProtoFuncTrim, (intptr_t)0 }, + { "trimLeft", DontEnum|Function, (intptr_t)stringProtoFuncTrimLeft, (intptr_t)0 }, + { "trimRight", DontEnum|Function, (intptr_t)stringProtoFuncTrimRight, (intptr_t)0 }, { 0, 0, 0, 0 } }; extern JSC_CONST_HASHTABLE HashTable stringTable = - { 71, 63, stringTableValues, 0 }; + { 133, 127, stringTableValues, 0 }; } // namespace diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/CachedCall.h b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/CachedCall.h index b9fa484..eb48a03 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/CachedCall.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/CachedCall.h @@ -38,7 +38,7 @@ namespace JSC { : m_valid(false) , m_interpreter(callFrame->interpreter()) , m_exception(exception) - , m_globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : function->scope().node()->globalObject()) + , m_globalObjectScope(callFrame, function->scope().globalObject()) { ASSERT(!function->isHostFunction()); m_closure = m_interpreter->prepareForRepeatCall(function->jsExecutable(), callFrame, function, argCount, function->scope().node(), exception); @@ -52,7 +52,14 @@ namespace JSC { } void setThis(JSValue v) { m_closure.setArgument(0, v); } void setArgument(int n, JSValue v) { m_closure.setArgument(n + 1, v); } - CallFrame* newCallFrame() { return m_closure.newCallFrame; } + + CallFrame* newCallFrame(ExecState* exec) + { + CallFrame* callFrame = m_closure.newCallFrame; + callFrame->setScopeChain(exec->scopeChain()); + return callFrame; + } + ~CachedCall() { if (m_valid) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/CallFrame.h b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/CallFrame.h index b04e1c1..6432f99 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/CallFrame.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/CallFrame.h @@ -39,7 +39,11 @@ namespace JSC { public: JSObject* callee() const { return this[RegisterFile::Callee].object(); } CodeBlock* codeBlock() const { return this[RegisterFile::CodeBlock].Register::codeBlock(); } - ScopeChainNode* scopeChain() const { return this[RegisterFile::ScopeChain].Register::scopeChain(); } + ScopeChainNode* scopeChain() const + { + ASSERT(this[RegisterFile::ScopeChain].Register::scopeChain()); + return this[RegisterFile::ScopeChain].Register::scopeChain(); + } int argumentCount() const { return this[RegisterFile::ArgumentCount].i(); } JSValue thisValue(); @@ -51,14 +55,14 @@ namespace JSC { // Differs from dynamicGlobalObject() during function calls across web browser frames. JSGlobalObject* lexicalGlobalObject() const { - return scopeChain()->globalObject(); + return scopeChain()->globalObject; } // Differs from lexicalGlobalObject because this will have DOM window shell rather than // the actual DOM window, which can't be "this" for security reasons. JSObject* globalThisValue() const { - return scopeChain()->globalThisObject(); + return scopeChain()->globalThis; } // FIXME: Elsewhere, we use JSGlobalData* rather than JSGlobalData&. @@ -66,6 +70,7 @@ namespace JSC { // or a pointer everywhere. JSGlobalData& globalData() const { + ASSERT(scopeChain()->globalData); return *scopeChain()->globalData; } @@ -105,9 +110,9 @@ namespace JSC { Arguments* optionalCalleeArguments() const { return this[RegisterFile::OptionalCalleeArguments].arguments(); } Instruction* returnPC() const { return this[RegisterFile::ReturnPC].vPC(); } - void setCalleeArguments(JSValue arguments) { this[RegisterFile::OptionalCalleeArguments] = arguments; } - void setCallerFrame(CallFrame* callerFrame) { this[RegisterFile::CallerFrame] = callerFrame; } - void setScopeChain(ScopeChainNode* scopeChain) { this[RegisterFile::ScopeChain] = scopeChain; } + void setCalleeArguments(JSValue arguments) { static_cast<Register*>(this)[RegisterFile::OptionalCalleeArguments] = arguments; } + void setCallerFrame(CallFrame* callerFrame) { static_cast<Register*>(this)[RegisterFile::CallerFrame] = callerFrame; } + void setScopeChain(ScopeChainNode* scopeChain) { static_cast<Register*>(this)[RegisterFile::ScopeChain] = scopeChain; } ALWAYS_INLINE void init(CodeBlock* codeBlock, Instruction* vPC, ScopeChainNode* scopeChain, CallFrame* callerFrame, int returnValueRegister, int argc, JSObject* callee) @@ -117,8 +122,8 @@ namespace JSC { setCodeBlock(codeBlock); setScopeChain(scopeChain); setCallerFrame(callerFrame); - this[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. - this[RegisterFile::ReturnValueRegister] = Register::withInt(returnValueRegister); + static_cast<Register*>(this)[RegisterFile::ReturnPC] = vPC; // This is either an Instruction* or a pointer into JIT generated code stored as an Instruction*. + static_cast<Register*>(this)[RegisterFile::ReturnValueRegister] = Register::withInt(returnValueRegister); setArgumentCount(argc); // original argument count (for the sake of the "arguments" object) setCallee(callee); setCalleeArguments(JSValue()); @@ -135,9 +140,9 @@ namespace JSC { CallFrame* removeHostCallFrameFlag() { return reinterpret_cast<CallFrame*>(reinterpret_cast<intptr_t>(this) & ~HostCallFrameFlag); } private: - void setArgumentCount(int count) { this[RegisterFile::ArgumentCount] = Register::withInt(count); } - void setCallee(JSObject* callee) { this[RegisterFile::Callee] = callee; } - void setCodeBlock(CodeBlock* codeBlock) { this[RegisterFile::CodeBlock] = codeBlock; } + void setArgumentCount(int count) { static_cast<Register*>(this)[RegisterFile::ArgumentCount] = Register::withInt(count); } + void setCallee(JSObject* callee) { static_cast<Register*>(this)[RegisterFile::Callee] = callee; } + void setCodeBlock(CodeBlock* codeBlock) { static_cast<Register*>(this)[RegisterFile::CodeBlock] = codeBlock; } static const intptr_t HostCallFrameFlag = 1; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp index 4f00b2b..2164b1d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.cpp @@ -95,8 +95,8 @@ static int depth(CodeBlock* codeBlock, ScopeChain& sc) #if USE(INTERPRETER) NEVER_INLINE bool Interpreter::resolve(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) { - int dst = (vPC + 1)->u.operand; - int property = (vPC + 2)->u.operand; + int dst = vPC[1].u.operand; + int property = vPC[2].u.operand; ScopeChainNode* scopeChain = callFrame->scopeChain(); ScopeChainIterator iter = scopeChain->begin(); @@ -125,9 +125,9 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP { CodeBlock* codeBlock = callFrame->codeBlock(); - int dst = (vPC + 1)->u.operand; - int property = (vPC + 2)->u.operand; - int skip = (vPC + 3)->u.operand + codeBlock->needsFullScopeChain(); + int dst = vPC[1].u.operand; + int property = vPC[2].u.operand; + int skip = vPC[3].u.operand + codeBlock->needsFullScopeChain(); ScopeChainNode* scopeChain = callFrame->scopeChain(); ScopeChainIterator iter = scopeChain->begin(); @@ -156,12 +156,12 @@ NEVER_INLINE bool Interpreter::resolveSkip(CallFrame* callFrame, Instruction* vP NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) { - int dst = (vPC + 1)->u.operand; - JSGlobalObject* globalObject = static_cast<JSGlobalObject*>((vPC + 2)->u.jsCell); + int dst = vPC[1].u.operand; + JSGlobalObject* globalObject = static_cast<JSGlobalObject*>(vPC[2].u.jsCell); ASSERT(globalObject->isGlobalObject()); - int property = (vPC + 3)->u.operand; - Structure* structure = (vPC + 4)->u.structure; - int offset = (vPC + 5)->u.operand; + int property = vPC[3].u.operand; + Structure* structure = vPC[4].u.structure; + int offset = vPC[5].u.operand; if (structure == globalObject->structure()) { callFrame->r(dst) = JSValue(globalObject->getDirectOffset(offset)); @@ -196,16 +196,16 @@ NEVER_INLINE bool Interpreter::resolveGlobal(CallFrame* callFrame, Instruction* NEVER_INLINE void Interpreter::resolveBase(CallFrame* callFrame, Instruction* vPC) { - int dst = (vPC + 1)->u.operand; - int property = (vPC + 2)->u.operand; + int dst = vPC[1].u.operand; + int property = vPC[2].u.operand; callFrame->r(dst) = JSValue(JSC::resolveBase(callFrame, callFrame->codeBlock()->identifier(property), callFrame->scopeChain())); } NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) { - int baseDst = (vPC + 1)->u.operand; - int propDst = (vPC + 2)->u.operand; - int property = (vPC + 3)->u.operand; + int baseDst = vPC[1].u.operand; + int propDst = vPC[2].u.operand; + int property = vPC[3].u.operand; ScopeChainNode* scopeChain = callFrame->scopeChain(); ScopeChainIterator iter = scopeChain->begin(); @@ -237,51 +237,6 @@ NEVER_INLINE bool Interpreter::resolveBaseAndProperty(CallFrame* callFrame, Inst return false; } -NEVER_INLINE bool Interpreter::resolveBaseAndFunc(CallFrame* callFrame, Instruction* vPC, JSValue& exceptionValue) -{ - int baseDst = (vPC + 1)->u.operand; - int funcDst = (vPC + 2)->u.operand; - int property = (vPC + 3)->u.operand; - - ScopeChainNode* scopeChain = callFrame->scopeChain(); - ScopeChainIterator iter = scopeChain->begin(); - ScopeChainIterator end = scopeChain->end(); - - // FIXME: add scopeDepthIsZero optimization - - ASSERT(iter != end); - - CodeBlock* codeBlock = callFrame->codeBlock(); - Identifier& ident = codeBlock->identifier(property); - JSObject* base; - do { - base = *iter; - PropertySlot slot(base); - if (base->getPropertySlot(callFrame, ident, slot)) { - // ECMA 11.2.3 says that if we hit an activation the this value should be null. - // However, section 10.2.3 says that in the case where the value provided - // by the caller is null, the global object should be used. It also says - // that the section does not apply to internal functions, but for simplicity - // of implementation we use the global object anyway here. This guarantees - // that in host objects you always get a valid object for this. - // We also handle wrapper substitution for the global object at the same time. - JSObject* thisObj = base->toThisObject(callFrame); - JSValue result = slot.getValue(callFrame, ident); - exceptionValue = callFrame->globalData().exception; - if (exceptionValue) - return false; - - callFrame->r(baseDst) = JSValue(thisObj); - callFrame->r(funcDst) = JSValue(result); - return true; - } - ++iter; - } while (iter != end); - - exceptionValue = createUndefinedVariableError(callFrame, ident, vPC - codeBlock->instructions().begin(), codeBlock); - return false; -} - #endif // USE(INTERPRETER) ALWAYS_INLINE CallFrame* Interpreter::slideRegisterWindowForCall(CodeBlock* newCodeBlock, RegisterFile* registerFile, CallFrame* callFrame, size_t registerOffset, int argc) @@ -349,7 +304,7 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r if (!program.isString()) return program; - UString programSource = asString(program)->value(); + UString programSource = asString(program)->value(callFrame); LiteralParser preparser(callFrame, programSource, LiteralParser::NonStrictJSON); if (JSValue parsedObject = preparser.tryLiteralParse()) @@ -367,10 +322,19 @@ NEVER_INLINE JSValue Interpreter::callEval(CallFrame* callFrame, RegisterFile* r } Interpreter::Interpreter() - : m_sampler(0) + : m_sampleEntryDepth(0) , m_reentryDepth(0) { +#if HAVE(COMPUTED_GOTO) privateExecute(InitializeAndReturn, 0, 0, 0); + + for (int i = 0; i < numOpcodeIDs; ++i) + m_opcodeIDTable.add(m_opcodeTable[i], static_cast<OpcodeID>(i)); +#endif // HAVE(COMPUTED_GOTO) + +#if ENABLE(OPCODE_SAMPLING) + enableSampler(); +#endif } #ifndef NDEBUG @@ -389,7 +353,7 @@ void Interpreter::dumpRegisters(CallFrame* callFrame) printf("-----------------------------------------------------------------------------\n"); CodeBlock* codeBlock = callFrame->codeBlock(); - RegisterFile* registerFile = &callFrame->scopeChain()->globalObject()->globalData()->interpreter->registerFile(); + RegisterFile* registerFile = &callFrame->scopeChain()->globalObject->globalData()->interpreter->registerFile(); const Register* it; const Register* end; JSValue v; @@ -577,7 +541,8 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); if (debugger) { DebuggerCallFrame debuggerCallFrame(callFrame, exceptionValue); - debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset)); + bool hasHandler = codeBlock->handlerForBytecodeOffset(bytecodeOffset); + debugger->exception(debuggerCallFrame, codeBlock->ownerExecutable()->sourceID(), codeBlock->lineNumberForBytecodeOffset(callFrame, bytecodeOffset), hasHandler); } // If we throw in the middle of a call instruction, we need to notify @@ -587,7 +552,7 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV #if !ENABLE(JIT) if (isCallBytecode(codeBlock->instructions()[bytecodeOffset].u.opcode)) profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 2].u.operand).jsValue()); - else if (codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct)) + else if (codeBlock->instructions().size() > (bytecodeOffset + 8) && codeBlock->instructions()[bytecodeOffset + 8].u.opcode == getOpcode(op_construct)) profiler->didExecute(callFrame, callFrame->r(codeBlock->instructions()[bytecodeOffset + 10].u.operand).jsValue()); #else int functionRegisterIndex; @@ -659,7 +624,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S return jsNull(); } - DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject()); + DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject); JSGlobalObject* lastGlobalObject = m_registerFile.globalObject(); JSGlobalObject* globalObject = callFrame->dynamicGlobalObject(); @@ -678,7 +643,7 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S JSValue result; { - SamplingTool::CallRecord callRecord(m_sampler); + SamplingTool::CallRecord callRecord(m_sampler.get()); m_reentryDepth++; #if ENABLE(JIT) @@ -719,7 +684,7 @@ JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* return jsNull(); } - DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject()); + DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject); CallFrame* newCallFrame = CallFrame::create(oldEnd); size_t dst = 0; @@ -744,7 +709,7 @@ JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* JSValue result; { - SamplingTool::CallRecord callRecord(m_sampler); + SamplingTool::CallRecord callRecord(m_sampler.get()); m_reentryDepth++; #if ENABLE(JIT) @@ -812,7 +777,7 @@ JSValue Interpreter::execute(CallFrameClosure& closure, JSValue* exception) JSValue result; { - SamplingTool::CallRecord callRecord(m_sampler); + SamplingTool::CallRecord callRecord(m_sampler.get()); m_reentryDepth++; #if ENABLE(JIT) @@ -849,7 +814,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec } } - DynamicGlobalObjectScope globalObjectScope(callFrame, callFrame->globalData().dynamicGlobalObject ? callFrame->globalData().dynamicGlobalObject : scopeChain->globalObject()); + DynamicGlobalObjectScope globalObjectScope(callFrame, scopeChain->globalObject); EvalCodeBlock* codeBlock = &eval->bytecode(callFrame, scopeChain); @@ -914,7 +879,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec JSValue result; { - SamplingTool::CallRecord callRecord(m_sampler); + SamplingTool::CallRecord callRecord(m_sampler.get()); m_reentryDepth++; #if ENABLE(JIT) @@ -932,7 +897,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec return result; } -NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine, int column) +NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHookID, int firstLine, int lastLine) { Debugger* debugger = callFrame->dynamicGlobalObject()->debugger(); if (!debugger) @@ -946,7 +911,7 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook debugger->returnEvent(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine); return; case WillExecuteStatement: - debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine, column); + debugger->atStatement(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine); return; case WillExecuteProgram: debugger->willExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), firstLine); @@ -955,7 +920,7 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook debugger->didExecuteProgram(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine); return; case DidReachBreakpoint: - debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine, column); + debugger->didReachBreakpoint(callFrame, callFrame->codeBlock()->ownerExecutable()->sourceID(), lastLine); return; } } @@ -963,10 +928,10 @@ NEVER_INLINE void Interpreter::debug(CallFrame* callFrame, DebugHookID debugHook #if USE(INTERPRETER) NEVER_INLINE ScopeChainNode* Interpreter::createExceptionScope(CallFrame* callFrame, const Instruction* vPC) { - int dst = (++vPC)->u.operand; + int dst = vPC[1].u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); - Identifier& property = codeBlock->identifier((++vPC)->u.operand); - JSValue value = callFrame->r((++vPC)->u.operand).jsValue(); + Identifier& property = codeBlock->identifier(vPC[2].u.operand); + JSValue value = callFrame->r(vPC[3].u.operand).jsValue(); JSObject* scope = new (callFrame) JSStaticScopeObject(callFrame, property, value, DontDelete); callFrame->r(dst) = JSValue(scope); @@ -1018,22 +983,20 @@ NEVER_INLINE void Interpreter::tryCachePutByID(CallFrame* callFrame, CodeBlock* return; } - StructureChain* protoChain = structure->prototypeChain(callFrame); - if (!protoChain->isCacheable()) { - vPC[0] = getOpcode(op_put_by_id_generic); - return; - } - // Structure transition, cache transition info if (slot.type() == PutPropertySlot::NewProperty) { if (structure->isDictionary()) { vPC[0] = getOpcode(op_put_by_id_generic); return; } + + // put_by_id_transition checks the prototype chain for setters. + normalizePrototypeChain(callFrame, baseCell); + vPC[0] = getOpcode(op_put_by_id_transition); vPC[4] = structure->previousID(); vPC[5] = structure; - vPC[6] = protoChain; + vPC[6] = structure->prototypeChain(callFrame); vPC[7] = slot.cachedOffset(); codeBlock->refStructures(vPC); return; @@ -1111,41 +1074,46 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* return; } + if (structure->isDictionary()) { + vPC[0] = getOpcode(op_get_by_id_generic); + return; + } + if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { ASSERT(slot.slotBase().isObject()); JSObject* baseObject = asObject(slot.slotBase()); + size_t offset = slot.cachedOffset(); // Since we're accessing a prototype in a loop, it's a good bet that it // should not be treated as a dictionary. - if (baseObject->structure()->isDictionary()) - baseObject->setStructure(Structure::fromDictionaryTransition(baseObject->structure())); + if (baseObject->structure()->isDictionary()) { + baseObject->flattenDictionaryObject(); + offset = baseObject->structure()->get(propertyName); + } + + ASSERT(!baseObject->structure()->isUncacheableDictionary()); vPC[0] = getOpcode(op_get_by_id_proto); vPC[5] = baseObject->structure(); - vPC[6] = slot.cachedOffset(); + vPC[6] = offset; codeBlock->refStructures(vPC); return; } - size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot); + size_t offset = slot.cachedOffset(); + size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset); if (!count) { vPC[0] = getOpcode(op_get_by_id_generic); return; } - StructureChain* protoChain = structure->prototypeChain(callFrame); - if (!protoChain->isCacheable()) { - vPC[0] = getOpcode(op_get_by_id_generic); - return; - } - vPC[0] = getOpcode(op_get_by_id_chain); vPC[4] = structure; - vPC[5] = protoChain; + vPC[5] = structure->prototypeChain(callFrame); vPC[6] = count; - vPC[7] = slot.cachedOffset(); + vPC[7] = offset; codeBlock->refStructures(vPC); } @@ -1162,16 +1130,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi { // One-time initialization of our address tables. We have to put this code // here because our labels are only in scope inside this function. - if (flag == InitializeAndReturn) { + if (UNLIKELY(flag == InitializeAndReturn)) { #if HAVE(COMPUTED_GOTO) - #define ADD_BYTECODE(id, length) m_opcodeTable[id] = &&id; - FOR_EACH_OPCODE_ID(ADD_BYTECODE); - #undef ADD_BYTECODE - - #define ADD_OPCODE_ID(id, length) m_opcodeIDTable.add(&&id, id); - FOR_EACH_OPCODE_ID(ADD_OPCODE_ID); - #undef ADD_OPCODE_ID - ASSERT(m_opcodeIDTable.size() == numOpcodeIDs); + #define LIST_OPCODE_LABEL(id, length) &&id, + static Opcode labels[] = { FOR_EACH_OPCODE_ID(LIST_OPCODE_LABEL) }; + for (size_t i = 0; i < sizeof(labels) / sizeof(Opcode); ++i) + m_opcodeTable[i] = labels[i]; + #undef LIST_OPCODE_LABEL #endif // HAVE(COMPUTED_GOTO) return JSValue(); } @@ -1249,10 +1214,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Constructs a new empty Object instance using the original constructor, and puts the result in register dst. */ - int dst = (++vPC)->u.operand; + int dst = vPC[1].u.operand; callFrame->r(dst) = JSValue(constructEmptyObject(callFrame)); - ++vPC; + vPC += OPCODE_LENGTH(op_new_object); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_new_array) { @@ -1263,13 +1228,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi The array will contain argCount elements with values taken from registers starting at register firstArg. */ - int dst = (++vPC)->u.operand; - int firstArg = (++vPC)->u.operand; - int argCount = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int firstArg = vPC[2].u.operand; + int argCount = vPC[3].u.operand; ArgList args(callFrame->registers() + firstArg, argCount); callFrame->r(dst) = JSValue(constructArray(callFrame, args)); - ++vPC; + vPC += OPCODE_LENGTH(op_new_array); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_new_regexp) { @@ -1279,11 +1244,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi constructor from regexp regExp, and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int regExp = (++vPC)->u.operand; - callFrame->r(dst) = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject()->regExpStructure(), callFrame->codeBlock()->regexp(regExp))); + int dst = vPC[1].u.operand; + int regExp = vPC[2].u.operand; + callFrame->r(dst) = JSValue(new (globalData) RegExpObject(callFrame->scopeChain()->globalObject->regExpStructure(), callFrame->codeBlock()->regexp(regExp))); - ++vPC; + vPC += OPCODE_LENGTH(op_new_regexp); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_mov) { @@ -1291,11 +1256,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Copies register src to register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; callFrame->r(dst) = callFrame->r(src); - ++vPC; + vPC += OPCODE_LENGTH(op_mov); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_eq) { @@ -1305,9 +1270,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi as with the ECMAScript '==' operator, and puts the result as a boolean in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); if (src1.isInt32() && src2.isInt32()) callFrame->r(dst) = jsBoolean(src1.asInt32() == src2.asInt32()); else { @@ -1316,7 +1281,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_eq); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_eq_null) { @@ -1325,17 +1290,17 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Checks whether register src is null, as with the ECMAScript '!=' operator, and puts the result as a boolean in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); if (src.isUndefinedOrNull()) { callFrame->r(dst) = jsBoolean(true); - ++vPC; + vPC += OPCODE_LENGTH(op_eq_null); NEXT_INSTRUCTION(); } callFrame->r(dst) = jsBoolean(src.isCell() && src.asCell()->structure()->typeInfo().masqueradesAsUndefined()); - ++vPC; + vPC += OPCODE_LENGTH(op_eq_null); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_neq) { @@ -1345,9 +1310,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi equal, as with the ECMAScript '!=' operator, and puts the result as a boolean in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); if (src1.isInt32() && src2.isInt32()) callFrame->r(dst) = jsBoolean(src1.asInt32() != src2.asInt32()); else { @@ -1356,7 +1321,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_neq); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_neq_null) { @@ -1365,17 +1330,17 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Checks whether register src is not null, as with the ECMAScript '!=' operator, and puts the result as a boolean in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); if (src.isUndefinedOrNull()) { callFrame->r(dst) = jsBoolean(false); - ++vPC; + vPC += OPCODE_LENGTH(op_neq_null); NEXT_INSTRUCTION(); } callFrame->r(dst) = jsBoolean(!src.isCell() || !asCell(src)->structure()->typeInfo().masqueradesAsUndefined()); - ++vPC; + vPC += OPCODE_LENGTH(op_neq_null); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_stricteq) { @@ -1385,12 +1350,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi equal, as with the ECMAScript '===' operator, and puts the result as a boolean in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - callFrame->r(dst) = jsBoolean(JSValue::strictEqual(src1, src2)); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); + callFrame->r(dst) = jsBoolean(JSValue::strictEqual(callFrame, src1, src2)); - ++vPC; + vPC += OPCODE_LENGTH(op_stricteq); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_nstricteq) { @@ -1400,12 +1365,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi strictly equal, as with the ECMAScript '!==' operator, and puts the result as a boolean in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - callFrame->r(dst) = jsBoolean(!JSValue::strictEqual(src1, src2)); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); + callFrame->r(dst) = jsBoolean(!JSValue::strictEqual(callFrame, src1, src2)); - ++vPC; + vPC += OPCODE_LENGTH(op_nstricteq); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_less) { @@ -1415,14 +1380,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi with the ECMAScript '<' operator, and puts the result as a boolean in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); JSValue result = jsBoolean(jsLess(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; - ++vPC; + vPC += OPCODE_LENGTH(op_less); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_lesseq) { @@ -1432,14 +1397,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi register src2, as with the ECMAScript '<=' operator, and puts the result as a boolean in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); JSValue result = jsBoolean(jsLessEq(callFrame, src1, src2)); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; - ++vPC; + vPC += OPCODE_LENGTH(op_lesseq); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_pre_inc) { @@ -1448,7 +1413,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Converts register srcDst to number, adds one, and puts the result back in register srcDst. */ - int srcDst = (++vPC)->u.operand; + int srcDst = vPC[1].u.operand; JSValue v = callFrame->r(srcDst).jsValue(); if (v.isInt32() && v.asInt32() < INT_MAX) callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1); @@ -1458,7 +1423,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(srcDst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_pre_inc); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_pre_dec) { @@ -1467,7 +1432,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Converts register srcDst to number, subtracts one, and puts the result back in register srcDst. */ - int srcDst = (++vPC)->u.operand; + int srcDst = vPC[1].u.operand; JSValue v = callFrame->r(srcDst).jsValue(); if (v.isInt32() && v.asInt32() > INT_MIN) callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1); @@ -1477,7 +1442,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(srcDst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_pre_dec); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_post_inc) { @@ -1487,8 +1452,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi written to register dst, and the number plus one is written back to register srcDst. */ - int dst = (++vPC)->u.operand; - int srcDst = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int srcDst = vPC[2].u.operand; JSValue v = callFrame->r(srcDst).jsValue(); if (v.isInt32() && v.asInt32() < INT_MAX) { callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() + 1); @@ -1500,7 +1465,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = number; } - ++vPC; + vPC += OPCODE_LENGTH(op_post_inc); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_post_dec) { @@ -1510,8 +1475,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi written to register dst, and the number minus one is written back to register srcDst. */ - int dst = (++vPC)->u.operand; - int srcDst = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int srcDst = vPC[2].u.operand; JSValue v = callFrame->r(srcDst).jsValue(); if (v.isInt32() && v.asInt32() > INT_MIN) { callFrame->r(srcDst) = jsNumber(callFrame, v.asInt32() - 1); @@ -1523,7 +1488,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = number; } - ++vPC; + vPC += OPCODE_LENGTH(op_post_dec); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_to_jsnumber) { @@ -1532,8 +1497,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Converts register src to number, and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; JSValue srcVal = callFrame->r(src).jsValue(); @@ -1545,7 +1510,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_to_jsnumber); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_negate) { @@ -1554,8 +1519,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Converts register src to number, negates it, and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); if (src.isInt32() && src.asInt32()) callFrame->r(dst) = jsNumber(callFrame, -src.asInt32()); else { @@ -1564,7 +1529,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_negate); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_add) { @@ -1574,17 +1539,17 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi in register dst. (JS add may be string concatenation or numeric add, depending on the types of the operands.) */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() & 0xc0000000)) // no overflow + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); + if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() + src2.asInt32()); else { JSValue result = jsAdd(callFrame, src1, src2); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; } - vPC += 2; + vPC += OPCODE_LENGTH(op_add); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_mul) { @@ -1593,9 +1558,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Multiplies register src1 and register src2 (converted to numbers), and puts the product in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() * src2.asInt32()); else { @@ -1604,7 +1569,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - vPC += 2; + vPC += OPCODE_LENGTH(op_mul); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_div) { @@ -1614,15 +1579,15 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi register divisor (converted to number), and puts the quotient in register dst. */ - int dst = (++vPC)->u.operand; - JSValue dividend = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue divisor = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue(); JSValue result = jsNumber(callFrame, dividend.toNumber(callFrame) / divisor.toNumber(callFrame)); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; - vPC += 2; + vPC += OPCODE_LENGTH(op_div); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_mod) { @@ -1632,15 +1597,15 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi register divisor (converted to number), and puts the remainder in register dst. */ - int dst = (++vPC)->u.operand; - JSValue dividend = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue divisor = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue dividend = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue divisor = callFrame->r(vPC[3].u.operand).jsValue(); if (dividend.isInt32() && divisor.isInt32() && divisor.asInt32() != 0) { JSValue result = jsNumber(callFrame, dividend.asInt32() % divisor.asInt32()); ASSERT(result); callFrame->r(dst) = result; - ++vPC; + vPC += OPCODE_LENGTH(op_mod); NEXT_INSTRUCTION(); } @@ -1651,7 +1616,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSValue result = jsNumber(callFrame, fmod(d1, d2)); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; - ++vPC; + vPC += OPCODE_LENGTH(op_mod); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_sub) { @@ -1661,17 +1626,17 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi src1 (converted to number), and puts the difference in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() & 0xc0000000)) // no overflow + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); + if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() - src2.asInt32()); else { JSValue result = jsNumber(callFrame, src1.toNumber(callFrame) - src2.toNumber(callFrame)); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; } - vPC += 2; + vPC += OPCODE_LENGTH(op_sub); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_lshift) { @@ -1681,9 +1646,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi register shift (converted to uint32), and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - JSValue val = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue shift = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue val = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue shift = callFrame->r(vPC[3].u.operand).jsValue(); if (val.isInt32() && shift.isInt32()) callFrame->r(dst) = jsNumber(callFrame, val.asInt32() << (shift.asInt32() & 0x1f)); @@ -1693,7 +1658,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_lshift); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_rshift) { @@ -1703,9 +1668,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi to int32) by register shift (converted to uint32), and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - JSValue val = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue shift = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue val = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue shift = callFrame->r(vPC[3].u.operand).jsValue(); if (val.isInt32() && shift.isInt32()) callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f)); @@ -1715,7 +1680,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_rshift); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_urshift) { @@ -1725,9 +1690,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi to uint32) by register shift (converted to uint32), and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - JSValue val = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue shift = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue val = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue shift = callFrame->r(vPC[3].u.operand).jsValue(); if (val.isUInt32() && shift.isInt32()) callFrame->r(dst) = jsNumber(callFrame, val.asInt32() >> (shift.asInt32() & 0x1f)); else { @@ -1736,7 +1701,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_urshift); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_bitand) { @@ -1746,9 +1711,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi and register src2 (converted to int32), and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); if (src1.isInt32() && src2.isInt32()) callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() & src2.asInt32()); else { @@ -1757,7 +1722,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - vPC += 2; + vPC += OPCODE_LENGTH(op_bitand); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_bitxor) { @@ -1767,9 +1732,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi and register src2 (converted to int32), and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); if (src1.isInt32() && src2.isInt32()) callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() ^ src2.asInt32()); else { @@ -1778,7 +1743,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - vPC += 2; + vPC += OPCODE_LENGTH(op_bitxor); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_bitor) { @@ -1788,9 +1753,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi and register src2 (converted to int32), and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); if (src1.isInt32() && src2.isInt32()) callFrame->r(dst) = jsNumber(callFrame, src1.asInt32() | src2.asInt32()); else { @@ -1799,7 +1764,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = result; } - vPC += 2; + vPC += OPCODE_LENGTH(op_bitor); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_bitnot) { @@ -1808,8 +1773,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Computes bitwise NOT of register src1 (converted to int32), and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - JSValue src = callFrame->r((++vPC)->u.operand).jsValue(); + int dst = vPC[1].u.operand; + JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); if (src.isInt32()) callFrame->r(dst) = jsNumber(callFrame, ~src.asInt32()); else { @@ -1817,7 +1782,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; } - ++vPC; + vPC += OPCODE_LENGTH(op_bitnot); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_not) { @@ -1826,13 +1791,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Computes logical NOT of register src (converted to boolean), and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; JSValue result = jsBoolean(!callFrame->r(src).jsValue().toBoolean(callFrame)); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; - ++vPC; + vPC += OPCODE_LENGTH(op_not); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_instanceof) { @@ -1862,7 +1827,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi CHECK_FOR_EXCEPTION(); callFrame->r(dst) = jsBoolean(result); - vPC += 5; + vPC += OPCODE_LENGTH(op_instanceof); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_typeof) { @@ -1871,11 +1836,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Determines the type string for src according to ECMAScript rules, and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; callFrame->r(dst) = JSValue(jsTypeStringForValue(callFrame, callFrame->r(src).jsValue())); - ++vPC; + vPC += OPCODE_LENGTH(op_typeof); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_is_undefined) { @@ -1885,12 +1850,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi the ECMAScript rules is "undefined", and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; JSValue v = callFrame->r(src).jsValue(); callFrame->r(dst) = jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined()); - ++vPC; + vPC += OPCODE_LENGTH(op_is_undefined); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_is_boolean) { @@ -1900,11 +1865,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi the ECMAScript rules is "boolean", and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isBoolean()); - ++vPC; + vPC += OPCODE_LENGTH(op_is_boolean); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_is_number) { @@ -1914,11 +1879,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi the ECMAScript rules is "number", and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isNumber()); - ++vPC; + vPC += OPCODE_LENGTH(op_is_number); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_is_string) { @@ -1928,11 +1893,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi the ECMAScript rules is "string", and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; callFrame->r(dst) = jsBoolean(callFrame->r(src).jsValue().isString()); - ++vPC; + vPC += OPCODE_LENGTH(op_is_string); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_is_object) { @@ -1942,11 +1907,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi the ECMAScript rules is "object", and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; callFrame->r(dst) = jsBoolean(jsIsObjectType(callFrame->r(src).jsValue())); - ++vPC; + vPC += OPCODE_LENGTH(op_is_object); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_is_function) { @@ -1956,11 +1921,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi the ECMAScript rules is "function", and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; callFrame->r(dst) = jsBoolean(jsIsFunctionType(callFrame->r(src).jsValue())); - ++vPC; + vPC += OPCODE_LENGTH(op_is_function); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_in) { @@ -1972,9 +1937,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Raises an exception if register constructor is not an object. */ - int dst = (++vPC)->u.operand; - int property = (++vPC)->u.operand; - int base = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int property = vPC[2].u.operand; + int base = vPC[3].u.operand; JSValue baseVal = callFrame->r(base).jsValue(); if (isInvalidParamForIn(callFrame, callFrame->codeBlock(), vPC, baseVal, exceptionValue)) @@ -1993,7 +1958,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = jsBoolean(baseObj->hasProperty(callFrame, property)); } - ++vPC; + vPC += OPCODE_LENGTH(op_in); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_resolve) { @@ -2006,7 +1971,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (UNLIKELY(!resolve(callFrame, vPC, exceptionValue))) goto vm_throw; - vPC += 3; + vPC += OPCODE_LENGTH(op_resolve); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_resolve_skip) { @@ -2019,7 +1984,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (UNLIKELY(!resolveSkip(callFrame, vPC, exceptionValue))) goto vm_throw; - vPC += 4; + vPC += OPCODE_LENGTH(op_resolve_skip); NEXT_INSTRUCTION(); } @@ -2034,7 +1999,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (UNLIKELY(!resolveGlobal(callFrame, vPC, exceptionValue))) goto vm_throw; - vPC += 6; + vPC += OPCODE_LENGTH(op_resolve_global); NEXT_INSTRUCTION(); } @@ -2043,13 +2008,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Gets the global var at global slot index and places it in register dst. */ - int dst = (++vPC)->u.operand; - JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell); + int dst = vPC[1].u.operand; + JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[2].u.jsCell); ASSERT(scope->isGlobalObject()); - int index = (++vPC)->u.operand; + int index = vPC[3].u.operand; callFrame->r(dst) = scope->registerAt(index); - ++vPC; + vPC += OPCODE_LENGTH(op_get_global_var); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_put_global_var) { @@ -2057,13 +2022,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Puts value into global slot index. */ - JSGlobalObject* scope = static_cast<JSGlobalObject*>((++vPC)->u.jsCell); + JSGlobalObject* scope = static_cast<JSGlobalObject*>(vPC[1].u.jsCell); ASSERT(scope->isGlobalObject()); - int index = (++vPC)->u.operand; - int value = (++vPC)->u.operand; + int index = vPC[2].u.operand; + int value = vPC[3].u.operand; scope->registerAt(index) = JSValue(callFrame->r(value).jsValue()); - ++vPC; + vPC += OPCODE_LENGTH(op_put_global_var); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_get_scoped_var) { @@ -2072,9 +2037,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Loads the contents of the index-th local from the scope skip nodes from the top of the scope chain, and places it in register dst */ - int dst = (++vPC)->u.operand; - int index = (++vPC)->u.operand; - int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain(); + int dst = vPC[1].u.operand; + int index = vPC[2].u.operand; + int skip = vPC[3].u.operand + callFrame->codeBlock()->needsFullScopeChain(); ScopeChainNode* scopeChain = callFrame->scopeChain(); ScopeChainIterator iter = scopeChain->begin(); @@ -2088,16 +2053,16 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT((*iter)->isVariableObject()); JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); callFrame->r(dst) = scope->registerAt(index); - ++vPC; + vPC += OPCODE_LENGTH(op_get_scoped_var); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_put_scoped_var) { /* put_scoped_var index(n) skip(n) value(r) */ - int index = (++vPC)->u.operand; - int skip = (++vPC)->u.operand + callFrame->codeBlock()->needsFullScopeChain(); - int value = (++vPC)->u.operand; + int index = vPC[1].u.operand; + int skip = vPC[2].u.operand + callFrame->codeBlock()->needsFullScopeChain(); + int value = vPC[3].u.operand; ScopeChainNode* scopeChain = callFrame->scopeChain(); ScopeChainIterator iter = scopeChain->begin(); @@ -2111,7 +2076,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT((*iter)->isVariableObject()); JSVariableObject* scope = static_cast<JSVariableObject*>(*iter); scope->registerAt(index) = JSValue(callFrame->r(value).jsValue()); - ++vPC; + vPC += OPCODE_LENGTH(op_put_scoped_var); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_resolve_base) { @@ -2124,7 +2089,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ resolveBase(callFrame, vPC); - vPC += 3; + vPC += OPCODE_LENGTH(op_resolve_base); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_resolve_with_base) { @@ -2142,7 +2107,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (UNLIKELY(!resolveBaseAndProperty(callFrame, vPC, exceptionValue))) goto vm_throw; - vPC += 4; + vPC += OPCODE_LENGTH(op_resolve_with_base); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_get_by_id) { @@ -2165,7 +2130,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi tryCacheGetByID(callFrame, codeBlock, vPC, baseValue, ident, slot); callFrame->r(dst) = result; - vPC += 8; + vPC += OPCODE_LENGTH(op_get_by_id); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_get_by_id_self) { @@ -2191,7 +2156,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset)); - vPC += 8; + vPC += OPCODE_LENGTH(op_get_by_id_self); NEXT_INSTRUCTION(); } } @@ -2223,9 +2188,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int offset = vPC[6].u.operand; ASSERT(protoObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset)); + ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == protoObject->getDirectOffset(offset)); callFrame->r(dst) = JSValue(protoObject->getDirectOffset(offset)); - vPC += 8; + vPC += OPCODE_LENGTH(op_get_by_id_proto); NEXT_INSTRUCTION(); } } @@ -2238,14 +2204,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi // Polymorphic self access caching currently only supported when JITting. ASSERT_NOT_REACHED(); // This case of the switch must not be empty, else (op_get_by_id_self_list == op_get_by_id_chain)! - vPC += 8; + vPC += OPCODE_LENGTH(op_get_by_id_self_list); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_get_by_id_proto_list) { // Polymorphic prototype access caching currently only supported when JITting. ASSERT_NOT_REACHED(); // This case of the switch must not be empty, else (op_get_by_id_proto_list == op_get_by_id_chain)! - vPC += 8; + vPC += OPCODE_LENGTH(op_get_by_id_proto_list); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_get_by_id_chain) { @@ -2278,9 +2244,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int offset = vPC[7].u.operand; ASSERT(baseObject->get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); + ASSERT(baseValue.get(callFrame, callFrame->codeBlock()->identifier(vPC[3].u.operand)) == baseObject->getDirectOffset(offset)); callFrame->r(dst) = JSValue(baseObject->getDirectOffset(offset)); - vPC += 8; + vPC += OPCODE_LENGTH(op_get_by_id_chain); NEXT_INSTRUCTION(); } @@ -2310,7 +2277,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; - vPC += 8; + vPC += OPCODE_LENGTH(op_get_by_id_generic); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_get_array_length) { @@ -2326,7 +2293,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (LIKELY(isJSArray(globalData, baseValue))) { int dst = vPC[1].u.operand; callFrame->r(dst) = jsNumber(callFrame, asArray(baseValue)->length()); - vPC += 8; + vPC += OPCODE_LENGTH(op_get_array_length); NEXT_INSTRUCTION(); } @@ -2345,8 +2312,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSValue baseValue = callFrame->r(base).jsValue(); if (LIKELY(isJSString(globalData, baseValue))) { int dst = vPC[1].u.operand; - callFrame->r(dst) = jsNumber(callFrame, asString(baseValue)->value().size()); - vPC += 8; + callFrame->r(dst) = jsNumber(callFrame, asString(baseValue)->length()); + vPC += OPCODE_LENGTH(op_get_string_length); NEXT_INSTRUCTION(); } @@ -2376,7 +2343,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi tryCachePutByID(callFrame, codeBlock, vPC, baseValue, slot); - vPC += 8; + vPC += OPCODE_LENGTH(op_put_by_id); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_put_by_id_transition) { @@ -2421,7 +2388,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset); baseObject->putDirectOffset(offset, callFrame->r(value).jsValue()); - vPC += 8; + vPC += OPCODE_LENGTH(op_put_by_id_transition); NEXT_INSTRUCTION(); } } @@ -2456,7 +2423,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT(baseObject->offsetForLocation(baseObject->getDirectLocation(callFrame->codeBlock()->identifier(vPC[2].u.operand))) == offset); baseObject->putDirectOffset(offset, callFrame->r(value).jsValue()); - vPC += 8; + vPC += OPCODE_LENGTH(op_put_by_id_replace); NEXT_INSTRUCTION(); } } @@ -2483,7 +2450,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi baseValue.put(callFrame, ident, callFrame->r(value).jsValue(), slot); CHECK_FOR_EXCEPTION(); - vPC += 8; + vPC += OPCODE_LENGTH(op_put_by_id_generic); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_del_by_id) { @@ -2494,16 +2461,43 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi boolean indicating success (if true) or failure (if false) to register dst. */ - int dst = (++vPC)->u.operand; - int base = (++vPC)->u.operand; - int property = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int base = vPC[2].u.operand; + int property = vPC[3].u.operand; JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); Identifier& ident = callFrame->codeBlock()->identifier(property); JSValue result = jsBoolean(baseObj->deleteProperty(callFrame, ident)); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; - ++vPC; + vPC += OPCODE_LENGTH(op_del_by_id); + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_get_by_pname) { + int dst = vPC[1].u.operand; + int base = vPC[2].u.operand; + int property = vPC[3].u.operand; + int expected = vPC[4].u.operand; + int iter = vPC[5].u.operand; + int i = vPC[6].u.operand; + + JSValue baseValue = callFrame->r(base).jsValue(); + JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator(); + JSValue subscript = callFrame->r(property).jsValue(); + JSValue expectedSubscript = callFrame->r(expected).jsValue(); + int index = callFrame->r(i).i() - 1; + JSValue result; + int offset = 0; + if (subscript == expectedSubscript && baseValue.isCell() && (baseValue.asCell()->structure() == it->cachedStructure()) && it->getOffset(index, offset)) { + callFrame->r(dst) = asObject(baseValue)->getDirectOffset(offset); + vPC += OPCODE_LENGTH(op_get_by_pname); + NEXT_INSTRUCTION(); + } + Identifier propertyName(callFrame, subscript.toString(callFrame)); + result = baseValue.get(callFrame, propertyName); + CHECK_FOR_EXCEPTION(); + callFrame->r(dst) = result; + vPC += OPCODE_LENGTH(op_get_by_pname); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_get_by_val) { @@ -2514,9 +2508,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi in register dst. property is nominally converted to string but numbers are treated more efficiently. */ - int dst = (++vPC)->u.operand; - int base = (++vPC)->u.operand; - int property = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int base = vPC[2].u.operand; + int property = vPC[3].u.operand; JSValue baseValue = callFrame->r(base).jsValue(); JSValue subscript = callFrame->r(property).jsValue(); @@ -2532,7 +2526,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi else result = jsArray->JSArray::get(callFrame, i); } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) - result = asString(baseValue)->getIndex(&callFrame->globalData(), i); + result = asString(baseValue)->getIndex(callFrame, i); else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) result = asByteArray(baseValue)->getIndex(callFrame, i); else @@ -2544,7 +2538,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; - ++vPC; + vPC += OPCODE_LENGTH(op_get_by_val); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_put_by_val) { @@ -2558,9 +2552,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Unlike many opcodes, this one does not write any output to the register file. */ - int base = (++vPC)->u.operand; - int property = (++vPC)->u.operand; - int value = (++vPC)->u.operand; + int base = vPC[1].u.operand; + int property = vPC[2].u.operand; + int value = vPC[3].u.operand; JSValue baseValue = callFrame->r(base).jsValue(); JSValue subscript = callFrame->r(property).jsValue(); @@ -2594,7 +2588,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi } CHECK_FOR_EXCEPTION(); - ++vPC; + vPC += OPCODE_LENGTH(op_put_by_val); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_del_by_val) { @@ -2605,9 +2599,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi boolean indicating success (if true) or failure (if false) to register dst. */ - int dst = (++vPC)->u.operand; - int base = (++vPC)->u.operand; - int property = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int base = vPC[2].u.operand; + int property = vPC[3].u.operand; JSObject* baseObj = callFrame->r(base).jsValue().toObject(callFrame); // may throw @@ -2625,7 +2619,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; - ++vPC; + vPC += OPCODE_LENGTH(op_del_by_val); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_put_by_index) { @@ -2640,13 +2634,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi This opcode is mainly used to initialize array literals. */ - int base = (++vPC)->u.operand; - unsigned property = (++vPC)->u.operand; - int value = (++vPC)->u.operand; + int base = vPC[1].u.operand; + unsigned property = vPC[2].u.operand; + int value = vPC[3].u.operand; callFrame->r(base).jsValue().put(callFrame, property, callFrame->r(value).jsValue()); - ++vPC; + vPC += OPCODE_LENGTH(op_put_by_index); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_loop) { @@ -2661,7 +2655,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #if ENABLE(OPCODE_STATS) OpcodeStats::resetLastInstruction(); #endif - int target = (++vPC)->u.operand; + int target = vPC[1].u.operand; CHECK_FOR_TIMEOUT(); vPC += target; NEXT_INSTRUCTION(); @@ -2675,7 +2669,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #if ENABLE(OPCODE_STATS) OpcodeStats::resetLastInstruction(); #endif - int target = (++vPC)->u.operand; + int target = vPC[1].u.operand; vPC += target; NEXT_INSTRUCTION(); @@ -2689,15 +2683,35 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Additionally this loop instruction may terminate JS execution is the JS timeout is reached. */ - int cond = (++vPC)->u.operand; - int target = (++vPC)->u.operand; + int cond = vPC[1].u.operand; + int target = vPC[2].u.operand; if (callFrame->r(cond).jsValue().toBoolean(callFrame)) { vPC += target; CHECK_FOR_TIMEOUT(); NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_loop_if_true); + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_loop_if_false) { + /* loop_if_true cond(r) target(offset) + + Jumps to offset target from the current instruction, if and + only if register cond converts to boolean as false. + + Additionally this loop instruction may terminate JS execution is + the JS timeout is reached. + */ + int cond = vPC[1].u.operand; + int target = vPC[2].u.operand; + if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) { + vPC += target; + CHECK_FOR_TIMEOUT(); + NEXT_INSTRUCTION(); + } + + vPC += OPCODE_LENGTH(op_loop_if_true); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_jtrue) { @@ -2706,14 +2720,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Jumps to offset target from the current instruction, if and only if register cond converts to boolean as true. */ - int cond = (++vPC)->u.operand; - int target = (++vPC)->u.operand; + int cond = vPC[1].u.operand; + int target = vPC[2].u.operand; if (callFrame->r(cond).jsValue().toBoolean(callFrame)) { vPC += target; NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_jtrue); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_jfalse) { @@ -2722,14 +2736,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Jumps to offset target from the current instruction, if and only if register cond converts to boolean as false. */ - int cond = (++vPC)->u.operand; - int target = (++vPC)->u.operand; + int cond = vPC[1].u.operand; + int target = vPC[2].u.operand; if (!callFrame->r(cond).jsValue().toBoolean(callFrame)) { vPC += target; NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_jfalse); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_jeq_null) { @@ -2738,8 +2752,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Jumps to offset target from the current instruction, if and only if register src is null. */ - int src = (++vPC)->u.operand; - int target = (++vPC)->u.operand; + int src = vPC[1].u.operand; + int target = vPC[2].u.operand; JSValue srcValue = callFrame->r(src).jsValue(); if (srcValue.isUndefinedOrNull() || (srcValue.isCell() && srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) { @@ -2747,7 +2761,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_jeq_null); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_jneq_null) { @@ -2756,16 +2770,16 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Jumps to offset target from the current instruction, if and only if register src is not null. */ - int src = (++vPC)->u.operand; - int target = (++vPC)->u.operand; + int src = vPC[1].u.operand; + int target = vPC[2].u.operand; JSValue srcValue = callFrame->r(src).jsValue(); - if (!srcValue.isUndefinedOrNull() || (srcValue.isCell() && !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) { + if (!srcValue.isUndefinedOrNull() && (!srcValue.isCell() || !srcValue.asCell()->structure()->typeInfo().masqueradesAsUndefined())) { vPC += target; NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_jneq_null); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_jneq_ptr) { @@ -2774,16 +2788,16 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Jumps to offset target from the current instruction, if the value r is equal to ptr, using pointer equality. */ - int src = (++vPC)->u.operand; - JSValue ptr = JSValue((++vPC)->u.jsCell); - int target = (++vPC)->u.operand; + int src = vPC[1].u.operand; + JSValue ptr = JSValue(vPC[2].u.jsCell); + int target = vPC[3].u.operand; JSValue srcValue = callFrame->r(src).jsValue(); if (srcValue != ptr) { vPC += target; NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_jneq_ptr); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_loop_if_less) { @@ -2797,9 +2811,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Additionally this loop instruction may terminate JS execution is the JS timeout is reached. */ - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - int target = (++vPC)->u.operand; + JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue(); + int target = vPC[3].u.operand; bool result = jsLess(callFrame, src1, src2); CHECK_FOR_EXCEPTION(); @@ -2810,7 +2824,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_loop_if_less); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_loop_if_lesseq) { @@ -2824,9 +2838,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Additionally this loop instruction may terminate JS execution is the JS timeout is reached. */ - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - int target = (++vPC)->u.operand; + JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue(); + int target = vPC[3].u.operand; bool result = jsLessEq(callFrame, src1, src2); CHECK_FOR_EXCEPTION(); @@ -2837,7 +2851,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_loop_if_lesseq); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_jnless) { @@ -2848,9 +2862,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi target from the current instruction, if and only if the result of the comparison is false. */ - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - int target = (++vPC)->u.operand; + JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue(); + int target = vPC[3].u.operand; bool result = jsLess(callFrame, src1, src2); CHECK_FOR_EXCEPTION(); @@ -2860,7 +2874,30 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_jnless); + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_jless) { + /* jless src1(r) src2(r) target(offset) + + Checks whether register src1 is less than register src2, as + with the ECMAScript '<' operator, and then jumps to offset + target from the current instruction, if and only if the + result of the comparison is true. + */ + JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue(); + int target = vPC[3].u.operand; + + bool result = jsLess(callFrame, src1, src2); + CHECK_FOR_EXCEPTION(); + + if (result) { + vPC += target; + NEXT_INSTRUCTION(); + } + + vPC += OPCODE_LENGTH(op_jless); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_jnlesseq) { @@ -2871,9 +2908,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi and then jumps to offset target from the current instruction, if and only if theresult of the comparison is false. */ - JSValue src1 = callFrame->r((++vPC)->u.operand).jsValue(); - JSValue src2 = callFrame->r((++vPC)->u.operand).jsValue(); - int target = (++vPC)->u.operand; + JSValue src1 = callFrame->r(vPC[1].u.operand).jsValue(); + JSValue src2 = callFrame->r(vPC[2].u.operand).jsValue(); + int target = vPC[3].u.operand; bool result = jsLessEq(callFrame, src1, src2); CHECK_FOR_EXCEPTION(); @@ -2883,7 +2920,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi NEXT_INSTRUCTION(); } - ++vPC; + vPC += OPCODE_LENGTH(op_jnlesseq); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_switch_imm) { @@ -2895,9 +2932,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi table, and the value at jumpTable[scrutinee value] is non-zero, then that value is used as the jump offset, otherwise defaultOffset is used. */ - int tableIndex = (++vPC)->u.operand; - int defaultOffset = (++vPC)->u.operand; - JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue(); + int tableIndex = vPC[1].u.operand; + int defaultOffset = vPC[2].u.operand; + JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue(); if (scrutinee.isInt32()) vPC += callFrame->codeBlock()->immediateSwitchJumpTable(tableIndex).offsetForValue(scrutinee.asInt32(), defaultOffset); else { @@ -2919,13 +2956,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi table, and the value at jumpTable[scrutinee value] is non-zero, then that value is used as the jump offset, otherwise defaultOffset is used. */ - int tableIndex = (++vPC)->u.operand; - int defaultOffset = (++vPC)->u.operand; - JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue(); + int tableIndex = vPC[1].u.operand; + int defaultOffset = vPC[2].u.operand; + JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue(); if (!scrutinee.isString()) vPC += defaultOffset; else { - UString::Rep* value = asString(scrutinee)->value().rep(); + UString::Rep* value = asString(scrutinee)->value(callFrame).rep(); if (value->size() != 1) vPC += defaultOffset; else @@ -2942,13 +2979,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi jump table, then the value associated with the string is used as the jump offset, otherwise defaultOffset is used. */ - int tableIndex = (++vPC)->u.operand; - int defaultOffset = (++vPC)->u.operand; - JSValue scrutinee = callFrame->r((++vPC)->u.operand).jsValue(); + int tableIndex = vPC[1].u.operand; + int defaultOffset = vPC[2].u.operand; + JSValue scrutinee = callFrame->r(vPC[3].u.operand).jsValue(); if (!scrutinee.isString()) vPC += defaultOffset; else - vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value().rep(), defaultOffset); + vPC += callFrame->codeBlock()->stringSwitchJumpTable(tableIndex).offsetForValue(asString(scrutinee)->value(callFrame).rep(), defaultOffset); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_new_func) { @@ -2959,12 +2996,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi constructor, using the rules for function declarations, and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int func = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int func = vPC[2].u.operand; callFrame->r(dst) = JSValue(callFrame->codeBlock()->functionDecl(func)->make(callFrame, callFrame->scopeChain())); - ++vPC; + vPC += OPCODE_LENGTH(op_new_func); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_new_func_exp) { @@ -2975,8 +3012,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi constructor, using the rules for function expressions, and puts the result in register dst. */ - int dst = (++vPC)->u.operand; - int funcIndex = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int funcIndex = vPC[2].u.operand; FunctionExecutable* function = callFrame->codeBlock()->functionExpr(funcIndex); JSFunction* func = function->make(callFrame, callFrame->scopeChain()); @@ -2995,7 +3032,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(dst) = JSValue(func); - ++vPC; + vPC += OPCODE_LENGTH(op_new_func_exp); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_call_eval) { @@ -3020,7 +3057,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Register* newCallFrame = callFrame->registers() + registerOffset; Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; JSValue thisValue = argv[0].jsValue(); - JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); + JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject; if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { JSValue result = callEval(callFrame, registerFile, argv, argCount, registerOffset, exceptionValue); @@ -3028,7 +3065,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi goto vm_throw; callFrame->r(dst) = result; - vPC += 5; + vPC += OPCODE_LENGTH(op_call_eval); NEXT_INSTRUCTION(); } @@ -3088,7 +3125,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #else newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v)); #endif - Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; ArgList args(thisRegister + 1, argCount - 1); @@ -3099,14 +3135,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSValue returnValue; { - SamplingTool::HostCallRecord callRecord(m_sampler); + SamplingTool::HostCallRecord callRecord(m_sampler.get()); returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args); } CHECK_FOR_EXCEPTION(); callFrame->r(dst) = returnValue; - vPC += 5; + vPC += OPCODE_LENGTH(op_call); NEXT_INSTRUCTION(); } @@ -3116,8 +3152,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi goto vm_throw; } DEFINE_OPCODE(op_load_varargs) { - int argCountDst = (++vPC)->u.operand; - int argsOffset = (++vPC)->u.operand; + int argCountDst = vPC[1].u.operand; + int argsOffset = vPC[2].u.operand; JSValue arguments = callFrame->r(argsOffset).jsValue(); int32_t argCount = 0; @@ -3189,7 +3225,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi } CHECK_FOR_EXCEPTION(); callFrame->r(argCountDst) = Register::withInt(argCount + 1); - ++vPC; + vPC += OPCODE_LENGTH(op_load_varargs); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_call_varargs) { @@ -3246,7 +3282,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #else newCallFrame->init(0, vPC + 5, scopeChain, callFrame, dst, argCount, asObject(v)); #endif - + Register* thisRegister = newCallFrame->registers() - RegisterFile::CallFrameHeaderSize - argCount; ArgList args(thisRegister + 1, argCount - 1); @@ -3257,14 +3293,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSValue returnValue; { - SamplingTool::HostCallRecord callRecord(m_sampler); + SamplingTool::HostCallRecord callRecord(m_sampler.get()); returnValue = callData.native.function(newCallFrame, asObject(v), thisValue, args); } CHECK_FOR_EXCEPTION(); callFrame->r(dst) = returnValue; - vPC += 5; + vPC += OPCODE_LENGTH(op_call_varargs); NEXT_INSTRUCTION(); } @@ -3286,12 +3322,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi This opcode should only be used immediately before op_ret. */ - int src = (++vPC)->u.operand; + int src = vPC[1].u.operand; ASSERT(callFrame->codeBlock()->needsFullScopeChain()); asActivation(callFrame->r(src).jsValue())->copyRegisters(callFrame->optionalCalleeArguments()); - ++vPC; + vPC += OPCODE_LENGTH(op_tear_off_activation); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_tear_off_arguments) { @@ -3312,7 +3348,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (callFrame->optionalCalleeArguments()) callFrame->optionalCalleeArguments()->copyRegisters(); - ++vPC; + vPC += OPCODE_LENGTH(op_tear_off_arguments); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_ret) { @@ -3330,22 +3366,21 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi intptr_t sourceId = callFrame->codeBlock()->source()->asID(); #endif - int result = (++vPC)->u.operand; + int result = vPC[1].u.operand; if (callFrame->codeBlock()->needsFullScopeChain()) callFrame->scopeChain()->deref(); JSValue returnValue = callFrame->r(result).jsValue(); #ifdef QT_BUILD_SCRIPT_LIB - if (debugger) { + if (debugger) debugger->functionExit(returnValue, sourceId); - } #endif vPC = callFrame->returnPC(); int dst = callFrame->returnValueRegister(); callFrame = callFrame->callerFrame(); - + if (callFrame->hasHostCallFrameFlag()) return returnValue; @@ -3370,7 +3405,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi for (size_t count = codeBlock->m_numVars; i < count; ++i) callFrame->r(i) = jsUndefined(); - ++vPC; + vPC += OPCODE_LENGTH(op_enter); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_enter_with_activation) { @@ -3392,12 +3427,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi for (size_t count = codeBlock->m_numVars; i < count; ++i) callFrame->r(i) = jsUndefined(); - int dst = (++vPC)->u.operand; + int dst = vPC[1].u.operand; JSActivation* activation = new (globalData) JSActivation(callFrame, static_cast<FunctionExecutable*>(codeBlock->ownerExecutable())); callFrame->r(dst) = JSValue(activation); callFrame->setScopeChain(callFrame->scopeChain()->copy()->push(activation)); - ++vPC; + vPC += OPCODE_LENGTH(op_enter_with_activation); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_convert_this) { @@ -3412,12 +3447,12 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi block. */ - int thisRegister = (++vPC)->u.operand; + int thisRegister = vPC[1].u.operand; JSValue thisVal = callFrame->r(thisRegister).jsValue(); if (thisVal.needsThisConversion()) callFrame->r(thisRegister) = JSValue(thisVal.toThisObject(callFrame)); - ++vPC; + vPC += OPCODE_LENGTH(op_convert_this); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_init_arguments) { @@ -3431,7 +3466,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi block. */ callFrame->r(RegisterFile::ArgumentsRegister) = JSValue(); - ++vPC; + vPC += OPCODE_LENGTH(op_init_arguments); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_create_arguments) { @@ -3447,7 +3482,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->setCalleeArguments(arguments); callFrame->r(RegisterFile::ArgumentsRegister) = JSValue(arguments); } - ++vPC; + vPC += OPCODE_LENGTH(op_create_arguments); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_construct) { @@ -3486,11 +3521,10 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (prototype.isObject()) structure = asObject(prototype)->inheritorID(); else - structure = callDataScopeChain->globalObject()->emptyObjectStructure(); + structure = callDataScopeChain->globalObject->emptyObjectStructure(); #ifdef QT_BUILD_SCRIPT_LIB // ### world-class hack - QT_PREPEND_NAMESPACE(QScriptObject)* newObject - = new (globalData) QT_PREPEND_NAMESPACE(QScriptObject)(structure); + QT_PREPEND_NAMESPACE(QScriptObject)* newObject = new (globalData) QT_PREPEND_NAMESPACE(QScriptObject)(structure); #else JSObject* newObject = new (globalData) JSObject(structure); #endif @@ -3519,7 +3553,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ArgList args(callFrame->registers() + thisRegister + 1, argCount - 1); ScopeChainNode* scopeChain = callFrame->scopeChain(); - CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); #ifdef QT_BUILD_SCRIPT_LIB //we need the returnValue to be 0 as it is used as flags newCallFrame->init(0, vPC + 7, scopeChain, callFrame, 0, argCount, asObject(v)); @@ -3529,13 +3562,13 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSValue returnValue; { - SamplingTool::HostCallRecord callRecord(m_sampler); + SamplingTool::HostCallRecord callRecord(m_sampler.get()); returnValue = constructData.native.function(newCallFrame, asObject(v), args); } CHECK_FOR_EXCEPTION(); callFrame->r(dst) = JSValue(returnValue); - vPC += 7; + vPC += OPCODE_LENGTH(op_construct); NEXT_INSTRUCTION(); } @@ -3553,32 +3586,33 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = vPC[1].u.operand; if (LIKELY(callFrame->r(dst).jsValue().isObject())) { - vPC += 3; + vPC += OPCODE_LENGTH(op_construct_verify); NEXT_INSTRUCTION(); } int override = vPC[2].u.operand; callFrame->r(dst) = callFrame->r(override); - vPC += 3; + vPC += OPCODE_LENGTH(op_construct_verify); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_strcat) { - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; - int count = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; + int count = vPC[3].u.operand; - callFrame->r(dst) = concatenateStrings(callFrame, &callFrame->registers()[src], count); - ++vPC; + callFrame->r(dst) = jsString(callFrame, &callFrame->registers()[src], count); + CHECK_FOR_EXCEPTION(); + vPC += OPCODE_LENGTH(op_strcat); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_to_primitive) { - int dst = (++vPC)->u.operand; - int src = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int src = vPC[2].u.operand; callFrame->r(dst) = callFrame->r(src).jsValue().toPrimitive(callFrame); - ++vPC; + vPC += OPCODE_LENGTH(op_to_primitive); NEXT_INSTRUCTION(); } @@ -3589,7 +3623,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi of the current scope chain. The contents of the register scope are replaced by the result of toObject conversion of the scope. */ - int scope = (++vPC)->u.operand; + int scope = vPC[1].u.operand; JSValue v = callFrame->r(scope).jsValue(); JSObject* o = v.toObject(callFrame); CHECK_FOR_EXCEPTION(); @@ -3597,7 +3631,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi callFrame->r(scope) = JSValue(o); callFrame->setScopeChain(callFrame->scopeChain()->push(o)); - ++vPC; + vPC += OPCODE_LENGTH(op_push_scope); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_pop_scope) { @@ -3607,47 +3641,69 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ callFrame->setScopeChain(callFrame->scopeChain()->pop()); - ++vPC; + vPC += OPCODE_LENGTH(op_pop_scope); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_get_pnames) { - /* get_pnames dst(r) base(r) + /* get_pnames dst(r) base(r) i(n) size(n) breakTarget(offset) Creates a property name list for register base and puts it - in register dst. This is not a true JavaScript value, just - a synthetic value used to keep the iteration state in a - register. + in register dst, initializing i and size for iteration. If + base is undefined or null, jumps to breakTarget. */ - int dst = (++vPC)->u.operand; - int base = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int base = vPC[2].u.operand; + int i = vPC[3].u.operand; + int size = vPC[4].u.operand; + int breakTarget = vPC[5].u.operand; + + JSValue v = callFrame->r(base).jsValue(); + if (v.isUndefinedOrNull()) { + vPC += breakTarget; + NEXT_INSTRUCTION(); + } - callFrame->r(dst) = JSPropertyNameIterator::create(callFrame, callFrame->r(base).jsValue()); - ++vPC; + JSObject* o = v.toObject(callFrame); + Structure* structure = o->structure(); + JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache(); + if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame)) + jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o); + + callFrame->r(dst) = jsPropertyNameIterator; + callFrame->r(base) = JSValue(o); + callFrame->r(i) = Register::withInt(0); + callFrame->r(size) = Register::withInt(jsPropertyNameIterator->size()); + vPC += OPCODE_LENGTH(op_get_pnames); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_next_pname) { - /* next_pname dst(r) iter(r) target(offset) + /* next_pname dst(r) base(r) i(n) size(n) iter(r) target(offset) - Tries to copies the next name from property name list in - register iter. If there are names left, then copies one to - register dst, and jumps to offset target. If there are none - left, invalidates the iterator and continues to the next + Copies the next name from the property name list in + register iter to dst, then jumps to offset target. If there are no + names left, invalidates the iterator and continues to the next instruction. */ - int dst = (++vPC)->u.operand; - int iter = (++vPC)->u.operand; - int target = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int base = vPC[2].u.operand; + int i = vPC[3].u.operand; + int size = vPC[4].u.operand; + int iter = vPC[5].u.operand; + int target = vPC[6].u.operand; JSPropertyNameIterator* it = callFrame->r(iter).propertyNameIterator(); - if (JSValue temp = it->next(callFrame)) { - CHECK_FOR_TIMEOUT(); - callFrame->r(dst) = JSValue(temp); - vPC += target; - NEXT_INSTRUCTION(); + while (callFrame->r(i).i() != callFrame->r(size).i()) { + JSValue key = it->get(callFrame, asObject(callFrame->r(base).jsValue()), callFrame->r(i).i()); + callFrame->r(i) = Register::withInt(callFrame->r(i).i() + 1); + if (key) { + CHECK_FOR_TIMEOUT(); + callFrame->r(dst) = key; + vPC += target; + NEXT_INSTRUCTION(); + } } - it->invalidate(); - ++vPC; + vPC += OPCODE_LENGTH(op_next_pname); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_jmp_scopes) { @@ -3657,8 +3713,8 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi specified by immediate number count, then jumps to offset target. */ - int count = (++vPC)->u.operand; - int target = (++vPC)->u.operand; + int count = vPC[1].u.operand; + int target = vPC[2].u.operand; ScopeChainNode* tmp = callFrame->scopeChain(); while (count--) @@ -3681,7 +3737,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ callFrame->setScopeChain(createExceptionScope(callFrame, vPC)); - vPC += 4; + vPC += OPCODE_LENGTH(op_push_new_scope); NEXT_INSTRUCTION(); } #if HAVE(COMPUTED_GOTO) @@ -3706,11 +3762,11 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi } #endif - int ex = (++vPC)->u.operand; + int ex = vPC[1].u.operand; callFrame->r(ex) = exceptionValue; exceptionValue = JSValue(); - ++vPC; + vPC += OPCODE_LENGTH(op_catch); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_throw) { @@ -3724,7 +3780,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi else the script returns control to the nearest native caller. */ - int ex = (++vPC)->u.operand; + int ex = vPC[1].u.operand; exceptionValue = callFrame->r(ex).jsValue(); handler = throwException(callFrame, exceptionValue, vPC - callFrame->codeBlock()->instructions().begin(), true); @@ -3744,14 +3800,14 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi constant message as the message string. The result is written to register dst. */ - int dst = (++vPC)->u.operand; - int type = (++vPC)->u.operand; - int message = (++vPC)->u.operand; + int dst = vPC[1].u.operand; + int type = vPC[2].u.operand; + int message = vPC[3].u.operand; CodeBlock* codeBlock = callFrame->codeBlock(); callFrame->r(dst) = JSValue(Error::create(callFrame, (ErrorType)type, callFrame->r(message).jsValue().toString(callFrame), codeBlock->lineNumberForBytecodeOffset(callFrame, vPC - codeBlock->instructions().begin()), codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL())); - ++vPC; + vPC += OPCODE_LENGTH(op_new_error); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_end) { @@ -3766,7 +3822,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT(scopeChain->refCount > 1); scopeChain->deref(); } - int result = (++vPC)->u.operand; + int result = vPC[1].u.operand; return callFrame->r(result).jsValue(); } DEFINE_OPCODE(op_put_getter) { @@ -3780,9 +3836,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Unlike many opcodes, this one does not write any output to the register file. */ - int base = (++vPC)->u.operand; - int property = (++vPC)->u.operand; - int function = (++vPC)->u.operand; + int base = vPC[1].u.operand; + int property = vPC[2].u.operand; + int function = vPC[3].u.operand; ASSERT(callFrame->r(base).jsValue().isObject()); JSObject* baseObj = asObject(callFrame->r(base).jsValue()); @@ -3790,7 +3846,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT(callFrame->r(function).jsValue().isObject()); baseObj->defineGetter(callFrame, ident, asObject(callFrame->r(function).jsValue())); - ++vPC; + vPC += OPCODE_LENGTH(op_put_getter); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_put_setter) { @@ -3804,9 +3860,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Unlike many opcodes, this one does not write any output to the register file. */ - int base = (++vPC)->u.operand; - int property = (++vPC)->u.operand; - int function = (++vPC)->u.operand; + int base = vPC[1].u.operand; + int property = vPC[2].u.operand; + int function = vPC[3].u.operand; ASSERT(callFrame->r(base).jsValue().isObject()); JSObject* baseObj = asObject(callFrame->r(base).jsValue()); @@ -3814,7 +3870,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT(callFrame->r(function).jsValue().isObject()); baseObj->defineSetter(callFrame, ident, asObject(callFrame->r(function).jsValue()), 0); - ++vPC; + vPC += OPCODE_LENGTH(op_put_setter); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_method_check) { @@ -3827,9 +3883,9 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi Places the address of the next instruction into the retAddrDst register and jumps to offset target from the current instruction. */ - int retAddrDst = (++vPC)->u.operand; - int target = (++vPC)->u.operand; - callFrame->r(retAddrDst) = vPC + 1; + int retAddrDst = vPC[1].u.operand; + int target = vPC[2].u.operand; + callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr); vPC += target; NEXT_INSTRUCTION(); @@ -3841,24 +3897,23 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi differs from op_jmp because the target address is stored in a register, not as an immediate. */ - int retAddrSrc = (++vPC)->u.operand; + int retAddrSrc = vPC[1].u.operand; vPC = callFrame->r(retAddrSrc).vPC(); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_debug) { - /* debug debugHookID(n) firstLine(n) lastLine(n) columnNumber(n) + /* debug debugHookID(n) firstLine(n) lastLine(n) Notifies the debugger of the current state of execution. This opcode is only generated while the debugger is attached. */ - int debugHookID = (++vPC)->u.operand; - int firstLine = (++vPC)->u.operand; - int lastLine = (++vPC)->u.operand; - int column = (++vPC)->u.operand; + int debugHookID = vPC[1].u.operand; + int firstLine = vPC[2].u.operand; + int lastLine = vPC[3].u.operand; - debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); + debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); - ++vPC; + vPC += OPCODE_LENGTH(op_debug); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_profile_will_call) { @@ -3872,7 +3927,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (*enabledProfilerReference) (*enabledProfilerReference)->willExecute(callFrame, callFrame->r(function).jsValue()); - vPC += 2; + vPC += OPCODE_LENGTH(op_profile_will_call); NEXT_INSTRUCTION(); } DEFINE_OPCODE(op_profile_did_call) { @@ -3886,7 +3941,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (*enabledProfilerReference) (*enabledProfilerReference)->didExecute(callFrame, callFrame->r(function).jsValue()); - vPC += 2; + vPC += OPCODE_LENGTH(op_profile_did_call); NEXT_INSTRUCTION(); } vm_throw: { @@ -3992,4 +4047,40 @@ CallFrame* Interpreter::findFunctionCallFrame(CallFrame* callFrame, InternalFunc return 0; } +void Interpreter::enableSampler() +{ +#if ENABLE(OPCODE_SAMPLING) + if (!m_sampler) { + m_sampler.set(new SamplingTool(this)); + m_sampler->setup(); + } +#endif +} +void Interpreter::dumpSampleData(ExecState* exec) +{ +#if ENABLE(OPCODE_SAMPLING) + if (m_sampler) + m_sampler->dump(exec); +#else + UNUSED_PARAM(exec); +#endif +} +void Interpreter::startSampling() +{ +#if ENABLE(SAMPLING_THREAD) + if (!m_sampleEntryDepth) + SamplingThread::start(); + + m_sampleEntryDepth++; +#endif +} +void Interpreter::stopSampling() +{ +#if ENABLE(SAMPLING_THREAD) + m_sampleEntryDepth--; + if (!m_sampleEntryDepth) + SamplingThread::stop(); +#endif +} + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.h b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.h index 157e0c7..e17b055 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Interpreter.h @@ -105,13 +105,15 @@ namespace JSC { void getArgumentsData(CallFrame*, JSFunction*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); - void setSampler(SamplingTool* sampler) { m_sampler = sampler; } - SamplingTool* sampler() { return m_sampler; } + SamplingTool* sampler() { return m_sampler.get(); } NEVER_INLINE JSValue callEval(CallFrame*, RegisterFile*, Register* argv, int argc, int registerOffset, JSValue& exceptionValue); NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset, bool); - NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine, int column); + NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine); + void dumpSampleData(ExecState* exec); + void startSampling(); + void stopSampling(); private: enum ExecutionFlag { Normal, InitializeAndReturn }; @@ -127,7 +129,6 @@ namespace JSC { NEVER_INLINE bool resolveGlobal(CallFrame*, Instruction*, JSValue& exceptionValue); NEVER_INLINE void resolveBase(CallFrame*, Instruction* vPC); NEVER_INLINE bool resolveBaseAndProperty(CallFrame*, Instruction*, JSValue& exceptionValue); - NEVER_INLINE bool resolveBaseAndFunc(CallFrame*, Instruction*, JSValue& exceptionValue); NEVER_INLINE ScopeChainNode* createExceptionScope(CallFrame*, const Instruction* vPC); void tryCacheGetByID(CallFrame*, CodeBlock*, Instruction*, JSValue baseValue, const Identifier& propertyName, const PropertySlot&); @@ -149,7 +150,9 @@ namespace JSC { bool isCallBytecode(Opcode opcode) { return opcode == getOpcode(op_call) || opcode == getOpcode(op_construct) || opcode == getOpcode(op_call_eval); } - SamplingTool* m_sampler; + void enableSampler(); + int m_sampleEntryDepth; + OwnPtr<SamplingTool> m_sampler; int m_reentryDepth; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Register.h b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Register.h index ea1f849..3486fa7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Register.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/Register.h @@ -50,17 +50,18 @@ namespace JSC { class Register : public WTF::FastAllocBase { public: Register(); - Register(JSValue); + Register(const JSValue&); + Register& operator=(const JSValue&); JSValue jsValue() const; - Register(JSActivation*); - Register(CallFrame*); - Register(CodeBlock*); - Register(JSObject*); - Register(JSPropertyNameIterator*); - Register(ScopeChainNode*); - Register(Instruction*); + Register& operator=(JSActivation*); + Register& operator=(CallFrame*); + Register& operator=(CodeBlock*); + Register& operator=(JSObject*); + Register& operator=(JSPropertyNameIterator*); + Register& operator=(ScopeChainNode*); + Register& operator=(Instruction*); int32_t i() const; JSActivation* activation() const; @@ -74,12 +75,12 @@ namespace JSC { static Register withInt(int32_t i) { - return Register(i); + Register r; + r.u.i = i; + return r; } private: - Register(int32_t); - union { int32_t i; EncodedJSValue value; @@ -97,13 +98,25 @@ namespace JSC { ALWAYS_INLINE Register::Register() { #ifndef NDEBUG - u.value = JSValue::encode(JSValue()); + *this = JSValue(); +#endif + } + + ALWAYS_INLINE Register::Register(const JSValue& v) + { +#if ENABLE(JSC_ZOMBIES) + ASSERT(!v.isZombie()); #endif + u.value = JSValue::encode(v); } - ALWAYS_INLINE Register::Register(JSValue v) + ALWAYS_INLINE Register& Register::operator=(const JSValue& v) { +#if ENABLE(JSC_ZOMBIES) + ASSERT(!v.isZombie()); +#endif u.value = JSValue::encode(v); + return *this; } ALWAYS_INLINE JSValue Register::jsValue() const @@ -113,44 +126,46 @@ namespace JSC { // Interpreter functions - ALWAYS_INLINE Register::Register(JSActivation* activation) + ALWAYS_INLINE Register& Register::operator=(JSActivation* activation) { u.activation = activation; + return *this; } - ALWAYS_INLINE Register::Register(CallFrame* callFrame) + ALWAYS_INLINE Register& Register::operator=(CallFrame* callFrame) { u.callFrame = callFrame; + return *this; } - ALWAYS_INLINE Register::Register(CodeBlock* codeBlock) + ALWAYS_INLINE Register& Register::operator=(CodeBlock* codeBlock) { u.codeBlock = codeBlock; + return *this; } - ALWAYS_INLINE Register::Register(JSObject* object) + ALWAYS_INLINE Register& Register::operator=(JSObject* object) { u.object = object; + return *this; } - ALWAYS_INLINE Register::Register(Instruction* vPC) + ALWAYS_INLINE Register& Register::operator=(Instruction* vPC) { u.vPC = vPC; + return *this; } - ALWAYS_INLINE Register::Register(ScopeChainNode* scopeChain) + ALWAYS_INLINE Register& Register::operator=(ScopeChainNode* scopeChain) { u.scopeChain = scopeChain; + return *this; } - ALWAYS_INLINE Register::Register(JSPropertyNameIterator* propertyNameIterator) + ALWAYS_INLINE Register& Register::operator=(JSPropertyNameIterator* propertyNameIterator) { u.propertyNameIterator = propertyNameIterator; - } - - ALWAYS_INLINE Register::Register(int32_t i) - { - u.i = i; + return *this; } ALWAYS_INLINE int32_t Register::i() const diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/RegisterFile.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/RegisterFile.cpp index de5175e..939573b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/RegisterFile.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/RegisterFile.cpp @@ -36,7 +36,7 @@ RegisterFile::~RegisterFile() #if HAVE(MMAP) munmap(reinterpret_cast<char*>(m_buffer), ((m_max - m_start) + m_maxGlobals) * sizeof(Register)); #elif HAVE(VIRTUALALLOC) -#if PLATFORM(WINCE) +#if OS(WINCE) VirtualFree(m_buffer, DWORD(m_commitEnd) - DWORD(m_buffer), MEM_DECOMMIT); #endif VirtualFree(m_buffer, 0, MEM_RELEASE); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/RegisterFile.h b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/RegisterFile.h index 0eeff0e..34e2504 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/RegisterFile.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/interpreter/RegisterFile.h @@ -176,7 +176,7 @@ namespace JSC { #if HAVE(MMAP) m_buffer = reinterpret_cast<Register*>(mmap(0, bufferLength, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, VM_TAG_FOR_REGISTERFILE_MEMORY, 0)); if (m_buffer == MAP_FAILED) { -#if PLATFORM(WINCE) +#if OS(WINCE) fprintf(stderr, "Could not allocate register file: %d\n", GetLastError()); #else fprintf(stderr, "Could not allocate register file: %d\n", errno); @@ -186,7 +186,7 @@ namespace JSC { #elif HAVE(VIRTUALALLOC) m_buffer = static_cast<Register*>(VirtualAlloc(0, roundUpAllocationSize(bufferLength, commitSize), MEM_RESERVE, PAGE_READWRITE)); if (!m_buffer) { -#if PLATFORM(WINCE) +#if OS(WINCE) fprintf(stderr, "Could not allocate register file: %d\n", GetLastError()); #else fprintf(stderr, "Could not allocate register file: %d\n", errno); @@ -196,7 +196,7 @@ namespace JSC { size_t committedSize = roundUpAllocationSize(maxGlobals * sizeof(Register), commitSize); void* commitCheck = VirtualAlloc(m_buffer, committedSize, MEM_COMMIT, PAGE_READWRITE); if (commitCheck != m_buffer) { -#if PLATFORM(WINCE) +#if OS(WINCE) fprintf(stderr, "Could not allocate register file: %d\n", GetLastError()); #else fprintf(stderr, "Could not allocate register file: %d\n", errno); @@ -242,7 +242,7 @@ namespace JSC { if (newEnd > m_commitEnd) { size_t size = roundUpAllocationSize(reinterpret_cast<char*>(newEnd) - reinterpret_cast<char*>(m_commitEnd), commitSize); if (!VirtualAlloc(m_commitEnd, size, MEM_COMMIT, PAGE_READWRITE)) { -#if PLATFORM(WINCE) +#if OS(WINCE) fprintf(stderr, "Could not allocate register file: %d\n", GetLastError()); #else fprintf(stderr, "Could not allocate register file: %d\n", errno); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocator.h b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocator.h index 3274fcc..1fb8ff7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocator.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocator.h @@ -26,6 +26,7 @@ #ifndef ExecutableAllocator_h #define ExecutableAllocator_h +#include <stddef.h> // for ptrdiff_t #include <limits> #include <wtf/Assertions.h> #include <wtf/PassRefPtr.h> @@ -33,15 +34,21 @@ #include <wtf/UnusedParam.h> #include <wtf/Vector.h> -#if PLATFORM(IPHONE) +#if OS(IPHONE_OS) #include <libkern/OSCacheControl.h> #include <sys/mman.h> #endif -#if PLATFORM(SYMBIAN) +#if OS(SYMBIAN) #include <e32std.h> #endif +#if OS(WINCE) +// From pkfuncs.h (private header file from the Platform Builder) +#define CACHE_SYNC_ALL 0x07F +extern "C" __declspec(dllimport) void CacheRangeFlush(LPVOID pAddr, DWORD dwLength, DWORD dwFlags); +#endif + #define JIT_ALLOCATOR_PAGE_SIZE (ExecutableAllocator::pageSize) #define JIT_ALLOCATOR_LARGE_ALLOC_SIZE (ExecutableAllocator::pageSize * 4) @@ -78,6 +85,9 @@ private: struct Allocation { char* pages; size_t size; +#if OS(SYMBIAN) + RChunk* chunk; +#endif }; typedef Vector<Allocation, 2> AllocationList; @@ -176,22 +186,38 @@ public: #endif -#if PLATFORM(X86) || PLATFORM(X86_64) +#if CPU(X86) || CPU(X86_64) static void cacheFlush(void*, size_t) { } -#elif PLATFORM(ARM_THUMB2) && PLATFORM(IPHONE) +#elif CPU(ARM_THUMB2) && OS(IPHONE_OS) static void cacheFlush(void* code, size_t size) { sys_dcache_flush(code, size); sys_icache_invalidate(code, size); } -#elif PLATFORM(SYMBIAN) +#elif CPU(ARM_THUMB2) && OS(LINUX) + static void cacheFlush(void* code, size_t size) + { + asm volatile ( + "push {r7}\n" + "mov r0, %0\n" + "mov r1, %1\n" + "movw r7, #0x2\n" + "movt r7, #0xf\n" + "movs r2, #0x0\n" + "svc 0x0\n" + "pop {r7}\n" + : + : "r" (code), "r" (reinterpret_cast<char*>(code) + size) + : "r0", "r1", "r2"); + } +#elif OS(SYMBIAN) static void cacheFlush(void* code, size_t size) { User::IMB_Range(code, static_cast<char*>(code) + size); } -#elif PLATFORM(ARM_TRADITIONAL) && PLATFORM(LINUX) +#elif CPU(ARM_TRADITIONAL) && OS(LINUX) static void cacheFlush(void* code, size_t size) { asm volatile ( @@ -205,7 +231,12 @@ public: "pop {r7}\n" : : "r" (code), "r" (reinterpret_cast<char*>(code) + size) - : "r0", "r1"); + : "r0", "r1", "r2"); + } +#elif OS(WINCE) + static void cacheFlush(void* code, size_t size) + { + CacheRangeFlush(code, size, CACHE_SYNC_ALL); } #else #error "The cacheFlush support is missing on this platform." diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp index 7682b9c..dd1db4e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp @@ -29,7 +29,7 @@ #include <errno.h> -#if ENABLE(ASSEMBLER) && PLATFORM(MAC) && PLATFORM(X86_64) +#if ENABLE(ASSEMBLER) && OS(DARWIN) && CPU(X86_64) #include "TCSpinLock.h" #include <mach/mach_init.h> diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp index 13a8626..2eb0c87 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorPosix.cpp @@ -27,7 +27,7 @@ #include "ExecutableAllocator.h" -#if ENABLE(ASSEMBLER) +#if ENABLE(ASSEMBLER) && OS(UNIX) && !OS(SYMBIAN) #include <sys/mman.h> #include <unistd.h> @@ -35,7 +35,7 @@ namespace JSC { -#if !(PLATFORM(MAC) && PLATFORM(X86_64)) +#if !(OS(DARWIN) && !PLATFORM(QT) && CPU(X86_64)) void ExecutableAllocator::intializePageSize() { @@ -57,7 +57,7 @@ void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc) ASSERT_UNUSED(result, !result); } -#endif // !(PLATFORM(MAC) && PLATFORM(X86_64)) +#endif // !(OS(DARWIN) && !PLATFORM(QT) && CPU(X86_64)) #if ENABLE(ASSEMBLER_WX_EXCLUSIVE) void ExecutableAllocator::reprotectRegion(void* start, size_t size, ProtectionSeting setting) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp new file mode 100644 index 0000000..e82975c --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorSymbian.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + * + */ + +#include "config.h" + +#include "ExecutableAllocator.h" + +#if ENABLE(ASSEMBLER) && OS(SYMBIAN) + +#include <e32hal.h> +#include <e32std.h> + +// Set the page size to 256 Kb to compensate for moving memory model limitation +const size_t MOVING_MEM_PAGE_SIZE = 256 * 1024; + +namespace JSC { + +void ExecutableAllocator::intializePageSize() +{ +#if CPU(ARMV5_OR_LOWER) + // The moving memory model (as used in ARMv5 and earlier platforms) + // on Symbian OS limits the number of chunks for each process to 16. + // To mitigate this limitation increase the pagesize to + // allocate less of larger chunks. + ExecutableAllocator::pageSize = MOVING_MEM_PAGE_SIZE; +#else + TInt page_size; + UserHal::PageSizeInBytes(page_size); + ExecutableAllocator::pageSize = page_size; +#endif +} + +ExecutablePool::Allocation ExecutablePool::systemAlloc(size_t n) +{ + RChunk* codeChunk = new RChunk(); + + TInt errorCode = codeChunk->CreateLocalCode(n, n); + + char* allocation = reinterpret_cast<char*>(codeChunk->Base()); + if (!allocation) + CRASH(); + ExecutablePool::Allocation alloc = { allocation, n, codeChunk }; + return alloc; +} + +void ExecutablePool::systemRelease(const ExecutablePool::Allocation& alloc) +{ + alloc.chunk->Close(); + delete alloc.chunk; +} + +#if ENABLE(ASSEMBLER_WX_EXCLUSIVE) +#error "ASSEMBLER_WX_EXCLUSIVE not yet suported on this platform." +#endif + +} + +#endif // HAVE(ASSEMBLER) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorWin.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorWin.cpp index e6ac855..e38323c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorWin.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/ExecutableAllocatorWin.cpp @@ -27,7 +27,7 @@ #include "ExecutableAllocator.h" -#if ENABLE(ASSEMBLER) +#if ENABLE(ASSEMBLER) && OS(WINDOWS) #include "windows.h" diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JIT.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JIT.cpp index ea8434e..c0da66d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JIT.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JIT.cpp @@ -27,7 +27,7 @@ #include "JIT.h" // This probably does not belong here; adding here for now as a quick Windows build fix. -#if ENABLE(ASSEMBLER) && PLATFORM(X86) && !PLATFORM(MAC) +#if ENABLE(ASSEMBLER) && CPU(X86) && !OS(MAC_OS_X) #include "MacroAssembler.h" JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse2CheckState = NotCheckedSSE2; #endif @@ -37,7 +37,6 @@ JSC::MacroAssemblerX86Common::SSE2CheckState JSC::MacroAssemblerX86Common::s_sse #include "CodeBlock.h" #include "Interpreter.h" #include "JITInlineMethods.h" -#include "JITStubs.h" #include "JITStubCall.h" #include "JSArray.h" #include "JSFunction.h" @@ -202,7 +201,6 @@ void JIT::privateCompileMainPass() DEFINE_BINARY_OP(op_less) DEFINE_BINARY_OP(op_lesseq) DEFINE_BINARY_OP(op_urshift) - DEFINE_UNARY_OP(op_get_pnames) DEFINE_UNARY_OP(op_is_boolean) DEFINE_UNARY_OP(op_is_function) DEFINE_UNARY_OP(op_is_number) @@ -240,7 +238,9 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_eq_null) DEFINE_OP(op_get_by_id) DEFINE_OP(op_get_by_val) + DEFINE_OP(op_get_by_pname) DEFINE_OP(op_get_global_var) + DEFINE_OP(op_get_pnames) DEFINE_OP(op_get_scoped_var) DEFINE_OP(op_instanceof) DEFINE_OP(op_jeq_null) @@ -250,6 +250,7 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_jneq_null) DEFINE_OP(op_jneq_ptr) DEFINE_OP(op_jnless) + DEFINE_OP(op_jless) DEFINE_OP(op_jnlesseq) DEFINE_OP(op_jsr) DEFINE_OP(op_jtrue) @@ -258,6 +259,7 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_loop_if_less) DEFINE_OP(op_loop_if_lesseq) DEFINE_OP(op_loop_if_true) + DEFINE_OP(op_loop_if_false) DEFINE_OP(op_lshift) DEFINE_OP(op_method_check) DEFINE_OP(op_mod) @@ -385,14 +387,17 @@ void JIT::privateCompileSlowCases() DEFINE_SLOWCASE_OP(op_eq) DEFINE_SLOWCASE_OP(op_get_by_id) DEFINE_SLOWCASE_OP(op_get_by_val) + DEFINE_SLOWCASE_OP(op_get_by_pname) DEFINE_SLOWCASE_OP(op_instanceof) DEFINE_SLOWCASE_OP(op_jfalse) DEFINE_SLOWCASE_OP(op_jnless) + DEFINE_SLOWCASE_OP(op_jless) DEFINE_SLOWCASE_OP(op_jnlesseq) DEFINE_SLOWCASE_OP(op_jtrue) DEFINE_SLOWCASE_OP(op_loop_if_less) DEFINE_SLOWCASE_OP(op_loop_if_lesseq) DEFINE_SLOWCASE_OP(op_loop_if_true) + DEFINE_SLOWCASE_OP(op_loop_if_false) DEFINE_SLOWCASE_OP(op_lshift) DEFINE_SLOWCASE_OP(op_method_check) DEFINE_SLOWCASE_OP(op_mod) @@ -489,21 +494,21 @@ JITCode JIT::privateCompile() ASSERT(record.type == SwitchRecord::Immediate || record.type == SwitchRecord::Character); ASSERT(record.jumpTable.simpleJumpTable->branchOffsets.size() == record.jumpTable.simpleJumpTable->ctiOffsets.size()); - record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + 3 + record.defaultOffset]); + record.jumpTable.simpleJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + record.defaultOffset]); for (unsigned j = 0; j < record.jumpTable.simpleJumpTable->branchOffsets.size(); ++j) { unsigned offset = record.jumpTable.simpleJumpTable->branchOffsets[j]; - record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.simpleJumpTable->ctiDefault; + record.jumpTable.simpleJumpTable->ctiOffsets[j] = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + offset]) : record.jumpTable.simpleJumpTable->ctiDefault; } } else { ASSERT(record.type == SwitchRecord::String); - record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + 3 + record.defaultOffset]); + record.jumpTable.stringJumpTable->ctiDefault = patchBuffer.locationOf(m_labels[bytecodeIndex + record.defaultOffset]); StringJumpTable::StringOffsetTable::iterator end = record.jumpTable.stringJumpTable->offsetTable.end(); for (StringJumpTable::StringOffsetTable::iterator it = record.jumpTable.stringJumpTable->offsetTable.begin(); it != end; ++it) { unsigned offset = it->second.branchOffset; - it->second.ctiOffset = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + 3 + offset]) : record.jumpTable.stringJumpTable->ctiDefault; + it->second.ctiOffset = offset ? patchBuffer.locationOf(m_labels[bytecodeIndex + offset]) : record.jumpTable.stringJumpTable->ctiDefault; } } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JIT.h b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JIT.h index fcbc45e..8e0c9ac 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JIT.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JIT.h @@ -38,6 +38,8 @@ #define JIT_CLASS_ALIGNMENT #endif +#define ASSERT_JIT_OFFSET(actual, expected) ASSERT_WITH_MESSAGE(actual == expected, "JIT Offset \"%s\" should be %d, not %d.\n", #expected, static_cast<int>(actual), static_cast<int>(expected)); + #include "CodeBlock.h" #include "Interpreter.h" #include "JITCode.h" @@ -190,7 +192,7 @@ namespace JSC { // on x86/x86-64 it is ecx for performance reasons, since the // MacroAssembler will need to plant register swaps if it is not - // however the code will still function correctly. -#if PLATFORM(X86_64) +#if CPU(X86_64) static const RegisterID returnValueRegister = X86Registers::eax; static const RegisterID cachedResultRegister = X86Registers::eax; static const RegisterID firstArgumentRegister = X86Registers::edi; @@ -208,7 +210,7 @@ namespace JSC { static const FPRegisterID fpRegT0 = X86Registers::xmm0; static const FPRegisterID fpRegT1 = X86Registers::xmm1; static const FPRegisterID fpRegT2 = X86Registers::xmm2; -#elif PLATFORM(X86) +#elif CPU(X86) static const RegisterID returnValueRegister = X86Registers::eax; static const RegisterID cachedResultRegister = X86Registers::eax; // On x86 we always use fastcall conventions = but on @@ -226,7 +228,7 @@ namespace JSC { static const FPRegisterID fpRegT0 = X86Registers::xmm0; static const FPRegisterID fpRegT1 = X86Registers::xmm1; static const FPRegisterID fpRegT2 = X86Registers::xmm2; -#elif PLATFORM(ARM_THUMB2) +#elif CPU(ARM_THUMB2) static const RegisterID returnValueRegister = ARMRegisters::r0; static const RegisterID cachedResultRegister = ARMRegisters::r0; static const RegisterID firstArgumentRegister = ARMRegisters::r0; @@ -242,14 +244,13 @@ namespace JSC { static const FPRegisterID fpRegT0 = ARMRegisters::d0; static const FPRegisterID fpRegT1 = ARMRegisters::d1; static const FPRegisterID fpRegT2 = ARMRegisters::d2; -#elif PLATFORM(ARM_TRADITIONAL) +#elif CPU(ARM_TRADITIONAL) static const RegisterID returnValueRegister = ARMRegisters::r0; static const RegisterID cachedResultRegister = ARMRegisters::r0; static const RegisterID firstArgumentRegister = ARMRegisters::r0; static const RegisterID timeoutCheckRegister = ARMRegisters::r5; static const RegisterID callFrameRegister = ARMRegisters::r4; - static const RegisterID ctiReturnRegister = ARMRegisters::r6; static const RegisterID regT0 = ARMRegisters::r0; static const RegisterID regT1 = ARMRegisters::r1; @@ -386,6 +387,8 @@ namespace JSC { Address addressFor(unsigned index, RegisterID base = callFrameRegister); + void testPrototype(Structure*, JumpList& failureCases); + #if USE(JSVALUE32_64) Address tagFor(unsigned index, RegisterID base = callFrameRegister); Address payloadFor(unsigned index, RegisterID base = callFrameRegister); @@ -425,6 +428,7 @@ namespace JSC { #endif void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, Structure* structure, size_t cachedOffset); void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID resultTag, RegisterID resultPayload, size_t cachedOffset); + void compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset); void compilePutDirectOffset(RegisterID base, RegisterID valueTag, RegisterID valuePayload, Structure* structure, size_t cachedOffset); // Arithmetic opcode helpers @@ -432,7 +436,7 @@ namespace JSC { void emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType); void emitBinaryDoubleOp(OpcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true); -#if PLATFORM(X86) +#if CPU(X86) // These architecture specific value are used to enable patching - see comment on op_put_by_id. static const int patchOffsetPutByIdStructure = 7; static const int patchOffsetPutByIdExternalLoad = 13; @@ -461,6 +465,47 @@ namespace JSC { static const int patchOffsetMethodCheckProtoObj = 11; static const int patchOffsetMethodCheckProtoStruct = 18; static const int patchOffsetMethodCheckPutFunction = 29; +#elif CPU(ARM_TRADITIONAL) + // These architecture specific value are used to enable patching - see comment on op_put_by_id. + static const int patchOffsetPutByIdStructure = 4; + static const int patchOffsetPutByIdExternalLoad = 16; + static const int patchLengthPutByIdExternalLoad = 4; + static const int patchOffsetPutByIdPropertyMapOffset1 = 20; + static const int patchOffsetPutByIdPropertyMapOffset2 = 28; + // These architecture specific value are used to enable patching - see comment on op_get_by_id. + static const int patchOffsetGetByIdStructure = 4; + static const int patchOffsetGetByIdBranchToSlowCase = 16; + static const int patchOffsetGetByIdExternalLoad = 16; + static const int patchLengthGetByIdExternalLoad = 4; + static const int patchOffsetGetByIdPropertyMapOffset1 = 20; + static const int patchOffsetGetByIdPropertyMapOffset2 = 28; + static const int patchOffsetGetByIdPutResult = 36; +#if ENABLE(OPCODE_SAMPLING) + #error "OPCODE_SAMPLING is not yet supported" +#else + static const int patchOffsetGetByIdSlowCaseCall = 32; +#endif + static const int patchOffsetOpCallCompareToJump = 12; + + static const int patchOffsetMethodCheckProtoObj = 12; + static const int patchOffsetMethodCheckProtoStruct = 20; + static const int patchOffsetMethodCheckPutFunction = 32; + + // sequenceOpCall + static const int sequenceOpCallInstructionSpace = 12; + static const int sequenceOpCallConstantSpace = 2; + // sequenceMethodCheck + static const int sequenceMethodCheckInstructionSpace = 40; + static const int sequenceMethodCheckConstantSpace = 6; + // sequenceGetByIdHotPath + static const int sequenceGetByIdHotPathInstructionSpace = 36; + static const int sequenceGetByIdHotPathConstantSpace = 4; + // sequenceGetByIdSlowCase + static const int sequenceGetByIdSlowCaseInstructionSpace = 40; + static const int sequenceGetByIdSlowCaseConstantSpace = 2; + // sequencePutById + static const int sequencePutByIdInstructionSpace = 36; + static const int sequencePutByIdConstantSpace = 4; #else #error "JSVALUE32_64 not supported on this platform." #endif @@ -526,9 +571,10 @@ namespace JSC { #endif void compileGetDirectOffset(RegisterID base, RegisterID result, Structure* structure, size_t cachedOffset); void compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID result, size_t cachedOffset); + void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch); void compilePutDirectOffset(RegisterID base, RegisterID value, Structure* structure, size_t cachedOffset); -#if PLATFORM(X86_64) +#if CPU(X86_64) // These architecture specific value are used to enable patching - see comment on op_put_by_id. static const int patchOffsetPutByIdStructure = 10; static const int patchOffsetPutByIdExternalLoad = 20; @@ -542,7 +588,7 @@ namespace JSC { static const int patchOffsetGetByIdPropertyMapOffset = 31; static const int patchOffsetGetByIdPutResult = 31; #if ENABLE(OPCODE_SAMPLING) - static const int patchOffsetGetByIdSlowCaseCall = 63; + static const int patchOffsetGetByIdSlowCaseCall = 64; #else static const int patchOffsetGetByIdSlowCaseCall = 41; #endif @@ -551,7 +597,7 @@ namespace JSC { static const int patchOffsetMethodCheckProtoObj = 20; static const int patchOffsetMethodCheckProtoStruct = 30; static const int patchOffsetMethodCheckPutFunction = 50; -#elif PLATFORM(X86) +#elif CPU(X86) // These architecture specific value are used to enable patching - see comment on op_put_by_id. static const int patchOffsetPutByIdStructure = 7; static const int patchOffsetPutByIdExternalLoad = 13; @@ -578,30 +624,30 @@ namespace JSC { static const int patchOffsetMethodCheckProtoObj = 11; static const int patchOffsetMethodCheckProtoStruct = 18; static const int patchOffsetMethodCheckPutFunction = 29; -#elif PLATFORM(ARM_THUMB2) +#elif CPU(ARM_THUMB2) // These architecture specific value are used to enable patching - see comment on op_put_by_id. static const int patchOffsetPutByIdStructure = 10; - static const int patchOffsetPutByIdExternalLoad = 20; + static const int patchOffsetPutByIdExternalLoad = 26; static const int patchLengthPutByIdExternalLoad = 12; - static const int patchOffsetPutByIdPropertyMapOffset = 40; + static const int patchOffsetPutByIdPropertyMapOffset = 46; // These architecture specific value are used to enable patching - see comment on op_get_by_id. static const int patchOffsetGetByIdStructure = 10; - static const int patchOffsetGetByIdBranchToSlowCase = 20; - static const int patchOffsetGetByIdExternalLoad = 20; + static const int patchOffsetGetByIdBranchToSlowCase = 26; + static const int patchOffsetGetByIdExternalLoad = 26; static const int patchLengthGetByIdExternalLoad = 12; - static const int patchOffsetGetByIdPropertyMapOffset = 40; - static const int patchOffsetGetByIdPutResult = 44; + static const int patchOffsetGetByIdPropertyMapOffset = 46; + static const int patchOffsetGetByIdPutResult = 50; #if ENABLE(OPCODE_SAMPLING) static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE #else static const int patchOffsetGetByIdSlowCaseCall = 28; #endif - static const int patchOffsetOpCallCompareToJump = 10; + static const int patchOffsetOpCallCompareToJump = 16; - static const int patchOffsetMethodCheckProtoObj = 18; - static const int patchOffsetMethodCheckProtoStruct = 28; - static const int patchOffsetMethodCheckPutFunction = 46; -#elif PLATFORM(ARM_TRADITIONAL) + static const int patchOffsetMethodCheckProtoObj = 24; + static const int patchOffsetMethodCheckProtoStruct = 34; + static const int patchOffsetMethodCheckPutFunction = 58; +#elif CPU(ARM_TRADITIONAL) // These architecture specific value are used to enable patching - see comment on op_put_by_id. static const int patchOffsetPutByIdStructure = 4; static const int patchOffsetPutByIdExternalLoad = 16; @@ -617,17 +663,14 @@ namespace JSC { #if ENABLE(OPCODE_SAMPLING) #error "OPCODE_SAMPLING is not yet supported" #else - static const int patchOffsetGetByIdSlowCaseCall = 36; + static const int patchOffsetGetByIdSlowCaseCall = 28; #endif static const int patchOffsetOpCallCompareToJump = 12; static const int patchOffsetMethodCheckProtoObj = 12; static const int patchOffsetMethodCheckProtoStruct = 20; static const int patchOffsetMethodCheckPutFunction = 32; -#endif -#endif // USE(JSVALUE32_64) -#if PLATFORM(ARM_TRADITIONAL) // sequenceOpCall static const int sequenceOpCallInstructionSpace = 12; static const int sequenceOpCallConstantSpace = 2; @@ -638,12 +681,13 @@ namespace JSC { static const int sequenceGetByIdHotPathInstructionSpace = 28; static const int sequenceGetByIdHotPathConstantSpace = 3; // sequenceGetByIdSlowCase - static const int sequenceGetByIdSlowCaseInstructionSpace = 40; + static const int sequenceGetByIdSlowCaseInstructionSpace = 32; static const int sequenceGetByIdSlowCaseConstantSpace = 2; // sequencePutById static const int sequencePutByIdInstructionSpace = 28; static const int sequencePutByIdConstantSpace = 3; #endif +#endif // USE(JSVALUE32_64) #if defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL #define BEGIN_UNINTERRUPTED_SEQUENCE(name) beginUninterruptedSequence(name ## InstructionSpace, name ## ConstantSpace) @@ -680,6 +724,7 @@ namespace JSC { void emit_op_eq_null(Instruction*); void emit_op_get_by_id(Instruction*); void emit_op_get_by_val(Instruction*); + void emit_op_get_by_pname(Instruction*); void emit_op_get_global_var(Instruction*); void emit_op_get_scoped_var(Instruction*); void emit_op_init_arguments(Instruction*); @@ -691,6 +736,7 @@ namespace JSC { void emit_op_jneq_null(Instruction*); void emit_op_jneq_ptr(Instruction*); void emit_op_jnless(Instruction*); + void emit_op_jless(Instruction*); void emit_op_jnlesseq(Instruction*); void emit_op_jsr(Instruction*); void emit_op_jtrue(Instruction*); @@ -699,6 +745,7 @@ namespace JSC { void emit_op_loop_if_less(Instruction*); void emit_op_loop_if_lesseq(Instruction*); void emit_op_loop_if_true(Instruction*); + void emit_op_loop_if_false(Instruction*); void emit_op_lshift(Instruction*); void emit_op_method_check(Instruction*); void emit_op_mod(Instruction*); @@ -713,6 +760,7 @@ namespace JSC { void emit_op_new_func_exp(Instruction*); void emit_op_new_object(Instruction*); void emit_op_new_regexp(Instruction*); + void emit_op_get_pnames(Instruction*); void emit_op_next_pname(Instruction*); void emit_op_not(Instruction*); void emit_op_nstricteq(Instruction*); @@ -768,14 +816,17 @@ namespace JSC { void emitSlow_op_eq(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_get_by_id(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_get_by_val(Instruction*, Vector<SlowCaseEntry>::iterator&); + void emitSlow_op_get_by_pname(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_instanceof(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_jfalse(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_jnless(Instruction*, Vector<SlowCaseEntry>::iterator&); + void emitSlow_op_jless(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_jnlesseq(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_jtrue(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_loop_if_less(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_loop_if_lesseq(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_loop_if_true(Instruction*, Vector<SlowCaseEntry>::iterator&); + void emitSlow_op_loop_if_false(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_lshift(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_method_check(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&); @@ -903,6 +954,46 @@ namespace JSC { #endif #endif } JIT_CLASS_ALIGNMENT; + + inline void JIT::emit_op_loop(Instruction* currentInstruction) + { + emitTimeoutCheck(); + emit_op_jmp(currentInstruction); + } + + inline void JIT::emit_op_loop_if_true(Instruction* currentInstruction) + { + emitTimeoutCheck(); + emit_op_jtrue(currentInstruction); + } + + inline void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) + { + emitSlow_op_jtrue(currentInstruction, iter); + } + + inline void JIT::emit_op_loop_if_false(Instruction* currentInstruction) + { + emitTimeoutCheck(); + emit_op_jfalse(currentInstruction); + } + + inline void JIT::emitSlow_op_loop_if_false(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) + { + emitSlow_op_jfalse(currentInstruction, iter); + } + + inline void JIT::emit_op_loop_if_less(Instruction* currentInstruction) + { + emitTimeoutCheck(); + emit_op_jless(currentInstruction); + } + + inline void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) + { + emitSlow_op_jless(currentInstruction, iter); + } + } // namespace JSC #endif // ENABLE(JIT) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITArithmetic.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITArithmetic.cpp index 7afc1f2..feee8d2 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITArithmetic.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITArithmetic.cpp @@ -98,16 +98,16 @@ void JIT::emit_op_jnless(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op1)) { emitLoad(op2, regT3, regT2); notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target + 3); + addJump(branch32(LessThanOrEqual, regT2, Imm32(getConstantOperand(op1).asInt32())), target); } else if (isOperandConstantImmediateInt(op2)) { emitLoad(op1, regT1, regT0); notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3); + addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); } else { emitLoad2(op1, regT1, regT0, op2, regT3, regT2); notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThanOrEqual, regT0, regT2), target + 3); + addJump(branch32(GreaterThanOrEqual, regT0, regT2), target); } if (!supportsFloatingPoint()) { @@ -145,7 +145,70 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt stubCall.addArgument(op1); stubCall.addArgument(op2); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); +} + +void JIT::emit_op_jless(Instruction* currentInstruction) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + JumpList notInt32Op1; + JumpList notInt32Op2; + + // Int32 less. + if (isOperandConstantImmediateInt(op1)) { + emitLoad(op2, regT3, regT2); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addJump(branch32(GreaterThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); + } else if (isOperandConstantImmediateInt(op2)) { + emitLoad(op1, regT1, regT0); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target); + } else { + emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); + notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); + addJump(branch32(LessThan, regT0, regT2), target); + } + + if (!supportsFloatingPoint()) { + addSlowCase(notInt32Op1); + addSlowCase(notInt32Op2); + return; + } + Jump end = jump(); + + // Double less. + emitBinaryDoubleOp(op_jless, target, op1, op2, OperandTypes(), notInt32Op1, notInt32Op2, !isOperandConstantImmediateInt(op1), isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)); + end.link(this); +} + +void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + if (!supportsFloatingPoint()) { + if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // int32 check + linkSlowCase(iter); // int32 check + } else { + if (!isOperandConstantImmediateInt(op1)) { + linkSlowCase(iter); // double check + linkSlowCase(iter); // int32 check + } + if (isOperandConstantImmediateInt(op1) || !isOperandConstantImmediateInt(op2)) + linkSlowCase(iter); // double check + } + + JITStubCall stubCall(this, cti_op_jless); + stubCall.addArgument(op1); + stubCall.addArgument(op2); + stubCall.call(); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); } void JIT::emit_op_jnlesseq(Instruction* currentInstruction) @@ -161,16 +224,16 @@ void JIT::emit_op_jnlesseq(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op1)) { emitLoad(op2, regT3, regT2); notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target + 3); + addJump(branch32(LessThan, regT2, Imm32(getConstantOperand(op1).asInt32())), target); } else if (isOperandConstantImmediateInt(op2)) { emitLoad(op1, regT1, regT0); notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3); + addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target); } else { emitLoad2(op1, regT1, regT0, op2, regT3, regT2); notInt32Op1.append(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); notInt32Op2.append(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThan, regT0, regT2), target + 3); + addJump(branch32(GreaterThan, regT0, regT2), target); } if (!supportsFloatingPoint()) { @@ -208,7 +271,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE stubCall.addArgument(op1); stubCall.addArgument(op2); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); } // LeftShift (<<) @@ -829,11 +892,15 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi break; case op_jnless: emitLoadDouble(op1, fpRegT2); - addJump(branchDouble(DoubleLessThanOrEqual, fpRegT0, fpRegT2), dst + 3); + addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT0, fpRegT2), dst); + break; + case op_jless: + emitLoadDouble(op1, fpRegT2); + addJump(branchDouble(DoubleLessThan, fpRegT2, fpRegT0), dst); break; case op_jnlesseq: emitLoadDouble(op1, fpRegT2); - addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT2), dst + 3); + addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT0, fpRegT2), dst); break; default: ASSERT_NOT_REACHED(); @@ -882,11 +949,15 @@ void JIT::emitBinaryDoubleOp(OpcodeID opcodeID, unsigned dst, unsigned op1, unsi break; case op_jnless: emitLoadDouble(op2, fpRegT1); - addJump(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), dst + 3); + addJump(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), dst); + break; + case op_jless: + emitLoadDouble(op2, fpRegT1); + addJump(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), dst); break; case op_jnlesseq: emitLoadDouble(op2, fpRegT1); - addJump(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), dst + 3); + addJump(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), dst); break; default: ASSERT_NOT_REACHED(); @@ -1000,20 +1071,11 @@ void JIT::emit_op_div(Instruction* currentInstruction) divDouble(fpRegT1, fpRegT0); JumpList doubleResult; - if (!isOperandConstantImmediateInt(op1) || getConstantOperand(op1).asInt32() > 1) { - m_assembler.cvttsd2si_rr(fpRegT0, regT0); - convertInt32ToDouble(regT0, fpRegT1); - m_assembler.ucomisd_rr(fpRegT1, fpRegT0); - - doubleResult.append(m_assembler.jne()); - doubleResult.append(m_assembler.jp()); - - doubleResult.append(branchTest32(Zero, regT0)); + branchConvertDoubleToInt32(fpRegT0, regT0, doubleResult, fpRegT1); - // Int32 result. - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); - end.append(jump()); - } + // Int32 result. + emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); + end.append(jump()); // Double result. doubleResult.link(this); @@ -1054,7 +1116,7 @@ void JIT::emitSlow_op_div(Instruction* currentInstruction, Vector<SlowCaseEntry> /* ------------------------------ BEGIN: OP_MOD ------------------------------ */ -#if PLATFORM(X86) || PLATFORM(X86_64) +#if CPU(X86) || CPU(X86_64) void JIT::emit_op_mod(Instruction* currentInstruction) { @@ -1116,7 +1178,7 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry> stubCall.call(dst); } -#else // PLATFORM(X86) || PLATFORM(X86_64) +#else // CPU(X86) || CPU(X86_64) void JIT::emit_op_mod(Instruction* currentInstruction) { @@ -1134,7 +1196,7 @@ void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&) { } -#endif // PLATFORM(X86) || PLATFORM(X86_64) +#endif // CPU(X86) || CPU(X86_64) /* ------------------------------ END: OP_MOD ------------------------------ */ @@ -1152,13 +1214,8 @@ void JIT::emit_op_lshift(Instruction* currentInstruction) emitJumpSlowCaseIfNotImmediateInteger(regT2); emitFastArithImmToInt(regT0); emitFastArithImmToInt(regT2); -#if !PLATFORM(X86) - // Mask with 0x1f as per ecma-262 11.7.2 step 7. - // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction. - and32(Imm32(0x1f), regT2); -#endif lshift32(regT2, regT0); -#if !USE(JSVALUE64) +#if USE(JSVALUE32) addSlowCase(branchAdd32(Overflow, regT0, regT0)); signExtend32ToPtr(regT0, regT0); #endif @@ -1203,11 +1260,7 @@ void JIT::emit_op_rshift(Instruction* currentInstruction) emitGetVirtualRegister(op1, regT0); emitJumpSlowCaseIfNotImmediateInteger(regT0); // Mask with 0x1f as per ecma-262 11.7.2 step 7. -#if USE(JSVALUE64) rshift32(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0); -#else - rshiftPtr(Imm32(getConstantOperandImmediateInt(op2) & 0x1f), regT0); -#endif } else { emitGetVirtualRegisters(op1, regT0, op2, regT2); if (supportsFloatingPointTruncate()) { @@ -1234,15 +1287,9 @@ void JIT::emit_op_rshift(Instruction* currentInstruction) emitJumpSlowCaseIfNotImmediateInteger(regT2); } emitFastArithImmToInt(regT2); -#if !PLATFORM(X86) - // Mask with 0x1f as per ecma-262 11.7.2 step 7. - // On 32-bit x86 this is not necessary, since the shift anount is implicitly masked in the instruction. - and32(Imm32(0x1f), regT2); -#endif -#if USE(JSVALUE64) rshift32(regT2, regT0); -#else - rshiftPtr(regT2, regT0); +#if USE(JSVALUE32) + signExtend32ToPtr(regT0, regT0); #endif } #if USE(JSVALUE64) @@ -1313,7 +1360,7 @@ void JIT::emit_op_jnless(Instruction* currentInstruction) #else int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); #endif - addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target + 3); + addJump(branch32(GreaterThanOrEqual, regT0, Imm32(op2imm)), target); } else if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); @@ -1322,13 +1369,13 @@ void JIT::emit_op_jnless(Instruction* currentInstruction) #else int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); #endif - addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target + 3); + addJump(branch32(LessThanOrEqual, regT1, Imm32(op1imm)), target); } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT1); - addJump(branch32(GreaterThanOrEqual, regT0, regT1), target + 3); + addJump(branch32(GreaterThanOrEqual, regT0, regT1), target); } } @@ -1365,7 +1412,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt move(Imm32(op2imm), regT1); convertInt32ToDouble(regT1, fpRegT1); - emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), target + 3); + emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); @@ -1382,7 +1429,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt stubCall.addArgument(regT0); stubCall.addArgument(op2, regT2); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); } else if (isOperandConstantImmediateInt(op1)) { linkSlowCase(iter); @@ -1406,7 +1453,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt move(Imm32(op1imm), regT0); convertInt32ToDouble(regT0, fpRegT0); - emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), target + 3); + emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); @@ -1423,7 +1470,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt stubCall.addArgument(op1, regT2); stubCall.addArgument(regT1); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); } else { linkSlowCase(iter); @@ -1452,7 +1499,7 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); #endif - emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqual, fpRegT1, fpRegT0), target + 3); + emitJumpSlowToHot(branchDouble(DoubleLessThanOrEqualOrUnordered, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); @@ -1475,7 +1522,192 @@ void JIT::emitSlow_op_jnless(Instruction* currentInstruction, Vector<SlowCaseEnt stubCall.addArgument(regT0); stubCall.addArgument(regT1); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); + } +} + +void JIT::emit_op_jless(Instruction* currentInstruction) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + // We generate inline code for the following cases in the fast path: + // - int immediate to constant int immediate + // - constant int immediate to int immediate + // - int immediate to int immediate + + if (isOperandConstantImmediateInt(op2)) { + emitGetVirtualRegister(op1, regT0); + emitJumpSlowCaseIfNotImmediateInteger(regT0); +#if USE(JSVALUE64) + int32_t op2imm = getConstantOperandImmediateInt(op2); +#else + int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); +#endif + addJump(branch32(LessThan, regT0, Imm32(op2imm)), target); + } else if (isOperandConstantImmediateInt(op1)) { + emitGetVirtualRegister(op2, regT1); + emitJumpSlowCaseIfNotImmediateInteger(regT1); +#if USE(JSVALUE64) + int32_t op1imm = getConstantOperandImmediateInt(op1); +#else + int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); +#endif + addJump(branch32(GreaterThan, regT1, Imm32(op1imm)), target); + } else { + emitGetVirtualRegisters(op1, regT0, op2, regT1); + emitJumpSlowCaseIfNotImmediateInteger(regT0); + emitJumpSlowCaseIfNotImmediateInteger(regT1); + + addJump(branch32(LessThan, regT0, regT1), target); + } +} + +void JIT::emitSlow_op_jless(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned op1 = currentInstruction[1].u.operand; + unsigned op2 = currentInstruction[2].u.operand; + unsigned target = currentInstruction[3].u.operand; + + // We generate inline code for the following cases in the slow path: + // - floating-point number to constant int immediate + // - constant int immediate to floating-point number + // - floating-point number to floating-point number. + + if (isOperandConstantImmediateInt(op2)) { + linkSlowCase(iter); + + if (supportsFloatingPoint()) { +#if USE(JSVALUE64) + Jump fail1 = emitJumpIfNotImmediateNumber(regT0); + addPtr(tagTypeNumberRegister, regT0); + movePtrToDouble(regT0, fpRegT0); +#else + Jump fail1; + if (!m_codeBlock->isKnownNotImmediate(op1)) + fail1 = emitJumpIfNotJSCell(regT0); + + Jump fail2 = checkStructure(regT0, m_globalData->numberStructure.get()); + loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); +#endif + + int32_t op2imm = getConstantOperand(op2).asInt32(); + + move(Imm32(op2imm), regT1); + convertInt32ToDouble(regT1, fpRegT1); + + emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target); + + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); + +#if USE(JSVALUE64) + fail1.link(this); +#else + if (!m_codeBlock->isKnownNotImmediate(op1)) + fail1.link(this); + fail2.link(this); +#endif + } + + JITStubCall stubCall(this, cti_op_jless); + stubCall.addArgument(regT0); + stubCall.addArgument(op2, regT2); + stubCall.call(); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); + + } else if (isOperandConstantImmediateInt(op1)) { + linkSlowCase(iter); + + if (supportsFloatingPoint()) { +#if USE(JSVALUE64) + Jump fail1 = emitJumpIfNotImmediateNumber(regT1); + addPtr(tagTypeNumberRegister, regT1); + movePtrToDouble(regT1, fpRegT1); +#else + Jump fail1; + if (!m_codeBlock->isKnownNotImmediate(op2)) + fail1 = emitJumpIfNotJSCell(regT1); + + Jump fail2 = checkStructure(regT1, m_globalData->numberStructure.get()); + loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); +#endif + + int32_t op1imm = getConstantOperand(op1).asInt32(); + + move(Imm32(op1imm), regT0); + convertInt32ToDouble(regT0, fpRegT0); + + emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target); + + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); + +#if USE(JSVALUE64) + fail1.link(this); +#else + if (!m_codeBlock->isKnownNotImmediate(op2)) + fail1.link(this); + fail2.link(this); +#endif + } + + JITStubCall stubCall(this, cti_op_jless); + stubCall.addArgument(op1, regT2); + stubCall.addArgument(regT1); + stubCall.call(); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); + + } else { + linkSlowCase(iter); + + if (supportsFloatingPoint()) { +#if USE(JSVALUE64) + Jump fail1 = emitJumpIfNotImmediateNumber(regT0); + Jump fail2 = emitJumpIfNotImmediateNumber(regT1); + Jump fail3 = emitJumpIfImmediateInteger(regT1); + addPtr(tagTypeNumberRegister, regT0); + addPtr(tagTypeNumberRegister, regT1); + movePtrToDouble(regT0, fpRegT0); + movePtrToDouble(regT1, fpRegT1); +#else + Jump fail1; + if (!m_codeBlock->isKnownNotImmediate(op1)) + fail1 = emitJumpIfNotJSCell(regT0); + + Jump fail2; + if (!m_codeBlock->isKnownNotImmediate(op2)) + fail2 = emitJumpIfNotJSCell(regT1); + + Jump fail3 = checkStructure(regT0, m_globalData->numberStructure.get()); + Jump fail4 = checkStructure(regT1, m_globalData->numberStructure.get()); + loadDouble(Address(regT0, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT0); + loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); +#endif + + emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT0, fpRegT1), target); + + emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnless)); + +#if USE(JSVALUE64) + fail1.link(this); + fail2.link(this); + fail3.link(this); +#else + if (!m_codeBlock->isKnownNotImmediate(op1)) + fail1.link(this); + if (!m_codeBlock->isKnownNotImmediate(op2)) + fail2.link(this); + fail3.link(this); + fail4.link(this); +#endif + } + + linkSlowCase(iter); + JITStubCall stubCall(this, cti_op_jless); + stubCall.addArgument(regT0); + stubCall.addArgument(regT1); + stubCall.call(); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); } } @@ -1498,7 +1730,7 @@ void JIT::emit_op_jnlesseq(Instruction* currentInstruction) #else int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); #endif - addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target + 3); + addJump(branch32(GreaterThan, regT0, Imm32(op2imm)), target); } else if (isOperandConstantImmediateInt(op1)) { emitGetVirtualRegister(op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT1); @@ -1507,13 +1739,13 @@ void JIT::emit_op_jnlesseq(Instruction* currentInstruction) #else int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); #endif - addJump(branch32(LessThan, regT1, Imm32(op1imm)), target + 3); + addJump(branch32(LessThan, regT1, Imm32(op1imm)), target); } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT1); - addJump(branch32(GreaterThan, regT0, regT1), target + 3); + addJump(branch32(GreaterThan, regT0, regT1), target); } } @@ -1550,7 +1782,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE move(Imm32(op2imm), regT1); convertInt32ToDouble(regT1, fpRegT1); - emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), target + 3); + emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); @@ -1567,7 +1799,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE stubCall.addArgument(regT0); stubCall.addArgument(op2, regT2); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); } else if (isOperandConstantImmediateInt(op1)) { linkSlowCase(iter); @@ -1591,7 +1823,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE move(Imm32(op1imm), regT0); convertInt32ToDouble(regT0, fpRegT0); - emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), target + 3); + emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); @@ -1608,7 +1840,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE stubCall.addArgument(op1, regT2); stubCall.addArgument(regT1); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); } else { linkSlowCase(iter); @@ -1637,7 +1869,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE loadDouble(Address(regT1, OBJECT_OFFSETOF(JSNumberCell, m_value)), fpRegT1); #endif - emitJumpSlowToHot(branchDouble(DoubleLessThan, fpRegT1, fpRegT0), target + 3); + emitJumpSlowToHot(branchDouble(DoubleLessThanOrUnordered, fpRegT1, fpRegT0), target); emitJumpSlowToHot(jump(), OPCODE_LENGTH(op_jnlesseq)); @@ -1660,7 +1892,7 @@ void JIT::emitSlow_op_jnlesseq(Instruction* currentInstruction, Vector<SlowCaseE stubCall.addArgument(regT0); stubCall.addArgument(regT1); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(Zero, regT0), target); } } @@ -1849,7 +2081,7 @@ void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEn /* ------------------------------ BEGIN: OP_MOD ------------------------------ */ -#if PLATFORM(X86) || PLATFORM(X86_64) +#if CPU(X86) || CPU(X86_64) void JIT::emit_op_mod(Instruction* currentInstruction) { @@ -1898,7 +2130,7 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry> stubCall.call(result); } -#else // PLATFORM(X86) || PLATFORM(X86_64) +#else // CPU(X86) || CPU(X86_64) void JIT::emit_op_mod(Instruction* currentInstruction) { @@ -1917,7 +2149,7 @@ void JIT::emitSlow_op_mod(Instruction*, Vector<SlowCaseEntry>::iterator&) ASSERT_NOT_REACHED(); } -#endif // PLATFORM(X86) || PLATFORM(X86_64) +#endif // CPU(X86) || CPU(X86_64) /* ------------------------------ END: OP_MOD ------------------------------ */ @@ -2160,27 +2392,10 @@ void JIT::emit_op_div(Instruction* currentInstruction) } divDouble(fpRegT1, fpRegT0); - JumpList doubleResult; - Jump end; - bool attemptIntConversion = (!isOperandConstantImmediateInt(op1) || getConstantOperand(op1).asInt32() > 1) && isOperandConstantImmediateInt(op2); - if (attemptIntConversion) { - m_assembler.cvttsd2si_rr(fpRegT0, regT0); - doubleResult.append(branchTest32(Zero, regT0)); - m_assembler.ucomisd_rr(fpRegT1, fpRegT0); - - doubleResult.append(m_assembler.jne()); - doubleResult.append(m_assembler.jp()); - emitFastArithIntToImmNoCheck(regT0, regT0); - end = jump(); - } - // Double result. - doubleResult.link(this); moveDoubleToPtr(fpRegT0, regT0); subPtr(tagTypeNumberRegister, regT0); - if (attemptIntConversion) - end.link(this); emitPutVirtualRegister(dst, regT0); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITCall.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITCall.cpp index f4f6e62..07253e1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITCall.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITCall.cpp @@ -249,10 +249,10 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) stubCall.addArgument(JIT::Imm32(registerOffset)); stubCall.addArgument(JIT::Imm32(argCount)); stubCall.call(); - wasEval = branch32(Equal, regT1, Imm32(JSValue::EmptyValueTag)); + wasEval = branch32(NotEqual, regT1, Imm32(JSValue::EmptyValueTag)); } - emitLoad(callee, regT1, regT2); + emitLoad(callee, regT1, regT0); if (opcodeID == op_call) compileOpCallSetupArgs(instruction); @@ -260,12 +260,12 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) compileOpConstructSetupArgs(instruction); emitJumpSlowCaseIfNotJSCell(callee, regT1); - addSlowCase(branchPtr(NotEqual, Address(regT2), ImmPtr(m_globalData->jsFunctionVPtr))); + addSlowCase(branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsFunctionVPtr))); // First, in the case of a construct, allocate the new object. if (opcodeID == op_construct) { JITStubCall(this, cti_op_construct_JSConstruct).call(registerOffset - RegisterFile::CallFrameHeaderSize - argCount); - emitLoad(callee, regT1, regT2); + emitLoad(callee, regT1, regT0); } // Speculatively roll the callframe, assuming argCount will match the arity. @@ -278,7 +278,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned) if (opcodeID == op_call_eval) wasEval.link(this); - emitStore(dst, regT1, regT0);; + emitStore(dst, regT1, regT0); sampleCodeBlock(m_codeBlock); } @@ -321,7 +321,13 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca emitLoad(callee, regT1, regT0); DataLabelPtr addressOfLinkedFunctionCheck; + + BEGIN_UNINTERRUPTED_SEQUENCE(sequenceOpCall); + Jump jumpToSlow = branchPtrWithPatch(NotEqual, regT0, addressOfLinkedFunctionCheck, ImmPtr(0)); + + END_UNINTERRUPTED_SEQUENCE(sequenceOpCall); + addSlowCase(jumpToSlow); ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump); m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck; @@ -620,7 +626,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca END_UNINTERRUPTED_SEQUENCE(sequenceOpCall); addSlowCase(jumpToSlow); - ASSERT(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow) == patchOffsetOpCallCompareToJump); + ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, jumpToSlow), patchOffsetOpCallCompareToJump); m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck; // The following is the fast case, only used whan a callee can be linked. diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITInlineMethods.h b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITInlineMethods.h index f26457a..5af7565 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITInlineMethods.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITInlineMethods.h @@ -37,7 +37,7 @@ namespace JSC { // puts an arg onto the stack, as an arg to a context threaded function. ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumber) { - unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1; + unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX; poke(src, argumentStackOffset); } @@ -45,7 +45,7 @@ ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID src, unsigned argumentNumbe ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argumentNumber) { - unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1; + unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX; poke(Imm32(value), argumentStackOffset); } @@ -53,7 +53,7 @@ ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(unsigned value, unsigned argum ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argumentNumber) { - unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1; + unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX; poke(ImmPtr(value), argumentStackOffset); } @@ -61,7 +61,7 @@ ALWAYS_INLINE void JIT::emitPutJITStubArgConstant(void* value, unsigned argument ALWAYS_INLINE void JIT::emitGetJITStubArg(unsigned argumentNumber, RegisterID dst) { - unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1; + unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX; peek(dst, argumentStackOffset); } @@ -115,7 +115,7 @@ ALWAYS_INLINE JIT::Call JIT::emitNakedCall(CodePtr function) ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace) { -#if PLATFORM(ARM_TRADITIONAL) +#if CPU(ARM_TRADITIONAL) #ifndef NDEBUG // Ensure the label after the sequence can also fit insnSpace += sizeof(ARMWord); @@ -144,7 +144,7 @@ ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace) #endif -#if PLATFORM(ARM_THUMB2) +#if CPU(ARM) ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg) { @@ -161,7 +161,7 @@ ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address) loadPtr(address, linkRegister); } -#else // PLATFORM(X86) || PLATFORM(X86_64) || PLATFORM(ARM_TRADITIONAL) +#else // CPU(X86) || CPU(X86_64) ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg) { @@ -191,16 +191,13 @@ ALWAYS_INLINE void JIT::restoreArgumentReference() { move(stackPointerRegister, firstArgumentRegister); poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*)); -#if PLATFORM(ARM_TRADITIONAL) - move(ctiReturnRegister, ARMRegisters::lr); -#endif } ALWAYS_INLINE void JIT::restoreArgumentReferenceForTrampoline() { -#if PLATFORM(X86) +#if CPU(X86) // Within a trampoline the return address will be on the stack at this point. addPtr(Imm32(sizeof(void*)), stackPointerRegister, firstArgumentRegister); -#elif PLATFORM(ARM_THUMB2) +#elif CPU(ARM) move(stackPointerRegister, firstArgumentRegister); #endif // In the trampoline on x86-64, the first argument register is not overwritten. @@ -268,9 +265,9 @@ ALWAYS_INLINE void JIT::clearSamplingFlag(int32_t flag) #if ENABLE(SAMPLING_COUNTERS) ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t count) { -#if PLATFORM(X86_64) // Or any other 64-bit plattform. +#if CPU(X86_64) // Or any other 64-bit plattform. addPtr(Imm32(count), AbsoluteAddress(&counter.m_counter)); -#elif PLATFORM(X86) // Or any other little-endian 32-bit plattform. +#elif CPU(X86) // Or any other little-endian 32-bit plattform. intptr_t hiWord = reinterpret_cast<intptr_t>(&counter.m_counter) + sizeof(int32_t); add32(Imm32(count), AbsoluteAddress(&counter.m_counter)); addWithCarry32(Imm32(0), AbsoluteAddress(reinterpret_cast<void*>(hiWord))); @@ -281,7 +278,7 @@ ALWAYS_INLINE void JIT::emitCount(AbstractSamplingCounter& counter, uint32_t cou #endif #if ENABLE(OPCODE_SAMPLING) -#if PLATFORM(X86_64) +#if CPU(X86_64) ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostFunction) { move(ImmPtr(m_interpreter->sampler()->sampleSlot()), X86Registers::ecx); @@ -296,7 +293,7 @@ ALWAYS_INLINE void JIT::sampleInstruction(Instruction* instruction, bool inHostF #endif #if ENABLE(CODEBLOCK_SAMPLING) -#if PLATFORM(X86_64) +#if CPU(X86_64) ALWAYS_INLINE void JIT::sampleCodeBlock(CodeBlock* codeBlock) { move(ImmPtr(m_interpreter->sampler()->codeBlockSlot()), X86Registers::ecx); @@ -588,7 +585,7 @@ ALWAYS_INLINE bool JIT::getOperandConstantImmediateInt(unsigned op1, unsigned op ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID tag, RegisterID payload, unsigned argumentNumber) { - unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1; + unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX; poke(payload, argumentStackOffset); poke(tag, argumentStackOffset + 1); } @@ -597,7 +594,7 @@ ALWAYS_INLINE void JIT::emitPutJITStubArg(RegisterID tag, RegisterID payload, un ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch1, RegisterID scratch2) { - unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1; + unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX; if (m_codeBlock->isConstantRegisterIndex(src)) { JSValue constant = m_codeBlock->getConstant(src); poke(Imm32(constant.payload()), argumentStackOffset); @@ -820,7 +817,7 @@ ALWAYS_INLINE void JIT::emitFastArithImmToInt(RegisterID reg) #if USE(JSVALUE64) UNUSED_PARAM(reg); #else - rshiftPtr(Imm32(JSImmediate::IntegerPayloadShift), reg); + rshift32(Imm32(JSImmediate::IntegerPayloadShift), reg); #endif } @@ -849,7 +846,7 @@ ALWAYS_INLINE void JIT::emitTagAsBoolImmediate(RegisterID reg) // get arg puts an arg from the SF register array onto the stack, as an arg to a context threaded function. ALWAYS_INLINE void JIT::emitPutJITStubArgFromVirtualRegister(unsigned src, unsigned argumentNumber, RegisterID scratch) { - unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + 1; + unsigned argumentStackOffset = (argumentNumber * (sizeof(JSValue) / sizeof(void*))) + JITSTACKFRAME_ARGS_INDEX; if (m_codeBlock->isConstantRegisterIndex(src)) { JSValue value = m_codeBlock->getConstant(src); poke(ImmPtr(JSValue::encode(value)), argumentStackOffset); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITOpcodes.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITOpcodes.cpp index b5f6597..601f2d6 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITOpcodes.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITOpcodes.cpp @@ -33,6 +33,7 @@ #include "JSArray.h" #include "JSCell.h" #include "JSFunction.h" +#include "JSPropertyNameIterator.h" #include "LinkBuffer.h" namespace JSC { @@ -51,8 +52,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)); // Checks out okay! - get the length from the Ustring. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSString, m_value) + OBJECT_OFFSETOF(UString, m_rep)), regT2); - load32(Address(regT2, OBJECT_OFFSETOF(UString::Rep, len)), regT2); + load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_stringLength)), regT2); Jump string_failureCases3 = branch32(Above, regT2, Imm32(INT_MAX)); move(regT2, regT0); @@ -137,7 +137,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable loadPtr(Address(regT2, OBJECT_OFFSETOF(FunctionExecutable, m_jitCode)), regT0); jump(regT0); -#if PLATFORM(X86) +#if CPU(X86) || CPU(ARM_TRADITIONAL) Label nativeCallThunk = align(); preserveReturnAddressAfterCall(regT0); emitPutToCallFrameHeader(regT0, RegisterFile::ReturnPC); // Push return address @@ -148,6 +148,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable emitGetFromCallFrameHeaderPtr(RegisterFile::ScopeChain, regT1, regT1); emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); +#if CPU(X86) emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); /* We have two structs that we use to describe the stackframe we set up for our @@ -159,7 +160,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable * stack pointer by the right amount after the call. */ -#if COMPILER(MSVC) || PLATFORM(LINUX) +#if COMPILER(MSVC) || OS(LINUX) #if COMPILER(MSVC) #pragma pack(push) #pragma pack(4) @@ -222,7 +223,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable storePtr(regT2, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.payload))); storePtr(regT3, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue) + OBJECT_OFFSETOF(JSValue, u.asBits.tag))); -#if COMPILER(MSVC) || PLATFORM(LINUX) +#if COMPILER(MSVC) || OS(LINUX) // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register) addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86Registers::ecx); @@ -247,6 +248,66 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable // so pull them off now addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister); +#elif CPU(ARM_TRADITIONAL) + emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); + + // Allocate stack space for our arglist + COMPILE_ASSERT((sizeof(ArgList) & 0x7) == 0 && sizeof(JSValue) == 8 && sizeof(Register) == 8, ArgList_should_by_8byte_aligned); + subPtr(Imm32(sizeof(ArgList)), stackPointerRegister); + + // Set up arguments + subPtr(Imm32(1), regT0); // Don't include 'this' in argcount + + // Push argcount + storePtr(regT0, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_argCount))); + + // Calculate the start of the callframe header, and store in regT1 + move(callFrameRegister, regT1); + sub32(Imm32(RegisterFile::CallFrameHeaderSize * (int32_t)sizeof(Register)), regT1); + + // Calculate start of arguments as callframe header - sizeof(Register) * argcount (regT1) + mul32(Imm32(sizeof(Register)), regT0, regT0); + subPtr(regT0, regT1); + + // push pointer to arguments + storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args))); + + // Argument passing method: + // r0 - points to return value + // r1 - callFrame + // r2 - callee + // stack: this(JSValue) and a pointer to ArgList + + move(stackPointerRegister, regT3); + subPtr(Imm32(8), stackPointerRegister); + move(stackPointerRegister, regT0); + subPtr(Imm32(8 + 4 + 4 /* padding */), stackPointerRegister); + + // Setup arg4: + storePtr(regT3, Address(stackPointerRegister, 8)); + + // Setup arg3 + // regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this' + load32(Address(regT1, -(int32_t)sizeof(void*) * 2), regT3); + storePtr(regT3, Address(stackPointerRegister, 0)); + load32(Address(regT1, -(int32_t)sizeof(void*)), regT3); + storePtr(regT3, Address(stackPointerRegister, 4)); + + // Setup arg2: + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT2); + + // Setup arg1: + move(callFrameRegister, regT1); + + call(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data))); + + // Load return value + load32(Address(stackPointerRegister, 16), regT0); + load32(Address(stackPointerRegister, 20), regT1); + + addPtr(Imm32(sizeof(ArgList) + 16 + 8), stackPointerRegister); +#endif + // Check for an exception move(ImmPtr(&globalData->exception), regT2); Jump sawException = branch32(NotEqual, tagFor(0, regT2), Imm32(JSValue::EmptyValueTag)); @@ -267,7 +328,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); move(ImmPtr(&globalData->exceptionLocation), regT2); storePtr(regT1, regT2); - move(ImmPtr(reinterpret_cast<void*>(ctiVMThrowTrampoline)), regT2); + move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT2); emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*)); restoreReturnAddressBeforeReturn(regT2); @@ -345,59 +406,7 @@ void JIT::emit_op_end(Instruction* currentInstruction) void JIT::emit_op_jmp(Instruction* currentInstruction) { unsigned target = currentInstruction[1].u.operand; - addJump(jump(), target + 1); -} - -void JIT::emit_op_loop(Instruction* currentInstruction) -{ - unsigned target = currentInstruction[1].u.operand; - emitTimeoutCheck(); - addJump(jump(), target + 1); -} - -void JIT::emit_op_loop_if_less(Instruction* currentInstruction) -{ - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - - emitTimeoutCheck(); - - if (isOperandConstantImmediateInt(op1)) { - emitLoad(op2, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThan, regT0, Imm32(getConstantOperand(op1).asInt32())), target + 3); - return; - } - - if (isOperandConstantImmediateInt(op2)) { - emitLoad(op1, regT1, regT0); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThan, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3); - return; - } - - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThan, regT0, regT2), target + 3); -} - -void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - - if (!isOperandConstantImmediateInt(op1) && !isOperandConstantImmediateInt(op2)) - linkSlowCase(iter); // int32 check - linkSlowCase(iter); // int32 check - - JITStubCall stubCall(this, cti_op_loop_if_less); - stubCall.addArgument(op1); - stubCall.addArgument(op2); - stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3); + addJump(jump(), target); } void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction) @@ -411,21 +420,21 @@ void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction) if (isOperandConstantImmediateInt(op1)) { emitLoad(op2, regT1, regT0); addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op1).asInt32())), target + 3); + addJump(branch32(GreaterThanOrEqual, regT0, Imm32(getConstantOperand(op1).asInt32())), target); return; } if (isOperandConstantImmediateInt(op2)) { emitLoad(op1, regT1, regT0); addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target + 3); + addJump(branch32(LessThanOrEqual, regT0, Imm32(getConstantOperand(op2).asInt32())), target); return; } emitLoad2(op1, regT1, regT0, op2, regT3, regT2); addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag))); addSlowCase(branch32(NotEqual, regT3, Imm32(JSValue::Int32Tag))); - addJump(branch32(LessThanOrEqual, regT0, regT2), target + 3); + addJump(branch32(LessThanOrEqual, regT0, regT2), target); } void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -442,7 +451,7 @@ void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<Slo stubCall.addArgument(op1); stubCall.addArgument(op2); stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); } void JIT::emit_op_new_object(Instruction* currentInstruction) @@ -457,30 +466,20 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction) unsigned baseVal = currentInstruction[3].u.operand; unsigned proto = currentInstruction[4].u.operand; - // Load the operands (baseVal, proto, and value respectively) into registers. + // Load the operands into registers. // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result. - emitLoadPayload(proto, regT1); - emitLoadPayload(baseVal, regT0); emitLoadPayload(value, regT2); + emitLoadPayload(baseVal, regT0); + emitLoadPayload(proto, regT1); - // Check that baseVal & proto are cells. - emitJumpSlowCaseIfNotJSCell(proto); + // Check that value, baseVal, and proto are cells. + emitJumpSlowCaseIfNotJSCell(value); emitJumpSlowCaseIfNotJSCell(baseVal); + emitJumpSlowCaseIfNotJSCell(proto); - // Check that baseVal is an object, that it 'ImplementsHasInstance' but that it does not 'OverridesHasInstance'. + // Check that baseVal 'ImplementsDefaultHasInstance'. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); // FIXME: Maybe remove this test. - addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsHasInstance))); // FIXME: TOT checks ImplementsDefaultHasInstance. - - // If value is not an Object, return false. - emitLoadTag(value, regT0); - Jump valueIsImmediate = branch32(NotEqual, regT0, Imm32(JSValue::CellTag)); - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - Jump valueIsNotObject = branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)); // FIXME: Maybe remove this test. - - // Check proto is object. - loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); + addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance))); // Optimistically load the result true, and start looping. // Initially, regT1 still contains proto and regT2 still contains value. @@ -488,16 +487,14 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction) move(Imm32(JSValue::TrueTag), regT0); Label loop(this); - // Load the prototype of the object in regT2. If this is equal to regT1 - WIN! + // Load the prototype of the cell in regT2. If this is equal to regT1 - WIN! // Otherwise, check if we've hit null - if we have then drop out of the loop, if not go again. loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); load32(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2); Jump isInstance = branchPtr(Equal, regT2, regT1); - branch32(NotEqual, regT2, Imm32(0), loop); + branchTest32(NonZero, regT2).linkTo(loop, this); // We get here either by dropping out of the loop, or if value was not an Object. Result is false. - valueIsImmediate.link(this); - valueIsNotObject.link(this); move(Imm32(JSValue::FalseTag), regT0); // isInstance jumps right down to here, to skip setting the result to false (it has already set true). @@ -512,11 +509,10 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas unsigned baseVal = currentInstruction[3].u.operand; unsigned proto = currentInstruction[4].u.operand; + linkSlowCaseIfNotJSCell(iter, value); linkSlowCaseIfNotJSCell(iter, baseVal); linkSlowCaseIfNotJSCell(iter, proto); linkSlowCase(iter); - linkSlowCase(iter); - linkSlowCase(iter); JITStubCall stubCall(this, cti_op_instanceof); stubCall.addArgument(value); @@ -661,40 +657,6 @@ void JIT::emit_op_strcat(Instruction* currentInstruction) stubCall.call(currentInstruction[1].u.operand); } -void JIT::emit_op_loop_if_true(Instruction* currentInstruction) -{ - unsigned cond = currentInstruction[1].u.operand; - unsigned target = currentInstruction[2].u.operand; - - emitTimeoutCheck(); - - emitLoad(cond, regT1, regT0); - - Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); - addJump(branch32(NotEqual, regT0, Imm32(0)), target + 2); - Jump isNotZero = jump(); - - isNotInteger.link(this); - - addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target + 2); - addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::FalseTag))); - - isNotZero.link(this); -} - -void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned cond = currentInstruction[1].u.operand; - unsigned target = currentInstruction[2].u.operand; - - linkSlowCase(iter); - - JITStubCall stubCall(this, cti_op_jtrue); - stubCall.addArgument(cond); - stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 2); -} - void JIT::emit_op_resolve_base(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_base); @@ -785,11 +747,11 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction) emitLoad(cond, regT1, regT0); Jump isTrue = branch32(Equal, regT1, Imm32(JSValue::TrueTag)); - addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target + 2); + addJump(branch32(Equal, regT1, Imm32(JSValue::FalseTag)), target); Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); Jump isTrue2 = branch32(NotEqual, regT0, Imm32(0)); - addJump(jump(), target + 2); + addJump(jump(), target); if (supportsFloatingPoint()) { isNotInteger.link(this); @@ -798,7 +760,7 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction) zeroDouble(fpRegT0); emitLoadDouble(cond, fpRegT1); - addJump(branchDouble(DoubleEqual, fpRegT0, fpRegT1), target + 2); + addJump(branchDouble(DoubleEqualOrUnordered, fpRegT0, fpRegT1), target); } else addSlowCase(isNotInteger); @@ -815,7 +777,7 @@ void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEnt JITStubCall stubCall(this, cti_op_jtrue); stubCall.addArgument(cond); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), target + 2); // Inverted. + emitJumpSlowToHot(branchTest32(Zero, regT0), target); // Inverted. } void JIT::emit_op_jtrue(Instruction* currentInstruction) @@ -826,11 +788,11 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction) emitLoad(cond, regT1, regT0); Jump isFalse = branch32(Equal, regT1, Imm32(JSValue::FalseTag)); - addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target + 2); + addJump(branch32(Equal, regT1, Imm32(JSValue::TrueTag)), target); Jump isNotInteger = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); Jump isFalse2 = branch32(Equal, regT0, Imm32(0)); - addJump(jump(), target + 2); + addJump(jump(), target); if (supportsFloatingPoint()) { isNotInteger.link(this); @@ -839,7 +801,7 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction) zeroDouble(fpRegT0); emitLoadDouble(cond, fpRegT1); - addJump(branchDouble(DoubleNotEqual, fpRegT0, fpRegT1), target + 2); + addJump(branchDouble(DoubleNotEqual, fpRegT0, fpRegT1), target); } else addSlowCase(isNotInteger); @@ -856,7 +818,7 @@ void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntr JITStubCall stubCall(this, cti_op_jtrue); stubCall.addArgument(cond); stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 2); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); } void JIT::emit_op_jeq_null(Instruction* currentInstruction) @@ -870,7 +832,7 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction) // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2); + addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); @@ -881,7 +843,7 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction) set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1); or32(regT2, regT1); - addJump(branchTest32(NonZero, regT1), target + 2); + addJump(branchTest32(NonZero, regT1), target); wasNotImmediate.link(this); } @@ -897,7 +859,7 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2); + addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); @@ -908,7 +870,7 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) set32(Equal, regT1, Imm32(JSValue::UndefinedTag), regT1); or32(regT2, regT1); - addJump(branchTest32(Zero, regT1), target + 2); + addJump(branchTest32(Zero, regT1), target); wasNotImmediate.link(this); } @@ -920,8 +882,8 @@ void JIT::emit_op_jneq_ptr(Instruction* currentInstruction) unsigned target = currentInstruction[3].u.operand; emitLoad(src, regT1, regT0); - addJump(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)), target + 3); - addJump(branchPtr(NotEqual, regT0, ImmPtr(ptr)), target + 3); + addJump(branch32(NotEqual, regT1, Imm32(JSValue::CellTag)), target); + addJump(branchPtr(NotEqual, regT0, ImmPtr(ptr)), target); } void JIT::emit_op_jsr(Instruction* currentInstruction) @@ -929,7 +891,7 @@ void JIT::emit_op_jsr(Instruction* currentInstruction) int retAddrDst = currentInstruction[1].u.operand; int target = currentInstruction[2].u.operand; DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst)); - addJump(jump(), target + 2); + addJump(jump(), target); m_jsrSites.append(JSRInfo(storeLocation, label())); } @@ -1195,23 +1157,109 @@ void JIT::emit_op_throw(Instruction* currentInstruction) #endif } +void JIT::emit_op_get_pnames(Instruction* currentInstruction) +{ + int dst = currentInstruction[1].u.operand; + int base = currentInstruction[2].u.operand; + int i = currentInstruction[3].u.operand; + int size = currentInstruction[4].u.operand; + int breakTarget = currentInstruction[5].u.operand; + + JumpList isNotObject; + + emitLoad(base, regT1, regT0); + if (!m_codeBlock->isKnownNotImmediate(base)) + isNotObject.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); + if (base != m_codeBlock->thisRegister()) { + loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + isNotObject.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); + } + + // We could inline the case where you have a valid cache, but + // this call doesn't seem to be hot. + Label isObject(this); + JITStubCall getPnamesStubCall(this, cti_op_get_pnames); + getPnamesStubCall.addArgument(regT0); + getPnamesStubCall.call(dst); + load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3); + store32(Imm32(0), addressFor(i)); + store32(regT3, addressFor(size)); + Jump end = jump(); + + isNotObject.link(this); + addJump(branch32(Equal, regT1, Imm32(JSValue::NullTag)), breakTarget); + addJump(branch32(Equal, regT1, Imm32(JSValue::UndefinedTag)), breakTarget); + JITStubCall toObjectStubCall(this, cti_to_object); + toObjectStubCall.addArgument(regT1, regT0); + toObjectStubCall.call(base); + jump().linkTo(isObject, this); + + end.link(this); +} + void JIT::emit_op_next_pname(Instruction* currentInstruction) { int dst = currentInstruction[1].u.operand; - int iter = currentInstruction[2].u.operand; - int target = currentInstruction[3].u.operand; + int base = currentInstruction[2].u.operand; + int i = currentInstruction[3].u.operand; + int size = currentInstruction[4].u.operand; + int it = currentInstruction[5].u.operand; + int target = currentInstruction[6].u.operand; + + JumpList callHasProperty; + + Label begin(this); + load32(addressFor(i), regT0); + Jump end = branch32(Equal, regT0, addressFor(size)); + + // Grab key @ i + loadPtr(addressFor(it), regT1); + loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2); + load32(BaseIndex(regT2, regT0, TimesEight), regT2); + store32(Imm32(JSValue::CellTag), tagFor(dst)); + store32(regT2, payloadFor(dst)); + + // Increment i + add32(Imm32(1), regT0); + store32(regT0, addressFor(i)); + + // Verify that i is valid: + loadPtr(addressFor(base), regT0); + + // Test base's structure + loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))))); + + // Test base's prototype chain + loadPtr(Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedPrototypeChain))), regT3); + loadPtr(Address(regT3, OBJECT_OFFSETOF(StructureChain, m_vector)), regT3); + addJump(branchTestPtr(Zero, Address(regT3)), target); + + Label checkPrototype(this); + callHasProperty.append(branch32(Equal, Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), Imm32(JSValue::NullTag))); + loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT2); + loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3))); + addPtr(Imm32(sizeof(Structure*)), regT3); + branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this); - load32(Address(callFrameRegister, (iter * sizeof(Register))), regT0); + // Continue loop. + addJump(jump(), target); - JITStubCall stubCall(this, cti_op_next_pname); + // Slow case: Ask the object if i is valid. + callHasProperty.link(this); + loadPtr(addressFor(dst), regT1); + JITStubCall stubCall(this, cti_has_property); stubCall.addArgument(regT0); + stubCall.addArgument(regT1); stubCall.call(); - Jump endOfIter = branchTestPtr(Zero, regT0); - emitStore(dst, regT1, regT0); - map(m_bytecodeIndex + OPCODE_LENGTH(op_next_pname), dst, regT1, regT0); - addJump(jump(), target + 3); - endOfIter.link(this); + // Test for valid key. + addJump(branchTest32(NonZero, regT0), target); + jump().linkTo(begin, this); + + // End of loop. + end.link(this); } void JIT::emit_op_push_scope(Instruction* currentInstruction) @@ -1286,7 +1334,7 @@ void JIT::emit_op_jmp_scopes(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_jmp_scopes); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.call(); - addJump(jump(), currentInstruction[2].u.operand + 2); + addJump(jump(), currentInstruction[2].u.operand); } void JIT::emit_op_switch_imm(Instruction* currentInstruction) @@ -1361,7 +1409,6 @@ void JIT::emit_op_debug(Instruction* currentInstruction) stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); - stubCall.addArgument(Imm32(currentInstruction[4].u.operand)); stubCall.call(); } @@ -1464,8 +1511,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable Jump string_failureCases2 = branchPtr(NotEqual, Address(regT0), ImmPtr(m_globalData->jsStringVPtr)); // Checks out okay! - get the length from the Ustring. - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSString, m_value) + OBJECT_OFFSETOF(UString, m_rep)), regT0); - load32(Address(regT0, OBJECT_OFFSETOF(UString::Rep, len)), regT0); + load32(Address(regT0, OBJECT_OFFSETOF(JSString, m_stringLength)), regT0); Jump string_failureCases3 = branch32(Above, regT0, Imm32(JSImmediate::maxImmediateInt)); @@ -1560,7 +1606,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable emitPutToCallFrameHeader(regT1, RegisterFile::ScopeChain); -#if PLATFORM(X86_64) +#if CPU(X86_64) emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, X86Registers::ecx); // Allocate stack space for our arglist @@ -1596,7 +1642,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable call(Address(X86Registers::esi, OBJECT_OFFSETOF(JSFunction, m_data))); addPtr(Imm32(sizeof(ArgList)), stackPointerRegister); -#elif PLATFORM(X86) +#elif CPU(X86) emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); /* We have two structs that we use to describe the stackframe we set up for our @@ -1607,7 +1653,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable * not the rest of the callframe so we need a nice way to ensure we increment the * stack pointer by the right amount after the call. */ -#if COMPILER(MSVC) || PLATFORM(LINUX) +#if COMPILER(MSVC) || OS(LINUX) struct NativeCallFrameStructure { // CallFrame* callFrame; // passed in EDX JSObject* callee; @@ -1660,7 +1706,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable loadPtr(Address(regT1, -(int)sizeof(Register)), regT1); storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(NativeCallFrameStructure, thisValue))); -#if COMPILER(MSVC) || PLATFORM(LINUX) +#if COMPILER(MSVC) || OS(LINUX) // ArgList is passed by reference so is stackPointerRegister + 4 * sizeof(Register) addPtr(Imm32(OBJECT_OFFSETOF(NativeCallFrameStructure, result)), stackPointerRegister, X86Registers::ecx); @@ -1688,7 +1734,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable // so pull them off now addPtr(Imm32(NativeCallFrameSize - sizeof(NativeFunctionCalleeSignature)), stackPointerRegister); -#elif PLATFORM(ARM_TRADITIONAL) +#elif CPU(ARM) emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); // Allocate stack space for our arglist @@ -1722,9 +1768,8 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable move(callFrameRegister, regT0); // Setup arg4: This is a plain hack - move(stackPointerRegister, ARMRegisters::S0); + move(stackPointerRegister, ARMRegisters::r3); - move(ctiReturnRegister, ARMRegisters::lr); call(Address(regT1, OBJECT_OFFSETOF(JSFunction, m_data))); addPtr(Imm32(sizeof(ArgList)), stackPointerRegister); @@ -1755,7 +1800,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable emitGetFromCallFrameHeaderPtr(RegisterFile::ReturnPC, regT1); move(ImmPtr(&globalData->exceptionLocation), regT2); storePtr(regT1, regT2); - move(ImmPtr(reinterpret_cast<void*>(ctiVMThrowTrampoline)), regT2); + move(ImmPtr(FunctionPtr(ctiVMThrowTrampoline).value()), regT2); emitGetFromCallFrameHeaderPtr(RegisterFile::CallerFrame, callFrameRegister); poke(callFrameRegister, OBJECT_OFFSETOF(struct JITStackFrame, callFrame) / sizeof (void*)); restoreReturnAddressBeforeReturn(regT2); @@ -1831,49 +1876,8 @@ void JIT::emit_op_end(Instruction* currentInstruction) void JIT::emit_op_jmp(Instruction* currentInstruction) { unsigned target = currentInstruction[1].u.operand; - addJump(jump(), target + 1); - RECORD_JUMP_TARGET(target + 1); -} - -void JIT::emit_op_loop(Instruction* currentInstruction) -{ - emitTimeoutCheck(); - - unsigned target = currentInstruction[1].u.operand; - addJump(jump(), target + 1); -} - -void JIT::emit_op_loop_if_less(Instruction* currentInstruction) -{ - emitTimeoutCheck(); - - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - if (isOperandConstantImmediateInt(op2)) { - emitGetVirtualRegister(op1, regT0); - emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) - int32_t op2imm = getConstantOperandImmediateInt(op2); -#else - int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); -#endif - addJump(branch32(LessThan, regT0, Imm32(op2imm)), target + 3); - } else if (isOperandConstantImmediateInt(op1)) { - emitGetVirtualRegister(op2, regT0); - emitJumpSlowCaseIfNotImmediateInteger(regT0); -#if USE(JSVALUE64) - int32_t op1imm = getConstantOperandImmediateInt(op1); -#else - int32_t op1imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op1))); -#endif - addJump(branch32(GreaterThan, regT0, Imm32(op1imm)), target + 3); - } else { - emitGetVirtualRegisters(op1, regT0, op2, regT1); - emitJumpSlowCaseIfNotImmediateInteger(regT0); - emitJumpSlowCaseIfNotImmediateInteger(regT1); - addJump(branch32(LessThan, regT0, regT1), target + 3); - } + addJump(jump(), target); + RECORD_JUMP_TARGET(target); } void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction) @@ -1891,12 +1895,12 @@ void JIT::emit_op_loop_if_lesseq(Instruction* currentInstruction) #else int32_t op2imm = static_cast<int32_t>(JSImmediate::rawValue(getConstantOperand(op2))); #endif - addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target + 3); + addJump(branch32(LessThanOrEqual, regT0, Imm32(op2imm)), target); } else { emitGetVirtualRegisters(op1, regT0, op2, regT1); emitJumpSlowCaseIfNotImmediateInteger(regT0); emitJumpSlowCaseIfNotImmediateInteger(regT1); - addJump(branch32(LessThanOrEqual, regT0, regT1), target + 3); + addJump(branch32(LessThanOrEqual, regT0, regT1), target); } } @@ -1907,30 +1911,26 @@ void JIT::emit_op_new_object(Instruction* currentInstruction) void JIT::emit_op_instanceof(Instruction* currentInstruction) { + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + unsigned baseVal = currentInstruction[3].u.operand; + unsigned proto = currentInstruction[4].u.operand; + // Load the operands (baseVal, proto, and value respectively) into registers. // We use regT0 for baseVal since we will be done with this first, and we can then use it for the result. - emitGetVirtualRegister(currentInstruction[3].u.operand, regT0); - emitGetVirtualRegister(currentInstruction[4].u.operand, regT1); - emitGetVirtualRegister(currentInstruction[2].u.operand, regT2); + emitGetVirtualRegister(value, regT2); + emitGetVirtualRegister(baseVal, regT0); + emitGetVirtualRegister(proto, regT1); // Check that baseVal & proto are cells. - emitJumpSlowCaseIfNotJSCell(regT0); - emitJumpSlowCaseIfNotJSCell(regT1); + emitJumpSlowCaseIfNotJSCell(regT2, value); + emitJumpSlowCaseIfNotJSCell(regT0, baseVal); + emitJumpSlowCaseIfNotJSCell(regT1, proto); - // Check that baseVal is an object, that it 'ImplementsHasInstance' but that it does not 'OverridesHasInstance'. + // Check that baseVal 'ImplementsDefaultHasInstance'. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance))); - // If value is not an Object, return false. - Jump valueIsImmediate = emitJumpIfNotJSCell(regT2); - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - Jump valueIsNotObject = branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType)); - - // Check proto is object. - loadPtr(Address(regT1, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branch32(NotEqual, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); - // Optimistically load the result true, and start looping. // Initially, regT1 still contains proto and regT2 still contains value. // As we loop regT2 will be updated with its prototype, recursively walking the prototype chain. @@ -1942,16 +1942,14 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction) loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2); Jump isInstance = branchPtr(Equal, regT2, regT1); - branchPtr(NotEqual, regT2, ImmPtr(JSValue::encode(jsNull())), loop); + emitJumpIfJSCell(regT2).linkTo(loop, this); // We get here either by dropping out of the loop, or if value was not an Object. Result is false. - valueIsImmediate.link(this); - valueIsNotObject.link(this); move(ImmPtr(JSValue::encode(jsBoolean(false))), regT0); // isInstance jumps right down to here, to skip setting the result to false (it has already set true). isInstance.link(this); - emitPutVirtualRegister(currentInstruction[1].u.operand); + emitPutVirtualRegister(dst); } void JIT::emit_op_new_func(Instruction* currentInstruction) @@ -2125,21 +2123,6 @@ void JIT::emit_op_strcat(Instruction* currentInstruction) stubCall.call(currentInstruction[1].u.operand); } -void JIT::emit_op_loop_if_true(Instruction* currentInstruction) -{ - emitTimeoutCheck(); - - unsigned target = currentInstruction[2].u.operand; - emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); - - Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))); - addJump(emitJumpIfImmediateInteger(regT0), target + 2); - - addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target + 2); - addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false))))); - - isZero.link(this); -}; void JIT::emit_op_resolve_base(Instruction* currentInstruction) { JITStubCall stubCall(this, cti_op_resolve_base); @@ -2202,14 +2185,14 @@ void JIT::emit_op_jfalse(Instruction* currentInstruction) unsigned target = currentInstruction[2].u.operand; emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); - addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))), target + 2); + addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))), target); Jump isNonZero = emitJumpIfImmediateInteger(regT0); - addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))), target + 2); + addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(false)))), target); addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(true))))); isNonZero.link(this); - RECORD_JUMP_TARGET(target + 2); + RECORD_JUMP_TARGET(target); }; void JIT::emit_op_jeq_null(Instruction* currentInstruction) { @@ -2221,16 +2204,16 @@ void JIT::emit_op_jeq_null(Instruction* currentInstruction) // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2); + addJump(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null isImmediate.link(this); andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); - addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNull()))), target + 2); + addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNull()))), target); wasNotImmediate.link(this); - RECORD_JUMP_TARGET(target + 2); + RECORD_JUMP_TARGET(target); }; void JIT::emit_op_jneq_null(Instruction* currentInstruction) { @@ -2242,16 +2225,16 @@ void JIT::emit_op_jneq_null(Instruction* currentInstruction) // First, handle JSCell cases - check MasqueradesAsUndefined bit on the structure. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target + 2); + addJump(branchTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null isImmediate.link(this); andPtr(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT0); - addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsNull()))), target + 2); + addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsNull()))), target); wasNotImmediate.link(this); - RECORD_JUMP_TARGET(target + 2); + RECORD_JUMP_TARGET(target); } void JIT::emit_op_jneq_ptr(Instruction* currentInstruction) @@ -2261,9 +2244,9 @@ void JIT::emit_op_jneq_ptr(Instruction* currentInstruction) unsigned target = currentInstruction[3].u.operand; emitGetVirtualRegister(src, regT0); - addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue(ptr)))), target + 3); + addJump(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(JSValue(ptr)))), target); - RECORD_JUMP_TARGET(target + 3); + RECORD_JUMP_TARGET(target); } void JIT::emit_op_jsr(Instruction* currentInstruction) @@ -2271,10 +2254,10 @@ void JIT::emit_op_jsr(Instruction* currentInstruction) int retAddrDst = currentInstruction[1].u.operand; int target = currentInstruction[2].u.operand; DataLabelPtr storeLocation = storePtrWithPatch(ImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst)); - addJump(jump(), target + 2); + addJump(jump(), target); m_jsrSites.append(JSRInfo(storeLocation, label())); killLastResultRegister(); - RECORD_JUMP_TARGET(target + 2); + RECORD_JUMP_TARGET(target); } void JIT::emit_op_sret(Instruction* currentInstruction) @@ -2326,13 +2309,13 @@ void JIT::emit_op_jtrue(Instruction* currentInstruction) emitGetVirtualRegister(currentInstruction[1].u.operand, regT0); Jump isZero = branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsNumber(m_globalData, 0)))); - addJump(emitJumpIfImmediateInteger(regT0), target + 2); + addJump(emitJumpIfImmediateInteger(regT0), target); - addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target + 2); + addJump(branchPtr(Equal, regT0, ImmPtr(JSValue::encode(jsBoolean(true)))), target); addSlowCase(branchPtr(NotEqual, regT0, ImmPtr(JSValue::encode(jsBoolean(false))))); isZero.link(this); - RECORD_JUMP_TARGET(target + 2); + RECORD_JUMP_TARGET(target); } void JIT::emit_op_neq(Instruction* currentInstruction) @@ -2383,15 +2366,116 @@ void JIT::emit_op_throw(Instruction* currentInstruction) #endif } +void JIT::emit_op_get_pnames(Instruction* currentInstruction) +{ + int dst = currentInstruction[1].u.operand; + int base = currentInstruction[2].u.operand; + int i = currentInstruction[3].u.operand; + int size = currentInstruction[4].u.operand; + int breakTarget = currentInstruction[5].u.operand; + + JumpList isNotObject; + + emitGetVirtualRegister(base, regT0); + if (!m_codeBlock->isKnownNotImmediate(base)) + isNotObject.append(emitJumpIfNotJSCell(regT0)); + if (base != m_codeBlock->thisRegister()) { + loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + isNotObject.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); + } + + // We could inline the case where you have a valid cache, but + // this call doesn't seem to be hot. + Label isObject(this); + JITStubCall getPnamesStubCall(this, cti_op_get_pnames); + getPnamesStubCall.addArgument(regT0); + getPnamesStubCall.call(dst); + load32(Address(regT0, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStringsSize)), regT3); + store32(Imm32(0), addressFor(i)); + store32(regT3, addressFor(size)); + Jump end = jump(); + + isNotObject.link(this); + move(regT0, regT1); + and32(Imm32(~JSImmediate::ExtendedTagBitUndefined), regT1); + addJump(branch32(Equal, regT1, Imm32(JSImmediate::FullTagTypeNull)), breakTarget); + + JITStubCall toObjectStubCall(this, cti_to_object); + toObjectStubCall.addArgument(regT0); + toObjectStubCall.call(base); + jump().linkTo(isObject, this); + + end.link(this); +} + void JIT::emit_op_next_pname(Instruction* currentInstruction) { - JITStubCall stubCall(this, cti_op_next_pname); - stubCall.addArgument(currentInstruction[2].u.operand, regT2); + int dst = currentInstruction[1].u.operand; + int base = currentInstruction[2].u.operand; + int i = currentInstruction[3].u.operand; + int size = currentInstruction[4].u.operand; + int it = currentInstruction[5].u.operand; + int target = currentInstruction[6].u.operand; + + JumpList callHasProperty; + + Label begin(this); + load32(addressFor(i), regT0); + Jump end = branch32(Equal, regT0, addressFor(size)); + + // Grab key @ i + loadPtr(addressFor(it), regT1); + loadPtr(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_jsStrings)), regT2); + +#if USE(JSVALUE64) + loadPtr(BaseIndex(regT2, regT0, TimesEight), regT2); +#else + loadPtr(BaseIndex(regT2, regT0, TimesFour), regT2); +#endif + + emitPutVirtualRegister(dst, regT2); + + // Increment i + add32(Imm32(1), regT0); + store32(regT0, addressFor(i)); + + // Verify that i is valid: + emitGetVirtualRegister(base, regT0); + + // Test base's structure + loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + callHasProperty.append(branchPtr(NotEqual, regT2, Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure))))); + + // Test base's prototype chain + loadPtr(Address(Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedPrototypeChain))), regT3); + loadPtr(Address(regT3, OBJECT_OFFSETOF(StructureChain, m_vector)), regT3); + addJump(branchTestPtr(Zero, Address(regT3)), target); + + Label checkPrototype(this); + loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2); + callHasProperty.append(emitJumpIfNotJSCell(regT2)); + loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + callHasProperty.append(branchPtr(NotEqual, regT2, Address(regT3))); + addPtr(Imm32(sizeof(Structure*)), regT3); + branchTestPtr(NonZero, Address(regT3)).linkTo(checkPrototype, this); + + // Continue loop. + addJump(jump(), target); + + // Slow case: Ask the object if i is valid. + callHasProperty.link(this); + emitGetVirtualRegister(dst, regT1); + JITStubCall stubCall(this, cti_has_property); + stubCall.addArgument(regT0); + stubCall.addArgument(regT1); stubCall.call(); - Jump endOfIter = branchTestPtr(Zero, regT0); - emitPutVirtualRegister(currentInstruction[1].u.operand); - addJump(jump(), currentInstruction[3].u.operand + 3); - endOfIter.link(this); + + // Test for valid key. + addJump(branchTest32(NonZero, regT0), target); + jump().linkTo(begin, this); + + // End of loop. + end.link(this); } void JIT::emit_op_push_scope(Instruction* currentInstruction) @@ -2480,8 +2564,8 @@ void JIT::emit_op_jmp_scopes(Instruction* currentInstruction) JITStubCall stubCall(this, cti_op_jmp_scopes); stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.call(); - addJump(jump(), currentInstruction[2].u.operand + 2); - RECORD_JUMP_TARGET(currentInstruction[2].u.operand + 2); + addJump(jump(), currentInstruction[2].u.operand); + RECORD_JUMP_TARGET(currentInstruction[2].u.operand); } void JIT::emit_op_switch_imm(Instruction* currentInstruction) @@ -2552,7 +2636,6 @@ void JIT::emit_op_debug(Instruction* currentInstruction) stubCall.addArgument(Imm32(currentInstruction[1].u.operand)); stubCall.addArgument(Imm32(currentInstruction[2].u.operand)); stubCall.addArgument(Imm32(currentInstruction[3].u.operand)); - stubCall.addArgument(Imm32(currentInstruction[4].u.operand)); stubCall.call(); } @@ -2724,36 +2807,6 @@ void JIT::emitSlow_op_get_by_val(Instruction* currentInstruction, Vector<SlowCas stubCall.call(dst); } -void JIT::emitSlow_op_loop_if_less(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - unsigned op1 = currentInstruction[1].u.operand; - unsigned op2 = currentInstruction[2].u.operand; - unsigned target = currentInstruction[3].u.operand; - if (isOperandConstantImmediateInt(op2)) { - linkSlowCase(iter); - JITStubCall stubCall(this, cti_op_loop_if_less); - stubCall.addArgument(regT0); - stubCall.addArgument(op2, regT2); - stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3); - } else if (isOperandConstantImmediateInt(op1)) { - linkSlowCase(iter); - JITStubCall stubCall(this, cti_op_loop_if_less); - stubCall.addArgument(op1, regT2); - stubCall.addArgument(regT0); - stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3); - } else { - linkSlowCase(iter); - linkSlowCase(iter); - JITStubCall stubCall(this, cti_op_loop_if_less); - stubCall.addArgument(regT0); - stubCall.addArgument(regT1); - stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3); - } -} - void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { unsigned op2 = currentInstruction[2].u.operand; @@ -2764,7 +2817,7 @@ void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<Slo stubCall.addArgument(regT0); stubCall.addArgument(currentInstruction[2].u.operand, regT2); stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); } else { linkSlowCase(iter); linkSlowCase(iter); @@ -2772,7 +2825,7 @@ void JIT::emitSlow_op_loop_if_lesseq(Instruction* currentInstruction, Vector<Slo stubCall.addArgument(regT0); stubCall.addArgument(regT1); stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), target + 3); + emitJumpSlowToHot(branchTest32(NonZero, regT0), target); } } @@ -2794,15 +2847,6 @@ void JIT::emitSlow_op_put_by_val(Instruction* currentInstruction, Vector<SlowCas stubPutByValCall.call(); } -void JIT::emitSlow_op_loop_if_true(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) -{ - linkSlowCase(iter); - JITStubCall stubCall(this, cti_op_jtrue); - stubCall.addArgument(regT0); - stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand + 2); -} - void JIT::emitSlow_op_not(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { linkSlowCase(iter); @@ -2818,7 +2862,7 @@ void JIT::emitSlow_op_jfalse(Instruction* currentInstruction, Vector<SlowCaseEnt JITStubCall stubCall(this, cti_op_jtrue); stubCall.addArgument(regT0); stubCall.call(); - emitJumpSlowToHot(branchTest32(Zero, regT0), currentInstruction[2].u.operand + 2); // inverted! + emitJumpSlowToHot(branchTest32(Zero, regT0), currentInstruction[2].u.operand); // inverted! } void JIT::emitSlow_op_bitnot(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -2835,7 +2879,7 @@ void JIT::emitSlow_op_jtrue(Instruction* currentInstruction, Vector<SlowCaseEntr JITStubCall stubCall(this, cti_op_jtrue); stubCall.addArgument(regT0); stubCall.call(); - emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand + 2); + emitJumpSlowToHot(branchTest32(NonZero, regT0), currentInstruction[2].u.operand); } void JIT::emitSlow_op_bitxor(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -2901,16 +2945,20 @@ void JIT::emitSlow_op_nstricteq(Instruction* currentInstruction, Vector<SlowCase void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { - linkSlowCase(iter); - linkSlowCase(iter); - linkSlowCase(iter); - linkSlowCase(iter); + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + unsigned baseVal = currentInstruction[3].u.operand; + unsigned proto = currentInstruction[4].u.operand; + + linkSlowCaseIfNotJSCell(iter, value); + linkSlowCaseIfNotJSCell(iter, baseVal); + linkSlowCaseIfNotJSCell(iter, proto); linkSlowCase(iter); JITStubCall stubCall(this, cti_op_instanceof); - stubCall.addArgument(currentInstruction[2].u.operand, regT2); - stubCall.addArgument(currentInstruction[3].u.operand, regT2); - stubCall.addArgument(currentInstruction[4].u.operand, regT2); - stubCall.call(currentInstruction[1].u.operand); + stubCall.addArgument(value, regT2); + stubCall.addArgument(baseVal, regT2); + stubCall.addArgument(proto, regT2); + stubCall.call(dst); } void JIT::emitSlow_op_call(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITPropertyAccess.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITPropertyAccess.cpp index 9edfd01..ef95f99 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -33,6 +33,7 @@ #include "JITStubCall.h" #include "JSArray.h" #include "JSFunction.h" +#include "JSPropertyNameIterator.h" #include "Interpreter.h" #include "LinkBuffer.h" #include "RepatchBuffer.h" @@ -211,12 +212,17 @@ void JIT::emit_op_method_check(Instruction* currentInstruction) emitLoad(base, regT1, regT0); emitJumpSlowCaseIfNotJSCell(base, regT1); + BEGIN_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck); + Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), info.structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); DataLabelPtr protoStructureToCompare, protoObj = moveWithPatch(ImmPtr(0), regT2); Jump protoStructureCheck = branchPtrWithPatch(NotEqual, Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), protoStructureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); // This will be relinked to load the function without doing a load. DataLabelPtr putFunction = moveWithPatch(ImmPtr(0), regT0); + + END_UNINTERRUPTED_SEQUENCE(sequenceMethodCheck); + move(Imm32(JSValue::CellTag), regT1); Jump match = jump(); @@ -373,6 +379,9 @@ void JIT::compileGetByIdHotPath() // Additionally, for get_by_id we need patch the offset of the branch to the slow case (we patch this to jump // to array-length / prototype access tranpolines, and finally we also the the property-map access offset as a label // to jump back to if one of these trampolies finds a match. + + BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath); + Label hotPathBegin(this); m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin; m_propertyAccessInstructionIndex++; @@ -395,6 +404,8 @@ void JIT::compileGetByIdHotPath() Label putResult(this); ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult); + + END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath); } void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -416,13 +427,18 @@ void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<Sl linkSlowCaseIfNotJSCell(iter, base); linkSlowCase(iter); - Label coldPathBegin(this); + BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase); +#ifndef NDEBUG + Label coldPathBegin(this); +#endif JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id); stubCall.addArgument(regT1, regT0); stubCall.addArgument(ImmPtr(ident)); Call call = stubCall.call(dst); + END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase); + ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall); // Track the location of the call; this will be used to recover patch information. @@ -443,6 +459,8 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(base, regT1); + BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById); + Label hotPathBegin(this); m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].hotPathBegin = hotPathBegin; m_propertyAccessInstructionIndex++; @@ -460,6 +478,9 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT0, patchGetByIdDefaultOffset)); // payload DataLabel32 displacementLabel2 = storePtrWithAddressOffsetPatch(regT3, Address(regT0, patchGetByIdDefaultOffset)); // tag + + END_UNINTERRUPTED_SEQUENCE(sequencePutById); + ASSERT(differenceBetween(hotPathBegin, displacementLabel1) == patchOffsetPutByIdPropertyMapOffset1); ASSERT(differenceBetween(hotPathBegin, displacementLabel2) == patchOffsetPutByIdPropertyMapOffset2); } @@ -521,22 +542,26 @@ void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID res load32(Address(temp, offset + 4), resultTag); } +void JIT::testPrototype(Structure* structure, JumpList& failureCases) +{ + if (structure->m_prototype.isNull()) + return; + + failureCases.append(branchPtr(NotEqual, AbsoluteAddress(&asCell(structure->m_prototype)->m_structure), ImmPtr(asCell(structure->m_prototype)->m_structure))); +} + void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress) { // It is assumed that regT0 contains the basePayload and regT1 contains the baseTag. The value can be found on the stack. JumpList failureCases; failureCases.append(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); - - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - failureCases.append(branchPtr(NotEqual, regT2, ImmPtr(oldStructure))); + failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure))); + testPrototype(oldStructure, failureCases); // Verify that nothing in the prototype chain has a setter for this property. - for (RefPtr<Structure>* it = chain->head(); *it; ++it) { - loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2); - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - failureCases.append(branchPtr(NotEqual, regT2, ImmPtr(it->get()))); - } + for (RefPtr<Structure>* it = chain->head(); *it; ++it) + testPrototype(it->get(), failureCases); // Reallocate property storage if needed. Call callTarget; @@ -705,7 +730,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure); -#if PLATFORM(X86_64) +#if CPU(X86_64) move(ImmPtr(prototypeStructure), regT3); Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3); #else @@ -785,7 +810,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure); -#if PLATFORM(X86_64) +#if CPU(X86_64) move(ImmPtr(prototypeStructure), regT3); Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3); #else @@ -838,7 +863,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure); -#if PLATFORM(X86_64) +#if CPU(X86_64) move(ImmPtr(currStructure), regT3); bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3)); #else @@ -893,7 +918,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure); -#if PLATFORM(X86_64) +#if CPU(X86_64) move(ImmPtr(currStructure), regT3); bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3)); #else @@ -930,6 +955,69 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str #endif // !ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) +void JIT::compileGetDirectOffset(RegisterID base, RegisterID resultTag, RegisterID resultPayload, RegisterID structure, RegisterID offset) +{ + ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t)); + ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t)); + ASSERT(sizeof(JSValue) == 8); + + Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity)); + loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload); + loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSObject, m_inlineStorage)+OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag); + Jump finishedLoad = jump(); + notUsingInlineStorage.link(this); + loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), base); + loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayload); + loadPtr(BaseIndex(base, offset, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTag); + finishedLoad.link(this); +} + +void JIT::emit_op_get_by_pname(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned base = currentInstruction[2].u.operand; + unsigned property = currentInstruction[3].u.operand; + unsigned expected = currentInstruction[4].u.operand; + unsigned iter = currentInstruction[5].u.operand; + unsigned i = currentInstruction[6].u.operand; + + emitLoad2(property, regT1, regT0, base, regT3, regT2); + emitJumpSlowCaseIfNotJSCell(property, regT1); + addSlowCase(branchPtr(NotEqual, regT0, payloadFor(expected))); + // Property registers are now available as the property is known + emitJumpSlowCaseIfNotJSCell(base, regT3); + emitLoadPayload(iter, regT1); + + // Test base's structure + loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); + addSlowCase(branchPtr(NotEqual, regT0, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))); + load32(addressFor(i), regT3); + sub32(Imm32(1), regT3); + addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots)))); + compileGetDirectOffset(regT2, regT1, regT0, regT0, regT3); + + emitStore(dst, regT1, regT0); + map(m_bytecodeIndex + OPCODE_LENGTH(op_get_by_pname), dst, regT1, regT0); +} + +void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned base = currentInstruction[2].u.operand; + unsigned property = currentInstruction[3].u.operand; + + linkSlowCaseIfNotJSCell(iter, property); + linkSlowCase(iter); + linkSlowCaseIfNotJSCell(iter, base); + linkSlowCase(iter); + linkSlowCase(iter); + + JITStubCall stubCall(this, cti_op_get_by_val); + stubCall.addArgument(base); + stubCall.addArgument(property); + stubCall.call(dst); +} + #else // USE(JSVALUE32_64) void JIT::emit_op_get_by_val(Instruction* currentInstruction) @@ -963,6 +1051,62 @@ void JIT::emit_op_get_by_val(Instruction* currentInstruction) emitPutVirtualRegister(dst); } +void JIT::compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID structure, RegisterID offset, RegisterID scratch) +{ + ASSERT(sizeof(((Structure*)0)->m_propertyStorageCapacity) == sizeof(int32_t)); + ASSERT(sizeof(JSObject::inlineStorageCapacity) == sizeof(int32_t)); + + Jump notUsingInlineStorage = branch32(NotEqual, Address(structure, OBJECT_OFFSETOF(Structure, m_propertyStorageCapacity)), Imm32(JSObject::inlineStorageCapacity)); + loadPtr(BaseIndex(base, offset, ScalePtr, OBJECT_OFFSETOF(JSObject, m_inlineStorage)), result); + Jump finishedLoad = jump(); + notUsingInlineStorage.link(this); + loadPtr(Address(base, OBJECT_OFFSETOF(JSObject, m_externalStorage)), scratch); + loadPtr(BaseIndex(scratch, offset, ScalePtr, 0), result); + finishedLoad.link(this); +} + +void JIT::emit_op_get_by_pname(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned base = currentInstruction[2].u.operand; + unsigned property = currentInstruction[3].u.operand; + unsigned expected = currentInstruction[4].u.operand; + unsigned iter = currentInstruction[5].u.operand; + unsigned i = currentInstruction[6].u.operand; + + emitGetVirtualRegister(property, regT0); + addSlowCase(branchPtr(NotEqual, regT0, addressFor(expected))); + emitGetVirtualRegisters(base, regT0, iter, regT1); + emitJumpSlowCaseIfNotJSCell(regT0, base); + + // Test base's structure + loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); + addSlowCase(branchPtr(NotEqual, regT2, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_cachedStructure)))); + load32(addressFor(i), regT3); + sub32(Imm32(1), regT3); + addSlowCase(branch32(AboveOrEqual, regT3, Address(regT1, OBJECT_OFFSETOF(JSPropertyNameIterator, m_numCacheableSlots)))); + compileGetDirectOffset(regT0, regT0, regT2, regT3, regT1); + + emitPutVirtualRegister(dst, regT0); +} + +void JIT::emitSlow_op_get_by_pname(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned base = currentInstruction[2].u.operand; + unsigned property = currentInstruction[3].u.operand; + + linkSlowCase(iter); + linkSlowCaseIfNotJSCell(iter, base); + linkSlowCase(iter); + linkSlowCase(iter); + + JITStubCall stubCall(this, cti_op_get_by_val); + stubCall.addArgument(base, regT2); + stubCall.addArgument(property, regT2); + stubCall.call(dst); +} + void JIT::emit_op_put_by_val(Instruction* currentInstruction) { unsigned base = currentInstruction[1].u.operand; @@ -1128,9 +1272,9 @@ void JIT::emit_op_method_check(Instruction* currentInstruction) Jump match = jump(); - ASSERT(differenceBetween(info.structureToCompare, protoObj) == patchOffsetMethodCheckProtoObj); - ASSERT(differenceBetween(info.structureToCompare, protoStructureToCompare) == patchOffsetMethodCheckProtoStruct); - ASSERT(differenceBetween(info.structureToCompare, putFunction) == patchOffsetMethodCheckPutFunction); + ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj); + ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoStructureToCompare), patchOffsetMethodCheckProtoStruct); + ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, putFunction), patchOffsetMethodCheckPutFunction); // Link the failure cases here. notCell.link(this); @@ -1197,22 +1341,22 @@ void JIT::compileGetByIdHotPath(int, int baseVReg, Identifier*, unsigned propert DataLabelPtr structureToCompare; Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); addSlowCase(structureCheck); - ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetGetByIdStructure); - ASSERT(differenceBetween(hotPathBegin, structureCheck) == patchOffsetGetByIdBranchToSlowCase); + ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure); + ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase) Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0); Label externalLoadComplete(this); - ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetGetByIdExternalLoad); - ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthGetByIdExternalLoad); + ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetGetByIdExternalLoad); + ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthGetByIdExternalLoad); DataLabel32 displacementLabel = loadPtrWithAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0); - ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetGetByIdPropertyMapOffset); + ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel), patchOffsetGetByIdPropertyMapOffset); Label putResult(this); END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath); - ASSERT(differenceBetween(hotPathBegin, putResult) == patchOffsetGetByIdPutResult); + ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, putResult), patchOffsetGetByIdPutResult); } void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -1247,7 +1391,7 @@ void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase); - ASSERT(differenceBetween(coldPathBegin, call) == patchOffsetGetByIdSlowCaseCall); + ASSERT_JIT_OFFSET(differenceBetween(coldPathBegin, call), patchOffsetGetByIdSlowCaseCall); // Track the location of the call; this will be used to recover patch information. m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex].callReturnLocation = call; @@ -1278,19 +1422,19 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over. DataLabelPtr structureToCompare; addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), structureToCompare, ImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)))); - ASSERT(differenceBetween(hotPathBegin, structureToCompare) == patchOffsetPutByIdStructure); + ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure); // Plant a load from a bogus ofset in the object's property map; we will patch this later, if it is to be used. Label externalLoad = loadPtrWithPatchToLEA(Address(regT0, OBJECT_OFFSETOF(JSObject, m_externalStorage)), regT0); Label externalLoadComplete(this); - ASSERT(differenceBetween(hotPathBegin, externalLoad) == patchOffsetPutByIdExternalLoad); - ASSERT(differenceBetween(externalLoad, externalLoadComplete) == patchLengthPutByIdExternalLoad); + ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, externalLoad), patchOffsetPutByIdExternalLoad); + ASSERT_JIT_OFFSET(differenceBetween(externalLoad, externalLoadComplete), patchLengthPutByIdExternalLoad); DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT0, patchGetByIdDefaultOffset)); END_UNINTERRUPTED_SEQUENCE(sequencePutById); - ASSERT(differenceBetween(hotPathBegin, displacementLabel) == patchOffsetPutByIdPropertyMapOffset); + ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, displacementLabel), patchOffsetPutByIdPropertyMapOffset); } void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -1347,35 +1491,27 @@ void JIT::compileGetDirectOffset(JSObject* base, RegisterID temp, RegisterID res } } +void JIT::testPrototype(Structure* structure, JumpList& failureCases) +{ + if (structure->m_prototype.isNull()) + return; + + move(ImmPtr(&asCell(structure->m_prototype)->m_structure), regT2); + move(ImmPtr(asCell(structure->m_prototype)->m_structure), regT3); + failureCases.append(branchPtr(NotEqual, Address(regT2), regT3)); +} + void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress) { JumpList failureCases; // Check eax is an object of the right Structure. failureCases.append(emitJumpIfNotJSCell(regT0)); failureCases.append(branchPtr(NotEqual, Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(oldStructure))); - JumpList successCases; - - // ecx = baseObject - loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - // proto(ecx) = baseObject->structure()->prototype() - failureCases.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType))); + testPrototype(oldStructure, failureCases); - loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2); - // ecx = baseObject->m_structure - for (RefPtr<Structure>* it = chain->head(); *it; ++it) { - // null check the prototype - successCases.append(branchPtr(Equal, regT2, ImmPtr(JSValue::encode(jsNull())))); - - // Check the structure id - failureCases.append(branchPtr(NotEqual, Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), ImmPtr(it->get()))); - - loadPtr(Address(regT2, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - failureCases.append(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType))); - loadPtr(Address(regT2, OBJECT_OFFSETOF(Structure, m_prototype)), regT2); - } - - successCases.link(this); + for (RefPtr<Structure>* it = chain->head(); *it; ++it) + testPrototype(it->get(), failureCases); Call callTarget; @@ -1540,7 +1676,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure); -#if PLATFORM(X86_64) +#if CPU(X86_64) move(ImmPtr(prototypeStructure), regT3); Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3); #else @@ -1615,7 +1751,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure); -#if PLATFORM(X86_64) +#if CPU(X86_64) move(ImmPtr(prototypeStructure), regT3); Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3); #else @@ -1668,7 +1804,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure); -#if PLATFORM(X86_64) +#if CPU(X86_64) move(ImmPtr(currStructure), regT3); bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3)); #else @@ -1721,7 +1857,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str // Check the prototype object's Structure had not changed. Structure** prototypeStructureAddress = &(protoObject->m_structure); -#if PLATFORM(X86_64) +#if CPU(X86_64) move(ImmPtr(currStructure), regT3); bucketsOfFail.append(branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), regT3)); #else diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubCall.h b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubCall.h index cb5354b..cfbd7dc 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubCall.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubCall.h @@ -26,7 +26,7 @@ #ifndef JITStubCall_h #define JITStubCall_h -#include <wtf/Platform.h> +#include "MacroAssemblerCodeRef.h" #if ENABLE(JIT) @@ -36,58 +36,58 @@ namespace JSC { public: JITStubCall(JIT* jit, JSObject* (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) - , m_stub(reinterpret_cast<void*>(stub)) + , m_stub(stub) , m_returnType(Cell) - , m_stackIndex(stackIndexStart) + , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } JITStubCall(JIT* jit, JSPropertyNameIterator* (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) - , m_stub(reinterpret_cast<void*>(stub)) + , m_stub(stub) , m_returnType(Cell) - , m_stackIndex(stackIndexStart) + , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } JITStubCall(JIT* jit, void* (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) - , m_stub(reinterpret_cast<void*>(stub)) + , m_stub(stub) , m_returnType(VoidPtr) - , m_stackIndex(stackIndexStart) + , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } JITStubCall(JIT* jit, int (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) - , m_stub(reinterpret_cast<void*>(stub)) + , m_stub(stub) , m_returnType(Int) - , m_stackIndex(stackIndexStart) + , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } JITStubCall(JIT* jit, bool (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) - , m_stub(reinterpret_cast<void*>(stub)) + , m_stub(stub) , m_returnType(Int) - , m_stackIndex(stackIndexStart) + , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } JITStubCall(JIT* jit, void (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) - , m_stub(reinterpret_cast<void*>(stub)) + , m_stub(stub) , m_returnType(Void) - , m_stackIndex(stackIndexStart) + , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } #if USE(JSVALUE32_64) JITStubCall(JIT* jit, EncodedJSValue (JIT_STUB *stub)(STUB_ARGS_DECLARATION)) : m_jit(jit) - , m_stub(reinterpret_cast<void*>(stub)) + , m_stub(stub) , m_returnType(Value) - , m_stackIndex(stackIndexStart) + , m_stackIndex(JITSTACKFRAME_ARGS_INDEX) { } #endif @@ -145,7 +145,7 @@ namespace JSC { void getArgument(size_t argumentNumber, JIT::RegisterID tag, JIT::RegisterID payload) { - size_t stackIndex = stackIndexStart + (argumentNumber * stackIndexStep); + size_t stackIndex = JITSTACKFRAME_ARGS_INDEX + (argumentNumber * stackIndexStep); m_jit->peek(payload, stackIndex); m_jit->peek(tag, stackIndex + 1); } @@ -171,7 +171,7 @@ namespace JSC { m_jit->restoreArgumentReference(); JIT::Call call = m_jit->call(); - m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeIndex, m_stub)); + m_jit->m_calls.append(CallRecord(call, m_jit->m_bytecodeIndex, m_stub.value())); #if ENABLE(OPCODE_SAMPLING) if (m_jit->m_bytecodeIndex != (unsigned)-1) @@ -222,10 +222,9 @@ namespace JSC { private: static const size_t stackIndexStep = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 2 : 1; - static const size_t stackIndexStart = 1; // Index 0 is reserved for restoreArgumentReference(). JIT* m_jit; - void* m_stub; + FunctionPtr m_stub; enum { Void, VoidPtr, Int, Value, Cell } m_returnType; size_t m_stackIndex; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubs.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubs.cpp index b098728..91b9401 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubs.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubs.cpp @@ -56,6 +56,7 @@ #include "RegExpPrototype.h" #include "Register.h" #include "SamplingTool.h" +#include <wtf/StdLibExtras.h> #include <stdarg.h> #include <stdio.h> @@ -67,25 +68,37 @@ using namespace std; namespace JSC { -#if PLATFORM(DARWIN) || PLATFORM(WIN_OS) +#if OS(DARWIN) || OS(WINDOWS) #define SYMBOL_STRING(name) "_" #name #else #define SYMBOL_STRING(name) #name #endif -#if PLATFORM(IPHONE) +#if OS(IPHONE_OS) #define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name) #else #define THUMB_FUNC_PARAM(name) #endif -#if PLATFORM(DARWIN) +#if OS(LINUX) && CPU(X86_64) +#define SYMBOL_STRING_RELOCATION(name) #name "@plt" +#else +#define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name) +#endif + +#if OS(DARWIN) // Mach-O platform #define HIDE_SYMBOL(name) ".private_extern _" #name -#elif PLATFORM(AIX) +#elif OS(AIX) // IBM's own file format #define HIDE_SYMBOL(name) ".lglobl " #name -#elif PLATFORM(LINUX) || PLATFORM(FREEBSD) || PLATFORM(OPENBSD) || PLATFORM(SOLARIS) || (PLATFORM(HPUX) && PLATFORM(IA64)) || PLATFORM(SYMBIAN) || PLATFORM(NETBSD) +#elif OS(LINUX) \ + || OS(FREEBSD) \ + || OS(OPENBSD) \ + || OS(SOLARIS) \ + || (OS(HPUX) && CPU(IA64)) \ + || OS(SYMBIAN) \ + || OS(NETBSD) // ELF platform #define HIDE_SYMBOL(name) ".hidden " #name #else @@ -94,7 +107,7 @@ namespace JSC { #if USE(JSVALUE32_64) -#if COMPILER(GCC) && PLATFORM(X86) +#if COMPILER(GCC) && CPU(X86) // These ASSERTs remind you that, if you change the layout of JITStackFrame, you // need to change the assembly trampolines below to match. @@ -104,6 +117,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, callFrame) == 0x58, JITStackFrame_ COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x50, JITStackFrame_code_offset_matches_ctiTrampoline); asm volatile ( +".text\n" ".globl " SYMBOL_STRING(ctiTrampoline) "\n" HIDE_SYMBOL(ctiTrampoline) "\n" SYMBOL_STRING(ctiTrampoline) ":" "\n" @@ -131,7 +145,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" #if !USE(JIT_STUB_ARGUMENT_VA_LIST) "movl %esp, %ecx" "\n" #endif - "call " SYMBOL_STRING(cti_vm_throw) "\n" + "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" "addl $0x3c, %esp" "\n" "popl %ebx" "\n" "popl %edi" "\n" @@ -152,7 +166,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "ret" "\n" ); -#elif COMPILER(GCC) && PLATFORM(X86_64) +#elif COMPILER(GCC) && CPU(X86_64) #if USE(JIT_STUB_ARGUMENT_VA_LIST) #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64." @@ -197,7 +211,7 @@ asm volatile ( HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" "movq %rsp, %rdi" "\n" - "call " SYMBOL_STRING(cti_vm_throw) "\n" + "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" "addq $0x48, %rsp" "\n" "popq %rbx" "\n" "popq %r15" "\n" @@ -222,7 +236,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "ret" "\n" ); -#elif COMPILER(GCC) && PLATFORM(ARM_THUMB2) +#elif COMPILER(GCC) && CPU(ARM_THUMB2) #if USE(JIT_STUB_ARGUMENT_VA_LIST) #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7." @@ -232,9 +246,9 @@ asm volatile ( ".text" "\n" ".align 2" "\n" ".globl " SYMBOL_STRING(ctiTrampoline) "\n" +HIDE_SYMBOL(ctiTrampoline) "\n" ".thumb" "\n" ".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n" -HIDE_SYMBOL(ctiTrampoline) "\n" SYMBOL_STRING(ctiTrampoline) ":" "\n" "sub sp, sp, #0x3c" "\n" "str lr, [sp, #0x20]" "\n" @@ -259,12 +273,12 @@ asm volatile ( ".text" "\n" ".align 2" "\n" ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" +HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" ".thumb" "\n" ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n" -HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" "cpy r0, sp" "\n" - "bl " SYMBOL_STRING(cti_vm_throw) "\n" + "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" "ldr r6, [sp, #0x2c]" "\n" "ldr r5, [sp, #0x28]" "\n" "ldr r4, [sp, #0x24]" "\n" @@ -277,9 +291,9 @@ asm volatile ( ".text" "\n" ".align 2" "\n" ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" +HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" ".thumb" "\n" ".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n" -HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "ldr r6, [sp, #0x2c]" "\n" "ldr r5, [sp, #0x28]" "\n" @@ -289,7 +303,44 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "bx lr" "\n" ); -#elif COMPILER(MSVC) +#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL) + +asm volatile ( +".globl " SYMBOL_STRING(ctiTrampoline) "\n" +HIDE_SYMBOL(ctiTrampoline) "\n" +SYMBOL_STRING(ctiTrampoline) ":" "\n" + "stmdb sp!, {r1-r3}" "\n" + "stmdb sp!, {r4-r8, lr}" "\n" + "sub sp, sp, #68" "\n" + "mov r4, r2" "\n" + "mov r5, #512" "\n" + // r0 contains the code + "mov lr, pc" "\n" + "mov pc, r0" "\n" + "add sp, sp, #68" "\n" + "ldmia sp!, {r4-r8, lr}" "\n" + "add sp, sp, #12" "\n" + "mov pc, lr" "\n" +); + +asm volatile ( +".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" +HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" +SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" + "mov r0, sp" "\n" + "bl " SYMBOL_STRING(cti_vm_throw) "\n" + +// Both has the same return sequence +".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" +HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" +SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" + "add sp, sp, #68" "\n" + "ldmia sp!, {r4-r8, lr}" "\n" + "add sp, sp, #12" "\n" + "mov pc, lr" "\n" +); + +#elif COMPILER(MSVC) && CPU(X86) #if USE(JIT_STUB_ARGUMENT_VA_LIST) #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC." @@ -353,11 +404,13 @@ extern "C" { } } -#endif // COMPILER(GCC) && PLATFORM(X86) +#else + #error "JIT not supported on this platform." +#endif #else // USE(JSVALUE32_64) -#if COMPILER(GCC) && PLATFORM(X86) +#if COMPILER(GCC) && CPU(X86) // These ASSERTs remind you that, if you change the layout of JITStackFrame, you // need to change the assembly trampolines below to match. @@ -366,6 +419,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x30, JITStackFrame_code_ COMPILE_ASSERT(offsetof(struct JITStackFrame, savedEBX) == 0x1c, JITStackFrame_stub_argument_space_matches_ctiTrampoline); asm volatile ( +".text\n" ".globl " SYMBOL_STRING(ctiTrampoline) "\n" HIDE_SYMBOL(ctiTrampoline) "\n" SYMBOL_STRING(ctiTrampoline) ":" "\n" @@ -393,7 +447,7 @@ SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" #if !USE(JIT_STUB_ARGUMENT_VA_LIST) "movl %esp, %ecx" "\n" #endif - "call " SYMBOL_STRING(cti_vm_throw) "\n" + "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" "addl $0x1c, %esp" "\n" "popl %ebx" "\n" "popl %edi" "\n" @@ -414,7 +468,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "ret" "\n" ); -#elif COMPILER(GCC) && PLATFORM(X86_64) +#elif COMPILER(GCC) && CPU(X86_64) #if USE(JIT_STUB_ARGUMENT_VA_LIST) #error "JIT_STUB_ARGUMENT_VA_LIST not supported on x86-64." @@ -427,6 +481,7 @@ COMPILE_ASSERT(offsetof(struct JITStackFrame, code) == 0x48, JITStackFrame_code_ COMPILE_ASSERT(offsetof(struct JITStackFrame, savedRBX) == 0x78, JITStackFrame_stub_argument_space_matches_ctiTrampoline); asm volatile ( +".text\n" ".globl " SYMBOL_STRING(ctiTrampoline) "\n" HIDE_SYMBOL(ctiTrampoline) "\n" SYMBOL_STRING(ctiTrampoline) ":" "\n" @@ -465,7 +520,7 @@ asm volatile ( HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" "movq %rsp, %rdi" "\n" - "call " SYMBOL_STRING(cti_vm_throw) "\n" + "call " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" "addq $0x78, %rsp" "\n" "popq %rbx" "\n" "popq %r15" "\n" @@ -490,7 +545,7 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "ret" "\n" ); -#elif COMPILER(GCC) && PLATFORM(ARM_THUMB2) +#elif COMPILER(GCC) && CPU(ARM_THUMB2) #if USE(JIT_STUB_ARGUMENT_VA_LIST) #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7." @@ -532,7 +587,7 @@ HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" ".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" "cpy r0, sp" "\n" - "bl " SYMBOL_STRING(cti_vm_throw) "\n" + "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" "ldr r6, [sp, #0x2c]" "\n" "ldr r5, [sp, #0x28]" "\n" "ldr r4, [sp, #0x24]" "\n" @@ -557,30 +612,24 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" "bx lr" "\n" ); -#elif COMPILER(GCC) && PLATFORM(ARM_TRADITIONAL) +#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL) asm volatile ( +".text\n" ".globl " SYMBOL_STRING(ctiTrampoline) "\n" HIDE_SYMBOL(ctiTrampoline) "\n" SYMBOL_STRING(ctiTrampoline) ":" "\n" "stmdb sp!, {r1-r3}" "\n" "stmdb sp!, {r4-r8, lr}" "\n" - "mov r6, pc" "\n" - "add r6, r6, #40" "\n" - "sub sp, sp, #32" "\n" - "ldr r4, [sp, #60]" "\n" + "sub sp, sp, #36" "\n" + "mov r4, r2" "\n" "mov r5, #512" "\n" - // r0 contains the code - "add r8, pc, #4" "\n" - "str r8, [sp, #-4]!" "\n" + "mov lr, pc" "\n" "mov pc, r0" "\n" - "add sp, sp, #32" "\n" + "add sp, sp, #36" "\n" "ldmia sp!, {r4-r8, lr}" "\n" "add sp, sp, #12" "\n" "mov pc, lr" "\n" - - // the return instruction - "ldr pc, [sp], #4" "\n" ); asm volatile ( @@ -588,22 +637,58 @@ asm volatile ( HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" "mov r0, sp" "\n" - "mov lr, r6" "\n" - "add r8, pc, #4" "\n" - "str r8, [sp, #-4]!" "\n" - "b " SYMBOL_STRING(cti_vm_throw) "\n" + "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" // Both has the same return sequence ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" - "add sp, sp, #32" "\n" + "add sp, sp, #36" "\n" "ldmia sp!, {r4-r8, lr}" "\n" "add sp, sp, #12" "\n" "mov pc, lr" "\n" ); -#elif COMPILER(MSVC) +#elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL) + +__asm EncodedJSValue ctiTrampoline(void*, RegisterFile*, CallFrame*, JSValue*, Profiler**, JSGlobalData*) +{ + ARM + stmdb sp!, {r1-r3} + stmdb sp!, {r4-r8, lr} + sub sp, sp, #36 + mov r4, r2 + mov r5, #512 + mov lr, pc + bx r0 + add sp, sp, #36 + ldmia sp!, {r4-r8, lr} + add sp, sp, #12 + bx lr +} + +__asm void ctiVMThrowTrampoline() +{ + ARM + PRESERVE8 + mov r0, sp + bl cti_vm_throw + add sp, sp, #36 + ldmia sp!, {r4-r8, lr} + add sp, sp, #12 + bx lr +} + +__asm void ctiOpThrowNotCaught() +{ + ARM + add sp, sp, #36 + ldmia sp!, {r4-r8, lr} + add sp, sp, #12 + bx lr +} + +#elif COMPILER(MSVC) && CPU(X86) #if USE(JIT_STUB_ARGUMENT_VA_LIST) #error "JIT_STUB_ARGUMENT_VA_LIST configuration not supported on MSVC." @@ -666,7 +751,9 @@ extern "C" { } } -#endif // COMPILER(GCC) && PLATFORM(X86) +#else + #error "JIT not supported on this platform." +#endif #endif // USE(JSVALUE32_64) @@ -680,7 +767,7 @@ JITThunks::JITThunks(JSGlobalData* globalData) { JIT::compileCTIMachineTrampolines(globalData, &m_executablePool, &m_ctiStringLengthTrampoline, &m_ctiVirtualCallLink, &m_ctiVirtualCall, &m_ctiNativeCallThunk); -#if PLATFORM(ARM_THUMB2) +#if CPU(ARM_THUMB2) // Unfortunate the arm compiler does not like the use of offsetof on JITStackFrame (since it contains non POD types), // and the OBJECT_OFFSETOF macro does not appear constantish enough for it to be happy with its use in COMPILE_ASSERT // macros. @@ -732,11 +819,15 @@ NEVER_INLINE void JITThunks::tryCachePutByID(CallFrame* callFrame, CodeBlock* co // Structure transition, cache transition info if (slot.type() == PutPropertySlot::NewProperty) { - StructureChain* prototypeChain = structure->prototypeChain(callFrame); - if (!prototypeChain->isCacheable() || structure->isDictionary()) { + if (structure->isDictionary()) { ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_put_by_id_generic)); return; } + + // put_by_id_transition checks the prototype chain for setters. + normalizePrototypeChain(callFrame, baseCell); + + StructureChain* prototypeChain = structure->prototypeChain(callFrame); stubInfo->initPutByIdTransition(structure->previousID(), structure, prototypeChain); JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), prototypeChain, returnAddress); return; @@ -796,35 +887,42 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co return; } + if (structure->isDictionary()) { + ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); + return; + } + if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { ASSERT(slot.slotBase().isObject()); JSObject* slotBaseObject = asObject(slot.slotBase()); - + size_t offset = slot.cachedOffset(); + // Since we're accessing a prototype in a loop, it's a good bet that it // should not be treated as a dictionary. - if (slotBaseObject->structure()->isDictionary()) - slotBaseObject->setStructure(Structure::fromDictionaryTransition(slotBaseObject->structure())); + if (slotBaseObject->structure()->isDictionary()) { + slotBaseObject->flattenDictionaryObject(); + offset = slotBaseObject->structure()->get(propertyName); + } stubInfo->initGetByIdProto(structure, slotBaseObject->structure()); - JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), slot.cachedOffset(), returnAddress); + ASSERT(!structure->isDictionary()); + ASSERT(!slotBaseObject->structure()->isDictionary()); + JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), offset, returnAddress); return; } - size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot); + size_t offset = slot.cachedOffset(); + size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset); if (!count) { stubInfo->accessType = access_get_by_id_generic; return; } StructureChain* prototypeChain = structure->prototypeChain(callFrame); - if (!prototypeChain->isCacheable()) { - ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); - return; - } stubInfo->initGetByIdChain(structure, prototypeChain); - JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, slot.cachedOffset(), returnAddress); + JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, offset, returnAddress); } #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) @@ -920,7 +1018,7 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD } \ } while (0) -#if PLATFORM(ARM_THUMB2) +#if CPU(ARM_THUMB2) #define DEFINE_STUB_FUNCTION(rtype, op) \ extern "C" { \ @@ -941,6 +1039,57 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD ); \ rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \ +#elif CPU(ARM_TRADITIONAL) && COMPILER(GCC) + +#if USE(JSVALUE32_64) +#define THUNK_RETURN_ADDRESS_OFFSET 64 +#else +#define THUNK_RETURN_ADDRESS_OFFSET 32 +#endif + +COMPILE_ASSERT(offsetof(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET, JITStackFrame_thunkReturnAddress_offset_mismatch); + +#define DEFINE_STUB_FUNCTION(rtype, op) \ + extern "C" { \ + rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ + }; \ + asm volatile ( \ + ".globl " SYMBOL_STRING(cti_##op) "\n" \ + HIDE_SYMBOL(cti_##op) "\n" \ + SYMBOL_STRING(cti_##op) ":" "\n" \ + "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ + "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \ + "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ + "mov pc, lr" "\n" \ + ); \ + rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) + +#elif CPU(ARM_TRADITIONAL) && COMPILER(RVCT) + +#define DEFINE_STUB_FUNCTION(rtype, op) rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) + +/* The following is a workaround for RVCT toolchain; precompiler macros are not expanded before the code is passed to the assembler */ + +/* The following section is a template to generate code for GeneratedJITStubs_RVCT.h */ +/* The pattern "#xxx#" will be replaced with "xxx" */ + +/* +RVCT(extern "C" #rtype# JITStubThunked_#op#(STUB_ARGS_DECLARATION);) +RVCT(__asm #rtype# cti_#op#(STUB_ARGS_DECLARATION)) +RVCT({) +RVCT( ARM) +RVCT( IMPORT JITStubThunked_#op#) +RVCT( str lr, [sp, #32]) +RVCT( bl JITStubThunked_#op#) +RVCT( ldr lr, [sp, #32]) +RVCT( bx lr) +RVCT(}) +RVCT() +*/ + +/* Include the generated file */ +#include "GeneratedJITStubs_RVCT.h" + #else #define DEFINE_STUB_FUNCTION(rtype, op) rtype JIT_STUB cti_##op(STUB_ARGS_DECLARATION) #endif @@ -972,38 +1121,19 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_add) JSValue v1 = stackFrame.args[0].jsValue(); JSValue v2 = stackFrame.args[1].jsValue(); - - double left; - double right = 0.0; - - bool rightIsNumber = v2.getNumber(right); - if (rightIsNumber && v1.getNumber(left)) - return JSValue::encode(jsNumber(stackFrame.globalData, left + right)); - CallFrame* callFrame = stackFrame.callFrame; - bool leftIsString = v1.isString(); - if (leftIsString && v2.isString()) { - RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep()); - if (UNLIKELY(!value)) { - throwOutOfMemoryError(callFrame); - VM_THROW_EXCEPTION(); - } - - return JSValue::encode(jsString(stackFrame.globalData, value.release())); + if (v1.isString()) { + JSValue result = v2.isString() + ? jsString(callFrame, asString(v1), asString(v2)) + : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame)); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValue::encode(result); } - if (rightIsNumber & leftIsString) { - RefPtr<UString::Rep> value = v2.isInt32() ? - concatenate(asString(v1)->value().rep(), v2.asInt32()) : - concatenate(asString(v1)->value().rep(), right); - - if (UNLIKELY(!value)) { - throwOutOfMemoryError(callFrame); - VM_THROW_EXCEPTION(); - } - return JSValue::encode(jsString(stackFrame.globalData, value.release())); - } + double left = 0.0, right; + if (v1.getNumber(left) && v2.getNumber(right)) + return JSValue::encode(jsNumber(stackFrame.globalData, left + right)); // All other cases are pretty uncommon JSValue result = jsAddSlowCase(callFrame, v1, v2); @@ -1053,19 +1183,6 @@ DEFINE_STUB_FUNCTION(void, register_file_check) throwStackOverflowError(oldCallFrame, stackFrame.globalData, ReturnAddressPtr(oldCallFrame->returnPC()), STUB_RETURN_ADDRESS); } -DEFINE_STUB_FUNCTION(int, op_loop_if_less) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - JSValue src1 = stackFrame.args[0].jsValue(); - JSValue src2 = stackFrame.args[1].jsValue(); - CallFrame* callFrame = stackFrame.callFrame; - - bool result = jsLess(callFrame, src1, src2); - CHECK_FOR_EXCEPTION_AT_END(); - return result; -} - DEFINE_STUB_FUNCTION(int, op_loop_if_lesseq) { STUB_INIT_STACK_FRAME(stackFrame); @@ -1204,7 +1321,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check) // Since we're accessing a prototype in a loop, it's a good bet that it // should not be treated as a dictionary. if (slotBaseObject->structure()->isDictionary()) - slotBaseObject->setStructure(Structure::fromDictionaryTransition(slotBaseObject->structure())); + slotBaseObject->flattenDictionaryObject(); // The result fetched should always be the callee! ASSERT(result == JSValue(callee)); @@ -1222,7 +1339,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check) // for now. For now it performs a check on a special object on the global object only used for this // purpose. The object is in no way exposed, and as such the check will always pass. if (slot.slotBase() == baseValue) { - JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject()->methodCallDummy(), STUB_RETURN_ADDRESS); + JIT::patchMethodCallProto(codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS); return JSValue::encode(result); } } @@ -1332,14 +1449,15 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) STUB_INIT_STACK_FRAME(stackFrame); CallFrame* callFrame = stackFrame.callFrame; + const Identifier& propertyName = stackFrame.args[1].identifier(); JSValue baseValue = stackFrame.args[0].jsValue(); PropertySlot slot(baseValue); - JSValue result = baseValue.get(callFrame, stackFrame.args[1].identifier(), slot); + JSValue result = baseValue.get(callFrame, propertyName, slot); CHECK_FOR_EXCEPTION(); - if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isUncacheableDictionary()) { + if (!baseValue.isCell() || !slot.isCacheable() || asCell(baseValue)->structure()->isDictionary()) { ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); return JSValue::encode(result); } @@ -1350,32 +1468,34 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) ASSERT(slot.slotBase().isObject()); JSObject* slotBaseObject = asObject(slot.slotBase()); + + size_t offset = slot.cachedOffset(); if (slot.slotBase() == baseValue) ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); else if (slot.slotBase() == asCell(baseValue)->structure()->prototypeForLookup(callFrame)) { + ASSERT(!asCell(baseValue)->structure()->isDictionary()); // Since we're accessing a prototype in a loop, it's a good bet that it // should not be treated as a dictionary. - if (slotBaseObject->structure()->isDictionary()) - slotBaseObject->setStructure(Structure::fromDictionaryTransition(slotBaseObject->structure())); + if (slotBaseObject->structure()->isDictionary()) { + slotBaseObject->flattenDictionaryObject(); + offset = slotBaseObject->structure()->get(propertyName); + } int listIndex; PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); - JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset()); + JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), offset); if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full)); - } else if (size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot)) { - StructureChain* protoChain = structure->prototypeChain(callFrame); - if (!protoChain->isCacheable()) { - ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_fail)); - return JSValue::encode(result); - } - + } else if (size_t count = normalizePrototypeChain(callFrame, baseValue, slot.slotBase(), propertyName, offset)) { + ASSERT(!asCell(baseValue)->structure()->isDictionary()); int listIndex; PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); - JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, slot.cachedOffset()); + + StructureChain* protoChain = structure->prototypeChain(callFrame); + JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, offset); if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full)); @@ -1452,7 +1572,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_instanceof) // ECMA-262 15.3.5.3: // Throw an exception either if baseVal is not an object, or if it does not implement 'HasInstance' (i.e. is a function). - TypeInfo typeInfo(UnspecifiedType, 0); + TypeInfo typeInfo(UnspecifiedType); if (!baseVal.isObject() || !(typeInfo = asObject(baseVal)->structure()->typeInfo()).implementsHasInstance()) { CallFrame* callFrame = stackFrame.callFrame; CodeBlock* codeBlock = callFrame->codeBlock(); @@ -1520,7 +1640,7 @@ DEFINE_STUB_FUNCTION(void*, op_call_JSFunction) { STUB_INIT_STACK_FRAME(stackFrame); -#ifndef NDEBUG +#if !ASSERT_DISABLED CallData callData; ASSERT(stackFrame.args[0].jsValue().getCallData(callData) == CallTypeJS); #endif @@ -1769,7 +1889,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct) VM_THROW_EXCEPTION(); } -#ifndef NDEBUG +#if !ASSERT_DISABLED ConstructData constructData; ASSERT(constructor->getConstructData(constructData) == ConstructTypeJS); #endif @@ -1778,7 +1898,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_construct_JSConstruct) if (stackFrame.args[3].jsValue().isObject()) structure = asObject(stackFrame.args[3].jsValue())->inheritorID(); else - structure = constructor->scope().node()->globalObject()->emptyObjectStructure(); + structure = constructor->scope().node()->globalObject->emptyObjectStructure(); #ifdef QT_BUILD_SCRIPT_LIB return new (stackFrame.globalData) QT_PREPEND_NAMESPACE(QScriptObject)(structure); #else @@ -1843,7 +1963,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val) } else if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) { // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_string)); - result = asString(baseValue)->getIndex(stackFrame.globalData, i); + result = asString(baseValue)->getIndex(callFrame, i); } else if (isJSByteArray(globalData, baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array)); @@ -1874,7 +1994,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string) if (LIKELY(subscript.isUInt32())) { uint32_t i = subscript.asUInt32(); if (isJSString(globalData, baseValue) && asString(baseValue)->canGetIndex(i)) - result = asString(baseValue)->getIndex(stackFrame.globalData, i); + result = asString(baseValue)->getIndex(callFrame, i); else { result = baseValue.get(callFrame, i); if (!isJSString(globalData, baseValue)) @@ -2039,19 +2159,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_lesseq) return JSValue::encode(result); } -DEFINE_STUB_FUNCTION(int, op_loop_if_true) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - JSValue src1 = stackFrame.args[0].jsValue(); - - CallFrame* callFrame = stackFrame.callFrame; - - bool result = src1.toBoolean(callFrame); - CHECK_FOR_EXCEPTION_AT_END(); - return result; -} - DEFINE_STUB_FUNCTION(int, op_load_varargs) { STUB_INIT_STACK_FRAME(stackFrame); @@ -2326,8 +2433,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_post_inc) return JSValue::encode(number); } -#if USE(JSVALUE32_64) - DEFINE_STUB_FUNCTION(int, op_eq) { STUB_INIT_STACK_FRAME(stackFrame); @@ -2335,6 +2440,7 @@ DEFINE_STUB_FUNCTION(int, op_eq) JSValue src1 = stackFrame.args[0].jsValue(); JSValue src2 = stackFrame.args[1].jsValue(); +#if USE(JSVALUE32_64) start: if (src2.isUndefined()) { return src1.isNull() || @@ -2390,20 +2496,20 @@ DEFINE_STUB_FUNCTION(int, op_eq) if (cell1->isString()) { if (src2.isInt32()) - return static_cast<JSString*>(cell1)->value().toDouble() == src2.asInt32(); + return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asInt32(); if (src2.isDouble()) - return static_cast<JSString*>(cell1)->value().toDouble() == src2.asDouble(); + return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == src2.asDouble(); if (src2.isTrue()) - return static_cast<JSString*>(cell1)->value().toDouble() == 1.0; + return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 1.0; if (src2.isFalse()) - return static_cast<JSString*>(cell1)->value().toDouble() == 0.0; + return static_cast<JSString*>(cell1)->value(stackFrame.callFrame).toDouble() == 0.0; JSCell* cell2 = asCell(src2); if (cell2->isString()) - return static_cast<JSString*>(cell1)->value() == static_cast<JSString*>(cell2)->value(); + return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame); src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame); CHECK_FOR_EXCEPTION(); @@ -2420,8 +2526,18 @@ DEFINE_STUB_FUNCTION(int, op_eq) src1 = asObject(cell1)->toPrimitive(stackFrame.callFrame); CHECK_FOR_EXCEPTION(); goto start; + +#else // USE(JSVALUE32_64) + CallFrame* callFrame = stackFrame.callFrame; + + bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2); + CHECK_FOR_EXCEPTION_AT_END(); + return result; +#endif // USE(JSVALUE32_64) } +#if USE(JSVALUE32_64) + DEFINE_STUB_FUNCTION(int, op_eq_strings) { STUB_INIT_STACK_FRAME(stackFrame); @@ -2431,26 +2547,10 @@ DEFINE_STUB_FUNCTION(int, op_eq_strings) ASSERT(string1->isString()); ASSERT(string2->isString()); - return string1->value() == string2->value(); -} - -#else // USE(JSVALUE32_64) - -DEFINE_STUB_FUNCTION(int, op_eq) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - JSValue src1 = stackFrame.args[0].jsValue(); - JSValue src2 = stackFrame.args[1].jsValue(); - - CallFrame* callFrame = stackFrame.callFrame; - - bool result = JSValue::equalSlowCaseInline(callFrame, src1, src2); - CHECK_FOR_EXCEPTION_AT_END(); - return result; + return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame); } -#endif // USE(JSVALUE32_64) +#endif DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift) { @@ -2668,7 +2768,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_call_eval) Register* newCallFrame = callFrame->registers() + registerOffset; Register* argv = newCallFrame - RegisterFile::CallFrameHeaderSize - argCount; JSValue thisValue = argv[0].jsValue(); - JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject(); + JSGlobalObject* globalObject = callFrame->scopeChain()->globalObject; if (thisValue == globalObject && funcVal == globalObject->evalFunction()) { JSValue exceptionValue; @@ -2699,7 +2799,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_throw) if (!handler) { *stackFrame.exception = exceptionValue; - STUB_SET_RETURN_ADDRESS(reinterpret_cast<void*>(ctiOpThrowNotCaught)); + STUB_SET_RETURN_ADDRESS(FunctionPtr(ctiOpThrowNotCaught).value()); return JSValue::encode(jsNull()); } @@ -2714,18 +2814,22 @@ DEFINE_STUB_FUNCTION(JSPropertyNameIterator*, op_get_pnames) { STUB_INIT_STACK_FRAME(stackFrame); - return JSPropertyNameIterator::create(stackFrame.callFrame, stackFrame.args[0].jsValue()); + CallFrame* callFrame = stackFrame.callFrame; + JSObject* o = stackFrame.args[0].jsObject(); + Structure* structure = o->structure(); + JSPropertyNameIterator* jsPropertyNameIterator = structure->enumerationCache(); + if (!jsPropertyNameIterator || jsPropertyNameIterator->cachedPrototypeChain() != structure->prototypeChain(callFrame)) + jsPropertyNameIterator = JSPropertyNameIterator::create(callFrame, o); + return jsPropertyNameIterator; } -DEFINE_STUB_FUNCTION(EncodedJSValue, op_next_pname) +DEFINE_STUB_FUNCTION(int, has_property) { STUB_INIT_STACK_FRAME(stackFrame); - JSPropertyNameIterator* it = stackFrame.args[0].propertyNameIterator(); - JSValue temp = it->next(stackFrame.callFrame); - if (!temp) - it->invalidate(); - return JSValue::encode(temp); + JSObject* base = stackFrame.args[0].jsObject(); + JSString* property = stackFrame.args[1].jsString(); + return base->hasProperty(stackFrame.callFrame, Identifier(stackFrame.callFrame, property->value(stackFrame.callFrame))); } DEFINE_STUB_FUNCTION(JSObject*, op_push_scope) @@ -2802,7 +2906,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_stricteq) JSValue src1 = stackFrame.args[0].jsValue(); JSValue src2 = stackFrame.args[1].jsValue(); - return JSValue::encode(jsBoolean(JSValue::strictEqual(src1, src2))); + return JSValue::encode(jsBoolean(JSValue::strictEqual(stackFrame.callFrame, src1, src2))); } DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_primitive) @@ -2816,7 +2920,9 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_strcat) { STUB_INIT_STACK_FRAME(stackFrame); - return JSValue::encode(concatenateStrings(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32())); + JSValue result = jsString(stackFrame.callFrame, &stackFrame.callFrame->registers()[stackFrame.args[0].int32()], stackFrame.args[1].int32()); + CHECK_FOR_EXCEPTION_AT_END(); + return JSValue::encode(result); } DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq) @@ -2826,7 +2932,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_nstricteq) JSValue src1 = stackFrame.args[0].jsValue(); JSValue src2 = stackFrame.args[1].jsValue(); - return JSValue::encode(jsBoolean(!JSValue::strictEqual(src1, src2))); + return JSValue::encode(jsBoolean(!JSValue::strictEqual(stackFrame.callFrame, src1, src2))); } DEFINE_STUB_FUNCTION(EncodedJSValue, op_to_jsnumber) @@ -2935,7 +3041,7 @@ DEFINE_STUB_FUNCTION(void*, op_switch_char) void* result = codeBlock->characterSwitchJumpTable(tableIndex).ctiDefault.executableAddress(); if (scrutinee.isString()) { - UString::Rep* value = asString(scrutinee)->value().rep(); + UString::Rep* value = asString(scrutinee)->value(callFrame).rep(); if (value->size() == 1) result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]).executableAddress(); } @@ -2955,7 +3061,7 @@ DEFINE_STUB_FUNCTION(void*, op_switch_string) void* result = codeBlock->stringSwitchJumpTable(tableIndex).ctiDefault.executableAddress(); if (scrutinee.isString()) { - UString::Rep* value = asString(scrutinee)->value().rep(); + UString::Rep* value = asString(scrutinee)->value(callFrame).rep(); result = codeBlock->stringSwitchJumpTable(tableIndex).ctiForValue(value).executableAddress(); } @@ -3034,9 +3140,8 @@ DEFINE_STUB_FUNCTION(void, op_debug) int debugHookID = stackFrame.args[0].int32(); int firstLine = stackFrame.args[1].int32(); int lastLine = stackFrame.args[2].int32(); - int column = stackFrame.args[3].int32(); - stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine, column); + stackFrame.globalData->interpreter->debug(callFrame, static_cast<DebugHookID>(debugHookID), firstLine, lastLine); } #ifdef QT_BUILD_SCRIPT_LIB @@ -3092,6 +3197,14 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, vm_throw) return JSValue::encode(exceptionValue); } +DEFINE_STUB_FUNCTION(EncodedJSValue, to_object) +{ + STUB_INIT_STACK_FRAME(stackFrame); + + CallFrame* callFrame = stackFrame.callFrame; + return JSValue::encode(stackFrame.args[0].jsValue().toObject(callFrame)); +} + } // namespace JSC - #endif // ENABLE(JIT) +#endif // ENABLE(JIT) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubs.h b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubs.h index c2b8c02..da80133 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubs.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jit/JITStubs.h @@ -63,6 +63,7 @@ namespace JSC { int32_t asInt32; JSValue jsValue() { return JSValue::decode(asEncodedJSValue); } + JSObject* jsObject() { return static_cast<JSObject*>(asPointer); } Identifier& identifier() { return *static_cast<Identifier*>(asPointer); } int32_t int32() { return asInt32; } CodeBlock* codeBlock() { return static_cast<CodeBlock*>(asPointer); } @@ -74,7 +75,7 @@ namespace JSC { ReturnAddressPtr returnAddress() { return ReturnAddressPtr(asPointer); } }; -#if PLATFORM(X86_64) +#if CPU(X86_64) struct JITStackFrame { void* reserved; // Unused JITStubArg args[6]; @@ -98,7 +99,7 @@ namespace JSC { // When JIT code makes a call, it pushes its return address just below the rest of the stack. ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; } }; -#elif PLATFORM(X86) +#elif CPU(X86) #if COMPILER(MSVC) #pragma pack(push) #pragma pack(4) @@ -129,7 +130,7 @@ namespace JSC { #if COMPILER(MSVC) #pragma pack(pop) #endif // COMPILER(MSVC) -#elif PLATFORM(ARM_THUMB2) +#elif CPU(ARM_THUMB2) struct JITStackFrame { void* reserved; // Unused JITStubArg args[6]; @@ -157,11 +158,13 @@ namespace JSC { ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; } }; -#elif PLATFORM(ARM_TRADITIONAL) +#elif CPU(ARM_TRADITIONAL) struct JITStackFrame { JITStubArg padding; // Unused JITStubArg args[7]; + ReturnAddressPtr thunkReturnAddress; + void* preservedR4; void* preservedR5; void* preservedR6; @@ -172,16 +175,20 @@ namespace JSC { RegisterFile* registerFile; CallFrame* callFrame; JSValue* exception; + + // These arguments passed on the stack. Profiler** enabledProfilerReference; JSGlobalData* globalData; // When JIT code makes a call, it pushes its return address just below the rest of the stack. - ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; } + ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; } }; #else #error "JITStackFrame not defined for this platform." #endif +#define JITSTACKFRAME_ARGS_INDEX (OBJECT_OFFSETOF(JITStackFrame, args) / sizeof(void*)) + #if USE(JIT_STUB_ARGUMENT_VA_LIST) #define STUB_ARGS_DECLARATION void* args, ... #define STUB_ARGS (reinterpret_cast<void**>(vl_args) - 1) @@ -195,16 +202,16 @@ namespace JSC { #define STUB_ARGS_DECLARATION void** args #define STUB_ARGS (args) - #if PLATFORM(X86) && COMPILER(MSVC) + #if CPU(X86) && COMPILER(MSVC) #define JIT_STUB __fastcall - #elif PLATFORM(X86) && COMPILER(GCC) + #elif CPU(X86) && COMPILER(GCC) #define JIT_STUB __attribute__ ((fastcall)) #else #define JIT_STUB #endif #endif -#if PLATFORM(X86_64) +#if CPU(X86_64) struct VoidPtrPair { void* first; void* second; @@ -289,7 +296,6 @@ extern "C" { EncodedJSValue JIT_STUB cti_op_mod(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_mul(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_negate(STUB_ARGS_DECLARATION); - EncodedJSValue JIT_STUB cti_op_next_pname(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_not(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_nstricteq(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_post_dec(STUB_ARGS_DECLARATION); @@ -311,6 +317,7 @@ extern "C" { EncodedJSValue JIT_STUB cti_op_typeof(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_urshift(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_vm_throw(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_to_object(STUB_ARGS_DECLARATION); JSObject* JIT_STUB cti_op_construct_JSConstruct(STUB_ARGS_DECLARATION); JSObject* JIT_STUB cti_op_new_array(STUB_ARGS_DECLARATION); JSObject* JIT_STUB cti_op_new_error(STUB_ARGS_DECLARATION); @@ -332,10 +339,9 @@ extern "C" { int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION); int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION); int JIT_STUB cti_op_load_varargs(STUB_ARGS_DECLARATION); - int JIT_STUB cti_op_loop_if_less(STUB_ARGS_DECLARATION); int JIT_STUB cti_op_loop_if_lesseq(STUB_ARGS_DECLARATION); - int JIT_STUB cti_op_loop_if_true(STUB_ARGS_DECLARATION); int JIT_STUB cti_timeout_check(STUB_ARGS_DECLARATION); + int JIT_STUB cti_has_property(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_create_arguments(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_create_arguments_no_params(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_debug(STUB_ARGS_DECLARATION); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/jsc.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/jsc.cpp index ee4e393..252fb96 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/jsc.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/jsc.cpp @@ -29,6 +29,7 @@ #include "JSArray.h" #include "JSFunction.h" #include "JSLock.h" +#include "JSString.h" #include "PrototypeFunction.h" #include "SamplingTool.h" #include <math.h> @@ -36,7 +37,7 @@ #include <stdlib.h> #include <string.h> -#if !PLATFORM(WIN_OS) +#if !OS(WINDOWS) #include <unistd.h> #endif @@ -53,10 +54,10 @@ #include <signal.h> #endif -#if COMPILER(MSVC) && !PLATFORM(WINCE) +#if COMPILER(MSVC) && !OS(WINCE) #include <crtdbg.h> -#include <windows.h> #include <mmsystem.h> +#include <windows.h> #endif #if PLATFORM(QT) @@ -87,8 +88,8 @@ static JSValue JSC_HOST_CALL functionClearSamplingFlags(ExecState*, JSObject*, J struct Script { bool isFile; - char *argument; - + char* argument; + Script(bool isFile, char *argument) : isFile(isFile) , argument(argument) @@ -173,12 +174,12 @@ GlobalObject::GlobalObject(const Vector<UString>& arguments) JSValue JSC_HOST_CALL functionPrint(ExecState* exec, JSObject*, JSValue, const ArgList& args) { for (unsigned i = 0; i < args.size(); ++i) { - if (i != 0) + if (i) putchar(' '); - + printf("%s", args.at(i).toString(exec).UTF8String().c_str()); } - + putchar('\n'); fflush(stdout); return jsUndefined(); @@ -193,7 +194,7 @@ JSValue JSC_HOST_CALL functionDebug(ExecState* exec, JSObject*, JSValue, const A JSValue JSC_HOST_CALL functionGC(ExecState* exec, JSObject*, JSValue, const ArgList&) { JSLock lock(SilenceAssertionsOnly); - exec->heap()->collect(); + exec->heap()->collectAllGarbage(); return jsUndefined(); } @@ -291,8 +292,18 @@ JSValue JSC_HOST_CALL functionReadline(ExecState* exec, JSObject*, JSValue, cons JSValue JSC_HOST_CALL functionQuit(ExecState* exec, JSObject*, JSValue, const ArgList&) { + // Technically, destroying the heap in the middle of JS execution is a no-no, + // but we want to maintain compatibility with the Mozilla test suite, so + // we pretend that execution has terminated to avoid ASSERTs, then tear down the heap. + exec->globalData().dynamicGlobalObject = 0; + cleanupGlobalData(&exec->globalData()); exit(EXIT_SUCCESS); + +#if COMPILER(MSVC) && OS(WINCE) + // Without this, Visual Studio will complain that this method does not return a value. + return jsUndefined(); +#endif } // Use SEH for Release builds only to get rid of the crash report dialog @@ -312,7 +323,7 @@ int jscmain(int argc, char** argv, JSGlobalData*); int main(int argc, char** argv) { -#if defined(_DEBUG) && PLATFORM(WIN_OS) +#if defined(_DEBUG) && OS(WINDOWS) _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); @@ -321,7 +332,7 @@ int main(int argc, char** argv) _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); #endif -#if COMPILER(MSVC) && !PLATFORM(WINCE) +#if COMPILER(MSVC) && !OS(WINCE) timeBeginPeriod(1); #endif @@ -360,11 +371,8 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr if (dump) BytecodeGenerator::setDumpsGeneratedCode(true); -#if ENABLE(OPCODE_SAMPLING) - Interpreter* interpreter = globalObject->globalData()->interpreter; - interpreter->setSampler(new SamplingTool(interpreter)); - interpreter->sampler()->setup(); -#endif + JSGlobalData* globalData = globalObject->globalData(); + #if ENABLE(SAMPLING_FLAGS) SamplingFlags::start(); #endif @@ -381,9 +389,7 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr fileName = "[Command Line]"; } -#if ENABLE(SAMPLING_THREAD) - SamplingThread::start(); -#endif + globalData->startSampling(); Completion completion = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), makeSource(script, fileName)); success = success && completion.complType() != Throw; @@ -394,20 +400,14 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr printf("End: %s\n", completion.value().toString(globalObject->globalExec()).ascii()); } -#if ENABLE(SAMPLING_THREAD) - SamplingThread::stop(); -#endif - + globalData->stopSampling(); globalObject->globalExec()->clearException(); } #if ENABLE(SAMPLING_FLAGS) SamplingFlags::stop(); #endif -#if ENABLE(OPCODE_SAMPLING) - interpreter->sampler()->dump(globalObject->globalExec()); - delete interpreter->sampler(); -#endif + globalData->dumpSampleData(globalObject->globalExec()); #if ENABLE(SAMPLING_COUNTERS) AbstractSamplingCounter::dump(); #endif @@ -473,30 +473,27 @@ static void parseArguments(int argc, char** argv, Options& options, JSGlobalData int i = 1; for (; i < argc; ++i) { const char* arg = argv[i]; - if (strcmp(arg, "-f") == 0) { + if (!strcmp(arg, "-f")) { if (++i == argc) printUsageStatement(globalData); options.scripts.append(Script(true, argv[i])); continue; } - if (strcmp(arg, "-e") == 0) { + if (!strcmp(arg, "-e")) { if (++i == argc) printUsageStatement(globalData); options.scripts.append(Script(false, argv[i])); continue; } - if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) { - printUsageStatement(globalData, true); - } - if (strcmp(arg, "-i") == 0) { + if (!strcmp(arg, "-i")) { options.interactive = true; continue; } - if (strcmp(arg, "-d") == 0) { + if (!strcmp(arg, "-d")) { options.dump = true; continue; } - if (strcmp(arg, "-s") == 0) { + if (!strcmp(arg, "-s")) { #if HAVE(SIGNAL_H) signal(SIGILL, _exit); signal(SIGFPE, _exit); @@ -505,16 +502,18 @@ static void parseArguments(int argc, char** argv, Options& options, JSGlobalData #endif continue; } - if (strcmp(arg, "--") == 0) { + if (!strcmp(arg, "--")) { ++i; break; } + if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) + printUsageStatement(globalData, true); options.scripts.append(Script(true, argv[i])); } - + if (options.scripts.isEmpty()) options.interactive = true; - + for (; i < argc; ++i) options.arguments.append(argv[i]); } @@ -542,20 +541,20 @@ static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& return false; } - size_t buffer_size = 0; - size_t buffer_capacity = 1024; + size_t bufferSize = 0; + size_t bufferCapacity = 1024; - buffer.resize(buffer_capacity); + buffer.resize(bufferCapacity); while (!feof(f) && !ferror(f)) { - buffer_size += fread(buffer.data() + buffer_size, 1, buffer_capacity - buffer_size, f); - if (buffer_size == buffer_capacity) { // guarantees space for trailing '\0' - buffer_capacity *= 2; - buffer.resize(buffer_capacity); + bufferSize += fread(buffer.data() + bufferSize, 1, bufferCapacity - bufferSize, f); + if (bufferSize == bufferCapacity) { // guarantees space for trailing '\0' + bufferCapacity *= 2; + buffer.resize(bufferCapacity); } } fclose(f); - buffer[buffer_size] = '\0'; + buffer[bufferSize] = '\0'; return true; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/os-win32/WinMain.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/os-win32/WinMain.cpp new file mode 100644 index 0000000..17800d0 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/os-win32/WinMain.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009 Patrick Gansterer (paroga@paroga.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" +#include "Vector.h" +#include <winbase.h> +#include <winnls.h> +#include <wtf/UnusedParam.h> + +int main(int argc, char** argv); + +static inline char* convertToUtf8(LPCWSTR widecharString, int length) +{ + int requiredSize = WideCharToMultiByte(CP_UTF8, 0, widecharString, length, 0, 0, 0, 0); + char* multibyteString = new char[requiredSize + 1]; + + WideCharToMultiByte(CP_UTF8, 0, widecharString, length, multibyteString, requiredSize, 0, 0); + multibyteString[requiredSize] = '\0'; + + return multibyteString; +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) +{ + UNUSED_PARAM(hInstance); + UNUSED_PARAM(hPrevInstance); + UNUSED_PARAM(nCmdShow); + + Vector<char*> arguments; + TCHAR buffer[MAX_PATH]; + + int length = GetModuleFileNameW(0, buffer, MAX_PATH); + arguments.append(convertToUtf8(buffer, length)); + + WCHAR* commandLine = lpCmdLine; + while (commandLine[0] != '\0') { + int commandLineLength = 1; + WCHAR endChar = ' '; + + while (commandLine[0] == ' ') + ++commandLine; + + if (commandLine[0] == '\"') { + ++commandLine; + endChar = '\"'; + } + + while (commandLine[commandLineLength] != endChar && commandLine[commandLineLength] != '\0') + ++commandLineLength; + + arguments.append(convertToUtf8(commandLine, commandLineLength)); + + commandLine += commandLineLength; + if (endChar != ' ' && commandLine[0] != '\0') + ++commandLine; + } + + int res = main(arguments.size(), arguments.data()); + + for (size_t i = 0; i < arguments.size(); i++) + delete arguments[i]; + + return res; +} diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Grammar.y b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Grammar.y index fa4ffd0..717a266 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Grammar.y +++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Grammar.y @@ -27,6 +27,7 @@ #include "JSObject.h" #include "JSString.h" +#include "Lexer.h" #include "NodeConstructors.h" #include "NodeInfo.h" #include <stdlib.h> @@ -42,13 +43,12 @@ // Default values for bison. #define YYDEBUG 0 // Set to 1 to debug a parse error. #define jscyydebug 0 // Set to 1 to debug a parse error. -#if !PLATFORM(DARWIN) +#if !OS(DARWIN) // Avoid triggering warnings in older bison by not setting this on the Darwin platform. // FIXME: Is this still needed? #define YYERROR_VERBOSE #endif -int jscyylex(void* lvalp, void* llocp, void* globalPtr); int jscyyerror(const char*); static inline bool allowAutomaticSemicolon(JSC::Lexer&, int); @@ -179,7 +179,7 @@ static inline void appendToVarDeclarationList(JSGlobalData* globalData, ParserAr template <typename T> inline void setStatementLocation(StatementNode* statement, const T& start, const T& end) { - statement->setLoc(start.first_line, end.last_line, start.first_column); + statement->setLoc(start.first_line, end.last_line); } static inline void setExceptionLocation(ThrowableExpressionData* node, unsigned start, unsigned divot, unsigned end) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.cpp index a85ed3d..e616c7a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.cpp @@ -39,19 +39,10 @@ using namespace Unicode; // We can't specify the namespace in yacc's C output, so do it here instead. using namespace JSC; -#ifndef KDE_USE_FINAL #include "Grammar.h" -#endif - #include "Lookup.h" #include "Lexer.lut.h" -// A bridge for yacc from the C world to the C++ world. -int jscyylex(void* lvalp, void* llocp, void* globalData) -{ - return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp); -} - namespace JSC { static const UChar byteOrderMark = 0xFEFF; @@ -652,6 +643,8 @@ inStringEscapeSequence: shiftLineTerminator(); goto inString; } + if (m_current == -1) + goto returnError; record16(singleEscape(m_current)); shift1(); goto inString; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.h index 174e05a..c76696c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Lexer.h @@ -136,6 +136,12 @@ namespace JSC { return (convertHex(c1, c2) << 8) | convertHex(c3, c4); } + // A bridge for yacc from the C world to the C++ world. + inline int jscyylex(void* lvalp, void* llocp, void* globalData) + { + return static_cast<JSGlobalData*>(globalData)->lexer->lex(lvalp, llocp); + } + } // namespace JSC #endif // Lexer_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/NodeConstructors.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/NodeConstructors.h index 5431e18..8c9135f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/NodeConstructors.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/NodeConstructors.h @@ -46,7 +46,6 @@ namespace JSC { inline StatementNode::StatementNode(JSGlobalData* globalData) : Node(globalData) , m_lastLine(-1) - , m_column(-1) { } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.cpp index 89bbc11..4b97e9a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.cpp @@ -49,71 +49,13 @@ using namespace WTF; namespace JSC { -/* - Details of the emitBytecode function. - - Return value: The register holding the production's value. - dst: An optional parameter specifying the most efficient destination at - which to store the production's value. The callee must honor dst. - - The dst argument provides for a crude form of copy propagation. For example, - - x = 1 - - becomes - - load r[x], 1 - - instead of - - load r0, 1 - mov r[x], r0 - - because the assignment node, "x =", passes r[x] as dst to the number node, "1". -*/ - -// ------------------------------ ThrowableExpressionData -------------------------------- - -static void substitute(UString& string, const UString& substring) -{ - int position = string.find("%s"); - ASSERT(position != -1); - UString newString = string.substr(0, position); - newString.append(substring); - newString.append(string.substr(position + 2)); - string = newString; -} - -RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* message) -{ - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message)); - generator.emitThrow(exception); - return exception; -} - -RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const UString& label) -{ - UString message = messageTemplate; - substitute(message, label); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* exception = generator.emitNewError(generator.newTemporary(), type, jsString(generator.globalData(), message)); - generator.emitThrow(exception); - return exception; -} - -inline RegisterID* ThrowableExpressionData::emitThrowError(BytecodeGenerator& generator, ErrorType type, const char* messageTemplate, const Identifier& label) -{ - return emitThrowError(generator, type, messageTemplate, label.ustring()); -} // ------------------------------ StatementNode -------------------------------- -void StatementNode::setLoc(int firstLine, int lastLine, int column) +void StatementNode::setLoc(int firstLine, int lastLine) { m_line = firstLine; m_lastLine = lastLine; - m_column = column; } // ------------------------------ SourceElements -------------------------------- @@ -131,1754 +73,6 @@ inline StatementNode* SourceElements::singleStatement() const return size == 1 ? m_statements[0] : 0; } -inline StatementNode* SourceElements::lastStatement() const -{ - size_t size = m_statements.size(); - return size ? m_statements[size - 1] : 0; -} - -// ------------------------------ NullNode ------------------------------------- - -RegisterID* NullNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.emitLoad(dst, jsNull()); -} - -// ------------------------------ BooleanNode ---------------------------------- - -RegisterID* BooleanNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.emitLoad(dst, m_value); -} - -// ------------------------------ NumberNode ----------------------------------- - -RegisterID* NumberNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.emitLoad(dst, m_value); -} - -// ------------------------------ StringNode ----------------------------------- - -RegisterID* StringNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.emitLoad(dst, m_value); -} - -// ------------------------------ RegExpNode ----------------------------------- - -RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegExp> regExp = RegExp::create(generator.globalData(), m_pattern.ustring(), m_flags.ustring()); - if (!regExp->isValid()) - return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage()); - if (dst == generator.ignoredResult()) - return 0; - return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get()); -} - -// ------------------------------ ThisNode ------------------------------------- - -RegisterID* ThisNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - return 0; - return generator.moveToDestinationIfNeeded(dst, generator.thisRegister()); -} - -// ------------------------------ ResolveNode ---------------------------------- - -bool ResolveNode::isPure(BytecodeGenerator& generator) const -{ - return generator.isLocal(m_ident); -} - -RegisterID* ResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RegisterID* local = generator.registerFor(m_ident)) { - if (dst == generator.ignoredResult()) - return 0; - return generator.moveToDestinationIfNeeded(dst, local); - } - - generator.emitExpressionInfo(m_startOffset + m_ident.size(), m_ident.size(), 0); - return generator.emitResolve(generator.finalDestination(dst), m_ident); -} - -// ------------------------------ ArrayNode ------------------------------------ - -RegisterID* ArrayNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - // FIXME: Should we put all of this code into emitNewArray? - - unsigned length = 0; - ElementNode* firstPutElement; - for (firstPutElement = m_element; firstPutElement; firstPutElement = firstPutElement->next()) { - if (firstPutElement->elision()) - break; - ++length; - } - - if (!firstPutElement && !m_elision) - return generator.emitNewArray(generator.finalDestination(dst), m_element); - - RefPtr<RegisterID> array = generator.emitNewArray(generator.tempDestination(dst), m_element); - - for (ElementNode* n = firstPutElement; n; n = n->next()) { - RegisterID* value = generator.emitNode(n->value()); - length += n->elision(); - generator.emitPutByIndex(array.get(), length++, value); - } - - if (m_elision) { - RegisterID* value = generator.emitLoad(0, jsNumber(generator.globalData(), m_elision + length)); - generator.emitPutById(array.get(), generator.propertyNames().length, value); - } - - return generator.moveToDestinationIfNeeded(dst, array.get()); -} - -bool ArrayNode::isSimpleArray() const -{ - if (m_elision || m_optional) - return false; - for (ElementNode* ptr = m_element; ptr; ptr = ptr->next()) { - if (ptr->elision()) - return false; - } - return true; -} - -ArgumentListNode* ArrayNode::toArgumentList(JSGlobalData* globalData) const -{ - ASSERT(!m_elision && !m_optional); - ElementNode* ptr = m_element; - if (!ptr) - return 0; - ArgumentListNode* head = new (globalData) ArgumentListNode(globalData, ptr->value()); - ArgumentListNode* tail = head; - ptr = ptr->next(); - for (; ptr; ptr = ptr->next()) { - ASSERT(!ptr->elision()); - tail = new (globalData) ArgumentListNode(globalData, tail, ptr->value()); - } - return head; -} - -// ------------------------------ ObjectLiteralNode ---------------------------- - -RegisterID* ObjectLiteralNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (!m_list) { - if (dst == generator.ignoredResult()) - return 0; - return generator.emitNewObject(generator.finalDestination(dst)); - } - return generator.emitNode(dst, m_list); -} - -// ------------------------------ PropertyListNode ----------------------------- - -RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> newObj = generator.tempDestination(dst); - - generator.emitNewObject(newObj.get()); - - for (PropertyListNode* p = this; p; p = p->m_next) { - RegisterID* value = generator.emitNode(p->m_node->m_assign); - - switch (p->m_node->m_type) { - case PropertyNode::Constant: { - generator.emitPutById(newObj.get(), p->m_node->name(), value); - break; - } - case PropertyNode::Getter: { - generator.emitPutGetter(newObj.get(), p->m_node->name(), value); - break; - } - case PropertyNode::Setter: { - generator.emitPutSetter(newObj.get(), p->m_node->name(), value); - break; - } - default: - ASSERT_NOT_REACHED(); - } - } - - return generator.moveToDestinationIfNeeded(dst, newObj.get()); -} - -// ------------------------------ BracketAccessorNode -------------------------------- - -RegisterID* BracketAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments, m_subscript->isPure(generator)); - RegisterID* property = generator.emitNode(m_subscript); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property); -} - -// ------------------------------ DotAccessorNode -------------------------------- - -RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RegisterID* base = generator.emitNode(m_base); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitGetById(generator.finalDestination(dst), base, m_ident); -} - -// ------------------------------ ArgumentListNode ----------------------------- - -RegisterID* ArgumentListNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - ASSERT(m_expr); - return generator.emitNode(dst, m_expr); -} - -// ------------------------------ NewExprNode ---------------------------------- - -RegisterID* NewExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> func = generator.emitNode(m_expr); - return generator.emitConstruct(generator.finalDestination(dst), func.get(), m_args, divot(), startOffset(), endOffset()); -} - -// ------------------------------ EvalFunctionCallNode ---------------------------------- - -RegisterID* EvalFunctionCallNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> func = generator.tempDestination(dst); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); - generator.emitExpressionInfo(divot() - startOffset() + 4, 4, 0); - generator.emitResolveWithBase(thisRegister.get(), func.get(), generator.propertyNames().eval); - return generator.emitCallEval(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); -} - -// ------------------------------ FunctionCallValueNode ---------------------------------- - -RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> func = generator.emitNode(m_expr); - RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); -} - -// ------------------------------ FunctionCallResolveNode ---------------------------------- - -RegisterID* FunctionCallResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RefPtr<RegisterID> local = generator.registerFor(m_ident)) { - RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, thisRegister.get()), local.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); - } - - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { - RefPtr<RegisterID> func = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); - RefPtr<RegisterID> thisRegister = generator.emitLoad(generator.newTemporary(), jsNull()); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); - } - - RefPtr<RegisterID> func = generator.newTemporary(); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); - int identifierStart = divot() - startOffset(); - generator.emitExpressionInfo(identifierStart + m_ident.size(), m_ident.size(), 0); - generator.emitResolveWithBase(thisRegister.get(), func.get(), m_ident); - return generator.emitCall(generator.finalDestination(dst, func.get()), func.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); -} - -// ------------------------------ FunctionCallBracketNode ---------------------------------- - -RegisterID* FunctionCallBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNode(m_base); - RegisterID* property = generator.emitNode(m_subscript); - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr<RegisterID> function = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property); - RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); -} - -// ------------------------------ FunctionCallDotNode ---------------------------------- - -RegisterID* FunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> function = generator.tempDestination(dst); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); - generator.emitNode(thisRegister.get(), m_base); - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - generator.emitMethodCheck(); - generator.emitGetById(function.get(), thisRegister.get(), m_ident); - return generator.emitCall(generator.finalDestination(dst, function.get()), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); -} - -RegisterID* CallFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<Label> realCall = generator.newLabel(); - RefPtr<Label> end = generator.newLabel(); - RefPtr<RegisterID> base = generator.emitNode(m_base); - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); - RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get()); - generator.emitJumpIfNotFunctionCall(function.get(), realCall.get()); - { - RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); - ArgumentListNode* oldList = m_args->m_listNode; - if (m_args->m_listNode && m_args->m_listNode->m_expr) { - generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); - m_args->m_listNode = m_args->m_listNode->m_next; - } else - generator.emitLoad(thisRegister.get(), jsNull()); - - generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); - generator.emitJump(end.get()); - m_args->m_listNode = oldList; - } - generator.emitLabel(realCall.get()); - { - RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); - } - generator.emitLabel(end.get()); - return finalDestination.get(); -} - -static bool areTrivialApplyArguments(ArgumentsNode* args) -{ - return !args->m_listNode || !args->m_listNode->m_expr || !args->m_listNode->m_next - || (!args->m_listNode->m_next->m_next && args->m_listNode->m_next->m_expr->isSimpleArray()); -} - -RegisterID* ApplyFunctionCallDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - // A few simple cases can be trivially handled as ordinary function calls. - // function.apply(), function.apply(arg) -> identical to function.call - // function.apply(thisArg, [arg0, arg1, ...]) -> can be trivially coerced into function.call(thisArg, arg0, arg1, ...) and saves object allocation - bool mayBeCall = areTrivialApplyArguments(m_args); - - RefPtr<Label> realCall = generator.newLabel(); - RefPtr<Label> end = generator.newLabel(); - RefPtr<RegisterID> base = generator.emitNode(m_base); - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr<RegisterID> function = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); - RefPtr<RegisterID> finalDestination = generator.finalDestination(dst, function.get()); - generator.emitJumpIfNotFunctionApply(function.get(), realCall.get()); - { - if (mayBeCall) { - RefPtr<RegisterID> realFunction = generator.emitMove(generator.tempDestination(dst), base.get()); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); - ArgumentListNode* oldList = m_args->m_listNode; - if (m_args->m_listNode && m_args->m_listNode->m_expr) { - generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); - m_args->m_listNode = m_args->m_listNode->m_next; - if (m_args->m_listNode) { - ASSERT(m_args->m_listNode->m_expr->isSimpleArray()); - ASSERT(!m_args->m_listNode->m_next); - m_args->m_listNode = static_cast<ArrayNode*>(m_args->m_listNode->m_expr)->toArgumentList(generator.globalData()); - } - } else - generator.emitLoad(thisRegister.get(), jsNull()); - generator.emitCall(finalDestination.get(), realFunction.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); - m_args->m_listNode = oldList; - } else { - ASSERT(m_args->m_listNode && m_args->m_listNode->m_next); - RefPtr<RegisterID> realFunction = generator.emitMove(generator.newTemporary(), base.get()); - RefPtr<RegisterID> argsCountRegister = generator.newTemporary(); - RefPtr<RegisterID> thisRegister = generator.newTemporary(); - RefPtr<RegisterID> argsRegister = generator.newTemporary(); - generator.emitNode(thisRegister.get(), m_args->m_listNode->m_expr); - ArgumentListNode* args = m_args->m_listNode->m_next; - bool isArgumentsApply = false; - if (args->m_expr->isResolveNode()) { - ResolveNode* resolveNode = static_cast<ResolveNode*>(args->m_expr); - isArgumentsApply = generator.willResolveToArguments(resolveNode->identifier()); - if (isArgumentsApply) - generator.emitMove(argsRegister.get(), generator.uncheckedRegisterForArguments()); - } - if (!isArgumentsApply) - generator.emitNode(argsRegister.get(), args->m_expr); - while ((args = args->m_next)) - generator.emitNode(args->m_expr); - - generator.emitLoadVarargs(argsCountRegister.get(), argsRegister.get()); - generator.emitCallVarargs(finalDestination.get(), realFunction.get(), thisRegister.get(), argsCountRegister.get(), divot(), startOffset(), endOffset()); - } - generator.emitJump(end.get()); - } - generator.emitLabel(realCall.get()); - { - RefPtr<RegisterID> thisRegister = generator.emitMove(generator.newTemporary(), base.get()); - generator.emitCall(finalDestination.get(), function.get(), thisRegister.get(), m_args, divot(), startOffset(), endOffset()); - } - generator.emitLabel(end.get()); - return finalDestination.get(); -} - -// ------------------------------ PostfixResolveNode ---------------------------------- - -static RegisterID* emitPreIncOrDec(BytecodeGenerator& generator, RegisterID* srcDst, Operator oper) -{ - return (oper == OpPlusPlus) ? generator.emitPreInc(srcDst) : generator.emitPreDec(srcDst); -} - -static RegisterID* emitPostIncOrDec(BytecodeGenerator& generator, RegisterID* dst, RegisterID* srcDst, Operator oper) -{ - if (srcDst == dst) - return generator.emitToJSNumber(dst, srcDst); - return (oper == OpPlusPlus) ? generator.emitPostInc(dst, srcDst) : generator.emitPostDec(dst, srcDst); -} - -RegisterID* PostfixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RegisterID* local = generator.registerFor(m_ident)) { - if (generator.isLocalConstant(m_ident)) { - if (dst == generator.ignoredResult()) - return 0; - return generator.emitToJSNumber(generator.finalDestination(dst), local); - } - - if (dst == generator.ignoredResult()) - return emitPreIncOrDec(generator, local, m_operator); - return emitPostIncOrDec(generator, generator.finalDestination(dst), local, m_operator); - } - - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { - RefPtr<RegisterID> value = generator.emitGetScopedVar(generator.newTemporary(), depth, index, globalObject); - RegisterID* oldValue; - if (dst == generator.ignoredResult()) { - oldValue = 0; - emitPreIncOrDec(generator, value.get(), m_operator); - } else { - oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); - } - generator.emitPutScopedVar(depth, index, value.get(), globalObject); - return oldValue; - } - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RefPtr<RegisterID> value = generator.newTemporary(); - RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), value.get(), m_ident); - RegisterID* oldValue; - if (dst == generator.ignoredResult()) { - oldValue = 0; - emitPreIncOrDec(generator, value.get(), m_operator); - } else { - oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator); - } - generator.emitPutById(base.get(), m_ident, value.get()); - return oldValue; -} - -// ------------------------------ PostfixBracketNode ---------------------------------- - -RegisterID* PostfixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNode(m_base); - RefPtr<RegisterID> property = generator.emitNode(m_subscript); - - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr<RegisterID> value = generator.emitGetByVal(generator.newTemporary(), base.get(), property.get()); - RegisterID* oldValue; - if (dst == generator.ignoredResult()) { - oldValue = 0; - if (m_operator == OpPlusPlus) - generator.emitPreInc(value.get()); - else - generator.emitPreDec(value.get()); - } else { - oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); - } - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutByVal(base.get(), property.get(), value.get()); - return oldValue; -} - -// ------------------------------ PostfixDotNode ---------------------------------- - -RegisterID* PostfixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNode(m_base); - - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr<RegisterID> value = generator.emitGetById(generator.newTemporary(), base.get(), m_ident); - RegisterID* oldValue; - if (dst == generator.ignoredResult()) { - oldValue = 0; - if (m_operator == OpPlusPlus) - generator.emitPreInc(value.get()); - else - generator.emitPreDec(value.get()); - } else { - oldValue = (m_operator == OpPlusPlus) ? generator.emitPostInc(generator.finalDestination(dst), value.get()) : generator.emitPostDec(generator.finalDestination(dst), value.get()); - } - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutById(base.get(), m_ident, value.get()); - return oldValue; -} - -// ------------------------------ PostfixErrorNode ----------------------------------- - -RegisterID* PostfixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) -{ - return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus - ? "Postfix ++ operator applied to value that is not a reference." - : "Postfix -- operator applied to value that is not a reference."); -} - -// ------------------------------ DeleteResolveNode ----------------------------------- - -RegisterID* DeleteResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (generator.registerFor(m_ident)) - return generator.emitLoad(generator.finalDestination(dst), false); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RegisterID* base = generator.emitResolveBase(generator.tempDestination(dst), m_ident); - return generator.emitDeleteById(generator.finalDestination(dst, base), base, m_ident); -} - -// ------------------------------ DeleteBracketNode ----------------------------------- - -RegisterID* DeleteBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> r0 = generator.emitNode(m_base); - RegisterID* r1 = generator.emitNode(m_subscript); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitDeleteByVal(generator.finalDestination(dst), r0.get(), r1); -} - -// ------------------------------ DeleteDotNode ----------------------------------- - -RegisterID* DeleteDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RegisterID* r0 = generator.emitNode(m_base); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitDeleteById(generator.finalDestination(dst), r0, m_ident); -} - -// ------------------------------ DeleteValueNode ----------------------------------- - -RegisterID* DeleteValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitNode(generator.ignoredResult(), m_expr); - - // delete on a non-location expression ignores the value and returns true - return generator.emitLoad(generator.finalDestination(dst), true); -} - -// ------------------------------ VoidNode ------------------------------------- - -RegisterID* VoidNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) { - generator.emitNode(generator.ignoredResult(), m_expr); - return 0; - } - RefPtr<RegisterID> r0 = generator.emitNode(m_expr); - return generator.emitLoad(dst, jsUndefined()); -} - -// ------------------------------ TypeOfValueNode ----------------------------------- - -RegisterID* TypeOfResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RegisterID* local = generator.registerFor(m_ident)) { - if (dst == generator.ignoredResult()) - return 0; - return generator.emitTypeOf(generator.finalDestination(dst), local); - } - - RefPtr<RegisterID> scratch = generator.emitResolveBase(generator.tempDestination(dst), m_ident); - generator.emitGetById(scratch.get(), scratch.get(), m_ident); - if (dst == generator.ignoredResult()) - return 0; - return generator.emitTypeOf(generator.finalDestination(dst, scratch.get()), scratch.get()); -} - -// ------------------------------ TypeOfValueNode ----------------------------------- - -RegisterID* TypeOfValueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) { - generator.emitNode(generator.ignoredResult(), m_expr); - return 0; - } - RefPtr<RegisterID> src = generator.emitNode(m_expr); - return generator.emitTypeOf(generator.finalDestination(dst), src.get()); -} - -// ------------------------------ PrefixResolveNode ---------------------------------- - -RegisterID* PrefixResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RegisterID* local = generator.registerFor(m_ident)) { - if (generator.isLocalConstant(m_ident)) { - if (dst == generator.ignoredResult()) - return 0; - RefPtr<RegisterID> r0 = generator.emitLoad(generator.finalDestination(dst), (m_operator == OpPlusPlus) ? 1.0 : -1.0); - return generator.emitBinaryOp(op_add, r0.get(), local, r0.get(), OperandTypes()); - } - - emitPreIncOrDec(generator, local, m_operator); - return generator.moveToDestinationIfNeeded(dst, local); - } - - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - if (generator.findScopedProperty(m_ident, index, depth, false, globalObject) && index != missingSymbolMarker()) { - RefPtr<RegisterID> propDst = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); - emitPreIncOrDec(generator, propDst.get(), m_operator); - generator.emitPutScopedVar(depth, index, propDst.get(), globalObject); - return generator.moveToDestinationIfNeeded(dst, propDst.get()); - } - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - RefPtr<RegisterID> propDst = generator.tempDestination(dst); - RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), propDst.get(), m_ident); - emitPreIncOrDec(generator, propDst.get(), m_operator); - generator.emitPutById(base.get(), m_ident, propDst.get()); - return generator.moveToDestinationIfNeeded(dst, propDst.get()); -} - -// ------------------------------ PrefixBracketNode ---------------------------------- - -RegisterID* PrefixBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNode(m_base); - RefPtr<RegisterID> property = generator.emitNode(m_subscript); - RefPtr<RegisterID> propDst = generator.tempDestination(dst); - - generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); - RegisterID* value = generator.emitGetByVal(propDst.get(), base.get(), property.get()); - if (m_operator == OpPlusPlus) - generator.emitPreInc(value); - else - generator.emitPreDec(value); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutByVal(base.get(), property.get(), value); - return generator.moveToDestinationIfNeeded(dst, propDst.get()); -} - -// ------------------------------ PrefixDotNode ---------------------------------- - -RegisterID* PrefixDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNode(m_base); - RefPtr<RegisterID> propDst = generator.tempDestination(dst); - - generator.emitExpressionInfo(divot() + m_subexpressionDivotOffset, m_subexpressionStartOffset, endOffset() - m_subexpressionDivotOffset); - RegisterID* value = generator.emitGetById(propDst.get(), base.get(), m_ident); - if (m_operator == OpPlusPlus) - generator.emitPreInc(value); - else - generator.emitPreDec(value); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutById(base.get(), m_ident, value); - return generator.moveToDestinationIfNeeded(dst, propDst.get()); -} - -// ------------------------------ PrefixErrorNode ----------------------------------- - -RegisterID* PrefixErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) -{ - return emitThrowError(generator, ReferenceError, m_operator == OpPlusPlus - ? "Prefix ++ operator applied to value that is not a reference." - : "Prefix -- operator applied to value that is not a reference."); -} - -// ------------------------------ Unary Operation Nodes ----------------------------------- - -RegisterID* UnaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RegisterID* src = generator.emitNode(m_expr); - return generator.emitUnaryOp(opcodeID(), generator.finalDestination(dst), src); -} - -// ------------------------------ Binary Operation Nodes ----------------------------------- - -// BinaryOpNode::emitStrcat: -// -// This node generates an op_strcat operation. This opcode can handle concatenation of three or -// more values, where we can determine a set of separate op_add operations would be operating on -// string values. -// -// This function expects to be operating on a graph of AST nodes looking something like this: -// -// (a)... (b) -// \ / -// (+) (c) -// \ / -// [d] ((+)) -// \ / -// [+=] -// -// The assignment operation is optional, if it exists the register holding the value on the -// lefthand side of the assignment should be passing as the optional 'lhs' argument. -// -// The method should be called on the node at the root of the tree of regular binary add -// operations (marked in the diagram with a double set of parentheses). This node must -// be performing a string concatenation (determined by statically detecting that at least -// one child must be a string). -// -// Since the minimum number of values being concatenated together is expected to be 3, if -// a lhs to a concatenating assignment is not provided then the root add should have at -// least one left child that is also an add that can be determined to be operating on strings. -// -RegisterID* BinaryOpNode::emitStrcat(BytecodeGenerator& generator, RegisterID* dst, RegisterID* lhs, ReadModifyResolveNode* emitExpressionInfoForMe) -{ - ASSERT(isAdd()); - ASSERT(resultDescriptor().definitelyIsString()); - - // Create a list of expressions for all the adds in the tree of nodes we can convert into - // a string concatenation. The rightmost node (c) is added first. The rightmost node is - // added first, and the leftmost child is never added, so the vector produced for the - // example above will be [ c, b ]. - Vector<ExpressionNode*, 16> reverseExpressionList; - reverseExpressionList.append(m_expr2); - - // Examine the left child of the add. So long as this is a string add, add its right-child - // to the list, and keep processing along the left fork. - ExpressionNode* leftMostAddChild = m_expr1; - while (leftMostAddChild->isAdd() && leftMostAddChild->resultDescriptor().definitelyIsString()) { - reverseExpressionList.append(static_cast<AddNode*>(leftMostAddChild)->m_expr2); - leftMostAddChild = static_cast<AddNode*>(leftMostAddChild)->m_expr1; - } - - Vector<RefPtr<RegisterID>, 16> temporaryRegisters; - - // If there is an assignment, allocate a temporary to hold the lhs after conversion. - // We could possibly avoid this (the lhs is converted last anyway, we could let the - // op_strcat node handle its conversion if required). - if (lhs) - temporaryRegisters.append(generator.newTemporary()); - - // Emit code for the leftmost node ((a) in the example). - temporaryRegisters.append(generator.newTemporary()); - RegisterID* leftMostAddChildTempRegister = temporaryRegisters.last().get(); - generator.emitNode(leftMostAddChildTempRegister, leftMostAddChild); - - // Note on ordering of conversions: - // - // We maintain the same ordering of conversions as we would see if the concatenations - // was performed as a sequence of adds (otherwise this optimization could change - // behaviour should an object have been provided a valueOf or toString method). - // - // Considering the above example, the sequnce of execution is: - // * evaluate operand (a) - // * evaluate operand (b) - // * convert (a) to primitive <- (this would be triggered by the first add) - // * convert (b) to primitive <- (ditto) - // * evaluate operand (c) - // * convert (c) to primitive <- (this would be triggered by the second add) - // And optionally, if there is an assignment: - // * convert (d) to primitive <- (this would be triggered by the assigning addition) - // - // As such we do not plant an op to convert the leftmost child now. Instead, use - // 'leftMostAddChildTempRegister' as a flag to trigger generation of the conversion - // once the second node has been generated. However, if the leftmost child is an - // immediate we can trivially determine that no conversion will be required. - // If this is the case - if (leftMostAddChild->isString()) - leftMostAddChildTempRegister = 0; - - while (reverseExpressionList.size()) { - ExpressionNode* node = reverseExpressionList.last(); - reverseExpressionList.removeLast(); - - // Emit the code for the current node. - temporaryRegisters.append(generator.newTemporary()); - generator.emitNode(temporaryRegisters.last().get(), node); - - // On the first iteration of this loop, when we first reach this point we have just - // generated the second node, which means it is time to convert the leftmost operand. - if (leftMostAddChildTempRegister) { - generator.emitToPrimitive(leftMostAddChildTempRegister, leftMostAddChildTempRegister); - leftMostAddChildTempRegister = 0; // Only do this once. - } - // Plant a conversion for this node, if necessary. - if (!node->isString()) - generator.emitToPrimitive(temporaryRegisters.last().get(), temporaryRegisters.last().get()); - } - ASSERT(temporaryRegisters.size() >= 3); - - // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. - // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. - if (emitExpressionInfoForMe) - generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); - - // If there is an assignment convert the lhs now. This will also copy lhs to - // the temporary register we allocated for it. - if (lhs) - generator.emitToPrimitive(temporaryRegisters[0].get(), lhs); - - return generator.emitStrcat(generator.finalDestination(dst, temporaryRegisters[0].get()), temporaryRegisters[0].get(), temporaryRegisters.size()); -} - -RegisterID* BinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - OpcodeID opcodeID = this->opcodeID(); - - if (opcodeID == op_add && m_expr1->isAdd() && m_expr1->resultDescriptor().definitelyIsString()) - return emitStrcat(generator, dst); - - if (opcodeID == op_neq) { - if (m_expr1->isNull() || m_expr2->isNull()) { - RefPtr<RegisterID> src = generator.tempDestination(dst); - generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); - return generator.emitUnaryOp(op_neq_null, generator.finalDestination(dst, src.get()), src.get()); - } - } - - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2); - return generator.emitBinaryOp(opcodeID, generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); -} - -RegisterID* EqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (m_expr1->isNull() || m_expr2->isNull()) { - RefPtr<RegisterID> src = generator.tempDestination(dst); - generator.emitNode(src.get(), m_expr1->isNull() ? m_expr2 : m_expr1); - return generator.emitUnaryOp(op_eq_null, generator.finalDestination(dst, src.get()), src.get()); - } - - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2); - return generator.emitEqualityOp(op_eq, generator.finalDestination(dst, src1.get()), src1.get(), src2); -} - -RegisterID* StrictEqualNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2); - return generator.emitEqualityOp(op_stricteq, generator.finalDestination(dst, src1.get()), src1.get(), src2); -} - -RegisterID* ReverseBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2); - return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src2, src1.get(), OperandTypes(m_expr2->resultDescriptor(), m_expr1->resultDescriptor())); -} - -RegisterID* ThrowableBinaryOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); - RegisterID* src2 = generator.emitNode(m_expr2); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitBinaryOp(opcodeID(), generator.finalDestination(dst, src1.get()), src1.get(), src2, OperandTypes(m_expr1->resultDescriptor(), m_expr2->resultDescriptor())); -} - -RegisterID* InstanceOfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> src1 = generator.emitNodeForLeftHandSide(m_expr1, m_rightHasAssignments, m_expr2->isPure(generator)); - RefPtr<RegisterID> src2 = generator.emitNode(m_expr2); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitGetByIdExceptionInfo(op_instanceof); - RegisterID* src2Prototype = generator.emitGetById(generator.newTemporary(), src2.get(), generator.globalData()->propertyNames->prototype); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitInstanceOf(generator.finalDestination(dst, src1.get()), src1.get(), src2.get(), src2Prototype); -} - -// ------------------------------ LogicalOpNode ---------------------------- - -RegisterID* LogicalOpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> temp = generator.tempDestination(dst); - RefPtr<Label> target = generator.newLabel(); - - generator.emitNode(temp.get(), m_expr1); - if (m_operator == OpLogicalAnd) - generator.emitJumpIfFalse(temp.get(), target.get()); - else - generator.emitJumpIfTrue(temp.get(), target.get()); - generator.emitNode(temp.get(), m_expr2); - generator.emitLabel(target.get()); - - return generator.moveToDestinationIfNeeded(dst, temp.get()); -} - -// ------------------------------ ConditionalNode ------------------------------ - -RegisterID* ConditionalNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> newDst = generator.finalDestination(dst); - RefPtr<Label> beforeElse = generator.newLabel(); - RefPtr<Label> afterElse = generator.newLabel(); - - RegisterID* cond = generator.emitNode(m_logical); - generator.emitJumpIfFalse(cond, beforeElse.get()); - - generator.emitNode(newDst.get(), m_expr1); - generator.emitJump(afterElse.get()); - - generator.emitLabel(beforeElse.get()); - generator.emitNode(newDst.get(), m_expr2); - - generator.emitLabel(afterElse.get()); - - return newDst.get(); -} - -// ------------------------------ ReadModifyResolveNode ----------------------------------- - -// FIXME: should this be moved to be a method on BytecodeGenerator? -static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& generator, RegisterID* dst, RegisterID* src1, ExpressionNode* m_right, Operator oper, OperandTypes types, ReadModifyResolveNode* emitExpressionInfoForMe = 0) -{ - OpcodeID opcodeID; - switch (oper) { - case OpMultEq: - opcodeID = op_mul; - break; - case OpDivEq: - opcodeID = op_div; - break; - case OpPlusEq: - if (m_right->isAdd() && m_right->resultDescriptor().definitelyIsString()) - return static_cast<AddNode*>(m_right)->emitStrcat(generator, dst, src1, emitExpressionInfoForMe); - opcodeID = op_add; - break; - case OpMinusEq: - opcodeID = op_sub; - break; - case OpLShift: - opcodeID = op_lshift; - break; - case OpRShift: - opcodeID = op_rshift; - break; - case OpURShift: - opcodeID = op_urshift; - break; - case OpAndEq: - opcodeID = op_bitand; - break; - case OpXOrEq: - opcodeID = op_bitxor; - break; - case OpOrEq: - opcodeID = op_bitor; - break; - case OpModEq: - opcodeID = op_mod; - break; - default: - ASSERT_NOT_REACHED(); - return dst; - } - - RegisterID* src2 = generator.emitNode(m_right); - - // Certain read-modify nodes require expression info to be emitted *after* m_right has been generated. - // If this is required the node is passed as 'emitExpressionInfoForMe'; do so now. - if (emitExpressionInfoForMe) - generator.emitExpressionInfo(emitExpressionInfoForMe->divot(), emitExpressionInfoForMe->startOffset(), emitExpressionInfoForMe->endOffset()); - - return generator.emitBinaryOp(opcodeID, dst, src1, src2, types); -} - -RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RegisterID* local = generator.registerFor(m_ident)) { - if (generator.isLocalConstant(m_ident)) { - return emitReadModifyAssignment(generator, generator.finalDestination(dst), local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - } - - if (generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) { - RefPtr<RegisterID> result = generator.newTemporary(); - generator.emitMove(result.get(), local); - emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - generator.emitMove(local, result.get()); - return generator.moveToDestinationIfNeeded(dst, result.get()); - } - - RegisterID* result = emitReadModifyAssignment(generator, local, local, m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - return generator.moveToDestinationIfNeeded(dst, result); - } - - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { - RefPtr<RegisterID> src1 = generator.emitGetScopedVar(generator.tempDestination(dst), depth, index, globalObject); - RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - generator.emitPutScopedVar(depth, index, result, globalObject); - return result; - } - - RefPtr<RegisterID> src1 = generator.tempDestination(dst); - generator.emitExpressionInfo(divot() - startOffset() + m_ident.size(), m_ident.size(), 0); - RefPtr<RegisterID> base = generator.emitResolveWithBase(generator.newTemporary(), src1.get(), m_ident); - RegisterID* result = emitReadModifyAssignment(generator, generator.finalDestination(dst, src1.get()), src1.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this); - return generator.emitPutById(base.get(), m_ident, result); -} - -// ------------------------------ AssignResolveNode ----------------------------------- - -RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (RegisterID* local = generator.registerFor(m_ident)) { - if (generator.isLocalConstant(m_ident)) - return generator.emitNode(dst, m_right); - - RegisterID* result = generator.emitNode(local, m_right); - return generator.moveToDestinationIfNeeded(dst, result); - } - - int index = 0; - size_t depth = 0; - JSObject* globalObject = 0; - if (generator.findScopedProperty(m_ident, index, depth, true, globalObject) && index != missingSymbolMarker()) { - if (dst == generator.ignoredResult()) - dst = 0; - RegisterID* value = generator.emitNode(dst, m_right); - generator.emitPutScopedVar(depth, index, value, globalObject); - return value; - } - - RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); - if (dst == generator.ignoredResult()) - dst = 0; - RegisterID* value = generator.emitNode(dst, m_right); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitPutById(base.get(), m_ident, value); -} - -// ------------------------------ AssignDotNode ----------------------------------- - -RegisterID* AssignDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); - RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); - RegisterID* result = generator.emitNode(value.get(), m_right); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutById(base.get(), m_ident, result); - return generator.moveToDestinationIfNeeded(dst, result); -} - -// ------------------------------ ReadModifyDotNode ----------------------------------- - -RegisterID* ReadModifyDotNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_rightHasAssignments, m_right->isPure(generator)); - - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr<RegisterID> value = generator.emitGetById(generator.tempDestination(dst), base.get(), m_ident); - RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - return generator.emitPutById(base.get(), m_ident, updatedValue); -} - -// ------------------------------ AssignErrorNode ----------------------------------- - -RegisterID* AssignErrorNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) -{ - return emitThrowError(generator, ReferenceError, "Left side of assignment is not a reference."); -} - -// ------------------------------ AssignBracketNode ----------------------------------- - -RegisterID* AssignBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); - RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); - RefPtr<RegisterID> value = generator.destinationForAssignResult(dst); - RegisterID* result = generator.emitNode(value.get(), m_right); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutByVal(base.get(), property.get(), result); - return generator.moveToDestinationIfNeeded(dst, result); -} - -// ------------------------------ ReadModifyBracketNode ----------------------------------- - -RegisterID* ReadModifyBracketNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<RegisterID> base = generator.emitNodeForLeftHandSide(m_base, m_subscriptHasAssignments || m_rightHasAssignments, m_subscript->isPure(generator) && m_right->isPure(generator)); - RefPtr<RegisterID> property = generator.emitNodeForLeftHandSide(m_subscript, m_rightHasAssignments, m_right->isPure(generator)); - - generator.emitExpressionInfo(divot() - m_subexpressionDivotOffset, startOffset() - m_subexpressionDivotOffset, m_subexpressionEndOffset); - RefPtr<RegisterID> value = generator.emitGetByVal(generator.tempDestination(dst), base.get(), property.get()); - RegisterID* updatedValue = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor())); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutByVal(base.get(), property.get(), updatedValue); - - return updatedValue; -} - -// ------------------------------ CommaNode ------------------------------------ - -RegisterID* CommaNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - ASSERT(m_expressions.size() > 1); - for (size_t i = 0; i < m_expressions.size() - 1; i++) - generator.emitNode(generator.ignoredResult(), m_expressions[i]); - return generator.emitNode(dst, m_expressions.last()); -} - -// ------------------------------ ConstDeclNode ------------------------------------ - -RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator) -{ - if (RegisterID* local = generator.constRegisterFor(m_ident)) { - if (!m_init) - return local; - - return generator.emitNode(local, m_init); - } - - if (generator.codeType() != EvalCode) { - if (m_init) - return generator.emitNode(m_init); - else - return generator.emitResolve(generator.newTemporary(), m_ident); - } - // FIXME: While this code should only be hit in eval code, it will potentially - // assign to the wrong base if m_ident exists in an intervening dynamic scope. - RefPtr<RegisterID> base = generator.emitResolveBase(generator.newTemporary(), m_ident); - RegisterID* value = m_init ? generator.emitNode(m_init) : generator.emitLoad(0, jsUndefined()); - return generator.emitPutById(base.get(), m_ident, value); -} - -RegisterID* ConstDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) -{ - RegisterID* result = 0; - for (ConstDeclNode* n = this; n; n = n->m_next) - result = n->emitCodeSingle(generator); - - return result; -} - -// ------------------------------ ConstStatementNode ----------------------------- - -RegisterID* ConstStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - return generator.emitNode(m_next); -} - -// ------------------------------ SourceElements ------------------------------- - -inline void SourceElements::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - size_t size = m_statements.size(); - for (size_t i = 0; i < size; ++i) - generator.emitNode(dst, m_statements[i]); -} - -// ------------------------------ BlockNode ------------------------------------ - -inline StatementNode* BlockNode::lastStatement() const -{ - return m_statements ? m_statements->lastStatement() : 0; -} - -RegisterID* BlockNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (m_statements) - m_statements->emitBytecode(generator, dst); - return 0; -} - -// ------------------------------ EmptyStatementNode --------------------------- - -RegisterID* EmptyStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - return dst; -} - -// ------------------------------ DebuggerStatementNode --------------------------- - -RegisterID* DebuggerStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(DidReachBreakpoint, firstLine(), lastLine(), column()); - return dst; -} - -// ------------------------------ ExprStatementNode ---------------------------- - -RegisterID* ExprStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - ASSERT(m_expr); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - return generator.emitNode(dst, m_expr); -} - -// ------------------------------ VarStatementNode ---------------------------- - -RegisterID* VarStatementNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) -{ - ASSERT(m_expr); - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - return generator.emitNode(m_expr); -} - -// ------------------------------ IfNode --------------------------------------- - -RegisterID* IfNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - RefPtr<Label> afterThen = generator.newLabel(); - - RegisterID* cond = generator.emitNode(m_condition); - generator.emitJumpIfFalse(cond, afterThen.get()); - - generator.emitNode(dst, m_ifBlock); - generator.emitLabel(afterThen.get()); - - // FIXME: This should return the last statement executed so that it can be returned as a Completion. - return 0; -} - -// ------------------------------ IfElseNode --------------------------------------- - -RegisterID* IfElseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - RefPtr<Label> beforeElse = generator.newLabel(); - RefPtr<Label> afterElse = generator.newLabel(); - - RegisterID* cond = generator.emitNode(m_condition); - generator.emitJumpIfFalse(cond, beforeElse.get()); - - generator.emitNode(dst, m_ifBlock); - generator.emitJump(afterElse.get()); - - generator.emitLabel(beforeElse.get()); - - generator.emitNode(dst, m_elseBlock); - - generator.emitLabel(afterElse.get()); - - // FIXME: This should return the last statement executed so that it can be returned as a Completion. - return 0; -} - -// ------------------------------ DoWhileNode ---------------------------------- - -RegisterID* DoWhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); - - RefPtr<Label> topOfLoop = generator.newLabel(); - generator.emitLabel(topOfLoop.get()); - - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); - - generator.emitLabel(scope->continueTarget()); -#ifndef QT_BUILD_SCRIPT_LIB - generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), column()); -#endif - RegisterID* cond = generator.emitNode(m_expr); - generator.emitJumpIfTrue(cond, topOfLoop.get()); - - generator.emitLabel(scope->breakTarget()); - return result.get(); -} - -// ------------------------------ WhileNode ------------------------------------ - -RegisterID* WhileNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); -#ifdef QT_BUILD_SCRIPT_LIB - generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), column()); -#endif - generator.emitJump(scope->continueTarget()); - - RefPtr<Label> topOfLoop = generator.newLabel(); - generator.emitLabel(topOfLoop.get()); - - generator.emitNode(dst, m_statement); - - generator.emitLabel(scope->continueTarget()); -#ifndef QT_BUILD_SCRIPT_LIB - generator.emitDebugHook(WillExecuteStatement, m_expr->lineNo(), m_expr->lineNo(), column()); -#endif - RegisterID* cond = generator.emitNode(m_expr); - generator.emitJumpIfTrue(cond, topOfLoop.get()); - - generator.emitLabel(scope->breakTarget()); - - // FIXME: This should return the last statement executed so that it can be returned as a Completion - return 0; -} - -// ------------------------------ ForNode -------------------------------------- - -RegisterID* ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); - - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - if (m_expr1) - generator.emitNode(generator.ignoredResult(), m_expr1); - - RefPtr<Label> condition = generator.newLabel(); - generator.emitJump(condition.get()); - - RefPtr<Label> topOfLoop = generator.newLabel(); - generator.emitLabel(topOfLoop.get()); - - RefPtr<RegisterID> result = generator.emitNode(dst, m_statement); - - generator.emitLabel(scope->continueTarget()); -#ifndef QT_BUILD_SCRIPT_LIB - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); -#endif - if (m_expr3) - generator.emitNode(generator.ignoredResult(), m_expr3); - - generator.emitLabel(condition.get()); - if (m_expr2) { - RegisterID* cond = generator.emitNode(m_expr2); - generator.emitJumpIfTrue(cond, topOfLoop.get()); - } else - generator.emitJump(topOfLoop.get()); - - generator.emitLabel(scope->breakTarget()); - return result.get(); -} - -// ------------------------------ ForInNode ------------------------------------ - -RegisterID* ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Loop); - - if (!m_lexpr->isLocation()) - return emitThrowError(generator, ReferenceError, "Left side of for-in statement is not a reference."); - - RefPtr<Label> continueTarget = generator.newLabel(); - - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - if (m_init) - generator.emitNode(generator.ignoredResult(), m_init); - RegisterID* forInBase = generator.emitNode(m_expr); - RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), forInBase); - generator.emitJump(scope->continueTarget()); - - RefPtr<Label> loopStart = generator.newLabel(); - generator.emitLabel(loopStart.get()); - - RegisterID* propertyName; - if (m_lexpr->isResolveNode()) { - const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier(); - propertyName = generator.registerFor(ident); - if (!propertyName) { - propertyName = generator.newTemporary(); - RefPtr<RegisterID> protect = propertyName; - RegisterID* base = generator.emitResolveBase(generator.newTemporary(), ident); - - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitPutById(base, ident, propertyName); - } - } else if (m_lexpr->isDotAccessorNode()) { - DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr); - const Identifier& ident = assignNode->identifier(); - propertyName = generator.newTemporary(); - RefPtr<RegisterID> protect = propertyName; - RegisterID* base = generator.emitNode(assignNode->base()); - - generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset()); - generator.emitPutById(base, ident, propertyName); - } else { - ASSERT(m_lexpr->isBracketAccessorNode()); - BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr); - propertyName = generator.newTemporary(); - RefPtr<RegisterID> protect = propertyName; - RefPtr<RegisterID> base = generator.emitNode(assignNode->base()); - RegisterID* subscript = generator.emitNode(assignNode->subscript()); - - generator.emitExpressionInfo(assignNode->divot(), assignNode->startOffset(), assignNode->endOffset()); - generator.emitPutByVal(base.get(), subscript, propertyName); - } - - generator.emitNode(dst, m_statement); - - generator.emitLabel(scope->continueTarget()); - generator.emitNextPropertyName(propertyName, iter.get(), loopStart.get()); -#ifndef QT_BUILD_SCRIPT_LIB - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); -#endif - generator.emitLabel(scope->breakTarget()); - return dst; -} - -// ------------------------------ ContinueNode --------------------------------- - -// ECMA 12.7 -RegisterID* ContinueNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - LabelScope* scope = generator.continueTarget(m_ident); - - if (!scope) - return m_ident.isEmpty() - ? emitThrowError(generator, SyntaxError, "Invalid continue statement.") - : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident); - - generator.emitJumpScopes(scope->continueTarget(), scope->scopeDepth()); - return dst; -} - -// ------------------------------ BreakNode ------------------------------------ - -// ECMA 12.8 -RegisterID* BreakNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - LabelScope* scope = generator.breakTarget(m_ident); - - if (!scope) - return m_ident.isEmpty() - ? emitThrowError(generator, SyntaxError, "Invalid break statement.") - : emitThrowError(generator, SyntaxError, "Undefined label: '%s'.", m_ident); - - generator.emitJumpScopes(scope->breakTarget(), scope->scopeDepth()); - return dst; -} - -// ------------------------------ ReturnNode ----------------------------------- - -RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - if (generator.codeType() != FunctionCode) - return emitThrowError(generator, SyntaxError, "Invalid return statement."); - - if (dst == generator.ignoredResult()) - dst = 0; - RegisterID* r0 = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined()); - RefPtr<RegisterID> returnRegister; - if (generator.scopeDepth()) { - RefPtr<Label> l0 = generator.newLabel(); - if (generator.hasFinaliser() && !r0->isTemporary()) { - returnRegister = generator.emitMove(generator.newTemporary(), r0); - r0 = returnRegister.get(); - } - generator.emitJumpScopes(l0.get(), 0); - generator.emitLabel(l0.get()); - } - generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine(), column()); - return generator.emitReturn(r0); -} - -// ------------------------------ WithNode ------------------------------------- - -RegisterID* WithNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - RefPtr<RegisterID> scope = generator.newTemporary(); - generator.emitNode(scope.get(), m_expr); // scope must be protected until popped - generator.emitExpressionInfo(m_divot, m_expressionLength, 0); - generator.emitPushScope(scope.get()); - RegisterID* result = generator.emitNode(dst, m_statement); - generator.emitPopScope(); - return result; -} - -// ------------------------------ CaseClauseNode -------------------------------- - -inline void CaseClauseNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (m_statements) - m_statements->emitBytecode(generator, dst); -} - -// ------------------------------ CaseBlockNode -------------------------------- - -enum SwitchKind { - SwitchUnset = 0, - SwitchNumber = 1, - SwitchString = 2, - SwitchNeither = 3 -}; - -static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& literalVector, SwitchKind& typeForTable, bool& singleCharacterSwitch, int32_t& min_num, int32_t& max_num) -{ - for (; list; list = list->getNext()) { - ExpressionNode* clauseExpression = list->getClause()->expr(); - literalVector.append(clauseExpression); - if (clauseExpression->isNumber()) { - double value = static_cast<NumberNode*>(clauseExpression)->value(); - int32_t intVal = static_cast<int32_t>(value); - if ((typeForTable & ~SwitchNumber) || (intVal != value)) { - typeForTable = SwitchNeither; - break; - } - if (intVal < min_num) - min_num = intVal; - if (intVal > max_num) - max_num = intVal; - typeForTable = SwitchNumber; - continue; - } - if (clauseExpression->isString()) { - if (typeForTable & ~SwitchString) { - typeForTable = SwitchNeither; - break; - } - const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring(); - if (singleCharacterSwitch &= value.size() == 1) { - int32_t intVal = value.rep()->data()[0]; - if (intVal < min_num) - min_num = intVal; - if (intVal > max_num) - max_num = intVal; - } - typeForTable = SwitchString; - continue; - } - typeForTable = SwitchNeither; - break; - } -} - -SwitchInfo::SwitchType CaseBlockNode::tryOptimizedSwitch(Vector<ExpressionNode*, 8>& literalVector, int32_t& min_num, int32_t& max_num) -{ - SwitchKind typeForTable = SwitchUnset; - bool singleCharacterSwitch = true; - - processClauseList(m_list1, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); - processClauseList(m_list2, literalVector, typeForTable, singleCharacterSwitch, min_num, max_num); - - if (typeForTable == SwitchUnset || typeForTable == SwitchNeither) - return SwitchInfo::SwitchNone; - - if (typeForTable == SwitchNumber) { - int32_t range = max_num - min_num; - if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) - return SwitchInfo::SwitchImmediate; - return SwitchInfo::SwitchNone; - } - - ASSERT(typeForTable == SwitchString); - - if (singleCharacterSwitch) { - int32_t range = max_num - min_num; - if (min_num <= max_num && range <= 1000 && (range / literalVector.size()) < 10) - return SwitchInfo::SwitchCharacter; - } - - return SwitchInfo::SwitchString; -} - -RegisterID* CaseBlockNode::emitBytecodeForBlock(BytecodeGenerator& generator, RegisterID* switchExpression, RegisterID* dst) -{ - RefPtr<Label> defaultLabel; - Vector<RefPtr<Label>, 8> labelVector; - Vector<ExpressionNode*, 8> literalVector; - int32_t min_num = std::numeric_limits<int32_t>::max(); - int32_t max_num = std::numeric_limits<int32_t>::min(); - SwitchInfo::SwitchType switchType = tryOptimizedSwitch(literalVector, min_num, max_num); - - if (switchType != SwitchInfo::SwitchNone) { - // Prepare the various labels - for (uint32_t i = 0; i < literalVector.size(); i++) - labelVector.append(generator.newLabel()); - defaultLabel = generator.newLabel(); - generator.beginSwitch(switchExpression, switchType); - } else { - // Setup jumps - for (ClauseListNode* list = m_list1; list; list = list->getNext()) { - RefPtr<RegisterID> clauseVal = generator.newTemporary(); - generator.emitNode(clauseVal.get(), list->getClause()->expr()); - generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); - labelVector.append(generator.newLabel()); - generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); - } - - for (ClauseListNode* list = m_list2; list; list = list->getNext()) { - RefPtr<RegisterID> clauseVal = generator.newTemporary(); - generator.emitNode(clauseVal.get(), list->getClause()->expr()); - generator.emitBinaryOp(op_stricteq, clauseVal.get(), clauseVal.get(), switchExpression, OperandTypes()); - labelVector.append(generator.newLabel()); - generator.emitJumpIfTrue(clauseVal.get(), labelVector[labelVector.size() - 1].get()); - } - defaultLabel = generator.newLabel(); - generator.emitJump(defaultLabel.get()); - } - - RegisterID* result = 0; - - size_t i = 0; - for (ClauseListNode* list = m_list1; list; list = list->getNext()) { - generator.emitLabel(labelVector[i++].get()); - list->getClause()->emitBytecode(generator, dst); - } - - if (m_defaultClause) { - generator.emitLabel(defaultLabel.get()); - m_defaultClause->emitBytecode(generator, dst); - } - - for (ClauseListNode* list = m_list2; list; list = list->getNext()) { - generator.emitLabel(labelVector[i++].get()); - list->getClause()->emitBytecode(generator, dst); - } - if (!m_defaultClause) - generator.emitLabel(defaultLabel.get()); - - ASSERT(i == labelVector.size()); - if (switchType != SwitchInfo::SwitchNone) { - ASSERT(labelVector.size() == literalVector.size()); - generator.endSwitch(labelVector.size(), labelVector.data(), literalVector.data(), defaultLabel.get(), min_num, max_num); - } - return result; -} - -// ------------------------------ SwitchNode ----------------------------------- - -RegisterID* SwitchNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::Switch); - - RefPtr<RegisterID> r0 = generator.emitNode(m_expr); - RegisterID* r1 = m_block->emitBytecodeForBlock(generator, r0.get(), dst); - - generator.emitLabel(scope->breakTarget()); - return r1; -} - -// ------------------------------ LabelNode ------------------------------------ - -RegisterID* LabelNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - if (generator.breakTarget(m_name)) - return emitThrowError(generator, SyntaxError, "Duplicate label: %s.", m_name); - - RefPtr<LabelScope> scope = generator.newLabelScope(LabelScope::NamedLabel, &m_name); - RegisterID* r0 = generator.emitNode(dst, m_statement); - - generator.emitLabel(scope->breakTarget()); - return r0; -} - -// ------------------------------ ThrowNode ------------------------------------ - -RegisterID* ThrowNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); - - if (dst == generator.ignoredResult()) - dst = 0; - RefPtr<RegisterID> expr = generator.emitNode(m_expr); - generator.emitExpressionInfo(divot(), startOffset(), endOffset()); - generator.emitThrow(expr.get()); - return 0; -} - -// ------------------------------ TryNode -------------------------------------- - -RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - // NOTE: The catch and finally blocks must be labeled explicitly, so the - // optimizer knows they may be jumped to from anywhere. - -#ifndef QT_BUILD_SCRIPT_LIB - generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine(), column()); -#endif - - RefPtr<Label> tryStartLabel = generator.newLabel(); - RefPtr<Label> finallyStart; - RefPtr<RegisterID> finallyReturnAddr; - if (m_finallyBlock) { - finallyStart = generator.newLabel(); - finallyReturnAddr = generator.newTemporary(); - generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get()); - } - - generator.emitLabel(tryStartLabel.get()); - generator.emitNode(dst, m_tryBlock); - - if (m_catchBlock) { - RefPtr<Label> catchEndLabel = generator.newLabel(); - - // Normal path: jump over the catch block. - generator.emitJump(catchEndLabel.get()); - - // Uncaught exception path: the catch block. - RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); - RefPtr<RegisterID> exceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get()); - if (m_catchHasEval) { - RefPtr<RegisterID> dynamicScopeObject = generator.emitNewObject(generator.newTemporary()); - generator.emitPutById(dynamicScopeObject.get(), m_exceptionIdent, exceptionRegister.get()); - generator.emitMove(exceptionRegister.get(), dynamicScopeObject.get()); - generator.emitPushScope(exceptionRegister.get()); - } else - generator.emitPushNewScope(exceptionRegister.get(), m_exceptionIdent, exceptionRegister.get()); - generator.emitNode(dst, m_catchBlock); - generator.emitPopScope(); - generator.emitLabel(catchEndLabel.get()); - } - - if (m_finallyBlock) { - generator.popFinallyContext(); - // there may be important registers live at the time we jump - // to a finally block (such as for a return or throw) so we - // ref the highest register ever used as a conservative - // approach to not clobbering anything important - RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister(); - RefPtr<Label> finallyEndLabel = generator.newLabel(); - - // Normal path: invoke the finally block, then jump over it. - generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); - generator.emitJump(finallyEndLabel.get()); - - // Uncaught exception path: invoke the finally block, then re-throw the exception. - RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); - RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get()); - generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); - generator.emitThrow(tempExceptionRegister.get()); - - // The finally block. - generator.emitLabel(finallyStart.get()); - generator.emitNode(dst, m_finallyBlock); - generator.emitSubroutineReturn(finallyReturnAddr.get()); - - generator.emitLabel(finallyEndLabel.get()); - } - - return dst; -} - // -----------------------------ScopeNodeData --------------------------- ScopeNodeData::ScopeNodeData(ParserArena& arena, SourceElements* statements, VarStack* varStack, FunctionStack* funcStack, int numConstants) @@ -1910,12 +104,6 @@ ScopeNode::ScopeNode(JSGlobalData* globalData, const SourceCode& source, SourceE { } -inline void ScopeNode::emitStatementsBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (m_data->m_statements) - m_data->m_statements->emitBytecode(generator, dst); -} - StatementNode* ScopeNode::singleStatement() const { return m_data->m_statements ? m_data->m_statements->singleStatement() : 0; @@ -1939,19 +127,6 @@ PassRefPtr<ProgramNode> ProgramNode::create(JSGlobalData* globalData, SourceElem return node.release(); } -RegisterID* ProgramNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) -{ - generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine(), column()); - - RefPtr<RegisterID> dstRegister = generator.newTemporary(); - generator.emitLoad(dstRegister.get(), jsUndefined()); - emitStatementsBytecode(generator, dstRegister.get()); - - generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine(), column()); - generator.emitEnd(dstRegister.get()); - return 0; -} - // ------------------------------ EvalNode ----------------------------- inline EvalNode::EvalNode(JSGlobalData* globalData, SourceElements* children, VarStack* varStack, FunctionStack* funcStack, const SourceCode& source, CodeFeatures features, int numConstants) @@ -1970,19 +145,6 @@ PassRefPtr<EvalNode> EvalNode::create(JSGlobalData* globalData, SourceElements* return node.release(); } -RegisterID* EvalNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) -{ - generator.emitDebugHook(WillExecuteProgram, firstLine(), lastLine(), column()); - - RefPtr<RegisterID> dstRegister = generator.newTemporary(); - generator.emitLoad(dstRegister.get(), jsUndefined()); - emitStatementsBytecode(generator, dstRegister.get()); - - generator.emitDebugHook(DidExecuteProgram, firstLine(), lastLine(), column()); - generator.emitEnd(dstRegister.get()); - return 0; -} - // ------------------------------ FunctionBodyNode ----------------------------- FunctionParameters::FunctionParameters(ParameterNode* firstParameter) @@ -2001,10 +163,6 @@ inline FunctionBodyNode::FunctionBodyNode(JSGlobalData* globalData, SourceElemen { } -FunctionBodyNode::~FunctionBodyNode() -{ -} - void FunctionBodyNode::finishParsing(const SourceCode& source, ParameterNode* firstParameter, const Identifier& ident) { setSource(source); @@ -2034,37 +192,4 @@ PassRefPtr<FunctionBodyNode> FunctionBodyNode::create(JSGlobalData* globalData, return node.release(); } -RegisterID* FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*) -{ - generator.emitDebugHook(DidEnterCallFrame, firstLine(), lastLine(), column()); - emitStatementsBytecode(generator, generator.ignoredResult()); - StatementNode* singleStatement = this->singleStatement(); - if (singleStatement && singleStatement->isBlock()) { - StatementNode* lastStatementInBlock = static_cast<BlockNode*>(singleStatement)->lastStatement(); - if (lastStatementInBlock && lastStatementInBlock->isReturnNode()) - return 0; - } - - RegisterID* r0 = generator.emitLoad(0, jsUndefined()); - generator.emitDebugHook(WillLeaveCallFrame, firstLine(), lastLine(), column()); - generator.emitReturn(r0); - return 0; -} - -// ------------------------------ FuncDeclNode --------------------------------- - -RegisterID* FuncDeclNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - if (dst == generator.ignoredResult()) - dst = 0; - return dst; -} - -// ------------------------------ FuncExprNode --------------------------------- - -RegisterID* FuncExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) -{ - return generator.emitNewFunctionExpression(generator.finalDestination(dst), this); -} - } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.h index 2f8d850..c216ea8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Nodes.h @@ -40,6 +40,7 @@ namespace JSC { class ArgumentListNode; class BytecodeGenerator; class FunctionBodyNode; + class Label; class PropertyListNode; class ReadModifyResolveNode; class RegisterID; @@ -151,6 +152,9 @@ namespace JSC { virtual bool isCommaNode() const { return false; } virtual bool isSimpleArray() const { return false; } virtual bool isAdd() const { return false; } + virtual bool hasConditionContextCodegen() const { return false; } + + virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label*, Label*, bool) { ASSERT_NOT_REACHED(); } virtual ExpressionNode* stripUnaryPlus() { return this; } @@ -165,10 +169,9 @@ namespace JSC { StatementNode(JSGlobalData*); public: - void setLoc(int firstLine, int lastLine, int column); + void setLoc(int firstLine, int lastLine); int firstLine() const { return lineNo(); } int lastLine() const { return m_lastLine; } - int column() const { return m_column; } virtual bool isEmptyStatement() const { return false; } virtual bool isReturnNode() const { return false; } @@ -178,7 +181,6 @@ namespace JSC { private: int m_lastLine; - int m_column; }; class NullNode : public ExpressionNode { @@ -759,6 +761,7 @@ namespace JSC { protected: ExpressionNode* expr() { return m_expr; } + const ExpressionNode* expr() const { return m_expr; } private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); @@ -790,6 +793,9 @@ namespace JSC { class LogicalNotNode : public UnaryOpNode { public: LogicalNotNode(JSGlobalData*, ExpressionNode*); + private: + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); + virtual bool hasConditionContextCodegen() const { return expr()->hasConditionContextCodegen(); } }; class BinaryOpNode : public ExpressionNode { @@ -954,6 +960,8 @@ namespace JSC { private: virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0); + void emitBytecodeInConditionContext(BytecodeGenerator&, Label* trueTarget, Label* falseTarget, bool fallThroughMeansTrue); + virtual bool hasConditionContextCodegen() const { return true; } ExpressionNode* m_expr1; ExpressionNode* m_expr2; @@ -1460,8 +1468,6 @@ namespace JSC { static FunctionBodyNode* create(JSGlobalData*); static PassRefPtr<FunctionBodyNode> create(JSGlobalData*, SourceElements*, VarStack*, FunctionStack*, const SourceCode&, CodeFeatures, int numConstants); - virtual ~FunctionBodyNode(); - FunctionParameters* parameters() const { return m_parameters.get(); } size_t parameterCount() const { return m_parameters->size(); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Parser.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Parser.h index 7f20480..894f709 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/Parser.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/Parser.h @@ -83,8 +83,7 @@ namespace JSC { source, m_features, m_numConstants); - int column = m_source->startOffset(); //is it good way to find column number? - result->setLoc(m_source->firstLine(), m_lastLine, column); + result->setLoc(m_source->firstLine(), m_lastLine); } m_arena.reset(); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/ParserArena.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/ParserArena.h index 2fd4fc1..eef8e93 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/ParserArena.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/ParserArena.h @@ -34,7 +34,7 @@ namespace JSC { class ParserArenaDeletable; class ParserArenaRefCounted; - class IdentifierArena { + class IdentifierArena : public FastAllocBase { public: ALWAYS_INLINE const Identifier& makeIdentifier(JSGlobalData*, const UChar* characters, size_t length); const Identifier& makeNumericIdentifier(JSGlobalData*, double number); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/parser/SourceCode.h b/src/3rdparty/javascriptcore/JavaScriptCore/parser/SourceCode.h index 305b804..bef8e78 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/parser/SourceCode.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/parser/SourceCode.h @@ -37,7 +37,8 @@ namespace JSC { class SourceCode { public: SourceCode() - : m_startChar(0) + : m_provider(0) + , m_startChar(0) , m_endChar(0) , m_firstLine(0) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/pcre/dftables b/src/3rdparty/javascriptcore/JavaScriptCore/pcre/dftables index 1f0ea01..669b948 100755 --- a/src/3rdparty/javascriptcore/JavaScriptCore/pcre/dftables +++ b/src/3rdparty/javascriptcore/JavaScriptCore/pcre/dftables @@ -269,4 +269,5 @@ sub readHeaderValues() eval $content; die "$@" if $@; + unlink $tempFile; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/pcre/pcre.pri b/src/3rdparty/javascriptcore/JavaScriptCore/pcre/pcre.pri index c33c67c..4f59e17 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/pcre/pcre.pri +++ b/src/3rdparty/javascriptcore/JavaScriptCore/pcre/pcre.pri @@ -3,8 +3,6 @@ VPATH += $$PWD INCLUDEPATH += $$PWD $$OUTPUT_DIR/JavaScriptCore/tmp DEPENDPATH += $$PWD -isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp - SOURCES += \ pcre_compile.cpp \ pcre_exec.cpp \ @@ -12,24 +10,3 @@ SOURCES += \ pcre_ucp_searchfuncs.cpp \ pcre_xclass.cpp -!CONFIG(QTDIR_build) { - defineTest(addExtraCompiler) { - QMAKE_EXTRA_COMPILERS += $$1 - generated_files.depends += compiler_$${1}_make_all - export(QMAKE_EXTRA_COMPILERS) - export(generated_files.depends) - return(true) - } -} - -# GENERATOR: "chartables.c": compile and execute the chartables generator (and add it to sources) -win32-msvc*|wince*: PREPROCESSOR = "--preprocessor=\"$$QMAKE_CC /E\"" -DFTABLES = $$PWD/dftables -ctgen.input = DFTABLES -ctgen.output = $$GENERATED_SOURCES_DIR/chartables.c -ctgen.commands = perl $$DFTABLES ${QMAKE_FILE_OUT} $$PREPROCESSOR -ctgen.CONFIG += target_predeps no_link -ctgen.variable_out = GENERATED_SOURCES -ctgen.dependency_type = TYPE_C -ctgen.clean = ${QMAKE_FILE_OUT} ${QMAKE_VAR_GENERATED_SOURCES_DIR}${QMAKE_FILE_BASE} -addExtraCompiler(ctgen) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/pcre/pcre_exec.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/pcre/pcre_exec.cpp index 16619d4..8ca2eb4 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/pcre/pcre_exec.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/pcre/pcre_exec.cpp @@ -2164,14 +2164,14 @@ void Histogram::add(const JSRegExp* re, double elapsedTime) HistogramTimeLogger::HistogramTimeLogger(const JSRegExp* re) : m_re(re) - , m_startTime(getCurrentUTCTimeWithMicroseconds()) + , m_startTime(currentTimeMS()) { } HistogramTimeLogger::~HistogramTimeLogger() { static Histogram histogram; - histogram.add(m_re, getCurrentUTCTimeWithMicroseconds() - m_startTime); + histogram.add(m_re, currentTimeMS() - m_startTime); } #endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/HeavyProfile.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/HeavyProfile.cpp deleted file mode 100644 index e69de29..0000000 --- a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/HeavyProfile.cpp +++ /dev/null diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/HeavyProfile.h b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/HeavyProfile.h deleted file mode 100644 index e69de29..0000000 --- a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/HeavyProfile.h +++ /dev/null diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/ProfileGenerator.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/ProfileGenerator.cpp index dc68ecb..17d37d7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/ProfileGenerator.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/ProfileGenerator.cpp @@ -63,7 +63,7 @@ void ProfileGenerator::addParentForConsoleStart(ExecState* exec) JSValue function; exec->interpreter()->retrieveLastCaller(exec, lineNumber, sourceID, sourceURL, function); - m_currentNode = ProfileNode::create(Profiler::createCallIdentifier(&exec->globalData(), function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get()); + m_currentNode = ProfileNode::create(Profiler::createCallIdentifier(exec, function ? function.toThisObject(exec) : 0, sourceURL, lineNumber), m_head.get(), m_head.get()); m_head->insertNode(m_currentNode.get()); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/ProfileNode.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/ProfileNode.cpp index 19050aa..fb126b3 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/ProfileNode.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/ProfileNode.cpp @@ -33,15 +33,17 @@ #include <stdio.h> #include <wtf/DateMath.h> -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #include <windows.h> #endif +using namespace WTF; + namespace JSC { static double getCount() { -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) static LARGE_INTEGER frequency = {0}; if (!frequency.QuadPart) QueryPerformanceFrequency(&frequency); @@ -49,7 +51,7 @@ static double getCount() QueryPerformanceCounter(&counter); return static_cast<double>(counter.QuadPart) / frequency.QuadPart; #else - return WTF::getCurrentUTCTimeWithMicroseconds(); + return currentTimeMS(); #endif } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/Profiler.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/Profiler.cpp index 6f72e08..fe8727a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/Profiler.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/Profiler.cpp @@ -46,7 +46,7 @@ static const char* GlobalCodeExecution = "(program)"; static const char* AnonymousFunction = "(anonymous function)"; static unsigned ProfilesUID = 0; -static CallIdentifier createCallIdentifierFromFunctionImp(JSGlobalData*, JSFunction*); +static CallIdentifier createCallIdentifierFromFunctionImp(ExecState*, JSFunction*); Profiler* Profiler::s_sharedProfiler = 0; Profiler* Profiler::s_sharedEnabledProfilerReference = 0; @@ -109,14 +109,14 @@ void Profiler::willExecute(ExecState* exec, JSValue function) { ASSERT(!m_currentProfiles.isEmpty()); - dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(&exec->globalData(), function, "", 0), exec->lexicalGlobalObject()->profileGroup()); + dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup()); } void Profiler::willExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber) { ASSERT(!m_currentProfiles.isEmpty()); - CallIdentifier callIdentifier = createCallIdentifier(&exec->globalData(), JSValue(), sourceURL, startingLineNumber); + CallIdentifier callIdentifier = createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber); dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::willExecute, callIdentifier, exec->lexicalGlobalObject()->profileGroup()); } @@ -125,17 +125,17 @@ void Profiler::didExecute(ExecState* exec, JSValue function) { ASSERT(!m_currentProfiles.isEmpty()); - dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), function, "", 0), exec->lexicalGlobalObject()->profileGroup()); + dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, function, "", 0), exec->lexicalGlobalObject()->profileGroup()); } void Profiler::didExecute(ExecState* exec, const UString& sourceURL, int startingLineNumber) { ASSERT(!m_currentProfiles.isEmpty()); - dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(&exec->globalData(), JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup()); + dispatchFunctionToProfiles(m_currentProfiles, &ProfileGenerator::didExecute, createCallIdentifier(exec, JSValue(), sourceURL, startingLineNumber), exec->lexicalGlobalObject()->profileGroup()); } -CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber) +CallIdentifier Profiler::createCallIdentifier(ExecState* exec, JSValue functionValue, const UString& defaultSourceURL, int defaultLineNumber) { if (!functionValue) return CallIdentifier(GlobalCodeExecution, defaultSourceURL, defaultLineNumber); @@ -144,17 +144,17 @@ CallIdentifier Profiler::createCallIdentifier(JSGlobalData* globalData, JSValue if (asObject(functionValue)->inherits(&JSFunction::info)) { JSFunction* function = asFunction(functionValue); if (!function->executable()->isHostFunction()) - return createCallIdentifierFromFunctionImp(globalData, function); + return createCallIdentifierFromFunctionImp(exec, function); } if (asObject(functionValue)->inherits(&InternalFunction::info)) - return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(globalData), defaultSourceURL, defaultLineNumber); - return CallIdentifier("(" + asObject(functionValue)->className() + " object)", defaultSourceURL, defaultLineNumber); + return CallIdentifier(static_cast<InternalFunction*>(asObject(functionValue))->name(exec), defaultSourceURL, defaultLineNumber); + return CallIdentifier(makeString("(", asObject(functionValue)->className(), " object)"), defaultSourceURL, defaultLineNumber); } -CallIdentifier createCallIdentifierFromFunctionImp(JSGlobalData* globalData, JSFunction* function) +CallIdentifier createCallIdentifierFromFunctionImp(ExecState* exec, JSFunction* function) { ASSERT(!function->isHostFunction()); - const UString& name = function->calculatedDisplayName(globalData); + const UString& name = function->calculatedDisplayName(exec); return CallIdentifier(name.isEmpty() ? AnonymousFunction : name, function->jsExecutable()->sourceURL(), function->jsExecutable()->lineNo()); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/Profiler.h b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/Profiler.h index 21621bf..4b8b4a0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/Profiler.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/Profiler.h @@ -52,7 +52,7 @@ namespace JSC { } static Profiler* profiler(); - static CallIdentifier createCallIdentifier(JSGlobalData*, JSValue, const UString& sourceURL, int lineNumber); + static CallIdentifier createCallIdentifier(ExecState* exec, JSValue, const UString& sourceURL, int lineNumber); void startProfiling(ExecState*, const UString& title); PassRefPtr<Profile> stopProfiling(ExecState*, const UString& title); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/TreeProfile.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/TreeProfile.cpp deleted file mode 100644 index e69de29..0000000 --- a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/TreeProfile.cpp +++ /dev/null diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/TreeProfile.h b/src/3rdparty/javascriptcore/JavaScriptCore/profiler/TreeProfile.h deleted file mode 100644 index e69de29..0000000 --- a/src/3rdparty/javascriptcore/JavaScriptCore/profiler/TreeProfile.h +++ /dev/null diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.h index 3227770..8e1fdbe 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArgList.h @@ -104,7 +104,11 @@ namespace JSC { void append(JSValue v) { ASSERT(!m_isReadOnly); - + +#if ENABLE(JSC_ZOMBIES) + ASSERT(!v.isZombie()); +#endif + if (m_isUsingInlineBuffer && m_size < inlineCapacity) { m_vector.uncheckedAppend(v); ++m_size; @@ -187,6 +191,10 @@ namespace JSC { : m_args(args) , m_argCount(argCount) { +#if ENABLE(JSC_ZOMBIES) + for (size_t i = 0; i < argCount; i++) + ASSERT(!m_args[i].isZombie()); +#endif } ArgList(Register* args, int argCount) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.cpp index d90ea15..bb30e3b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.cpp @@ -204,6 +204,19 @@ bool Arguments::getOwnPropertyDescriptor(ExecState* exec, const Identifier& prop return JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); } +void Arguments::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + if (mode == IncludeDontEnumProperties) { + for (unsigned i = 0; i < d->numArguments; ++i) { + if (!d->deletedArguments || !d->deletedArguments[i]) + propertyNames.add(Identifier(exec, UString::from(i))); + } + propertyNames.add(exec->propertyNames().callee); + propertyNames.add(exec->propertyNames().length); + } + JSObject::getOwnPropertyNames(exec, propertyNames, mode); +} + void Arguments::put(ExecState* exec, unsigned i, JSValue value, PutPropertySlot& slot) { if (i < d->numArguments && (!d->deletedArguments || !d->deletedArguments[i])) { @@ -244,7 +257,7 @@ void Arguments::put(ExecState* exec, const Identifier& propertyName, JSValue val JSObject::put(exec, propertyName, value, slot); } -bool Arguments::deleteProperty(ExecState* exec, unsigned i, bool checkDontDelete) +bool Arguments::deleteProperty(ExecState* exec, unsigned i) { if (i < d->numArguments) { if (!d->deletedArguments) { @@ -257,10 +270,10 @@ bool Arguments::deleteProperty(ExecState* exec, unsigned i, bool checkDontDelete } } - return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i)), checkDontDelete); + return JSObject::deleteProperty(exec, Identifier(exec, UString::from(i))); } -bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) +bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); @@ -285,17 +298,7 @@ bool Arguments::deleteProperty(ExecState* exec, const Identifier& propertyName, return true; } - return JSObject::deleteProperty(exec, propertyName, checkDontDelete); -} - -bool Arguments::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const -{ - if ((propertyName == exec->propertyNames().length) - || (propertyName == exec->propertyNames().callee)) { - attributes = DontEnum; - return true; - } - return JSObject::getPropertyAttributes(exec, propertyName, attributes); + return JSObject::deleteProperty(exec, propertyName); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.h index 2aa0921..d4a8c95 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Arguments.h @@ -85,19 +85,22 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; + private: void getArgumentsData(CallFrame*, JSObject*&, ptrdiff_t& firstParameterIndex, Register*& argv, int& argc); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); - virtual bool deleteProperty(ExecState*, unsigned propertyName, bool checkDontDelete = true); - virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + virtual bool deleteProperty(ExecState*, unsigned propertyName); virtual const ClassInfo* classInfo() const { return &info; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.cpp index c60cb0e..fb44494 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.cpp @@ -37,7 +37,7 @@ ASSERT_CLASS_FITS_IN_CELL(ArrayConstructor); static JSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState*, JSObject*, JSValue, const ArgList&); -ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype, Structure* prototypeFunctionStructure) +ArrayConstructor::ArrayConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ArrayPrototype* arrayPrototype, Structure* prototypeFunctionStructure) : InternalFunction(&exec->globalData(), structure, Identifier(exec, arrayPrototype->classInfo()->className)) { // ECMA 15.4.3.1 Array.prototype @@ -50,7 +50,7 @@ ArrayConstructor::ArrayConstructor(ExecState* exec, PassRefPtr<Structure> struct putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().isArray, arrayConstructorIsArray), DontEnum); } -static JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args) +static inline JSObject* constructArrayWithSizeQuirk(ExecState* exec, const ArgList& args) { // a single numeric argument denotes the array size (!) if (args.size() == 1 && args.at(0).isNumber()) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.h index 2b79510..6d25400 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class ArrayConstructor : public InternalFunction { public: - ArrayConstructor(ExecState*, PassRefPtr<Structure>, ArrayPrototype*, Structure*); + ArrayConstructor(ExecState*, NonNullPassRefPtr<Structure>, ArrayPrototype*, Structure*); virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.cpp index c453b22..ce814b2 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -115,7 +115,7 @@ const ClassInfo ArrayPrototype::info = {"Array", &JSArray::info, 0, ExecState::a */ // ECMA 15.4.4 -ArrayPrototype::ArrayPrototype(PassRefPtr<Structure> structure) +ArrayPrototype::ArrayPrototype(NonNullPassRefPtr<Structure> structure) : JSArray(structure) { } @@ -204,8 +204,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue buffer.append(rep->data(), rep->size()); } ASSERT(buffer.size() == totalSize); - unsigned finalSize = buffer.size(); - return jsString(exec, UString(buffer.releaseBuffer(), finalSize, false)); + return jsString(exec, UString::adopt(buffer)); } JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -745,8 +744,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec, JSObject*, JSValue th cachedCall.setArgument(0, array->getIndex(k)); cachedCall.setArgument(1, jsNumber(exec, k)); cachedCall.setArgument(2, thisObj); - - if (!cachedCall.call().toBoolean(exec)) + JSValue result = cachedCall.call(); + if (!result.toBoolean(cachedCall.newCallFrame(exec))) return jsBoolean(false); } } @@ -846,8 +845,8 @@ JSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec, JSObject*, JSValue thi cachedCall.setArgument(0, array->getIndex(k)); cachedCall.setArgument(1, jsNumber(exec, k)); cachedCall.setArgument(2, thisObj); - - if (cachedCall.call().toBoolean(exec)) + JSValue result = cachedCall.call(); + if (result.toBoolean(cachedCall.newCallFrame(exec))) return jsBoolean(true); } } @@ -1034,7 +1033,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue JSValue e = getProperty(exec, thisObj, index); if (!e) continue; - if (JSValue::strictEqual(searchElement, e)) + if (JSValue::strictEqual(exec, searchElement, e)) return jsNumber(exec, index); } @@ -1065,7 +1064,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSVa JSValue e = getProperty(exec, thisObj, index); if (!e) continue; - if (JSValue::strictEqual(searchElement, e)) + if (JSValue::strictEqual(exec, searchElement, e)) return jsNumber(exec, index); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.h index 6f7ed12..e52914c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ArrayPrototype.h @@ -28,7 +28,7 @@ namespace JSC { class ArrayPrototype : public JSArray { public: - explicit ArrayPrototype(PassRefPtr<Structure>); + explicit ArrayPrototype(NonNullPassRefPtr<Structure>); bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BatchedTransitionOptimizer.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BatchedTransitionOptimizer.h index 929a5e7..74089a5 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BatchedTransitionOptimizer.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BatchedTransitionOptimizer.h @@ -43,7 +43,7 @@ namespace JSC { ~BatchedTransitionOptimizer() { - m_object->setStructure(Structure::fromDictionaryTransition(m_object->structure())); + m_object->flattenDictionaryObject(); } private: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanConstructor.cpp index 9fcba37..b0d8df3 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanConstructor.cpp @@ -28,7 +28,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(BooleanConstructor); -BooleanConstructor::BooleanConstructor(ExecState* exec, PassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype) +BooleanConstructor::BooleanConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, BooleanPrototype* booleanPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, booleanPrototype->classInfo()->className)) { putDirectWithoutTransition(exec->propertyNames().prototype, booleanPrototype, DontEnum | DontDelete | ReadOnly); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanConstructor.h index d9f51ab..1d8a26a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class BooleanConstructor : public InternalFunction { public: - BooleanConstructor(ExecState*, PassRefPtr<Structure>, BooleanPrototype*); + BooleanConstructor(ExecState*, NonNullPassRefPtr<Structure>, BooleanPrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.cpp index 01f695a..c9b3846 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.cpp @@ -27,7 +27,7 @@ ASSERT_CLASS_FITS_IN_CELL(BooleanObject); const ClassInfo BooleanObject::info = { "Boolean", 0, 0, 0 }; -BooleanObject::BooleanObject(PassRefPtr<Structure> structure) +BooleanObject::BooleanObject(NonNullPassRefPtr<Structure> structure) : JSWrapperObject(structure) { } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.h index 5f3e5f0..69c2e51 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanObject.h @@ -27,14 +27,14 @@ namespace JSC { class BooleanObject : public JSWrapperObject { public: - explicit BooleanObject(PassRefPtr<Structure>); + explicit BooleanObject(NonNullPassRefPtr<Structure>); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.cpp index cf4fbd7..8d338f9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.cpp @@ -37,7 +37,7 @@ static JSValue JSC_HOST_CALL booleanProtoFuncValueOf(ExecState*, JSObject*, JSVa // ECMA 15.6.4 -BooleanPrototype::BooleanPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) +BooleanPrototype::BooleanPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) : BooleanObject(structure) { setInternalValue(jsBoolean(false)); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.h index 16f80b5..cc69b3f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/BooleanPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class BooleanPrototype : public BooleanObject { public: - BooleanPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); + BooleanPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure); }; } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CallData.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CallData.h index ef4988b..32e1e52 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CallData.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CallData.h @@ -60,12 +60,12 @@ namespace JSC { } inline operator NativeFunction() const {return ptr;} inline operator bool() const {return ptr;} - + JSValue operator()(ExecState* exec, JSObject* jsobj, JSValue thisValue, const ArgList& argList) const; }; #endif -#if defined(QT_BUILD_SCRIPT_LIB) && PLATFORM(SOLARIS) +#if defined(QT_BUILD_SCRIPT_LIB) && OS(SOLARIS) struct #else union diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp index abe15c8..29df7a5 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.cpp @@ -32,6 +32,7 @@ #include "JSONObject.h" #include "JSString.h" #include "JSValue.h" +#include "JSZombie.h" #include "MarkStack.h" #include "Nodes.h" #include "Tracing.h" @@ -44,7 +45,7 @@ #include <wtf/UnusedParam.h> #include <wtf/VMTags.h> -#if PLATFORM(DARWIN) +#if OS(DARWIN) #include <mach/mach_init.h> #include <mach/mach_port.h> @@ -52,29 +53,29 @@ #include <mach/thread_act.h> #include <mach/vm_map.h> -#elif PLATFORM(SYMBIAN) +#elif OS(SYMBIAN) #include <e32std.h> #include <e32cmn.h> #include <unistd.h> -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) #include <windows.h> #include <malloc.h> -#elif PLATFORM(HAIKU) +#elif OS(HAIKU) #include <OS.h> -#elif PLATFORM(UNIX) +#elif OS(UNIX) #include <stdlib.h> -#if !PLATFORM(HAIKU) +#if !OS(HAIKU) #include <sys/mman.h> #endif #include <unistd.h> -#if PLATFORM(SOLARIS) +#if OS(SOLARIS) #include <thread.h> #else #include <pthread.h> @@ -84,7 +85,7 @@ #include <pthread_np.h> #endif -#if PLATFORM(QNX) +#if OS(QNX) #include <fcntl.h> #include <sys/procfs.h> #include <stdio.h> @@ -103,26 +104,22 @@ namespace JSC { const size_t GROWTH_FACTOR = 2; const size_t LOW_WATER_FACTOR = 4; -const size_t ALLOCATIONS_PER_COLLECTION = 4000; +const size_t ALLOCATIONS_PER_COLLECTION = 3600; // This value has to be a macro to be used in max() without introducing // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. #define MIN_ARRAY_SIZE (static_cast<size_t>(14)) -#if PLATFORM(SYMBIAN) +#if OS(SYMBIAN) const size_t MAX_NUM_BLOCKS = 256; // Max size of collector heap set to 16 MB static RHeap* userChunk = 0; #endif #if ENABLE(JSC_MULTIPLE_THREADS) -#if PLATFORM(DARWIN) +#if OS(DARWIN) typedef mach_port_t PlatformThread; -#elif PLATFORM(WIN_OS) -struct PlatformThread { - PlatformThread(DWORD _id, HANDLE _handle) : id(_id), handle(_handle) {} - DWORD id; - HANDLE handle; -}; +#elif OS(WINDOWS) +typedef HANDLE PlatformThread; #endif class Heap::Thread { @@ -151,8 +148,8 @@ Heap::Heap(JSGlobalData* globalData) , m_globalData(globalData) { ASSERT(globalData); - -#if PLATFORM(SYMBIAN) + +#if OS(SYMBIAN) // Symbian OpenC supports mmap but currently not the MAP_ANON flag. // Using fastMalloc() does not properly align blocks on 64k boundaries // and previous implementation was flawed/incomplete. @@ -170,10 +167,10 @@ Heap::Heap(JSGlobalData* globalData) if (!userChunk) CRASH(); } -#endif // PLATFORM(SYMBIAN) +#endif // OS(SYMBIAN) - memset(&primaryHeap, 0, sizeof(CollectorHeap)); - memset(&numberHeap, 0, sizeof(CollectorHeap)); + memset(&m_heap, 0, sizeof(CollectorHeap)); + allocateBlock(); } Heap::~Heap() @@ -189,6 +186,9 @@ void Heap::destroy() if (!m_globalData) return; + ASSERT(!m_globalData->dynamicGlobalObject); + ASSERT(!isBusy()); + // The global object is not GC protected at this point, so sweeping may delete it // (and thus the global data) before other objects that may use the global data. RefPtr<JSGlobalData> protect(m_globalData); @@ -196,13 +196,7 @@ void Heap::destroy() delete m_markListSet; m_markListSet = 0; - sweep<PrimaryHeap>(); - // No need to sweep number heap, because the JSNumber destructor doesn't do anything. - - ASSERT(!primaryHeap.numLiveObjects); - - freeBlocks(&primaryHeap); - freeBlocks(&numberHeap); + freeBlocks(); #if ENABLE(JSC_MULTIPLE_THREADS) if (m_currentThreadRegistrar) { @@ -221,27 +215,23 @@ void Heap::destroy() m_globalData = 0; } -template <HeapType heapType> NEVER_INLINE CollectorBlock* Heap::allocateBlock() { // Disable the use of vm_map for the Qt build on Darwin, because when compiled on 10.4 // it crashes on 10.5 -#if PLATFORM(DARWIN) && !PLATFORM(QT) +#if OS(DARWIN) && !PLATFORM(QT) vm_address_t address = 0; - // FIXME: tag the region as a JavaScriptCore heap when we get a registered VM tag: <rdar://problem/6054788>. vm_map(current_task(), &address, BLOCK_SIZE, BLOCK_OFFSET_MASK, VM_FLAGS_ANYWHERE | VM_TAG_FOR_COLLECTOR_MEMORY, MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT); -#elif PLATFORM(SYMBIAN) +#elif OS(SYMBIAN) // Allocate a 64 kb aligned CollectorBlock unsigned char* mask = reinterpret_cast<unsigned char*>(userChunk->Alloc(BLOCK_SIZE)); if (!mask) CRASH(); uintptr_t address = reinterpret_cast<uintptr_t>(mask); - - memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE); -#elif PLATFORM(WINCE) +#elif OS(WINCE) void* address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); -#elif PLATFORM(WIN_OS) -#if COMPILER(MINGW) && !PLATFORM(X86_64) +#elif OS(WINDOWS) +#if COMPILER(MINGW) && !CPU(X86_64) void* address = __mingw_aligned_malloc(BLOCK_SIZE, BLOCK_SIZE); #else void* address = _aligned_malloc(BLOCK_SIZE, BLOCK_SIZE); @@ -250,7 +240,6 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock() #elif HAVE(POSIX_MEMALIGN) void* address; posix_memalign(&address, BLOCK_SIZE, BLOCK_SIZE); - memset(address, 0, BLOCK_SIZE); #else #if ENABLE(JSC_MULTIPLE_THREADS) @@ -276,58 +265,66 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock() munmap(reinterpret_cast<char*>(address + adjust + BLOCK_SIZE), extra - adjust); address += adjust; - memset(reinterpret_cast<void*>(address), 0, BLOCK_SIZE); #endif + // Initialize block. + CollectorBlock* block = reinterpret_cast<CollectorBlock*>(address); - block->freeList = block->cells; block->heap = this; - block->type = heapType; + clearMarkBits(block); - CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; - size_t numBlocks = heap.numBlocks; - if (heap.usedBlocks == numBlocks) { + Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get(); + for (size_t i = 0; i < HeapConstants::cellsPerBlock; ++i) + new (block->cells + i) JSCell(dummyMarkableCellStructure); + + // Add block to blocks vector. + + size_t numBlocks = m_heap.numBlocks; + if (m_heap.usedBlocks == numBlocks) { static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR; if (numBlocks > maxNumBlocks) CRASH(); numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR); - heap.numBlocks = numBlocks; - heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*))); + m_heap.numBlocks = numBlocks; + m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, numBlocks * sizeof(CollectorBlock*))); } - heap.blocks[heap.usedBlocks++] = block; + m_heap.blocks[m_heap.usedBlocks++] = block; return block; } -template <HeapType heapType> NEVER_INLINE void Heap::freeBlock(size_t block) { - CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; + m_heap.didShrink = true; - freeBlock(heap.blocks[block]); + ObjectIterator it(m_heap, block); + ObjectIterator end(m_heap, block + 1); + for ( ; it != end; ++it) + (*it)->~JSCell(); + freeBlockPtr(m_heap.blocks[block]); // swap with the last block so we compact as we go - heap.blocks[block] = heap.blocks[heap.usedBlocks - 1]; - heap.usedBlocks--; + m_heap.blocks[block] = m_heap.blocks[m_heap.usedBlocks - 1]; + m_heap.usedBlocks--; - if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) { - heap.numBlocks = heap.numBlocks / GROWTH_FACTOR; - heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*))); + if (m_heap.numBlocks > MIN_ARRAY_SIZE && m_heap.usedBlocks < m_heap.numBlocks / LOW_WATER_FACTOR) { + m_heap.numBlocks = m_heap.numBlocks / GROWTH_FACTOR; + m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(CollectorBlock*))); } } -NEVER_INLINE void Heap::freeBlock(CollectorBlock* block) +NEVER_INLINE void Heap::freeBlockPtr(CollectorBlock* block) { // Disable the use of vm_deallocate for the Qt build on Darwin, because when compiled on 10.4 // it crashes on 10.5 -#if PLATFORM(DARWIN) && !PLATFORM(QT) +#if OS(DARWIN) && !PLATFORM(QT) vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE); -#elif PLATFORM(SYMBIAN) +#elif OS(SYMBIAN) userChunk->Free(reinterpret_cast<TAny*>(block)); -#elif PLATFORM(WINCE) +#elif OS(WINCE) VirtualFree(block, 0, MEM_RELEASE); -#elif PLATFORM(WIN_OS) -#if COMPILER(MINGW) && !PLATFORM(X86_64) +#elif OS(WINDOWS) +#if COMPILER(MINGW) && !CPU(X86_64) __mingw_aligned_free(block); #else _aligned_free(block); @@ -339,13 +336,34 @@ NEVER_INLINE void Heap::freeBlock(CollectorBlock* block) #endif } -void Heap::freeBlocks(CollectorHeap* heap) +void Heap::freeBlocks() { - for (size_t i = 0; i < heap->usedBlocks; ++i) - if (heap->blocks[i]) - freeBlock(heap->blocks[i]); - fastFree(heap->blocks); - memset(heap, 0, sizeof(CollectorHeap)); + ProtectCountSet protectedValuesCopy = m_protectedValues; + + clearMarkBits(); + ProtectCountSet::iterator protectedValuesEnd = protectedValuesCopy.end(); + for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it) + markCell(it->first); + + m_heap.nextCell = 0; + m_heap.nextBlock = 0; + DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell); + DeadObjectIterator end(m_heap, m_heap.usedBlocks); + for ( ; it != end; ++it) + (*it)->~JSCell(); + + ASSERT(!protectedObjectCount()); + + protectedValuesEnd = protectedValuesCopy.end(); + for (ProtectCountSet::iterator it = protectedValuesCopy.begin(); it != protectedValuesEnd; ++it) + it->first->~JSCell(); + + for (size_t block = 0; block < m_heap.usedBlocks; ++block) + freeBlockPtr(m_heap.blocks[block]); + + fastFree(m_heap.blocks); + + memset(&m_heap, 0, sizeof(CollectorHeap)); } void Heap::recordExtraCost(size_t cost) @@ -360,123 +378,109 @@ void Heap::recordExtraCost(size_t cost) // are either very short lived temporaries, or have extremely long lifetimes. So // if a large value survives one garbage collection, there is not much point to // collecting more frequently as long as it stays alive. - // NOTE: we target the primaryHeap unconditionally as JSNumber doesn't modify cost - primaryHeap.extraCost += cost; + if (m_heap.extraCost > maxExtraCost && m_heap.extraCost > m_heap.usedBlocks * BLOCK_SIZE / 2) { + // If the last iteration through the heap deallocated blocks, we need + // to clean up remaining garbage before marking. Otherwise, the conservative + // marking mechanism might follow a pointer to unmapped memory. + if (m_heap.didShrink) + sweep(); + reset(); + } + m_heap.extraCost += cost; } -template <HeapType heapType> ALWAYS_INLINE void* Heap::heapAllocate(size_t s) +void* Heap::allocate(size_t s) { - typedef typename HeapConstants<heapType>::Block Block; - typedef typename HeapConstants<heapType>::Cell Cell; - - CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; + typedef HeapConstants::Block Block; + typedef HeapConstants::Cell Cell; + ASSERT(JSLock::lockCount() > 0); ASSERT(JSLock::currentThreadIsHoldingLock()); - ASSERT_UNUSED(s, s <= HeapConstants<heapType>::cellSize); + ASSERT_UNUSED(s, s <= HeapConstants::cellSize); - ASSERT(heap.operationInProgress == NoOperation); - ASSERT(heapType == PrimaryHeap || heap.extraCost == 0); - // FIXME: If another global variable access here doesn't hurt performance - // too much, we could CRASH() in NDEBUG builds, which could help ensure we - // don't spend any time debugging cases where we allocate inside an object's - // deallocation code. + ASSERT(m_heap.operationInProgress == NoOperation); #if COLLECT_ON_EVERY_ALLOCATION - collect(); + collectAllGarbage(); + ASSERT(m_heap.operationInProgress == NoOperation); #endif - size_t numLiveObjects = heap.numLiveObjects; - size_t usedBlocks = heap.usedBlocks; - size_t i = heap.firstBlockWithPossibleSpace; - - // if we have a huge amount of extra cost, we'll try to collect even if we still have - // free cells left. - if (heapType == PrimaryHeap && heap.extraCost > ALLOCATIONS_PER_COLLECTION) { - size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect; - size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect; - const size_t newCost = numNewObjects + heap.extraCost; - if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect) - goto collect; - } +allocate: - ASSERT(heap.operationInProgress == NoOperation); -#ifndef NDEBUG - // FIXME: Consider doing this in NDEBUG builds too (see comment above). - heap.operationInProgress = Allocation; -#endif + // Fast case: find the next garbage cell and recycle it. -scan: - Block* targetBlock; - size_t targetBlockUsedCells; - if (i != usedBlocks) { - targetBlock = reinterpret_cast<Block*>(heap.blocks[i]); - targetBlockUsedCells = targetBlock->usedCells; - ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock); - while (targetBlockUsedCells == HeapConstants<heapType>::cellsPerBlock) { - if (++i == usedBlocks) - goto collect; - targetBlock = reinterpret_cast<Block*>(heap.blocks[i]); - targetBlockUsedCells = targetBlock->usedCells; - ASSERT(targetBlockUsedCells <= HeapConstants<heapType>::cellsPerBlock); - } - heap.firstBlockWithPossibleSpace = i; - } else { + do { + ASSERT(m_heap.nextBlock < m_heap.usedBlocks); + Block* block = reinterpret_cast<Block*>(m_heap.blocks[m_heap.nextBlock]); + do { + ASSERT(m_heap.nextCell < HeapConstants::cellsPerBlock); + if (!block->marked.get(m_heap.nextCell)) { // Always false for the last cell in the block + Cell* cell = block->cells + m_heap.nextCell; -collect: - size_t numLiveObjectsAtLastCollect = heap.numLiveObjectsAtLastCollect; - size_t numNewObjects = numLiveObjects - numLiveObjectsAtLastCollect; - const size_t newCost = numNewObjects + heap.extraCost; + m_heap.operationInProgress = Allocation; + JSCell* imp = reinterpret_cast<JSCell*>(cell); + imp->~JSCell(); + m_heap.operationInProgress = NoOperation; - if (newCost >= ALLOCATIONS_PER_COLLECTION && newCost >= numLiveObjectsAtLastCollect) { -#ifndef NDEBUG - heap.operationInProgress = NoOperation; -#endif - bool foundGarbage = collect(); - numLiveObjects = heap.numLiveObjects; - usedBlocks = heap.usedBlocks; - i = heap.firstBlockWithPossibleSpace; -#ifndef NDEBUG - heap.operationInProgress = Allocation; -#endif - if (foundGarbage) - goto scan; - } + ++m_heap.nextCell; + return cell; + } + } while (++m_heap.nextCell != HeapConstants::cellsPerBlock); + m_heap.nextCell = 0; + } while (++m_heap.nextBlock != m_heap.usedBlocks); - // didn't find a block, and GC didn't reclaim anything, need to allocate a new block - targetBlock = reinterpret_cast<Block*>(allocateBlock<heapType>()); - heap.firstBlockWithPossibleSpace = heap.usedBlocks - 1; - targetBlockUsedCells = 0; - } + // Slow case: reached the end of the heap. Mark live objects and start over. - // find a free spot in the block and detach it from the free list - Cell* newCell = targetBlock->freeList; + reset(); + goto allocate; +} - // "next" field is a cell offset -- 0 means next cell, so a zeroed block is already initialized - targetBlock->freeList = (newCell + 1) + newCell->u.freeCell.next; +void Heap::resizeBlocks() +{ + m_heap.didShrink = false; - targetBlock->usedCells = static_cast<uint32_t>(targetBlockUsedCells + 1); - heap.numLiveObjects = numLiveObjects + 1; + size_t usedCellCount = markedCells(); + size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount); + size_t minBlockCount = (minCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; -#ifndef NDEBUG - // FIXME: Consider doing this in NDEBUG builds too (see comment above). - heap.operationInProgress = NoOperation; -#endif + size_t maxCellCount = 1.25f * minCellCount; + size_t maxBlockCount = (maxCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock; - return newCell; + if (m_heap.usedBlocks < minBlockCount) + growBlocks(minBlockCount); + else if (m_heap.usedBlocks > maxBlockCount) + shrinkBlocks(maxBlockCount); } -void* Heap::allocate(size_t s) +void Heap::growBlocks(size_t neededBlocks) { - return heapAllocate<PrimaryHeap>(s); + ASSERT(m_heap.usedBlocks < neededBlocks); + while (m_heap.usedBlocks < neededBlocks) + allocateBlock(); } -void* Heap::allocateNumber(size_t s) +void Heap::shrinkBlocks(size_t neededBlocks) { - return heapAllocate<NumberHeap>(s); + ASSERT(m_heap.usedBlocks > neededBlocks); + + // Clear the always-on last bit, so isEmpty() isn't fooled by it. + for (size_t i = 0; i < m_heap.usedBlocks; ++i) + m_heap.blocks[i]->marked.clear(HeapConstants::cellsPerBlock - 1); + + for (size_t i = 0; i != m_heap.usedBlocks && m_heap.usedBlocks != neededBlocks; ) { + if (m_heap.blocks[i]->marked.isEmpty()) { + freeBlock(i); + } else + ++i; + } + + // Reset the always-on last bit. + for (size_t i = 0; i < m_heap.usedBlocks; ++i) + m_heap.blocks[i]->marked.set(HeapConstants::cellsPerBlock - 1); } -#if PLATFORM(WINCE) +#if OS(WINCE) void* g_stackBase = 0; inline bool isPageWritable(void* page) @@ -532,7 +536,8 @@ static void* getStackBase(void* previousFrame) } } #endif -#if PLATFORM(HPUX) + +#if OS(HPUX) struct hpux_get_stack_base_data { pthread_t thread; @@ -576,7 +581,7 @@ static void *hpux_get_stack_base() } #endif -#if PLATFORM(QNX) +#if OS(QNX) static inline void *currentThreadStackBaseQNX() { static void* stackBase = 0; @@ -605,10 +610,10 @@ static inline void *currentThreadStackBaseQNX() static inline void* currentThreadStackBase() { -#if PLATFORM(DARWIN) +#if OS(DARWIN) pthread_t thread = pthread_self(); return pthread_get_stackaddr_np(thread); -#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(MSVC) +#elif OS(WINDOWS) && CPU(X86) && COMPILER(MSVC) // offset 0x18 from the FS segment register gives a pointer to // the thread information block for the current thread NT_TIB* pTib; @@ -617,10 +622,11 @@ static inline void* currentThreadStackBase() MOV pTib, EAX } return static_cast<void*>(pTib->StackBase); -#elif PLATFORM(WIN_OS) && PLATFORM(X86_64) && (COMPILER(MSVC) ||COMPILER(GCC)) +#elif OS(WINDOWS) && CPU(X86_64) && (COMPILER(MSVC) || COMPILER(GCC)) + // FIXME: why only for MSVC? PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); return reinterpret_cast<void*>(pTib->StackBase); -#elif PLATFORM(WIN_OS) && PLATFORM(X86) && COMPILER(GCC) +#elif OS(WINDOWS) && CPU(X86) && COMPILER(GCC) // offset 0x18 from the FS segment register gives a pointer to // the thread information block for the current thread NT_TIB* pTib; @@ -628,15 +634,15 @@ static inline void* currentThreadStackBase() : "=r" (pTib) ); return static_cast<void*>(pTib->StackBase); -#elif PLATFORM(QNX) - return currentThreadStackBaseQNX(); -#elif PLATFORM(HPUX) +#elif OS(HPUX) return hpux_get_stack_base(); -#elif PLATFORM(SOLARIS) +#elif OS(QNX) + return currentThreadStackBaseQNX(); +#elif OS(SOLARIS) stack_t s; thr_stksegment(&s); return s.ss_sp; -#elif PLATFORM(AIX) +#elif OS(AIX) pthread_t thread = pthread_self(); struct __pthrdsinfo threadinfo; char regbuf[256]; @@ -648,12 +654,12 @@ static inline void* currentThreadStackBase() return threadinfo.__pi_stackaddr; return 0; -#elif PLATFORM(OPENBSD) +#elif OS(OPENBSD) pthread_t thread = pthread_self(); stack_t stack; pthread_stackseg_np(thread, &stack); return stack.ss_sp; -#elif PLATFORM(SYMBIAN) +#elif OS(SYMBIAN) static void* stackBase = 0; if (stackBase == 0) { TThreadStackInfo info; @@ -662,11 +668,11 @@ static inline void* currentThreadStackBase() stackBase = (void*)info.iBase; } return (void*)stackBase; -#elif PLATFORM(HAIKU) +#elif OS(HAIKU) thread_info threadInfo; get_thread_info(find_thread(NULL), &threadInfo); return threadInfo.stack_end; -#elif PLATFORM(UNIX) +#elif OS(UNIX) static void* stackBase = 0; static size_t stackSize = 0; static pthread_t stackThread; @@ -674,7 +680,7 @@ static inline void* currentThreadStackBase() if (stackBase == 0 || thread != stackThread) { pthread_attr_t sattr; pthread_attr_init(&sattr); -#if HAVE(PTHREAD_NP_H) || PLATFORM(NETBSD) +#if HAVE(PTHREAD_NP_H) || OS(NETBSD) // e.g. on FreeBSD 5.4, neundorf@kde.org pthread_attr_get_np(thread, &sattr); #else @@ -688,7 +694,7 @@ static inline void* currentThreadStackBase() stackThread = thread; } return static_cast<char*>(stackBase) + stackSize; -#elif PLATFORM(WINCE) +#elif OS(WINCE) if (g_stackBase) return g_stackBase; else { @@ -704,11 +710,10 @@ static inline void* currentThreadStackBase() static inline PlatformThread getCurrentPlatformThread() { -#if PLATFORM(DARWIN) +#if OS(DARWIN) return pthread_mach_thread_np(pthread_self()); -#elif PLATFORM(WIN_OS) - HANDLE threadHandle = pthread_getw32threadhandle_np(pthread_self()); - return PlatformThread(GetCurrentThreadId(), threadHandle); +#elif OS(WINDOWS) + return pthread_getw32threadhandle_np(pthread_self()); #endif } @@ -777,10 +782,37 @@ void Heap::registerThread() #endif -#define IS_POINTER_ALIGNED(p) (((intptr_t)(p) & (sizeof(char*) - 1)) == 0) +inline bool isPointerAligned(void* p) +{ + return (((intptr_t)(p) & (sizeof(char*) - 1)) == 0); +} -// cell size needs to be a power of two for this to be valid -#define IS_HALF_CELL_ALIGNED(p) (((intptr_t)(p) & (CELL_MASK >> 1)) == 0) +// Cell size needs to be a power of two for isPossibleCell to be valid. +COMPILE_ASSERT(sizeof(CollectorCell) % 2 == 0, Collector_cell_size_is_power_of_two); + +#if USE(JSVALUE32) +static bool isHalfCellAligned(void *p) +{ + return (((intptr_t)(p) & (CELL_MASK >> 1)) == 0); +} + +static inline bool isPossibleCell(void* p) +{ + return isHalfCellAligned(p) && p; +} + +#else + +static inline bool isCellAligned(void *p) +{ + return (((intptr_t)(p) & CELL_MASK) == 0); +} + +static inline bool isPossibleCell(void* p) +{ + return isCellAligned(p) && p; +} +#endif // USE(JSVALUE32) void Heap::markConservatively(MarkStack& markStack, void* start, void* end) { @@ -791,46 +823,33 @@ void Heap::markConservatively(MarkStack& markStack, void* start, void* end) } ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000); - ASSERT(IS_POINTER_ALIGNED(start)); - ASSERT(IS_POINTER_ALIGNED(end)); + ASSERT(isPointerAligned(start)); + ASSERT(isPointerAligned(end)); char** p = static_cast<char**>(start); char** e = static_cast<char**>(end); - size_t usedPrimaryBlocks = primaryHeap.usedBlocks; - size_t usedNumberBlocks = numberHeap.usedBlocks; - CollectorBlock** primaryBlocks = primaryHeap.blocks; - CollectorBlock** numberBlocks = numberHeap.blocks; - - const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1); - + CollectorBlock** blocks = m_heap.blocks; while (p != e) { char* x = *p++; - if (IS_HALF_CELL_ALIGNED(x) && x) { + if (isPossibleCell(x)) { + size_t usedBlocks; uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x); xAsBits &= CELL_ALIGN_MASK; + uintptr_t offset = xAsBits & BLOCK_OFFSET_MASK; + const size_t lastCellOffset = sizeof(CollectorCell) * (CELLS_PER_BLOCK - 1); + if (offset > lastCellOffset) + continue; + CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset); - // Mark the the number heap, we can mark these Cells directly to avoid the virtual call cost - for (size_t block = 0; block < usedNumberBlocks; block++) { - if ((numberBlocks[block] == blockAddr) & (offset <= lastCellOffset)) { - Heap::markCell(reinterpret_cast<JSCell*>(xAsBits)); - goto endMarkLoop; - } + usedBlocks = m_heap.usedBlocks; + for (size_t block = 0; block < usedBlocks; block++) { + if (blocks[block] != blockAddr) + continue; + markStack.append(reinterpret_cast<JSCell*>(xAsBits)); + markStack.drain(); } - - // Mark the primary heap - for (size_t block = 0; block < usedPrimaryBlocks; block++) { - if ((primaryBlocks[block] == blockAddr) & (offset <= lastCellOffset)) { - if (reinterpret_cast<CollectorCell*>(xAsBits)->u.freeCell.zeroIfFree) { - markStack.append(reinterpret_cast<JSCell*>(xAsBits)); - markStack.drain(); - } - break; - } - } - endMarkLoop: - ; } } } @@ -869,10 +888,10 @@ void Heap::markCurrentThreadConservatively(MarkStack& markStack) static inline void suspendThread(const PlatformThread& platformThread) { -#if PLATFORM(DARWIN) +#if OS(DARWIN) thread_suspend(platformThread); -#elif PLATFORM(WIN_OS) - SuspendThread(platformThread.handle); +#elif OS(WINDOWS) + SuspendThread(platformThread); #else #error Need a way to suspend threads on this platform #endif @@ -880,10 +899,10 @@ static inline void suspendThread(const PlatformThread& platformThread) static inline void resumeThread(const PlatformThread& platformThread) { -#if PLATFORM(DARWIN) +#if OS(DARWIN) thread_resume(platformThread); -#elif PLATFORM(WIN_OS) - ResumeThread(platformThread.handle); +#elif OS(WINDOWS) + ResumeThread(platformThread); #else #error Need a way to resume threads on this platform #endif @@ -891,23 +910,23 @@ static inline void resumeThread(const PlatformThread& platformThread) typedef unsigned long usword_t; // word size, assumed to be either 32 or 64 bit -#if PLATFORM(DARWIN) +#if OS(DARWIN) -#if PLATFORM(X86) +#if CPU(X86) typedef i386_thread_state_t PlatformThreadRegisters; -#elif PLATFORM(X86_64) +#elif CPU(X86_64) typedef x86_thread_state64_t PlatformThreadRegisters; -#elif PLATFORM(PPC) +#elif CPU(PPC) typedef ppc_thread_state_t PlatformThreadRegisters; -#elif PLATFORM(PPC64) +#elif CPU(PPC64) typedef ppc_thread_state64_t PlatformThreadRegisters; -#elif PLATFORM(ARM) +#elif CPU(ARM) typedef arm_thread_state_t PlatformThreadRegisters; #else #error Unknown Architecture #endif -#elif PLATFORM(WIN_OS)&& PLATFORM(X86) +#elif OS(WINDOWS) && CPU(X86) typedef CONTEXT PlatformThreadRegisters; #else #error Need a thread register struct for this platform @@ -915,21 +934,21 @@ typedef CONTEXT PlatformThreadRegisters; static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, PlatformThreadRegisters& regs) { -#if PLATFORM(DARWIN) +#if OS(DARWIN) -#if PLATFORM(X86) +#if CPU(X86) unsigned user_count = sizeof(regs)/sizeof(int); thread_state_flavor_t flavor = i386_THREAD_STATE; -#elif PLATFORM(X86_64) +#elif CPU(X86_64) unsigned user_count = x86_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = x86_THREAD_STATE64; -#elif PLATFORM(PPC) +#elif CPU(PPC) unsigned user_count = PPC_THREAD_STATE_COUNT; thread_state_flavor_t flavor = PPC_THREAD_STATE; -#elif PLATFORM(PPC64) +#elif CPU(PPC64) unsigned user_count = PPC_THREAD_STATE64_COUNT; thread_state_flavor_t flavor = PPC_THREAD_STATE64; -#elif PLATFORM(ARM) +#elif CPU(ARM) unsigned user_count = ARM_THREAD_STATE_COUNT; thread_state_flavor_t flavor = ARM_THREAD_STATE; #else @@ -943,11 +962,11 @@ static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, P CRASH(); } return user_count * sizeof(usword_t); -// end PLATFORM(DARWIN) +// end OS(DARWIN) -#elif PLATFORM(WIN_OS) && PLATFORM(X86) +#elif OS(WINDOWS) && CPU(X86) regs.ContextFlags = CONTEXT_INTEGER | CONTEXT_CONTROL | CONTEXT_SEGMENTS; - GetThreadContext(platformThread.handle, ®s); + GetThreadContext(platformThread, ®s); return sizeof(CONTEXT); #else #error Need a way to get thread registers on this platform @@ -956,17 +975,17 @@ static size_t getPlatformThreadRegisters(const PlatformThread& platformThread, P static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) { -#if PLATFORM(DARWIN) +#if OS(DARWIN) #if __DARWIN_UNIX03 -#if PLATFORM(X86) +#if CPU(X86) return reinterpret_cast<void*>(regs.__esp); -#elif PLATFORM(X86_64) +#elif CPU(X86_64) return reinterpret_cast<void*>(regs.__rsp); -#elif PLATFORM(PPC) || PLATFORM(PPC64) +#elif CPU(PPC) || CPU(PPC64) return reinterpret_cast<void*>(regs.__r1); -#elif PLATFORM(ARM) +#elif CPU(ARM) return reinterpret_cast<void*>(regs.__sp); #else #error Unknown Architecture @@ -974,11 +993,11 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) #else // !__DARWIN_UNIX03 -#if PLATFORM(X86) +#if CPU(X86) return reinterpret_cast<void*>(regs.esp); -#elif PLATFORM(X86_64) +#elif CPU(X86_64) return reinterpret_cast<void*>(regs.rsp); -#elif (PLATFORM(PPC) || PLATFORM(PPC64)) +#elif CPU(PPC) || CPU(PPC64) return reinterpret_cast<void*>(regs.r1); #else #error Unknown Architecture @@ -986,8 +1005,8 @@ static inline void* otherThreadStackPointer(const PlatformThreadRegisters& regs) #endif // __DARWIN_UNIX03 -// end PLATFORM(DARWIN) -#elif PLATFORM(X86) && PLATFORM(WIN_OS) +// end OS(DARWIN) +#elif CPU(X86) && OS(WINDOWS) return reinterpret_cast<void*>((uintptr_t) regs.Esp); #else #error Need a way to get the stack pointer for another thread on this platform @@ -1041,16 +1060,6 @@ void Heap::markStackObjectsConservatively(MarkStack& markStack) #endif } -void Heap::setGCProtectNeedsLocking() -{ - // Most clients do not need to call this, with the notable exception of WebCore. - // Clients that use shared heap have JSLock protection, while others are supposed - // to do explicit locking. WebCore violates this contract in Database code, - // which calls gcUnprotect from a secondary thread. - if (!m_protectedValuesMutex) - m_protectedValuesMutex.set(new Mutex); -} - void Heap::protect(JSValue k) { ASSERT(k); @@ -1059,13 +1068,7 @@ void Heap::protect(JSValue k) if (!k.isCell()) return; - if (m_protectedValuesMutex) - m_protectedValuesMutex->lock(); - m_protectedValues.add(k.asCell()); - - if (m_protectedValuesMutex) - m_protectedValuesMutex->unlock(); } void Heap::unprotect(JSValue k) @@ -1076,133 +1079,80 @@ void Heap::unprotect(JSValue k) if (!k.isCell()) return; - if (m_protectedValuesMutex) - m_protectedValuesMutex->lock(); - m_protectedValues.remove(k.asCell()); - - if (m_protectedValuesMutex) - m_protectedValuesMutex->unlock(); } void Heap::markProtectedObjects(MarkStack& markStack) { - if (m_protectedValuesMutex) - m_protectedValuesMutex->lock(); - ProtectCountSet::iterator end = m_protectedValues.end(); for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) { markStack.append(it->first); markStack.drain(); } +} - if (m_protectedValuesMutex) - m_protectedValuesMutex->unlock(); +void Heap::clearMarkBits() +{ + for (size_t i = 0; i < m_heap.usedBlocks; ++i) + clearMarkBits(m_heap.blocks[i]); } -template <HeapType heapType> size_t Heap::sweep() +void Heap::clearMarkBits(CollectorBlock* block) { - typedef typename HeapConstants<heapType>::Block Block; - typedef typename HeapConstants<heapType>::Cell Cell; + // allocate assumes that the last cell in every block is marked. + block->marked.clearAll(); + block->marked.set(HeapConstants::cellsPerBlock - 1); +} - // SWEEP: delete everything with a zero refcount (garbage) and unmark everything else - CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap; - - size_t emptyBlocks = 0; - size_t numLiveObjects = heap.numLiveObjects; - - for (size_t block = 0; block < heap.usedBlocks; block++) { - Block* curBlock = reinterpret_cast<Block*>(heap.blocks[block]); - - size_t usedCells = curBlock->usedCells; - Cell* freeList = curBlock->freeList; - - if (usedCells == HeapConstants<heapType>::cellsPerBlock) { - // special case with a block where all cells are used -- testing indicates this happens often - for (size_t i = 0; i < HeapConstants<heapType>::cellsPerBlock; i++) { - if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) { - Cell* cell = curBlock->cells + i; - - if (heapType != NumberHeap) { - JSCell* imp = reinterpret_cast<JSCell*>(cell); - // special case for allocated but uninitialized object - // (We don't need this check earlier because nothing prior this point - // assumes the object has a valid vptr.) - if (cell->u.freeCell.zeroIfFree == 0) - continue; - - imp->~JSCell(); - } - - --usedCells; - --numLiveObjects; - - // put cell on the free list - cell->u.freeCell.zeroIfFree = 0; - cell->u.freeCell.next = freeList - (cell + 1); - freeList = cell; - } - } - } else { - size_t minimumCellsToProcess = usedCells; - for (size_t i = 0; (i < minimumCellsToProcess) & (i < HeapConstants<heapType>::cellsPerBlock); i++) { - Cell* cell = curBlock->cells + i; - if (cell->u.freeCell.zeroIfFree == 0) { - ++minimumCellsToProcess; - } else { - if (!curBlock->marked.get(i >> HeapConstants<heapType>::bitmapShift)) { - if (heapType != NumberHeap) { - JSCell* imp = reinterpret_cast<JSCell*>(cell); - imp->~JSCell(); - } - --usedCells; - --numLiveObjects; - - // put cell on the free list - cell->u.freeCell.zeroIfFree = 0; - cell->u.freeCell.next = freeList - (cell + 1); - freeList = cell; - } - } - } - } - - curBlock->usedCells = static_cast<uint32_t>(usedCells); - curBlock->freeList = freeList; - curBlock->marked.clearAll(); - - if (!usedCells) - ++emptyBlocks; - } - - if (heap.numLiveObjects != numLiveObjects) - heap.firstBlockWithPossibleSpace = 0; - - heap.numLiveObjects = numLiveObjects; - heap.numLiveObjectsAtLastCollect = numLiveObjects; - heap.extraCost = 0; - - if (!emptyBlocks) - return numLiveObjects; +size_t Heap::markedCells(size_t startBlock, size_t startCell) const +{ + ASSERT(startBlock <= m_heap.usedBlocks); + ASSERT(startCell < HeapConstants::cellsPerBlock); - size_t neededCells = 1.25f * (numLiveObjects + max(ALLOCATIONS_PER_COLLECTION, numLiveObjects)); - size_t neededBlocks = (neededCells + HeapConstants<heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock; - for (size_t block = 0; block < heap.usedBlocks; block++) { - if (heap.usedBlocks <= neededBlocks) - break; + if (startBlock >= m_heap.usedBlocks) + return 0; + + size_t result = 0; + result += m_heap.blocks[startBlock]->marked.count(startCell); + for (size_t i = startBlock + 1; i < m_heap.usedBlocks; ++i) + result += m_heap.blocks[i]->marked.count(); + + return result; +} - Block* curBlock = reinterpret_cast<Block*>(heap.blocks[block]); - if (curBlock->usedCells) - continue; +void Heap::sweep() +{ + ASSERT(m_heap.operationInProgress == NoOperation); + if (m_heap.operationInProgress != NoOperation) + CRASH(); + m_heap.operationInProgress = Collection; + +#if !ENABLE(JSC_ZOMBIES) + Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get(); +#endif - freeBlock<heapType>(block); - block--; // Don't move forward a step in this case + DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell); + DeadObjectIterator end(m_heap, m_heap.usedBlocks); + for ( ; it != end; ++it) { + JSCell* cell = *it; +#if ENABLE(JSC_ZOMBIES) + if (!cell->isZombie()) { + const ClassInfo* info = cell->classInfo(); + cell->~JSCell(); + new (cell) JSZombie(info, JSZombie::leakedZombieStructure()); + Heap::markCell(cell); + } +#else + cell->~JSCell(); + // Callers of sweep assume it's safe to mark any cell in the heap. + new (cell) JSCell(dummyMarkableCellStructure); +#endif } - return numLiveObjects; + m_heap.operationInProgress = NoOperation; } -bool Heap::collect() +void Heap::markRoots() { #ifndef NDEBUG if (m_globalData->isSharedInstance) { @@ -1211,27 +1161,34 @@ bool Heap::collect() } #endif - ASSERT((primaryHeap.operationInProgress == NoOperation) | (numberHeap.operationInProgress == NoOperation)); - if ((primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation)) + ASSERT(m_heap.operationInProgress == NoOperation); + if (m_heap.operationInProgress != NoOperation) CRASH(); - JAVASCRIPTCORE_GC_BEGIN(); - primaryHeap.operationInProgress = Collection; - numberHeap.operationInProgress = Collection; + m_heap.operationInProgress = Collection; - // MARK: first mark all referenced objects recursively starting out from the set of root objects MarkStack& markStack = m_globalData->markStack; + + // Reset mark bits. + clearMarkBits(); + + // Mark stack roots. markStackObjectsConservatively(markStack); + m_globalData->interpreter->registerFile().markCallFrames(markStack, this); + + // Mark explicitly registered roots. markProtectedObjects(markStack); + #if QT_BUILD_SCRIPT_LIB if (m_globalData->clientData) m_globalData->clientData->mark(markStack); #endif + + // Mark misc. other roots. if (m_markListSet && m_markListSet->size()) MarkedArgumentBuffer::markLists(markStack, *m_markListSet); if (m_globalData->exception) markStack.append(m_globalData->exception); - m_globalData->interpreter->registerFile().markCallFrames(markStack, this); m_globalData->smallStrings.markChildren(markStack); if (m_globalData->functionCodeBlockBeingReparsed) m_globalData->functionCodeBlockBeingReparsed->markAggregate(markStack); @@ -1240,41 +1197,28 @@ bool Heap::collect() markStack.drain(); markStack.compact(); - JAVASCRIPTCORE_GC_MARKED(); - - size_t originalLiveObjects = primaryHeap.numLiveObjects + numberHeap.numLiveObjects; - size_t numLiveObjects = sweep<PrimaryHeap>(); - numLiveObjects += sweep<NumberHeap>(); - - primaryHeap.operationInProgress = NoOperation; - numberHeap.operationInProgress = NoOperation; - JAVASCRIPTCORE_GC_END(originalLiveObjects, numLiveObjects); - return numLiveObjects < originalLiveObjects; + m_heap.operationInProgress = NoOperation; } -size_t Heap::objectCount() +size_t Heap::objectCount() const { - return primaryHeap.numLiveObjects + numberHeap.numLiveObjects - m_globalData->smallStrings.count(); + return m_heap.nextBlock * HeapConstants::cellsPerBlock // allocated full blocks + + m_heap.nextCell // allocated cells in current block + + markedCells(m_heap.nextBlock, m_heap.nextCell) // marked cells in remainder of m_heap + - m_heap.usedBlocks; // 1 cell per block is a dummy sentinel } -template <HeapType heapType> -static void addToStatistics(Heap::Statistics& statistics, const CollectorHeap& heap) +void Heap::addToStatistics(Heap::Statistics& statistics) const { - typedef HeapConstants<heapType> HC; - for (size_t i = 0; i < heap.usedBlocks; ++i) { - if (heap.blocks[i]) { - statistics.size += BLOCK_SIZE; - statistics.free += (HC::cellsPerBlock - heap.blocks[i]->usedCells) * HC::cellSize; - } - } + statistics.size += m_heap.usedBlocks * BLOCK_SIZE; + statistics.free += m_heap.usedBlocks * BLOCK_SIZE - (objectCount() * HeapConstants::cellSize); } Heap::Statistics Heap::statistics() const { Statistics statistics = { 0, 0 }; - JSC::addToStatistics<PrimaryHeap>(statistics, primaryHeap); - JSC::addToStatistics<NumberHeap>(statistics, numberHeap); + addToStatistics(statistics); return statistics; } @@ -1293,9 +1237,6 @@ size_t Heap::globalObjectCount() size_t Heap::protectedGlobalObjectCount() { - if (m_protectedValuesMutex) - m_protectedValuesMutex->lock(); - size_t count = 0; if (JSGlobalObject* head = m_globalData->head) { JSGlobalObject* o = head; @@ -1306,23 +1247,12 @@ size_t Heap::protectedGlobalObjectCount() } while (o != head); } - if (m_protectedValuesMutex) - m_protectedValuesMutex->unlock(); - return count; } size_t Heap::protectedObjectCount() { - if (m_protectedValuesMutex) - m_protectedValuesMutex->lock(); - - size_t result = m_protectedValues.size(); - - if (m_protectedValuesMutex) - m_protectedValuesMutex->unlock(); - - return result; + return m_protectedValues.size(); } static const char* typeName(JSCell* cell) @@ -1335,6 +1265,10 @@ static const char* typeName(JSCell* cell) #endif if (cell->isGetterSetter()) return "gettersetter"; + if (cell->isAPIValueWrapper()) + return "value wrapper"; + if (cell->isPropertyNameIterator()) + return "for-in iterator"; ASSERT(cell->isObject()); const ClassInfo* info = cell->classInfo(); return info ? info->className : "Object"; @@ -1344,32 +1278,70 @@ HashCountedSet<const char*>* Heap::protectedObjectTypeCounts() { HashCountedSet<const char*>* counts = new HashCountedSet<const char*>; - if (m_protectedValuesMutex) - m_protectedValuesMutex->lock(); - ProtectCountSet::iterator end = m_protectedValues.end(); for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) counts->add(typeName(it->first)); - if (m_protectedValuesMutex) - m_protectedValuesMutex->unlock(); - return counts; } bool Heap::isBusy() { - return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation); + return m_heap.operationInProgress != NoOperation; +} + +void Heap::reset() +{ + JAVASCRIPTCORE_GC_BEGIN(); + + markRoots(); + + JAVASCRIPTCORE_GC_MARKED(); + + m_heap.nextCell = 0; + m_heap.nextBlock = 0; + m_heap.nextNumber = 0; + m_heap.extraCost = 0; +#if ENABLE(JSC_ZOMBIES) + sweep(); +#endif + resizeBlocks(); + + JAVASCRIPTCORE_GC_END(); +} + +void Heap::collectAllGarbage() +{ + JAVASCRIPTCORE_GC_BEGIN(); + + // If the last iteration through the heap deallocated blocks, we need + // to clean up remaining garbage before marking. Otherwise, the conservative + // marking mechanism might follow a pointer to unmapped memory. + if (m_heap.didShrink) + sweep(); + + markRoots(); + + JAVASCRIPTCORE_GC_MARKED(); + + m_heap.nextCell = 0; + m_heap.nextBlock = 0; + m_heap.nextNumber = 0; + m_heap.extraCost = 0; + sweep(); + resizeBlocks(); + + JAVASCRIPTCORE_GC_END(); } -Heap::iterator Heap::primaryHeapBegin() +LiveObjectIterator Heap::primaryHeapBegin() { - return iterator(primaryHeap.blocks, primaryHeap.blocks + primaryHeap.usedBlocks); + return LiveObjectIterator(m_heap, 0); } -Heap::iterator Heap::primaryHeapEnd() +LiveObjectIterator Heap::primaryHeapEnd() { - return iterator(primaryHeap.blocks + primaryHeap.usedBlocks, primaryHeap.blocks + primaryHeap.usedBlocks); + return LiveObjectIterator(m_heap, m_heap.usedBlocks); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h index 0ecff19..7f7a679 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h @@ -28,9 +28,9 @@ #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> +#include <wtf/StdLibExtras.h> #include <wtf/Threading.h> -// This is supremely lame that we require pthreads to build on windows. #if ENABLE(JSC_MULTIPLE_THREADS) #include <pthread.h> #endif @@ -47,19 +47,21 @@ namespace JSC { class MarkStack; enum OperationInProgress { NoOperation, Allocation, Collection }; - enum HeapType { PrimaryHeap, NumberHeap }; - template <HeapType> class CollectorHeapIterator; + class LiveObjectIterator; struct CollectorHeap { + size_t nextBlock; + size_t nextCell; CollectorBlock** blocks; + + void* nextNumber; + size_t numBlocks; size_t usedBlocks; - size_t firstBlockWithPossibleSpace; - size_t numLiveObjects; - size_t numLiveObjectsAtLastCollect; size_t extraCost; + bool didShrink; OperationInProgress operationInProgress; }; @@ -67,36 +69,27 @@ namespace JSC { class Heap : public Noncopyable { public: class Thread; - typedef CollectorHeapIterator<PrimaryHeap> iterator; void destroy(); -#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE - // We can inline these functions because everything is compiled as - // one file, so the heapAllocate template definitions are available. - // However, allocateNumber is used via jsNumberCell outside JavaScriptCore. - // Thus allocateNumber needs to provide a non-inline version too. - void* inlineAllocateNumber(size_t s) { return heapAllocate<NumberHeap>(s); } - void* inlineAllocate(size_t s) { return heapAllocate<PrimaryHeap>(s); } -#endif void* allocateNumber(size_t); void* allocate(size_t); - bool collect(); bool isBusy(); // true if an allocation or collection is in progress + void collectAllGarbage(); - static const size_t minExtraCostSize = 256; + static const size_t minExtraCost = 256; + static const size_t maxExtraCost = 1024 * 1024; void reportExtraMemoryCost(size_t cost); - size_t objectCount(); + size_t objectCount() const; struct Statistics { size_t size; size_t free; }; Statistics statistics() const; - void setGCProtectNeedsLocking(); void protect(JSValue); void unprotect(JSValue); @@ -120,13 +113,12 @@ namespace JSC { JSGlobalData* globalData() const { return m_globalData; } static bool isNumber(JSCell*); - // Iterators for the object heap. - iterator primaryHeapBegin(); - iterator primaryHeapEnd(); + LiveObjectIterator primaryHeapBegin(); + LiveObjectIterator primaryHeapEnd(); private: - template <HeapType heapType> void* heapAllocate(size_t); - template <HeapType heapType> size_t sweep(); + void reset(); + void sweep(); static CollectorBlock* cellBlock(const JSCell*); static size_t cellOffset(const JSCell*); @@ -134,12 +126,22 @@ namespace JSC { Heap(JSGlobalData*); ~Heap(); - template <HeapType heapType> NEVER_INLINE CollectorBlock* allocateBlock(); - template <HeapType heapType> NEVER_INLINE void freeBlock(size_t); - NEVER_INLINE void freeBlock(CollectorBlock*); - void freeBlocks(CollectorHeap*); + NEVER_INLINE CollectorBlock* allocateBlock(); + NEVER_INLINE void freeBlock(size_t); + NEVER_INLINE void freeBlockPtr(CollectorBlock*); + void freeBlocks(); + void resizeBlocks(); + void growBlocks(size_t neededBlocks); + void shrinkBlocks(size_t neededBlocks); + void clearMarkBits(); + void clearMarkBits(CollectorBlock*); + size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const; void recordExtraCost(size_t); + + void addToStatistics(Statistics&) const; + + void markRoots(); void markProtectedObjects(MarkStack&); void markCurrentThreadConservatively(MarkStack&); void markCurrentThreadConservativelyInternal(MarkStack&); @@ -148,10 +150,8 @@ namespace JSC { typedef HashCountedSet<JSCell*> ProtectCountSet; - CollectorHeap primaryHeap; - CollectorHeap numberHeap; + CollectorHeap m_heap; - OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking(). ProtectCountSet m_protectedValues; HashSet<MarkedArgumentBuffer*>* m_markListSet; @@ -181,7 +181,7 @@ namespace JSC { #endif template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; -#if PLATFORM(WINCE) || PLATFORM(SYMBIAN) +#if OS(WINCE) || OS(SYMBIAN) const size_t BLOCK_SIZE = 64 * 1024; // 64k #else const size_t BLOCK_SIZE = 64 * 4096; // 256k @@ -196,87 +196,60 @@ namespace JSC { const size_t SMALL_CELL_SIZE = CELL_SIZE / 2; const size_t CELL_MASK = CELL_SIZE - 1; const size_t CELL_ALIGN_MASK = ~CELL_MASK; - const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2); - const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK; + const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells. + const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8; const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t); - + struct CollectorBitmap { uint32_t bits[BITMAP_WORDS]; bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } void clearAll() { memset(bits, 0, sizeof(bits)); } + size_t count(size_t startCell = 0) + { + size_t result = 0; + for ( ; (startCell & 0x1F) != 0; ++startCell) { + if (get(startCell)) + ++result; + } + for (size_t i = startCell >> 5; i < BITMAP_WORDS; ++i) + result += WTF::bitCount(bits[i]); + return result; + } + size_t isEmpty() // Much more efficient than testing count() == 0. + { + for (size_t i = 0; i < BITMAP_WORDS; ++i) + if (bits[i] != 0) + return false; + return true; + } }; struct CollectorCell { - union { - double memory[CELL_ARRAY_LENGTH]; - struct { - void* zeroIfFree; - ptrdiff_t next; - } freeCell; - } u; - }; - - struct SmallCollectorCell { - union { - double memory[CELL_ARRAY_LENGTH / 2]; - struct { - void* zeroIfFree; - ptrdiff_t next; - } freeCell; - } u; + double memory[CELL_ARRAY_LENGTH]; }; class CollectorBlock { public: CollectorCell cells[CELLS_PER_BLOCK]; - uint32_t usedCells; - CollectorCell* freeList; - CollectorBitmap marked; - Heap* heap; - HeapType type; - }; - - class SmallCellCollectorBlock { - public: - SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK]; - uint32_t usedCells; - SmallCollectorCell* freeList; CollectorBitmap marked; Heap* heap; - HeapType type; }; - - template <HeapType heapType> struct HeapConstants; - template <> struct HeapConstants<PrimaryHeap> { + struct HeapConstants { static const size_t cellSize = CELL_SIZE; static const size_t cellsPerBlock = CELLS_PER_BLOCK; - static const size_t bitmapShift = 0; typedef CollectorCell Cell; typedef CollectorBlock Block; }; - template <> struct HeapConstants<NumberHeap> { - static const size_t cellSize = SMALL_CELL_SIZE; - static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK; - static const size_t bitmapShift = 1; - typedef SmallCollectorCell Cell; - typedef SmallCellCollectorBlock Block; - }; - inline CollectorBlock* Heap::cellBlock(const JSCell* cell) { return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK); } - inline bool Heap::isNumber(JSCell* cell) - { - return Heap::cellBlock(cell)->type == NumberHeap; - } - inline size_t Heap::cellOffset(const JSCell* cell) { return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE; @@ -294,8 +267,20 @@ namespace JSC { inline void Heap::reportExtraMemoryCost(size_t cost) { - if (cost > minExtraCostSize) - recordExtraCost(cost / (CELL_SIZE * 2)); + if (cost > minExtraCost) + recordExtraCost(cost); + } + + inline void* Heap::allocateNumber(size_t s) + { + if (void* result = m_heap.nextNumber) { + m_heap.nextNumber = 0; + return result; + } + + void* result = allocate(s); + m_heap.nextNumber = static_cast<char*>(result) + (CELL_SIZE / 2); + return result; } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CollectorHeapIterator.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CollectorHeapIterator.h index e38a852..e4f2f91 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CollectorHeapIterator.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CollectorHeapIterator.h @@ -31,58 +31,108 @@ namespace JSC { - template <HeapType heapType> class CollectorHeapIterator { + class CollectorHeapIterator { public: - CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock); - - bool operator!=(const CollectorHeapIterator<heapType>& other) { return m_block != other.m_block || m_cell != other.m_cell; } - CollectorHeapIterator<heapType>& operator++(); + bool operator!=(const CollectorHeapIterator& other); JSCell* operator*() const; - private: - typedef typename HeapConstants<heapType>::Block Block; - typedef typename HeapConstants<heapType>::Cell Cell; - - Block** m_block; - Block** m_endBlock; - Cell* m_cell; - Cell* m_endCell; + protected: + CollectorHeapIterator(CollectorHeap&, size_t startBlock, size_t startCell); + void advance(size_t cellsPerBlock); + + CollectorHeap& m_heap; + size_t m_block; + size_t m_cell; + }; + + class LiveObjectIterator : public CollectorHeapIterator { + public: + LiveObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0); + LiveObjectIterator& operator++(); + }; + + class DeadObjectIterator : public CollectorHeapIterator { + public: + DeadObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0); + DeadObjectIterator& operator++(); + }; + + class ObjectIterator : public CollectorHeapIterator { + public: + ObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0); + ObjectIterator& operator++(); }; - template <HeapType heapType> - CollectorHeapIterator<heapType>::CollectorHeapIterator(CollectorBlock** block, CollectorBlock** endBlock) - : m_block(reinterpret_cast<Block**>(block)) - , m_endBlock(reinterpret_cast<Block**>(endBlock)) - , m_cell(m_block == m_endBlock ? 0 : (*m_block)->cells) - , m_endCell(m_block == m_endBlock ? 0 : (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock) + inline CollectorHeapIterator::CollectorHeapIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) + : m_heap(heap) + , m_block(startBlock) + , m_cell(startCell) + { + } + + inline bool CollectorHeapIterator::operator!=(const CollectorHeapIterator& other) + { + return m_block != other.m_block || m_cell != other.m_cell; + } + + inline JSCell* CollectorHeapIterator::operator*() const + { + return reinterpret_cast<JSCell*>(m_heap.blocks[m_block]->cells + m_cell); + } + + inline void CollectorHeapIterator::advance(size_t cellsPerBlock) + { + ++m_cell; + if (m_cell == cellsPerBlock) { + m_cell = 0; + ++m_block; + } + } + + inline LiveObjectIterator::LiveObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) + : CollectorHeapIterator(heap, startBlock, startCell - 1) + { + ++(*this); + } + + inline LiveObjectIterator& LiveObjectIterator::operator++() + { + if (m_block < m_heap.nextBlock || m_cell < m_heap.nextCell) { + advance(HeapConstants::cellsPerBlock); + return *this; + } + + do { + advance(HeapConstants::cellsPerBlock); + } while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell)); + return *this; + } + + inline DeadObjectIterator::DeadObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) + : CollectorHeapIterator(heap, startBlock, startCell - 1) { - if (m_cell && m_cell->u.freeCell.zeroIfFree == 0) - ++*this; + ++(*this); } - template <HeapType heapType> - CollectorHeapIterator<heapType>& CollectorHeapIterator<heapType>::operator++() + inline DeadObjectIterator& DeadObjectIterator::operator++() { do { - for (++m_cell; m_cell != m_endCell; ++m_cell) - if (m_cell->u.freeCell.zeroIfFree != 0) { - return *this; - } - - if (++m_block != m_endBlock) { - m_cell = (*m_block)->cells; - m_endCell = (*m_block)->cells + HeapConstants<heapType>::cellsPerBlock; - } - } while(m_block != m_endBlock); - - m_cell = 0; + advance(HeapConstants::cellsPerBlock); + ASSERT(m_block > m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell >= m_heap.nextCell)); + } while (m_block < m_heap.usedBlocks && m_heap.blocks[m_block]->marked.get(m_cell)); return *this; } - template <HeapType heapType> - JSCell* CollectorHeapIterator<heapType>::operator*() const + inline ObjectIterator::ObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell) + : CollectorHeapIterator(heap, startBlock, startCell - 1) { - return reinterpret_cast<JSCell*>(m_cell); + ++(*this); + } + + inline ObjectIterator& ObjectIterator::operator++() + { + advance(HeapConstants::cellsPerBlock); + return *this; } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CommonIdentifiers.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CommonIdentifiers.h index abe5038..de24f4a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/CommonIdentifiers.h @@ -50,6 +50,7 @@ macro(get) \ macro(getPrototypeOf) \ macro(getOwnPropertyDescriptor) \ + macro(getOwnPropertyNames) \ macro(hasOwnProperty) \ macro(ignoreCase) \ macro(index) \ diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Completion.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Completion.cpp index 3ad467d..2f88df9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Completion.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Completion.cpp @@ -31,18 +31,15 @@ #include "Debugger.h" #include <stdio.h> -#ifdef QT_BUILD_SCRIPT_LIB -#include "DebuggerCallFrame.h" -#endif - namespace JSC { Completion checkSyntax(ExecState* exec, const SourceCode& source) { JSLock lock(exec); + ASSERT(exec->globalData().identifierTable == currentIdentifierTable()); - ProgramExecutable program(exec, source); - JSObject* error = program.checkSyntax(exec); + RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); + JSObject* error = program->checkSyntax(exec); if (error) return Completion(Throw, error); @@ -52,23 +49,23 @@ Completion checkSyntax(ExecState* exec, const SourceCode& source) Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& source, JSValue thisValue) { JSLock lock(exec); + ASSERT(exec->globalData().identifierTable == currentIdentifierTable()); - ProgramExecutable program(exec, source); - JSObject* error = program.compile(exec, scopeChain.node()); + RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); + JSObject* error = program->compile(exec, scopeChain.node()); if (error) return Completion(Throw, error); JSObject* thisObj = (!thisValue || thisValue.isUndefinedOrNull()) ? exec->dynamicGlobalObject() : thisValue.toObject(exec); JSValue exception; - JSValue result = exec->interpreter()->execute(&program, exec, scopeChain.node(), thisObj, &exception); + JSValue result = exec->interpreter()->execute(program.get(), exec, scopeChain.node(), thisObj, &exception); if (exception) { if (exception.isObject() && asObject(exception)->isWatchdogException()) return Completion(Interrupted, exception); return Completion(Throw, exception); } - return Completion(Normal, result); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.cpp index 3dfc918..06f9459 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.cpp @@ -28,7 +28,6 @@ #include "JSFunction.h" - #ifdef QT_BUILD_SCRIPT_LIB #include "Debugger.h" #include "DebuggerCallFrame.h" @@ -53,13 +52,13 @@ JSObject* JSC::NativeConstrWrapper::operator() (ExecState* exec, JSObject* jsobj } #endif -JSObject* construct(ExecState* exec, JSValue callee, ConstructType constructType, const ConstructData& constructData, const ArgList& args) +JSObject* construct(ExecState* exec, JSValue object, ConstructType constructType, const ConstructData& constructData, const ArgList& args) { if (constructType == ConstructTypeHost) - return constructData.native.function(exec, asObject(callee), args); + return constructData.native.function(exec, asObject(object), args); ASSERT(constructType == ConstructTypeJS); // FIXME: Can this be done more efficiently using the constructData? - return asFunction(callee)->construct(exec, args); + return asFunction(object)->construct(exec, args); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.h index 1dcfb00..9298f51 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ConstructData.h @@ -70,7 +70,7 @@ namespace JSC { }; #endif -#if defined(QT_BUILD_SCRIPT_LIB) && PLATFORM(SOLARIS) +#if defined(QT_BUILD_SCRIPT_LIB) && OS(SOLARIS) struct #else union diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.cpp index 1879c3f..2e476b3 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.cpp @@ -35,7 +35,7 @@ #include <wtf/DateMath.h> #include <wtf/MathExtras.h> -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) extern "C" time_t time(time_t* timer); // Provided by libce. #endif @@ -57,7 +57,7 @@ static JSValue JSC_HOST_CALL dateParse(ExecState*, JSObject*, JSValue, const Arg static JSValue JSC_HOST_CALL dateNow(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL dateUTC(ExecState*, JSObject*, JSValue, const ArgList&); -DateConstructor::DateConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype) +DateConstructor::DateConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, DatePrototype* datePrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, datePrototype->classInfo()->className)) { putDirectWithoutTransition(exec->propertyNames().prototype, datePrototype, DontEnum|DontDelete|ReadOnly); @@ -77,14 +77,14 @@ JSObject* constructDate(ExecState* exec, const ArgList& args) double value; if (numArgs == 0) // new Date() ECMA 15.9.3.3 - value = getCurrentUTCTime(); + value = jsCurrentTime(); else if (numArgs == 1) { if (args.at(0).inherits(&DateInstance::info)) value = asDateInstance(args.at(0))->internalNumber(); else { JSValue primitive = args.at(0).toPrimitive(exec); if (primitive.isString()) - value = parseDate(primitive.getString()); + value = parseDate(exec, primitive.getString(exec)); else value = primitive.toNumber(exec); } @@ -108,13 +108,11 @@ JSObject* constructDate(ExecState* exec, const ArgList& args) t.second = args.at(5).toInt32(exec); t.isDST = -1; double ms = (numArgs >= 7) ? args.at(6).toNumber(exec) : 0; - value = gregorianDateTimeToMS(t, ms, false); + value = gregorianDateTimeToMS(exec, t, ms, false); } } - DateInstance* result = new (exec) DateInstance(exec->lexicalGlobalObject()->dateStructure()); - result->setInternalValue(jsNumber(exec, timeClip(value))); - return result; + return new (exec) DateInstance(exec, value); } static JSObject* constructWithDateConstructor(ExecState* exec, JSObject*, const ArgList& args) @@ -134,8 +132,12 @@ static JSValue JSC_HOST_CALL callDate(ExecState* exec, JSObject*, JSValue, const time_t localTime = time(0); tm localTM; getLocalTime(&localTime, &localTM); - GregorianDateTime ts(localTM); - return jsNontrivialString(exec, formatDate(ts) + " " + formatTime(ts, false)); + GregorianDateTime ts(exec, localTM); + DateConversionBuffer date; + DateConversionBuffer time; + formatDate(ts, date); + formatTime(ts, time); + return jsNontrivialString(exec, makeString(date, " ", time)); } CallType DateConstructor::getCallData(CallData& callData) @@ -146,12 +148,12 @@ CallType DateConstructor::getCallData(CallData& callData) static JSValue JSC_HOST_CALL dateParse(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, parseDate(args.at(0).toString(exec))); + return jsNumber(exec, parseDate(exec, args.at(0).toString(exec))); } static JSValue JSC_HOST_CALL dateNow(ExecState* exec, JSObject*, JSValue, const ArgList&) { - return jsNumber(exec, getCurrentUTCTime()); + return jsNumber(exec, jsCurrentTime()); } static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, const ArgList& args) @@ -175,7 +177,7 @@ static JSValue JSC_HOST_CALL dateUTC(ExecState* exec, JSObject*, JSValue, const t.minute = args.at(4).toInt32(exec); t.second = args.at(5).toInt32(exec); double ms = (n >= 7) ? args.at(6).toNumber(exec) : 0; - return jsNumber(exec, gregorianDateTimeToMS(t, ms, true)); + return jsNumber(exec, gregorianDateTimeToMS(exec, t, ms, true)); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.h index dcef3cc..10e450e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class DateConstructor : public InternalFunction { public: - DateConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*); + DateConstructor(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, DatePrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConversion.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConversion.cpp index a725478..f129407 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConversion.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConversion.cpp @@ -43,6 +43,7 @@ #include "config.h" #include "DateConversion.h" +#include "CallFrame.h" #include "UString.h" #include <wtf/DateMath.h> #include <wtf/StringExtras.h> @@ -51,51 +52,51 @@ using namespace WTF; namespace JSC { -double parseDate(const UString &date) +double parseDate(ExecState* exec, const UString &date) { - return parseDateFromNullTerminatedCharacters(date.UTF8String().c_str()); + if (date == exec->globalData().cachedDateString) + return exec->globalData().cachedDateStringValue; + double value = parseDateFromNullTerminatedCharacters(exec, date.UTF8String().c_str()); + exec->globalData().cachedDateString = date; + exec->globalData().cachedDateStringValue = value; + return value; } -UString formatDate(const GregorianDateTime &t) +void formatDate(const GregorianDateTime &t, DateConversionBuffer& buffer) { - char buffer[100]; - snprintf(buffer, sizeof(buffer), "%s %s %02d %04d", + snprintf(buffer, DateConversionBufferSize, "%s %s %02d %04d", weekdayName[(t.weekDay + 6) % 7], monthName[t.month], t.monthDay, t.year + 1900); - return buffer; } -UString formatDateUTCVariant(const GregorianDateTime &t) +void formatDateUTCVariant(const GregorianDateTime &t, DateConversionBuffer& buffer) { - char buffer[100]; - snprintf(buffer, sizeof(buffer), "%s, %02d %s %04d", + snprintf(buffer, DateConversionBufferSize, "%s, %02d %s %04d", weekdayName[(t.weekDay + 6) % 7], t.monthDay, monthName[t.month], t.year + 1900); - return buffer; } -UString formatTime(const GregorianDateTime &t, bool utc) +void formatTime(const GregorianDateTime &t, DateConversionBuffer& buffer) { - char buffer[100]; - if (utc) { - snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT", t.hour, t.minute, t.second); - } else { - int offset = abs(gmtoffset(t)); - char timeZoneName[70]; - struct tm gtm = t; - strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m); + int offset = abs(gmtoffset(t)); + char timeZoneName[70]; + struct tm gtm = t; + strftime(timeZoneName, sizeof(timeZoneName), "%Z", >m); - if (timeZoneName[0]) { - snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d (%s)", - t.hour, t.minute, t.second, - gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, timeZoneName); - } else { - snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d GMT%c%02d%02d", - t.hour, t.minute, t.second, - gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60); - } + if (timeZoneName[0]) { + snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d (%s)", + t.hour, t.minute, t.second, + gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60, timeZoneName); + } else { + snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT%c%02d%02d", + t.hour, t.minute, t.second, + gmtoffset(t) < 0 ? '-' : '+', offset / (60*60), (offset / 60) % 60); } - return UString(buffer); +} + +void formatTimeUTC(const GregorianDateTime &t, DateConversionBuffer& buffer) +{ + snprintf(buffer, DateConversionBufferSize, "%02d:%02d:%02d GMT", t.hour, t.minute, t.second); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConversion.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConversion.h index 0d12815..ff32b50 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConversion.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateConversion.h @@ -42,18 +42,21 @@ #ifndef DateConversion_h #define DateConversion_h -namespace WTF { - struct GregorianDateTime; -} +#include "UString.h" namespace JSC { -class UString; +class ExecState; +struct GregorianDateTime; -double parseDate(const UString&); -UString formatDate(const WTF::GregorianDateTime&); -UString formatDateUTCVariant(const WTF::GregorianDateTime&); -UString formatTime(const WTF::GregorianDateTime&, bool inputIsUTC); +static const unsigned DateConversionBufferSize = 100; +typedef char DateConversionBuffer[DateConversionBufferSize]; + +double parseDate(ExecState* exec, const UString&); +void formatDate(const GregorianDateTime&, DateConversionBuffer&); +void formatDateUTCVariant(const GregorianDateTime&, DateConversionBuffer&); +void formatTime(const GregorianDateTime&, DateConversionBuffer&); +void formatTimeUTC(const GregorianDateTime&, DateConversionBuffer&); } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstance.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstance.cpp index 62791ae..77a92be 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstance.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstance.cpp @@ -22,6 +22,8 @@ #include "config.h" #include "DateInstance.h" +#include "JSGlobalObject.h" + #include <math.h> #include <wtf/DateMath.h> #include <wtf/MathExtras.h> @@ -30,89 +32,50 @@ using namespace WTF; namespace JSC { -struct DateInstance::Cache { - double m_gregorianDateTimeCachedForMS; - GregorianDateTime m_cachedGregorianDateTime; - double m_gregorianDateTimeUTCCachedForMS; - GregorianDateTime m_cachedGregorianDateTimeUTC; -}; - const ClassInfo DateInstance::info = {"Date", 0, 0, 0}; -DateInstance::DateInstance(PassRefPtr<Structure> structure) +DateInstance::DateInstance(ExecState* exec, NonNullPassRefPtr<Structure> structure) : JSWrapperObject(structure) - , m_cache(0) { + setInternalValue(jsNaN(exec)); } -DateInstance::~DateInstance() +DateInstance::DateInstance(ExecState* exec, double time) + : JSWrapperObject(exec->lexicalGlobalObject()->dateStructure()) { - delete m_cache; + setInternalValue(jsNumber(exec, timeClip(time))); } -void DateInstance::msToGregorianDateTime(double milli, bool outputIsUTC, GregorianDateTime& t) const -{ - if (!m_cache) { - m_cache = new Cache; - m_cache->m_gregorianDateTimeCachedForMS = NaN; - m_cache->m_gregorianDateTimeUTCCachedForMS = NaN; - } - - if (outputIsUTC) { - if (m_cache->m_gregorianDateTimeUTCCachedForMS != milli) { - WTF::msToGregorianDateTime(milli, true, m_cache->m_cachedGregorianDateTimeUTC); - m_cache->m_gregorianDateTimeUTCCachedForMS = milli; - } - t.copyFrom(m_cache->m_cachedGregorianDateTimeUTC); - } else { - if (m_cache->m_gregorianDateTimeCachedForMS != milli) { - WTF::msToGregorianDateTime(milli, false, m_cache->m_cachedGregorianDateTime); - m_cache->m_gregorianDateTimeCachedForMS = milli; - } - t.copyFrom(m_cache->m_cachedGregorianDateTime); - } -} - -bool DateInstance::getTime(GregorianDateTime& t, int& offset) const +const GregorianDateTime* DateInstance::calculateGregorianDateTime(ExecState* exec) const { double milli = internalNumber(); if (isnan(milli)) - return false; - - msToGregorianDateTime(milli, false, t); - offset = gmtoffset(t); - return true; + return 0; + + if (!m_data) + m_data = exec->globalData().dateInstanceCache.add(milli); + + if (m_data->m_gregorianDateTimeCachedForMS != milli) { + msToGregorianDateTime(exec, milli, false, m_data->m_cachedGregorianDateTime); + m_data->m_gregorianDateTimeCachedForMS = milli; + } + return &m_data->m_cachedGregorianDateTime; } -bool DateInstance::getUTCTime(GregorianDateTime& t) const +const GregorianDateTime* DateInstance::calculateGregorianDateTimeUTC(ExecState* exec) const { double milli = internalNumber(); if (isnan(milli)) - return false; - - msToGregorianDateTime(milli, true, t); - return true; -} + return 0; -bool DateInstance::getTime(double& milli, int& offset) const -{ - milli = internalNumber(); - if (isnan(milli)) - return false; - - GregorianDateTime t; - msToGregorianDateTime(milli, false, t); - offset = gmtoffset(t); - return true; -} + if (!m_data) + m_data = exec->globalData().dateInstanceCache.add(milli); -bool DateInstance::getUTCTime(double& milli) const -{ - milli = internalNumber(); - if (isnan(milli)) - return false; - - return true; + if (m_data->m_gregorianDateTimeUTCCachedForMS != milli) { + msToGregorianDateTime(exec, milli, true, m_data->m_cachedGregorianDateTimeUTC); + m_data->m_gregorianDateTimeUTCCachedForMS = milli; + } + return &m_data->m_cachedGregorianDateTimeUTC; } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstance.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstance.h index 3b73521..44b7521 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstance.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstance.h @@ -31,27 +31,41 @@ namespace JSC { class DateInstance : public JSWrapperObject { public: - explicit DateInstance(PassRefPtr<Structure>); - virtual ~DateInstance(); + DateInstance(ExecState*, double); + explicit DateInstance(ExecState*, NonNullPassRefPtr<Structure>); double internalNumber() const { return internalValue().uncheckedGetNumber(); } - bool getTime(WTF::GregorianDateTime&, int& offset) const; - bool getUTCTime(WTF::GregorianDateTime&) const; - bool getTime(double& milliseconds, int& offset) const; - bool getUTCTime(double& milliseconds) const; - - static const ClassInfo info; - - void msToGregorianDateTime(double, bool outputIsUTC, WTF::GregorianDateTime&) const; + static JS_EXPORTDATA const ClassInfo info; + + const GregorianDateTime* gregorianDateTime(ExecState* exec) const + { + if (m_data && m_data->m_gregorianDateTimeCachedForMS == internalNumber()) + return &m_data->m_cachedGregorianDateTime; + return calculateGregorianDateTime(exec); + } + + const GregorianDateTime* gregorianDateTimeUTC(ExecState* exec) const + { + if (m_data && m_data->m_gregorianDateTimeUTCCachedForMS == internalNumber()) + return &m_data->m_cachedGregorianDateTimeUTC; + return calculateGregorianDateTimeUTC(exec); + } + + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); + } + + protected: + static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags; private: + const GregorianDateTime* calculateGregorianDateTime(ExecState*) const; + const GregorianDateTime* calculateGregorianDateTimeUTC(ExecState*) const; virtual const ClassInfo* classInfo() const { return &info; } - using JSWrapperObject::internalValue; - - struct Cache; - mutable Cache* m_cache; + mutable RefPtr<DateInstanceData> m_data; }; DateInstance* asDateInstance(JSValue); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstanceCache.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstanceCache.h new file mode 100644 index 0000000..d208580 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DateInstanceCache.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2009 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 DateInstanceCache_h +#define DateInstanceCache_h + +#include <wtf/DateMath.h> +#include <wtf/HashFunctions.h> +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> + +namespace JSC { + + extern const double NaN; + + class DateInstanceData : public RefCounted<DateInstanceData> { + public: + static PassRefPtr<DateInstanceData> create() { return adoptRef(new DateInstanceData); } + + double m_gregorianDateTimeCachedForMS; + GregorianDateTime m_cachedGregorianDateTime; + double m_gregorianDateTimeUTCCachedForMS; + GregorianDateTime m_cachedGregorianDateTimeUTC; + + private: + DateInstanceData() + : m_gregorianDateTimeCachedForMS(NaN) + , m_gregorianDateTimeUTCCachedForMS(NaN) + { + } + }; + + class DateInstanceCache { + public: + DateInstanceCache() + { + reset(); + } + + void reset() + { + for (size_t i = 0; i < cacheSize; ++i) + m_cache[i].key = NaN; + } + + DateInstanceData* add(double d) + { + CacheEntry& entry = lookup(d); + if (d == entry.key) + return entry.value.get(); + + entry.key = d; + entry.value = DateInstanceData::create(); + return entry.value.get(); + } + + private: + static const size_t cacheSize = 16; + + struct CacheEntry { + double key; + RefPtr<DateInstanceData> value; + }; + + CacheEntry& lookup(double d) { return m_cache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; } + + CacheEntry m_cache[cacheSize]; + }; + +} // namespace JSC + +#endif // DateInstanceCache_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.cpp index c6f7dec..ca9d4ea 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.cpp @@ -28,7 +28,6 @@ #include "JSString.h" #include "ObjectPrototype.h" #include "DateInstance.h" -#include <float.h> #if !PLATFORM(MAC) && HAVE(LANGINFO_H) #include <langinfo.h> @@ -60,7 +59,7 @@ #include <CoreFoundation/CoreFoundation.h> #endif -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); //provided by libce #endif @@ -198,7 +197,7 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L { #if HAVE(LANGINFO_H) static const nl_item formats[] = { D_T_FMT, D_FMT, T_FMT }; -#elif (PLATFORM(WINCE) && !PLATFORM(QT)) || PLATFORM(SYMBIAN) +#elif (OS(WINCE) && !PLATFORM(QT)) || OS(SYMBIAN) // strftime() does not support '#' on WinCE or Symbian static const char* const formatStrings[] = { "%c", "%x", "%X" }; #else @@ -251,12 +250,12 @@ static JSCell* formatLocaleDate(ExecState* exec, const GregorianDateTime& gdt, L return jsNontrivialString(exec, timebuffer); } -static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double timeInMilliseconds, LocaleDateTimeFormat format, const ArgList&) +static JSCell* formatLocaleDate(ExecState* exec, DateInstance* dateObject, double, LocaleDateTimeFormat format, const ArgList&) { - GregorianDateTime gregorianDateTime; - const bool notUTC = false; - dateObject->msToGregorianDateTime(timeInMilliseconds, notUTC, gregorianDateTime); - return formatLocaleDate(exec, gregorianDateTime, format); + const GregorianDateTime* gregorianDateTime = dateObject->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNontrivialString(exec, "Invalid Date"); + return formatLocaleDate(exec, *gregorianDateTime, format); } #endif // !PLATFORM(MAC) @@ -395,10 +394,9 @@ const ClassInfo DatePrototype::info = {"Date", &DateInstance::info, 0, ExecState // ECMA 15.9.4 -DatePrototype::DatePrototype(ExecState* exec, PassRefPtr<Structure> structure) - : DateInstance(structure) +DatePrototype::DatePrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure) + : DateInstance(exec, structure) { - setInternalValue(jsNaN(exec)); // The constructor will be added later, after DateConstructor has been built. } @@ -420,16 +418,16 @@ JSValue JSC_HOST_CALL dateProtoFuncToString(ExecState* exec, JSObject*, JSValue if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNontrivialString(exec, "Invalid Date"); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNontrivialString(exec, formatDate(t) + " " + formatTime(t, utc)); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNontrivialString(exec, "Invalid Date"); + DateConversionBuffer date; + DateConversionBuffer time; + formatDate(*gregorianDateTime, date); + formatTime(*gregorianDateTime, time); + return jsNontrivialString(exec, makeString(date, " ", time)); } JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -437,16 +435,16 @@ JSValue JSC_HOST_CALL dateProtoFuncToUTCString(ExecState* exec, JSObject*, JSVal if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNontrivialString(exec, "Invalid Date"); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc)); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNontrivialString(exec, "Invalid Date"); + DateConversionBuffer date; + DateConversionBuffer time; + formatDateUTCVariant(*gregorianDateTime, date); + formatTimeUTC(*gregorianDateTime, time); + return jsNontrivialString(exec, makeString(date, " ", time)); } JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -454,19 +452,15 @@ JSValue JSC_HOST_CALL dateProtoFuncToISOString(ExecState* exec, JSObject*, JSVal if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (!isfinite(milli)) - return jsNontrivialString(exec, "Invalid Date"); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNontrivialString(exec, "Invalid Date"); // Maximum amount of space we need in buffer: 6 (max. digits in year) + 2 * 5 (2 characters each for month, day, hour, minute, second) + 4 (. + 3 digits for milliseconds) // 6 for formatting and one for null termination = 27. We add one extra character to allow us to force null termination. char buffer[28]; - snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + t.year, t.month + 1, t.monthDay, t.hour, t.minute, t.second, static_cast<int>(fmod(milli, 1000))); + snprintf(buffer, sizeof(buffer) - 1, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", 1900 + gregorianDateTime->year, gregorianDateTime->month + 1, gregorianDateTime->monthDay, gregorianDateTime->hour, gregorianDateTime->minute, gregorianDateTime->second, static_cast<int>(fmod(thisDateObj->internalNumber(), 1000))); buffer[sizeof(buffer) - 1] = 0; return jsNontrivialString(exec, buffer); } @@ -476,16 +470,14 @@ JSValue JSC_HOST_CALL dateProtoFuncToDateString(ExecState* exec, JSObject*, JSVa if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNontrivialString(exec, "Invalid Date"); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNontrivialString(exec, formatDate(t)); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNontrivialString(exec, "Invalid Date"); + DateConversionBuffer date; + formatDate(*gregorianDateTime, date); + return jsNontrivialString(exec, date); } JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -493,16 +485,14 @@ JSValue JSC_HOST_CALL dateProtoFuncToTimeString(ExecState* exec, JSObject*, JSVa if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNontrivialString(exec, "Invalid Date"); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNontrivialString(exec, formatTime(t, utc)); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNontrivialString(exec, "Invalid Date"); + DateConversionBuffer time; + formatTime(*gregorianDateTime, time); + return jsNontrivialString(exec, time); } JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -511,11 +501,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleString(ExecState* exec, JSObject*, JS return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNontrivialString(exec, "Invalid Date"); - - return formatLocaleDate(exec, thisDateObj, milli, LocaleDateAndTime, args); + return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDateAndTime, args); } JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -524,11 +510,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleDateString(ExecState* exec, JSObject* return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNontrivialString(exec, "Invalid Date"); - - return formatLocaleDate(exec, thisDateObj, milli, LocaleDate, args); + return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleDate, args); } JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -537,11 +519,7 @@ JSValue JSC_HOST_CALL dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject* return throwError(exec, TypeError); DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNontrivialString(exec, "Invalid Date"); - - return formatLocaleDate(exec, thisDateObj, milli, LocaleTime, args); + return formatLocaleDate(exec, thisDateObj, thisDateObj->internalNumber(), LocaleTime, args); } JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -549,12 +527,7 @@ JSValue JSC_HOST_CALL dateProtoFuncGetTime(ExecState* exec, JSObject*, JSValue t if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - - return jsNumber(exec, milli); + return asDateInstance(thisValue)->internalValue(); } JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -562,16 +535,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetFullYear(ExecState* exec, JSObject*, JSVal if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, 1900 + t.year); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, 1900 + gregorianDateTime->year); } JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -579,16 +548,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject*, JS if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, 1900 + t.year); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, 1900 + gregorianDateTime->year); } JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -596,16 +561,16 @@ JSValue JSC_HOST_CALL dateProtoFuncToGMTString(ExecState* exec, JSObject*, JSVal if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNontrivialString(exec, "Invalid Date"); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNontrivialString(exec, formatDateUTCVariant(t) + " " + formatTime(t, utc)); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNontrivialString(exec, "Invalid Date"); + DateConversionBuffer date; + DateConversionBuffer time; + formatDateUTCVariant(*gregorianDateTime, date); + formatTimeUTC(*gregorianDateTime, time); + return jsNontrivialString(exec, makeString(date, " ", time)); } JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -613,16 +578,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMonth(ExecState* exec, JSObject*, JSValue if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.month); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->month); } JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -630,16 +591,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMonth(ExecState* exec, JSObject*, JSVal if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.month); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->month); } JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -647,16 +604,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetDate(ExecState* exec, JSObject*, JSValue t if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.monthDay); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->monthDay); } JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -664,16 +617,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCDate(ExecState* exec, JSObject*, JSValu if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.monthDay); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->monthDay); } JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -681,16 +630,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetDay(ExecState* exec, JSObject*, JSValue th if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.weekDay); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->weekDay); } JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -698,16 +643,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCDay(ExecState* exec, JSObject*, JSValue if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.weekDay); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->weekDay); } JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -715,16 +656,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetHours(ExecState* exec, JSObject*, JSValue if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.hour); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->hour); } JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -732,16 +669,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCHours(ExecState* exec, JSObject*, JSVal if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.hour); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->hour); } JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -749,16 +682,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetMinutes(ExecState* exec, JSObject*, JSValu if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.minute); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->minute); } JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -766,16 +695,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject*, JSV if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.minute); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->minute); } JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -783,16 +708,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetSeconds(ExecState* exec, JSObject*, JSValu if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.second); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->second); } JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -800,16 +721,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject*, JSV if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = true; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, t.second); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTimeUTC(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, gregorianDateTime->second); } JSValue JSC_HOST_CALL dateProtoFuncGetMilliSeconds(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) @@ -847,16 +764,12 @@ JSValue JSC_HOST_CALL dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject*, if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); - return jsNumber(exec, -gmtoffset(t) / minutesPerHour); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNaN(exec); + return jsNumber(exec, -gregorianDateTime->utcOffset / minutesPerHour); } JSValue JSC_HOST_CALL dateProtoFuncSetTime(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -889,16 +802,21 @@ static JSValue setNewValueFromTimeArgs(ExecState* exec, JSValue thisValue, const double secs = floor(milli / msPerSecond); double ms = milli - secs * msPerSecond; - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t); + const GregorianDateTime* other = inputIsUTC + ? thisDateObj->gregorianDateTimeUTC(exec) + : thisDateObj->gregorianDateTime(exec); + if (!other) + return jsNaN(exec); - if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) { + GregorianDateTime gregorianDateTime; + gregorianDateTime.copyFrom(*other); + if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &gregorianDateTime)) { JSValue result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } - JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); + JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC)); thisDateObj->setInternalValue(result); return result; } @@ -916,26 +834,28 @@ static JSValue setNewValueFromDateArgs(ExecState* exec, JSValue thisValue, const } double milli = thisDateObj->internalNumber(); - double ms = 0; - - GregorianDateTime t; - if (numArgsToUse == 3 && isnan(milli)) - // Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear) - // the time must be reset to +0 if it is NaN. - thisDateObj->msToGregorianDateTime(0, true, t); - else { - double secs = floor(milli / msPerSecond); - ms = milli - secs * msPerSecond; - thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t); + double ms = 0; + + GregorianDateTime gregorianDateTime; + if (numArgsToUse == 3 && isnan(milli)) + msToGregorianDateTime(exec, 0, true, gregorianDateTime); + else { + ms = milli - floor(milli / msPerSecond) * msPerSecond; + const GregorianDateTime* other = inputIsUTC + ? thisDateObj->gregorianDateTimeUTC(exec) + : thisDateObj->gregorianDateTime(exec); + if (!other) + return jsNaN(exec); + gregorianDateTime.copyFrom(*other); } - if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) { + if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &gregorianDateTime)) { JSValue result = jsNaN(exec); thisDateObj->setInternalValue(result); return result; } - JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, inputIsUTC)); + JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, inputIsUTC)); thisDateObj->setInternalValue(result); return result; } @@ -1029,8 +949,6 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); if (args.isEmpty()) { JSValue result = jsNaN(exec); @@ -1041,15 +959,16 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t double milli = thisDateObj->internalNumber(); double ms = 0; - GregorianDateTime t; + GregorianDateTime gregorianDateTime; if (isnan(milli)) // Based on ECMA 262 B.2.5 (setYear) // the time must be reset to +0 if it is NaN. - thisDateObj->msToGregorianDateTime(0, true, t); + msToGregorianDateTime(exec, 0, true, gregorianDateTime); else { double secs = floor(milli / msPerSecond); ms = milli - secs * msPerSecond; - thisDateObj->msToGregorianDateTime(milli, utc, t); + if (const GregorianDateTime* other = thisDateObj->gregorianDateTime(exec)) + gregorianDateTime.copyFrom(*other); } bool ok = true; @@ -1060,8 +979,8 @@ JSValue JSC_HOST_CALL dateProtoFuncSetYear(ExecState* exec, JSObject*, JSValue t return result; } - t.year = (year > 99 || year < 0) ? year - 1900 : year; - JSValue result = jsNumber(exec, gregorianDateTimeToMS(t, ms, utc)); + gregorianDateTime.year = (year > 99 || year < 0) ? year - 1900 : year; + JSValue result = jsNumber(exec, gregorianDateTimeToMS(exec, gregorianDateTime, ms, false)); thisDateObj->setInternalValue(result); return result; } @@ -1071,18 +990,14 @@ JSValue JSC_HOST_CALL dateProtoFuncGetYear(ExecState* exec, JSObject*, JSValue t if (!thisValue.inherits(&DateInstance::info)) return throwError(exec, TypeError); - const bool utc = false; - DateInstance* thisDateObj = asDateInstance(thisValue); - double milli = thisDateObj->internalNumber(); - if (isnan(milli)) - return jsNaN(exec); - GregorianDateTime t; - thisDateObj->msToGregorianDateTime(milli, utc, t); + const GregorianDateTime* gregorianDateTime = thisDateObj->gregorianDateTime(exec); + if (!gregorianDateTime) + return jsNaN(exec); // NOTE: IE returns the full year even in getYear. - return jsNumber(exec, t.year); + return jsNumber(exec, gregorianDateTime->year); } JSValue JSC_HOST_CALL dateProtoFuncToJSON(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.h index 12fabda..f565775 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/DatePrototype.h @@ -29,7 +29,7 @@ namespace JSC { class DatePrototype : public DateInstance { public: - DatePrototype(ExecState*, PassRefPtr<Structure>); + DatePrototype(ExecState*, NonNullPassRefPtr<Structure>); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); @@ -39,8 +39,12 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultGetPropertyNames)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | DateInstance::StructureFlags; + }; } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorConstructor.cpp index 07b7e23..b9c3f58 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorConstructor.cpp @@ -29,7 +29,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(ErrorConstructor); -ErrorConstructor::ErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, ErrorPrototype* errorPrototype) +ErrorConstructor::ErrorConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ErrorPrototype* errorPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, errorPrototype->classInfo()->className)) { // ECMA 15.11.3.1 Error.prototype diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorConstructor.h index 2dd4124..e3d789b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorConstructor.h @@ -30,7 +30,7 @@ namespace JSC { class ErrorConstructor : public InternalFunction { public: - ErrorConstructor(ExecState*, PassRefPtr<Structure>, ErrorPrototype*); + ErrorConstructor(ExecState*, NonNullPassRefPtr<Structure>, ErrorPrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorInstance.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorInstance.cpp index 2e2cdce..1cdb87a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorInstance.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorInstance.cpp @@ -25,7 +25,7 @@ namespace JSC { const ClassInfo ErrorInstance::info = { "Error", 0, 0, 0 }; -ErrorInstance::ErrorInstance(PassRefPtr<Structure> structure) +ErrorInstance::ErrorInstance(NonNullPassRefPtr<Structure> structure) : JSObject(structure) { } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorInstance.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorInstance.h index 6f9d262..9f53b51 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorInstance.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorInstance.h @@ -27,7 +27,7 @@ namespace JSC { class ErrorInstance : public JSObject { public: - explicit ErrorInstance(PassRefPtr<Structure>); + explicit ErrorInstance(NonNullPassRefPtr<Structure>); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorPrototype.cpp index 599390e..be9e4b8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorPrototype.cpp @@ -34,7 +34,7 @@ ASSERT_CLASS_FITS_IN_CELL(ErrorPrototype); static JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState*, JSObject*, JSValue, const ArgList&); // ECMA 15.9.4 -ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) +ErrorPrototype::ErrorPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) : ErrorInstance(structure) { // The constructor will be added later in ErrorConstructor's constructor @@ -48,21 +48,19 @@ ErrorPrototype::ErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, JSValue JSC_HOST_CALL errorProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { JSObject* thisObj = thisValue.toThisObject(exec); + JSValue name = thisObj->get(exec, exec->propertyNames().name); + JSValue message = thisObj->get(exec, exec->propertyNames().message); - UString s = "Error"; + // Mozilla-compatible format. - JSValue v = thisObj->get(exec, exec->propertyNames().name); - if (!v.isUndefined()) - s = v.toString(exec); - - v = thisObj->get(exec, exec->propertyNames().message); - if (!v.isUndefined()) { - // Mozilla-compatible format. - s += ": "; - s += v.toString(exec); + if (!name.isUndefined()) { + if (!message.isUndefined()) + return jsNontrivialString(exec, makeString(name.toString(exec), ": ", message.toString(exec))); + return jsNontrivialString(exec, name.toString(exec)); } - - return jsNontrivialString(exec, s); + if (!message.isUndefined()) + return jsNontrivialString(exec, makeString("Error: ", message.toString(exec))); + return jsNontrivialString(exec, "Error"); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorPrototype.h index 53d12d9..a561590 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ErrorPrototype.h @@ -29,7 +29,7 @@ namespace JSC { class ErrorPrototype : public ErrorInstance { public: - ErrorPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); + ErrorPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure); }; } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.cpp index cc18b95..9bb740e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -66,15 +66,18 @@ JSValue createStackOverflowError(ExecState* exec) return createError(exec, RangeError, "Maximum call stack size exceeded."); } +JSValue createTypeError(ExecState* exec, const char* message) +{ + return createError(exec, TypeError, message); +} + JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, unsigned bytecodeOffset, CodeBlock* codeBlock) { int startOffset = 0; int endOffset = 0; int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - UString message = "Can't find variable: "; - message.append(ident.ustring()); - JSObject* exception = Error::create(exec, ReferenceError, message, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); + JSObject* exception = Error::create(exec, ReferenceError, makeString("Can't find variable: ", ident.ustring()), line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionEndOffsetPropertyName), jsNumber(exec, divotPoint + endOffset), ReadOnly | DontDelete); @@ -83,59 +86,36 @@ JSValue createUndefinedVariableError(ExecState* exec, const Identifier& ident, u static UString createErrorMessage(ExecState* exec, CodeBlock* codeBlock, int, int expressionStart, int expressionStop, JSValue value, UString error) { - if (!expressionStop || expressionStart > codeBlock->source()->length()) { - UString errorText = value.toString(exec); - errorText.append(" is "); - errorText.append(error); - return errorText; - } + if (!expressionStop || expressionStart > codeBlock->source()->length()) + return makeString(value.toString(exec), " is ", error); + if (expressionStart < expressionStop) + return makeString("Result of expression '", codeBlock->source()->getRange(expressionStart, expressionStop), "' [", value.toString(exec), "] is ", error, "."); - UString errorText = "Result of expression "; - - if (expressionStart < expressionStop) { - errorText.append('\''); - errorText.append(codeBlock->source()->getRange(expressionStart, expressionStop)); - errorText.append("' ["); - errorText.append(value.toString(exec)); - errorText.append("] is "); - } else { - // No range information, so give a few characters of context - const UChar* data = codeBlock->source()->data(); - int dataLength = codeBlock->source()->length(); - int start = expressionStart; - int stop = expressionStart; - // Get up to 20 characters of context to the left and right of the divot, clamping to the line. - // then strip whitespace. - while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n') - start--; - while (start < (expressionStart - 1) && isStrWhiteSpace(data[start])) - start++; - while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n') - stop++; - while (stop > expressionStart && isStrWhiteSpace(data[stop])) - stop--; - errorText.append("near '..."); - errorText.append(codeBlock->source()->getRange(start, stop)); - errorText.append("...' ["); - errorText.append(value.toString(exec)); - errorText.append("] is "); - } - errorText.append(error); - errorText.append("."); - return errorText; + // No range information, so give a few characters of context + const UChar* data = codeBlock->source()->data(); + int dataLength = codeBlock->source()->length(); + int start = expressionStart; + int stop = expressionStart; + // Get up to 20 characters of context to the left and right of the divot, clamping to the line. + // then strip whitespace. + while (start > 0 && (expressionStart - start < 20) && data[start - 1] != '\n') + start--; + while (start < (expressionStart - 1) && isStrWhiteSpace(data[start])) + start++; + while (stop < dataLength && (stop - expressionStart < 20) && data[stop] != '\n') + stop++; + while (stop > expressionStart && isStrWhiteSpace(data[stop])) + stop--; + return makeString("Result of expression near '...", codeBlock->source()->getRange(start, stop), "...' [", value.toString(exec), "] is ", error, "."); } JSObject* createInvalidParamError(ExecState* exec, const char* op, JSValue value, unsigned bytecodeOffset, CodeBlock* codeBlock) { - UString message = "not a valid argument for '"; - message.append(op); - message.append("'"); - int startOffset = 0; int endOffset = 0; int divotPoint = 0; int line = codeBlock->expressionRangeForBytecodeOffset(exec, bytecodeOffset, divotPoint, startOffset, endOffset); - UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, message); + UString errorMessage = createErrorMessage(exec, codeBlock, line, divotPoint, divotPoint + endOffset, value, makeString("not a valid argument for '", op, "'")); JSObject* exception = Error::create(exec, TypeError, errorMessage, line, codeBlock->ownerExecutable()->sourceID(), codeBlock->ownerExecutable()->sourceURL()); exception->putWithAttributes(exec, Identifier(exec, expressionBeginOffsetPropertyName), jsNumber(exec, divotPoint - startOffset), ReadOnly | DontDelete); exception->putWithAttributes(exec, Identifier(exec, expressionCaretOffsetPropertyName), jsNumber(exec, divotPoint), ReadOnly | DontDelete); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.h index 4c5bec1..e739d09 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ExceptionHelpers.h @@ -44,6 +44,7 @@ namespace JSC { JSValue createInterruptedExecutionException(JSGlobalData*); JSValue createStackOverflowError(ExecState*); + JSValue createTypeError(ExecState*, const char* message); JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*); JSNotAnObjectErrorStub* createNotAnObjectErrorStub(ExecState*, bool isNull); JSObject* createInvalidParamError(ExecState*, const char* op, JSValue, unsigned bytecodeOffset, CodeBlock*); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp index 7586746..bc18cc9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.cpp @@ -30,6 +30,7 @@ #include "CodeBlock.h" #include "JIT.h" #include "Parser.h" +#include "StringBuilder.h" #include "Vector.h" namespace JSC { @@ -265,14 +266,13 @@ PassRefPtr<FunctionExecutable> FunctionExecutable::fromGlobalCode(const Identifi UString FunctionExecutable::paramString() const { FunctionParameters& parameters = *m_parameters; - UString s(""); + StringBuilder builder; for (size_t pos = 0; pos < parameters.size(); ++pos) { - if (!s.isEmpty()) - s += ", "; - s += parameters[pos].ustring(); + if (!builder.isEmpty()) + builder.append(", "); + builder.append(parameters[pos].ustring()); } - - return s; + return builder.release(); } }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h index 76764f9..d1d38de 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Executable.h @@ -158,11 +158,6 @@ namespace JSC { class EvalExecutable : public ScriptExecutable { public: - EvalExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source) - , m_evalCodeBlock(0) - { - } ~EvalExecutable(); @@ -181,6 +176,11 @@ namespace JSC { static PassRefPtr<EvalExecutable> create(ExecState* exec, const SourceCode& source) { return adoptRef(new EvalExecutable(exec, source)); } private: + EvalExecutable(ExecState* exec, const SourceCode& source) + : ScriptExecutable(exec, source) + , m_evalCodeBlock(0) + { + } EvalCodeBlock* m_evalCodeBlock; #if ENABLE(JIT) @@ -199,12 +199,11 @@ namespace JSC { class ProgramExecutable : public ScriptExecutable { public: - ProgramExecutable(ExecState* exec, const SourceCode& source) - : ScriptExecutable(exec, source) - , m_programCodeBlock(0) + static PassRefPtr<ProgramExecutable> create(ExecState* exec, const SourceCode& source) { + return adoptRef(new ProgramExecutable(exec, source)); } - + ~ProgramExecutable(); ProgramCodeBlock& bytecode(ExecState* exec, ScopeChainNode* scopeChainNode) @@ -223,6 +222,11 @@ namespace JSC { ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*) { ASSERT_NOT_REACHED(); return 0; } private: + ProgramExecutable(ExecState* exec, const SourceCode& source) + : ScriptExecutable(exec, source) + , m_programCodeBlock(0) + { + } ProgramCodeBlock* m_programCodeBlock; #if ENABLE(JIT) @@ -282,7 +286,9 @@ namespace JSC { size_t parameterCount() const { return m_parameters->size(); } size_t variableCount() const { return m_numVariables; } UString paramString() const; +#ifdef QT_BUILD_SCRIPT_LIB UString parameterName(int i) const { return (*m_parameters)[i].ustring(); } +#endif void recompile(ExecState*); ExceptionInfo* reparseExceptionInfo(JSGlobalData*, ScopeChainNode*, CodeBlock*); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.cpp index d5eb20f..9d55dd1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.cpp @@ -21,20 +21,21 @@ #include "config.h" #include "FunctionConstructor.h" +#include "Debugger.h" #include "FunctionPrototype.h" #include "JSFunction.h" #include "JSGlobalObject.h" #include "JSString.h" -#include "Parser.h" -#include "Debugger.h" #include "Lexer.h" #include "Nodes.h" +#include "Parser.h" +#include "StringBuilder.h" namespace JSC { ASSERT_CLASS_FITS_IN_CELL(FunctionConstructor); -FunctionConstructor::FunctionConstructor(ExecState* exec, PassRefPtr<Structure> structure, FunctionPrototype* functionPrototype) +FunctionConstructor::FunctionConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, FunctionPrototype* functionPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, functionPrototype->classInfo()->className)) { putDirectWithoutTransition(exec->propertyNames().prototype, functionPrototype, DontEnum | DontDelete | ReadOnly); @@ -76,12 +77,19 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi if (args.isEmpty()) program = "(function() { \n})"; else if (args.size() == 1) - program = "(function() { " + args.at(0).toString(exec) + "\n})"; + program = makeString("(function() { ", args.at(0).toString(exec), "\n})"); else { - program = "(function(" + args.at(0).toString(exec); - for (size_t i = 1; i < args.size() - 1; i++) - program += "," + args.at(i).toString(exec); - program += ") { " + args.at(args.size() - 1).toString(exec) + "\n})"; + StringBuilder builder; + builder.append("(function("); + builder.append(args.at(0).toString(exec)); + for (size_t i = 1; i < args.size() - 1; i++) { + builder.append(","); + builder.append(args.at(i).toString(exec)); + } + builder.append(") { "); + builder.append(args.at(args.size() - 1).toString(exec)); + builder.append("\n})"); + program = builder.release(); } int errLine; @@ -92,7 +100,7 @@ JSObject* constructFunction(ExecState* exec, const ArgList& args, const Identifi return throwError(exec, SyntaxError, errMsg, errLine, source.provider()->asID(), source.provider()->url()); JSGlobalObject* globalObject = exec->lexicalGlobalObject(); - ScopeChain scopeChain(globalObject, globalObject->globalData(), exec->globalThisValue()); + ScopeChain scopeChain(globalObject, globalObject->globalData(), globalObject, exec->globalThisValue()); return new (exec) JSFunction(exec, function, scopeChain.node()); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.h index e8486dc..197f320 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class FunctionConstructor : public InternalFunction { public: - FunctionConstructor(ExecState*, PassRefPtr<Structure>, FunctionPrototype*); + FunctionConstructor(ExecState*, NonNullPassRefPtr<Structure>, FunctionPrototype*); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.cpp index 1df998d..00f307e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -37,7 +37,7 @@ static JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState*, JSObject*, JS static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, const ArgList&); -FunctionPrototype::FunctionPrototype(ExecState* exec, PassRefPtr<Structure> structure) +FunctionPrototype::FunctionPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure) : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier) { putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum); @@ -76,7 +76,7 @@ static inline void insertSemicolonIfNeeded(UString& functionBody) UChar ch = functionBody[i]; if (!Lexer::isWhiteSpace(ch) && !Lexer::isLineTerminator(ch)) { if (ch != ';' && ch != '}') - functionBody = functionBody.substr(0, i + 1) + ";" + functionBody.substr(i + 1, functionBody.size() - (i + 1)); + functionBody = makeString(functionBody.substr(0, i + 1), ";", functionBody.substr(i + 1, functionBody.size() - (i + 1))); return; } } @@ -90,13 +90,13 @@ JSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec, JSObject*, JSVa FunctionExecutable* executable = function->jsExecutable(); UString sourceString = executable->source().toString(); insertSemicolonIfNeeded(sourceString); - return jsString(exec, "function " + function->name(&exec->globalData()) + "(" + executable->paramString() + ") " + sourceString); + return jsString(exec, makeString("function ", function->name(exec), "(", executable->paramString(), ") ", sourceString)); } } if (thisValue.inherits(&InternalFunction::info)) { InternalFunction* function = asInternalFunction(thisValue); - return jsString(exec, "function " + function->name(&exec->globalData()) + "() {\n [native code]\n}"); + return jsString(exec, makeString("function ", function->name(exec), "() {\n [native code]\n}")); } #ifdef QT_BUILD_SCRIPT_LIB //same error message as in the old engine, and in mozilla diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.h index 469191e..d1d6a1d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/FunctionPrototype.h @@ -29,12 +29,12 @@ namespace JSC { class FunctionPrototype : public InternalFunction { public: - FunctionPrototype(ExecState*, PassRefPtr<Structure>); + FunctionPrototype(ExecState*, NonNullPassRefPtr<Structure>); void addFunctionProperties(ExecState*, Structure* prototypeFunctionStructure, NativeFunctionWrapper** callFunction, NativeFunctionWrapper** applyFunction); static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); } private: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.h index 73dd854..68e9ea3 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GetterSetter.h @@ -50,7 +50,7 @@ namespace JSC { void setSetter(JSObject* setter) { m_setter = setter; } static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(GetterSetterType)); + return Structure::create(prototype, TypeInfo(GetterSetterType, OverridesMarkChildren)); } private: virtual bool isGetterSetter() const; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.cpp index 3074f95..c26002b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.cpp @@ -32,7 +32,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(GlobalEvalFunction); -GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, PassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject) +GlobalEvalFunction::GlobalEvalFunction(ExecState* exec, NonNullPassRefPtr<Structure> structure, int len, const Identifier& name, NativeFunction function, JSGlobalObject* cachedGlobalObject) : PrototypeFunction(exec, structure, len, name, function) , m_cachedGlobalObject(cachedGlobalObject) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.h index c56b0dc..389b1c3 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/GlobalEvalFunction.h @@ -32,14 +32,17 @@ namespace JSC { class GlobalEvalFunction : public PrototypeFunction { public: - GlobalEvalFunction(ExecState*, PassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); + GlobalEvalFunction(ExecState*, NonNullPassRefPtr<Structure>, int len, const Identifier&, NativeFunction, JSGlobalObject* expectedThisObject); JSGlobalObject* cachedGlobalObject() const { return m_cachedGlobalObject; } static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } + protected: + static const unsigned StructureFlags = ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | PrototypeFunction::StructureFlags; + private: virtual void markChildren(MarkStack&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.cpp index 7db723b..747c4ac 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.cpp @@ -28,6 +28,8 @@ #include <wtf/FastMalloc.h> #include <wtf/HashSet.h> +using WTF::ThreadSpecific; + namespace JSC { typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable; @@ -38,13 +40,13 @@ public: { HashSet<UString::Rep*>::iterator end = m_table.end(); for (HashSet<UString::Rep*>::iterator iter = m_table.begin(); iter != end; ++iter) - (*iter)->setIdentifierTable(0); + (*iter)->setIsIdentifier(false); } std::pair<HashSet<UString::Rep*>::iterator, bool> add(UString::Rep* value) { std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add(value); - (*result.first)->setIdentifierTable(this); + (*result.first)->setIsIdentifier(true); return result; } @@ -52,7 +54,7 @@ public: std::pair<HashSet<UString::Rep*>::iterator, bool> add(U value) { std::pair<HashSet<UString::Rep*>::iterator, bool> result = m_table.add<U, V>(value); - (*result.first)->setIdentifierTable(this); + (*result.first)->setIsIdentifier(true); return result; } @@ -77,7 +79,7 @@ void deleteIdentifierTable(IdentifierTable* table) bool Identifier::equal(const UString::Rep* r, const char* s) { - int length = r->len; + int length = r->size(); const UChar* d = r->data(); for (int i = 0; i != length; ++i) if (d[i] != (unsigned char)s[i]) @@ -87,7 +89,7 @@ bool Identifier::equal(const UString::Rep* r, const char* s) bool Identifier::equal(const UString::Rep* r, const UChar* s, int length) { - if (r->len != length) + if (r->size() != length) return false; const UChar* d = r->data(); for (int i = 0; i != length; ++i) @@ -110,13 +112,11 @@ struct CStringTranslator { static void translate(UString::Rep*& location, const char* c, unsigned hash) { size_t length = strlen(c); - UChar* d = static_cast<UChar*>(fastMalloc(sizeof(UChar) * length)); + UChar* d; + UString::Rep* r = UString::Rep::createUninitialized(length, d).releaseRef(); for (size_t i = 0; i != length; i++) d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend - - UString::Rep* r = UString::Rep::create(d, static_cast<int>(length)).releaseRef(); - r->_hash = hash; - + r->setHash(hash); location = r; } }; @@ -175,13 +175,11 @@ struct UCharBufferTranslator { static void translate(UString::Rep*& location, const UCharBuffer& buf, unsigned hash) { - UChar* d = static_cast<UChar*>(fastMalloc(sizeof(UChar) * buf.length)); + UChar* d; + UString::Rep* r = UString::Rep::createUninitialized(buf.length, d).releaseRef(); for (unsigned i = 0; i != buf.length; i++) d[i] = buf.s[i]; - - UString::Rep* r = UString::Rep::create(d, buf.length).releaseRef(); - r->_hash = hash; - + r->setHash(hash); location = r; } }; @@ -212,19 +210,19 @@ PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int le PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r) { - ASSERT(!r->identifierTable()); - if (r->len == 1) { + ASSERT(!r->isIdentifier()); + if (r->size() == 1) { UChar c = r->data()[0]; if (c <= 0xFF) r = globalData->smallStrings.singleCharacterStringRep(c); - if (r->identifierTable()) { + if (r->isIdentifier()) { #ifndef NDEBUG checkSameIdentifierTable(globalData, r); #endif return r; } } - if (!r->len) { + if (!r->size()) { UString::Rep::empty().hash(); return &UString::Rep::empty(); } @@ -238,19 +236,19 @@ PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep* void Identifier::remove(UString::Rep* r) { - r->identifierTable()->remove(r); + currentIdentifierTable()->remove(r); } #ifndef NDEBUG -void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep* rep) +void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep*) { - ASSERT(rep->identifierTable() == exec->globalData().identifierTable); + ASSERT_UNUSED(exec, exec->globalData().identifierTable == currentIdentifierTable()); } -void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep* rep) +void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep*) { - ASSERT(rep->identifierTable() == globalData->identifierTable); + ASSERT_UNUSED(globalData, globalData->identifierTable == currentIdentifierTable()); } #else @@ -265,4 +263,30 @@ void Identifier::checkSameIdentifierTable(JSGlobalData*, UString::Rep*) #endif +ThreadSpecific<ThreadIdentifierTableData>* g_identifierTableSpecific = 0; + +#if ENABLE(JSC_MULTIPLE_THREADS) + +pthread_once_t createIdentifierTableSpecificOnce = PTHREAD_ONCE_INIT; +static void createIdentifierTableSpecificCallback() +{ + ASSERT(!g_identifierTableSpecific); + g_identifierTableSpecific = new ThreadSpecific<ThreadIdentifierTableData>(); +} +void createIdentifierTableSpecific() +{ + pthread_once(&createIdentifierTableSpecificOnce, createIdentifierTableSpecificCallback); + ASSERT(g_identifierTableSpecific); +} + +#else + +void createIdentifierTableSpecific() +{ + ASSERT(!g_identifierTableSpecific); + g_identifierTableSpecific = new ThreadSpecific<ThreadIdentifierTableData>(); +} + +#endif + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.h index 2249179..1d1bd18 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Identifier.h @@ -22,6 +22,7 @@ #define Identifier_h #include "JSGlobalData.h" +#include "ThreadSpecific.h" #include "UString.h" namespace JSC { @@ -92,7 +93,7 @@ namespace JSC { static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r) { - if (r->identifierTable()) { + if (r->isIdentifier()) { #ifndef NDEBUG checkSameIdentifierTable(exec, r); #endif @@ -102,7 +103,7 @@ namespace JSC { } static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r) { - if (r->identifierTable()) { + if (r->isIdentifier()) { #ifndef NDEBUG checkSameIdentifierTable(globalData, r); #endif @@ -141,6 +142,67 @@ namespace JSC { IdentifierTable* createIdentifierTable(); void deleteIdentifierTable(IdentifierTable*); + struct ThreadIdentifierTableData { + ThreadIdentifierTableData() + : defaultIdentifierTable(0) + , currentIdentifierTable(0) + { + } + + IdentifierTable* defaultIdentifierTable; + IdentifierTable* currentIdentifierTable; + }; + + extern WTF::ThreadSpecific<ThreadIdentifierTableData>* g_identifierTableSpecific; + void createIdentifierTableSpecific(); + + inline IdentifierTable* defaultIdentifierTable() + { + if (!g_identifierTableSpecific) + createIdentifierTableSpecific(); + ThreadIdentifierTableData& data = **g_identifierTableSpecific; + + return data.defaultIdentifierTable; + } + + inline void setDefaultIdentifierTable(IdentifierTable* identifierTable) + { + if (!g_identifierTableSpecific) + createIdentifierTableSpecific(); + ThreadIdentifierTableData& data = **g_identifierTableSpecific; + + data.defaultIdentifierTable = identifierTable; + } + + inline IdentifierTable* currentIdentifierTable() + { + if (!g_identifierTableSpecific) + createIdentifierTableSpecific(); + ThreadIdentifierTableData& data = **g_identifierTableSpecific; + + return data.currentIdentifierTable; + } + + inline IdentifierTable* setCurrentIdentifierTable(IdentifierTable* identifierTable) + { + if (!g_identifierTableSpecific) + createIdentifierTableSpecific(); + ThreadIdentifierTableData& data = **g_identifierTableSpecific; + + IdentifierTable* oldIdentifierTable = data.currentIdentifierTable; + data.currentIdentifierTable = identifierTable; + return oldIdentifierTable; + } + + inline void resetCurrentIdentifierTable() + { + if (!g_identifierTableSpecific) + createIdentifierTableSpecific(); + ThreadIdentifierTableData& data = **g_identifierTableSpecific; + + data.currentIdentifierTable = data.defaultIdentifierTable; + } + } // namespace JSC #endif // Identifier_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InitializeThreading.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InitializeThreading.cpp index fea89f8..2605a9a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InitializeThreading.cpp @@ -41,7 +41,7 @@ using namespace WTF; namespace JSC { -#if PLATFORM(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS) +#if OS(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS) static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT; #endif @@ -49,15 +49,16 @@ static void initializeThreadingOnce() { WTF::initializeThreading(); initializeUString(); + JSGlobalData::storeVPtrs(); #if ENABLE(JSC_MULTIPLE_THREADS) s_dtoaP5Mutex = new Mutex; - WTF::initializeDates(); + initializeDates(); #endif } void initializeThreading() { -#if PLATFORM(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS) +#if OS(DARWIN) && ENABLE(JSC_MULTIPLE_THREADS) pthread_once(&initializeThreadingKeyOnce, initializeThreadingOnce); #else static bool initializedThreading = false; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.cpp index b5c9571..c48d628 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.cpp @@ -37,35 +37,35 @@ const ClassInfo* InternalFunction::classInfo() const return &info; } -InternalFunction::InternalFunction(JSGlobalData* globalData, PassRefPtr<Structure> structure, const Identifier& name) +InternalFunction::InternalFunction(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const Identifier& name) : JSObject(structure) { putDirect(globalData->propertyNames->name, jsString(globalData, name.ustring()), DontDelete | ReadOnly | DontEnum); } -const UString& InternalFunction::name(JSGlobalData* globalData) +const UString& InternalFunction::name(ExecState* exec) { - return asString(getDirect(globalData->propertyNames->name))->value(); + return asString(getDirect(exec->globalData().propertyNames->name))->value(exec); } -const UString InternalFunction::displayName(JSGlobalData* globalData) +const UString InternalFunction::displayName(ExecState* exec) { - JSValue displayName = getDirect(globalData->propertyNames->displayName); + JSValue displayName = getDirect(exec->globalData().propertyNames->displayName); - if (displayName && isJSString(globalData, displayName)) - return asString(displayName)->value(); + if (displayName && isJSString(&exec->globalData(), displayName)) + return asString(displayName)->value(exec); return UString::null(); } -const UString InternalFunction::calculatedDisplayName(JSGlobalData* globalData) +const UString InternalFunction::calculatedDisplayName(ExecState* exec) { - const UString explicitName = displayName(globalData); + const UString explicitName = displayName(exec); if (!explicitName.isEmpty()) return explicitName; - return name(globalData); + return name(exec); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.h index 37077f6..fa1e5aa 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/InternalFunction.h @@ -36,18 +36,20 @@ namespace JSC { virtual const ClassInfo* classInfo() const; static JS_EXPORTDATA const ClassInfo info; - const UString& name(JSGlobalData*); - const UString displayName(JSGlobalData*); - const UString calculatedDisplayName(JSGlobalData*); + const UString& name(ExecState*); + const UString displayName(ExecState*); + const UString calculatedDisplayName(ExecState*); static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasStandardGetOwnPropertySlot | HasDefaultMark)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); } protected: - InternalFunction(PassRefPtr<Structure> structure) : JSObject(structure) { } - InternalFunction(JSGlobalData*, PassRefPtr<Structure>, const Identifier&); + static const unsigned StructureFlags = ImplementsHasInstance | JSObject::StructureFlags; + + InternalFunction(NonNullPassRefPtr<Structure> structure) : JSObject(structure) { } + InternalFunction(JSGlobalData*, NonNullPassRefPtr<Structure>, const Identifier&); private: virtual CallType getCallData(CallData&) = 0; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.h index 88a8493..aca550e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSAPIValueWrapper.h @@ -39,7 +39,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(CompoundType)); + return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren | OverridesGetPropertyNames)); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.cpp index d989a89..22fdaaf 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.cpp @@ -39,7 +39,7 @@ ASSERT_CLASS_FITS_IN_CELL(JSActivation); const ClassInfo JSActivation::info = { "JSActivation", 0, 0, 0 }; -JSActivation::JSActivation(CallFrame* callFrame, PassRefPtr<FunctionExecutable> functionExecutable) +JSActivation::JSActivation(CallFrame* callFrame, NonNullPassRefPtr<FunctionExecutable> functionExecutable) : Base(callFrame->globalData().activationStructure, new JSActivationData(functionExecutable, callFrame->registers())) { } @@ -121,12 +121,12 @@ void JSActivation::putWithAttributes(ExecState* exec, const Identifier& property JSObject::putWithAttributes(exec, propertyName, value, attributes, true, slot); } -bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) +bool JSActivation::deleteProperty(ExecState* exec, const Identifier& propertyName) { if (propertyName == exec->propertyNames().arguments) return false; - return Base::deleteProperty(exec, propertyName, checkDontDelete); + return Base::deleteProperty(exec, propertyName); } JSObject* JSActivation::toThisObject(ExecState* exec) const diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.h index 90815a1..ee98191 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSActivation.h @@ -43,7 +43,7 @@ namespace JSC { class JSActivation : public JSVariableObject { typedef JSVariableObject Base; public: - JSActivation(CallFrame*, PassRefPtr<FunctionExecutable>); + JSActivation(CallFrame*, NonNullPassRefPtr<FunctionExecutable>); virtual ~JSActivation(); virtual void markChildren(MarkStack&); @@ -57,7 +57,7 @@ namespace JSC { virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual JSObject* toThisObject(ExecState*) const; @@ -66,11 +66,14 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); } + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; private: struct JSActivationData : public JSVariableObjectData { - JSActivationData(PassRefPtr<FunctionExecutable> _functionExecutable, Register* registers) + JSActivationData(NonNullPassRefPtr<FunctionExecutable> _functionExecutable, Register* registers) : JSVariableObjectData(_functionExecutable->generatedBytecode().symbolTable(), registers) , functionExecutable(_functionExecutable) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.cpp index 9e0ab59..2be7371 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.cpp @@ -130,7 +130,7 @@ inline void JSArray::checkConsistency(ConsistencyCheckType) #endif -JSArray::JSArray(PassRefPtr<Structure> structure) +JSArray::JSArray(NonNullPassRefPtr<Structure> structure) : JSObject(structure) { unsigned initialCapacity = 0; @@ -141,7 +141,7 @@ JSArray::JSArray(PassRefPtr<Structure> structure) checkConsistency(); } -JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength) +JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength) : JSObject(structure) { unsigned initialCapacity = min(initialLength, MIN_SPARSE_ARRAY_INDEX); @@ -152,6 +152,7 @@ JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength) m_storage->m_numValuesInVector = 0; m_storage->m_sparseValueMap = 0; m_storage->lazyCreationData = 0; + m_storage->reportedMapCapacity = 0; JSValue* vector = m_storage->m_vector; for (size_t i = 0; i < initialCapacity; ++i) @@ -162,7 +163,7 @@ JSArray::JSArray(PassRefPtr<Structure> structure, unsigned initialLength) Heap::heap(this)->reportExtraMemoryCost(initialCapacity * sizeof(JSValue)); } -JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list) +JSArray::JSArray(NonNullPassRefPtr<Structure> structure, const ArgList& list) : JSObject(structure) { unsigned initialCapacity = list.size(); @@ -172,6 +173,8 @@ JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list) m_vectorLength = initialCapacity; m_storage->m_numValuesInVector = initialCapacity; m_storage->m_sparseValueMap = 0; + m_storage->lazyCreationData = 0; + m_storage->reportedMapCapacity = 0; size_t i = 0; ArgList::const_iterator end = list.end(); @@ -185,6 +188,7 @@ JSArray::JSArray(PassRefPtr<Structure> structure, const ArgList& list) JSArray::~JSArray() { + ASSERT(vptr() == JSGlobalData::jsArrayVPtr); checkConsistency(DestructorConsistencyCheck); delete m_storage->m_sparseValueMap; @@ -328,13 +332,24 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu } // We miss some cases where we could compact the storage, such as a large array that is being filled from the end - // (which will only be compacted as we reach indices that are less than cutoff) - but this makes the check much faster. + // (which will only be compacted as we reach indices that are less than MIN_SPARSE_ARRAY_INDEX) - but this makes the check much faster. if ((i > MAX_STORAGE_VECTOR_INDEX) || !isDenseEnoughForVector(i + 1, storage->m_numValuesInVector + 1)) { if (!map) { map = new SparseArrayValueMap; storage->m_sparseValueMap = map; } - map->set(i, value); + + pair<SparseArrayValueMap::iterator, bool> result = map->add(i, value); + if (!result.second) { // pre-existing entry + result.first->second = value; + return; + } + + size_t capacity = map->capacity(); + if (capacity != storage->reportedMapCapacity) { + Heap::heap(this)->reportExtraMemoryCost((capacity - storage->reportedMapCapacity) * (sizeof(unsigned) + sizeof(JSValue))); + storage->reportedMapCapacity = capacity; + } return; } } @@ -380,8 +395,6 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu unsigned vectorLength = m_vectorLength; - Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); - if (newNumValuesInVector == storage->m_numValuesInVector + 1) { for (unsigned j = vectorLength; j < newVectorLength; ++j) storage->m_vector[j] = JSValue(); @@ -402,22 +415,24 @@ NEVER_INLINE void JSArray::putSlowCase(ExecState* exec, unsigned i, JSValue valu m_storage = storage; checkConsistency(); + + Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); } -bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) +bool JSArray::deleteProperty(ExecState* exec, const Identifier& propertyName) { bool isArrayIndex; unsigned i = propertyName.toArrayIndex(&isArrayIndex); if (isArrayIndex) - return deleteProperty(exec, i, checkDontDelete); + return deleteProperty(exec, i); if (propertyName == exec->propertyNames().length) return false; - return JSObject::deleteProperty(exec, propertyName, checkDontDelete); + return JSObject::deleteProperty(exec, propertyName); } -bool JSArray::deleteProperty(ExecState* exec, unsigned i, bool checkDontDelete) +bool JSArray::deleteProperty(ExecState* exec, unsigned i) { checkConsistency(); @@ -449,12 +464,12 @@ bool JSArray::deleteProperty(ExecState* exec, unsigned i, bool checkDontDelete) checkConsistency(); if (i > MAX_ARRAY_INDEX) - return deleteProperty(exec, Identifier::from(exec, i), checkDontDelete); + return deleteProperty(exec, Identifier::from(exec, i)); return false; } -void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) +void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { // FIXME: Filling PropertyNameArray with an identifier for every integer // is incredibly inefficient for large arrays. We need a different approach, @@ -474,7 +489,10 @@ void JSArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNa propertyNames.add(Identifier::from(exec, it->first)); } - JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + if (mode == IncludeDontEnumProperties) + propertyNames.add(exec->propertyNames().length); + + JSObject::getOwnPropertyNames(exec, propertyNames, mode); } bool JSArray::increaseVectorLength(unsigned newLength) @@ -492,13 +510,15 @@ bool JSArray::increaseVectorLength(unsigned newLength) if (!tryFastRealloc(storage, storageSize(newVectorLength)).getValue(storage)) return false; - Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); m_vectorLength = newVectorLength; for (unsigned i = vectorLength; i < newVectorLength; ++i) storage->m_vector[i] = JSValue(); m_storage = storage; + + Heap::heap(this)->reportExtraMemoryCost(storageSize(newVectorLength) - storageSize(vectorLength)); + return true; } @@ -785,7 +805,7 @@ struct AVLTreeAbstractorForArrayCompare { m_cachedCall->setThis(m_globalThisValue); m_cachedCall->setArgument(0, va); m_cachedCall->setArgument(1, vb); - compareResult = m_cachedCall->call().toNumber(m_cachedCall->newCallFrame()); + compareResult = m_cachedCall->call().toNumber(m_cachedCall->newCallFrame(m_exec)); } else { MarkedArgumentBuffer arguments; arguments.append(va); @@ -1051,26 +1071,4 @@ void JSArray::checkConsistency(ConsistencyCheckType type) #endif -JSArray* constructEmptyArray(ExecState* exec) -{ - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure()); -} - -JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength) -{ - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength); -} - -JSArray* constructArray(ExecState* exec, JSValue singleItemValue) -{ - MarkedArgumentBuffer values; - values.append(singleItemValue); - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); -} - -JSArray* constructArray(ExecState* exec, const ArgList& values) -{ - return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); -} - } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.h index 2613991..64b2ff1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSArray.h @@ -32,6 +32,7 @@ namespace JSC { unsigned m_numValuesInVector; SparseArrayValueMap* m_sparseValueMap; void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily. + size_t reportedMapCapacity; JSValue m_vector[1]; }; @@ -40,9 +41,9 @@ namespace JSC { friend class Walker; public: - explicit JSArray(PassRefPtr<Structure>); - JSArray(PassRefPtr<Structure>, unsigned initialLength); - JSArray(PassRefPtr<Structure>, const ArgList& initialValues); + explicit JSArray(NonNullPassRefPtr<Structure>); + JSArray(NonNullPassRefPtr<Structure>, unsigned initialLength); + JSArray(NonNullPassRefPtr<Structure>, const ArgList& initialValues); virtual ~JSArray(); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -87,16 +88,17 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } inline void markChildrenDirect(MarkStack& markStack); protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); - virtual bool deleteProperty(ExecState*, unsigned propertyName, bool checkDontDelete = true); - virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + virtual bool deleteProperty(ExecState*, unsigned propertyName); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual void markChildren(MarkStack&); void* lazyCreationData(); @@ -121,11 +123,6 @@ namespace JSC { JSArray* asArray(JSValue); - JSArray* constructEmptyArray(ExecState*); - JSArray* constructEmptyArray(ExecState*, unsigned initialLength); - JSArray* constructArray(ExecState*, JSValue singleItemValue); - JSArray* constructArray(ExecState*, const ArgList& values); - inline JSArray* asArray(JSCell* cell) { ASSERT(cell->inherits(&JSArray::info)); @@ -162,7 +159,7 @@ namespace JSC { inline void MarkStack::markChildren(JSCell* cell) { ASSERT(Heap::isCellMarked(cell)); - if (cell->structure()->typeInfo().hasDefaultMark()) { + if (!cell->structure()->typeInfo().overridesMarkChildren()) { #ifdef NDEBUG asObject(cell)->markChildrenDirect(*this); #else diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.cpp index 0907099..f8ab1e8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.cpp @@ -35,17 +35,25 @@ namespace JSC { const ClassInfo JSByteArray::s_defaultInfo = { "ByteArray", 0, 0, 0 }; -JSByteArray::JSByteArray(ExecState* exec, PassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo) +JSByteArray::JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure> structure, ByteArray* storage, const JSC::ClassInfo* classInfo) : JSObject(structure) , m_storage(storage) , m_classInfo(classInfo) { putDirect(exec->globalData().propertyNames->length, jsNumber(exec, m_storage->length()), ReadOnly | DontDelete); } - + +#if !ASSERT_DISABLED +JSByteArray::~JSByteArray() +{ + ASSERT(vptr() == JSGlobalData::jsByteArrayVPtr); +} +#endif + + PassRefPtr<Structure> JSByteArray::createStructure(JSValue prototype) { - PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark)); + PassRefPtr<Structure> result = Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); return result; } @@ -96,12 +104,12 @@ void JSByteArray::put(ExecState* exec, unsigned propertyName, JSValue value) setIndex(exec, propertyName, value); } -void JSByteArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) +void JSByteArray::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { unsigned length = m_storage->length(); for (unsigned i = 0; i < length; ++i) propertyNames.add(Identifier::from(exec, i)); - JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + JSObject::getOwnPropertyNames(exec, propertyNames, mode); } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.h index 5ea0505..5b7adcf 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSByteArray.h @@ -33,7 +33,7 @@ namespace JSC { class JSByteArray : public JSObject { - friend struct VPtrSet; + friend class JSGlobalData; public: bool canAccessIndex(unsigned i) { return i < m_storage->length(); } JSValue getIndex(ExecState* exec, unsigned i) @@ -73,7 +73,7 @@ namespace JSC { setIndex(i, byteValue); } - JSByteArray(ExecState* exec, PassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo); + JSByteArray(ExecState* exec, NonNullPassRefPtr<Structure>, WTF::ByteArray* storage, const JSC::ClassInfo* = &s_defaultInfo); static PassRefPtr<Structure> createStructure(JSValue prototype); virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); @@ -82,7 +82,7 @@ namespace JSC { virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue); - virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, bool includeNonEnumerable = false); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual const ClassInfo* classInfo() const { return m_classInfo; } static const ClassInfo s_defaultInfo; @@ -91,6 +91,13 @@ namespace JSC { WTF::ByteArray* storage() const { return m_storage.get(); } +#if !ASSERT_DISABLED + virtual ~JSByteArray(); +#endif + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags; + private: enum VPtrStealingHackType { VPtrStealingHack }; JSByteArray(VPtrStealingHackType) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.cpp index 1cfe72d..869fbfc 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.cpp @@ -59,10 +59,10 @@ static const union { } doubles; } NaNInf = { { -#if PLATFORM(BIG_ENDIAN) +#if CPU(BIG_ENDIAN) { 0x7f, 0xf8, 0, 0, 0, 0, 0, 0 }, { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } -#elif PLATFORM(MIDDLE_ENDIAN) +#elif CPU(MIDDLE_ENDIAN) { 0, 0, 0xf8, 0x7f, 0, 0, 0, 0 }, { 0, 0, 0xf0, 0x7f, 0, 0, 0, 0 } #else @@ -76,31 +76,22 @@ extern const double Inf = NaNInf.doubles.Inf_Double; #endif // !(defined NAN && defined INFINITY) -void* JSCell::operator new(size_t size, ExecState* exec) -{ -#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE - return exec->heap()->inlineAllocate(size); -#else - return exec->heap()->allocate(size); -#endif -} - bool JSCell::getUInt32(uint32_t&) const { return false; } -bool JSCell::getString(UString&stringValue) const +bool JSCell::getString(ExecState* exec, UString&stringValue) const { if (!isString()) return false; - stringValue = static_cast<const JSString*>(this)->value(); + stringValue = static_cast<const JSString*>(this)->value(exec); return true; } -UString JSCell::getString() const +UString JSCell::getString(ExecState* exec) const { - return isString() ? static_cast<const JSString*>(this)->value() : UString(); + return isString() ? static_cast<const JSString*>(this)->value(exec) : UString(); } JSObject* JSCell::getObject() @@ -157,14 +148,14 @@ void JSCell::put(ExecState* exec, unsigned identifier, JSValue value) toObject(exec)->put(exec, identifier, value); } -bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier, bool checkDontDelete) +bool JSCell::deleteProperty(ExecState* exec, const Identifier& identifier) { - return toObject(exec)->deleteProperty(exec, identifier, checkDontDelete); + return toObject(exec)->deleteProperty(exec, identifier); } -bool JSCell::deleteProperty(ExecState* exec, unsigned identifier, bool checkDontDelete) +bool JSCell::deleteProperty(ExecState* exec, unsigned identifier) { - return toObject(exec)->deleteProperty(exec, identifier, checkDontDelete); + return toObject(exec)->deleteProperty(exec, identifier); } JSObject* JSCell::toThisObject(ExecState* exec) const diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.h index d015b9c..36bfd66 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSCell.h @@ -42,14 +42,19 @@ namespace JSC { friend class JSString; friend class JSValue; friend class JSAPIValueWrapper; - friend struct VPtrSet; + friend class JSZombie; + friend class JSGlobalData; private: explicit JSCell(Structure*); - JSCell(); // Only used for initializing Collector blocks. virtual ~JSCell(); public: + static PassRefPtr<Structure> createDummyStructure() + { + return Structure::create(jsNull(), TypeInfo(UnspecifiedType)); + } + // Querying the type. #if USE(JSVALUE32) bool isNumber() const; @@ -59,12 +64,13 @@ namespace JSC { virtual bool isGetterSetter() const; bool inherits(const ClassInfo*) const; virtual bool isAPIValueWrapper() const { return false; } + virtual bool isPropertyNameIterator() const { return false; } Structure* structure() const; // Extracting the value. - bool getString(UString&) const; - UString getString() const; // null string if not a string + bool getString(ExecState* exec, UString&) const; + UString getString(ExecState* exec) const; // null string if not a string JSObject* getObject(); // NULL if not an object const JSObject* getObject() const; // NULL if not an object @@ -89,19 +95,23 @@ namespace JSC { void* operator new(size_t, void* placementNewDestination) { return placementNewDestination; } virtual void markChildren(MarkStack&); +#if ENABLE(JSC_ZOMBIES) + virtual bool isZombie() const { return false; } +#endif // Object operations, with the toObject operation included. virtual const ClassInfo* classInfo() const; virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); virtual void put(ExecState*, unsigned propertyName, JSValue); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); - virtual bool deleteProperty(ExecState*, unsigned propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + virtual bool deleteProperty(ExecState*, unsigned propertyName); virtual JSObject* toThisObject(ExecState*) const; virtual UString toThisString(ExecState*) const; virtual JSString* toThisJSString(ExecState*); virtual JSValue getJSNumber(); void* vptr() { return *reinterpret_cast<void**>(this); } + void setVPtr(void* vptr) { *reinterpret_cast<void**>(this) = vptr; } private: // Base implementation; for non-object classes implements getPropertySlot. @@ -112,24 +122,11 @@ namespace JSC { Structure* m_structure; }; - // FIXME: We should deprecate this and just use JSValue::asCell() instead. - JSCell* asCell(JSValue); - - inline JSCell* asCell(JSValue value) - { - return value.asCell(); - } - inline JSCell::JSCell(Structure* structure) : m_structure(structure) { } - // Only used for initializing Collector blocks. - inline JSCell::JSCell() - { - } - inline JSCell::~JSCell() { } @@ -137,7 +134,7 @@ namespace JSC { #if USE(JSVALUE32) inline bool JSCell::isNumber() const { - return Heap::isNumber(const_cast<JSCell*>(this)); + return m_structure->typeInfo().type() == NumberType; } #endif @@ -162,11 +159,12 @@ namespace JSC { inline void* JSCell::operator new(size_t size, JSGlobalData* globalData) { -#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE - return globalData->heap.inlineAllocate(size); -#else return globalData->heap.allocate(size); -#endif + } + + inline void* JSCell::operator new(size_t size, ExecState* exec) + { + return exec->heap()->allocate(size); } // --- JSValue inlines ---------------------------- @@ -186,14 +184,14 @@ namespace JSC { return isCell() && asCell()->isObject(); } - inline bool JSValue::getString(UString& s) const + inline bool JSValue::getString(ExecState* exec, UString& s) const { - return isCell() && asCell()->getString(s); + return isCell() && asCell()->getString(exec, s); } - inline UString JSValue::getString() const + inline UString JSValue::getString(ExecState* exec) const { - return isCell() ? asCell()->getString() : UString(); + return isCell() ? asCell()->getString(exec) : UString(); } inline JSObject* JSValue::getObject() const @@ -342,11 +340,6 @@ namespace JSC { append(value.asCell()); } - inline void Structure::markAggregate(MarkStack& markStack) - { - markStack.append(m_prototype); - } - inline Heap* Heap::heap(JSValue v) { if (!v.isCell()) @@ -358,7 +351,13 @@ namespace JSC { { return cellBlock(c)->heap; } - + +#if ENABLE(JSC_ZOMBIES) + inline bool JSValue::isZombie() const + { + return isCell() && asCell() && asCell()->isZombie(); + } +#endif } // namespace JSC #endif // JSCell_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.cpp index bf4e34d..d213b4a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.cpp @@ -50,13 +50,13 @@ bool JSFunction::isHostFunctionNonInline() const return isHostFunction(); } -JSFunction::JSFunction(PassRefPtr<Structure> structure) +JSFunction::JSFunction(NonNullPassRefPtr<Structure> structure) : Base(structure) , m_executable(adoptRef(new VPtrHackExecutable())) { } -JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int length, const Identifier& name, NativeFunction func) +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))) @@ -72,7 +72,7 @@ JSFunction::JSFunction(ExecState* exec, PassRefPtr<Structure> structure, int len #endif } -JSFunction::JSFunction(ExecState* exec, PassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode) +JSFunction::JSFunction(ExecState* exec, NonNullPassRefPtr<FunctionExecutable> executable, ScopeChainNode* scopeChainNode) : Base(&exec->globalData(), exec->lexicalGlobalObject()->functionStructure(), executable->name()) , m_executable(executable) { @@ -81,6 +81,8 @@ JSFunction::JSFunction(ExecState* exec, PassRefPtr<FunctionExecutable> executabl JSFunction::~JSFunction() { + ASSERT(vptr() == JSGlobalData::jsFunctionVPtr); + // JIT code for other functions may have had calls linked directly to the code for this function; these links // are based on a check for the this pointer value for this JSFunction - which will no longer be valid once // this memory is freed and may be reused (potentially for another, different JSFunction). @@ -206,6 +208,17 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN return Base::getOwnPropertyDescriptor(exec, propertyName, descriptor); } +void JSFunction::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + if (!isHostFunction() && (mode == IncludeDontEnumProperties)) { + propertyNames.add(exec->propertyNames().arguments); + propertyNames.add(exec->propertyNames().callee); + propertyNames.add(exec->propertyNames().caller); + propertyNames.add(exec->propertyNames().length); + } + Base::getOwnPropertyNames(exec, propertyNames, mode); +} + void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) { if (isHostFunction()) { @@ -217,13 +230,13 @@ void JSFunction::put(ExecState* exec, const Identifier& propertyName, JSValue va Base::put(exec, propertyName, value, slot); } -bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) +bool JSFunction::deleteProperty(ExecState* exec, const Identifier& propertyName) { if (isHostFunction()) - return Base::deleteProperty(exec, propertyName, checkDontDelete); + return Base::deleteProperty(exec, propertyName); if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length) return false; - return Base::deleteProperty(exec, propertyName, checkDontDelete); + return Base::deleteProperty(exec, propertyName); } // ECMA 13.2.2 [[Construct]] diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.h index 416a58a..bdb79b8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSFunction.h @@ -36,13 +36,13 @@ namespace JSC { class JSFunction : public InternalFunction { friend class JIT; - friend struct VPtrSet; + friend class JSGlobalData; typedef InternalFunction Base; public: - JSFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction); - JSFunction(ExecState*, PassRefPtr<FunctionExecutable>, ScopeChainNode*); + JSFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction); + JSFunction(ExecState*, NonNullPassRefPtr<FunctionExecutable>, ScopeChainNode*); virtual ~JSFunction(); JSObject* construct(ExecState*, const ArgList&); @@ -61,26 +61,30 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } NativeFunction nativeFunction() { - return *reinterpret_cast<NativeFunction*>(m_data); + return *WTF::bitwise_cast<NativeFunction*>(m_data); } virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); + protected: + const static unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | InternalFunction::StructureFlags; + private: - JSFunction(PassRefPtr<Structure>); + JSFunction(NonNullPassRefPtr<Structure>); bool isHostFunctionNonInline() const; virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual void markChildren(MarkStack&); @@ -94,7 +98,7 @@ namespace JSC { ScopeChain& scopeChain() { ASSERT(!isHostFunctionNonInline()); - return *reinterpret_cast<ScopeChain*>(m_data); + return *WTF::bitwise_cast<ScopeChain*>(m_data); } void clearScopeChain() { @@ -109,11 +113,11 @@ namespace JSC { void setScopeChain(const ScopeChain& sc) { ASSERT(!isHostFunctionNonInline()); - *reinterpret_cast<ScopeChain*>(m_data) = sc; + *WTF::bitwise_cast<ScopeChain*>(m_data) = sc; } void setNativeFunction(NativeFunction func) { - *reinterpret_cast<NativeFunction*>(m_data) = func; + *WTF::bitwise_cast<NativeFunction*>(m_data) = func; } unsigned char m_data[sizeof(void*)]; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.cpp index 4496d6c..34b5f82 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.cpp @@ -45,10 +45,10 @@ #include "JSNotAnObject.h" #include "JSPropertyNameIterator.h" #include "JSStaticScopeObject.h" -#include "Parser.h" #include "Lexer.h" #include "Lookup.h" #include "Nodes.h" +#include "Parser.h" #if ENABLE(JSC_MULTIPLE_THREADS) #include <wtf/Threading.h> @@ -71,40 +71,38 @@ extern JSC_CONST_HASHTABLE HashTable regExpTable; extern JSC_CONST_HASHTABLE HashTable regExpConstructorTable; extern JSC_CONST_HASHTABLE HashTable stringTable; -struct VPtrSet { - VPtrSet(); - - void* jsArrayVPtr; - void* jsByteArrayVPtr; - void* jsStringVPtr; - void* jsFunctionVPtr; -}; +void* JSGlobalData::jsArrayVPtr; +void* JSGlobalData::jsByteArrayVPtr; +void* JSGlobalData::jsStringVPtr; +void* JSGlobalData::jsFunctionVPtr; -VPtrSet::VPtrSet() +void JSGlobalData::storeVPtrs() { - // Bizarrely, calling fastMalloc here is faster than allocating space on the stack. - void* storage = fastMalloc(sizeof(CollectorBlock)); + CollectorCell cell; + void* storage = &cell; + COMPILE_ASSERT(sizeof(JSArray) <= sizeof(CollectorCell), sizeof_JSArray_must_be_less_than_CollectorCell); JSCell* jsArray = new (storage) JSArray(JSArray::createStructure(jsNull())); - jsArrayVPtr = jsArray->vptr(); + JSGlobalData::jsArrayVPtr = jsArray->vptr(); jsArray->~JSCell(); + COMPILE_ASSERT(sizeof(JSByteArray) <= sizeof(CollectorCell), sizeof_JSByteArray_must_be_less_than_CollectorCell); JSCell* jsByteArray = new (storage) JSByteArray(JSByteArray::VPtrStealingHack); - jsByteArrayVPtr = jsByteArray->vptr(); + JSGlobalData::jsByteArrayVPtr = jsByteArray->vptr(); jsByteArray->~JSCell(); + COMPILE_ASSERT(sizeof(JSString) <= sizeof(CollectorCell), sizeof_JSString_must_be_less_than_CollectorCell); JSCell* jsString = new (storage) JSString(JSString::VPtrStealingHack); - jsStringVPtr = jsString->vptr(); + JSGlobalData::jsStringVPtr = jsString->vptr(); jsString->~JSCell(); + COMPILE_ASSERT(sizeof(JSFunction) <= sizeof(CollectorCell), sizeof_JSFunction_must_be_less_than_CollectorCell); JSCell* jsFunction = new (storage) JSFunction(JSFunction::createStructure(jsNull())); - jsFunctionVPtr = jsFunction->vptr(); + JSGlobalData::jsFunctionVPtr = jsFunction->vptr(); jsFunction->~JSCell(); - - fastFree(storage); } -JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet) +JSGlobalData::JSGlobalData(bool isShared) : isSharedInstance(isShared) , clientData(0) , arrayTable(fastNew<HashTable>(JSC::arrayTable)) @@ -124,13 +122,10 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet) , propertyNameIteratorStructure(JSPropertyNameIterator::createStructure(jsNull())) , getterSetterStructure(GetterSetter::createStructure(jsNull())) , apiWrapperStructure(JSAPIValueWrapper::createStructure(jsNull())) + , dummyMarkableCellStructure(JSCell::createDummyStructure()) #if USE(JSVALUE32) , numberStructure(JSNumberCell::createStructure(jsNull())) #endif - , jsArrayVPtr(vptrSet.jsArrayVPtr) - , jsByteArrayVPtr(vptrSet.jsByteArrayVPtr) - , jsStringVPtr(vptrSet.jsStringVPtr) - , jsFunctionVPtr(vptrSet.jsFunctionVPtr) , identifierTable(createIdentifierTable()) , propertyNames(new CommonIdentifiers(this)) , emptyList(new MarkedArgumentBuffer) @@ -147,7 +142,9 @@ JSGlobalData::JSGlobalData(bool isShared, const VPtrSet& vptrSet) , dynamicGlobalObject(0) , functionCodeBlockBeingReparsed(0) , firstStringifierToMark(0) - , markStack(vptrSet.jsArrayVPtr) + , markStack(jsArrayVPtr) + , cachedUTCOffset(NaN) + , weakRandom(static_cast<int>(currentTime())) #ifndef NDEBUG , mainThreadOnly(false) #endif @@ -199,9 +196,17 @@ JSGlobalData::~JSGlobalData() delete clientData; } -PassRefPtr<JSGlobalData> JSGlobalData::create(bool isShared) +PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault() +{ + return adoptRef(new JSGlobalData(false)); +} + +PassRefPtr<JSGlobalData> JSGlobalData::create() { - return adoptRef(new JSGlobalData(isShared, VPtrSet())); + JSGlobalData* globalData = new JSGlobalData(false); + setDefaultIdentifierTable(globalData->identifierTable); + setCurrentIdentifierTable(globalData->identifierTable); + return adoptRef(globalData); } PassRefPtr<JSGlobalData> JSGlobalData::createLeaked() @@ -221,7 +226,7 @@ JSGlobalData& JSGlobalData::sharedInstance() { JSGlobalData*& instance = sharedInstanceInternal(); if (!instance) { - instance = create(true).releaseRef(); + instance = new JSGlobalData(true); #if ENABLE(JSC_MULTIPLE_THREADS) instance->makeUsableFromMultipleThreads(); #endif @@ -253,4 +258,27 @@ JSGlobalData::ClientData::~ClientData() { } +void JSGlobalData::resetDateCache() +{ + cachedUTCOffset = NaN; + dstOffsetCache.reset(); + cachedDateString = UString(); + dateInstanceCache.reset(); +} + +void JSGlobalData::startSampling() +{ + interpreter->startSampling(); +} + +void JSGlobalData::stopSampling() +{ + interpreter->stopSampling(); +} + +void JSGlobalData::dumpSampleData(ExecState* exec) +{ + interpreter->dumpSampleData(exec); +} + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.h index c9887e8..49a6c4c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalData.h @@ -30,6 +30,7 @@ #define JSGlobalData_h #include "Collector.h" +#include "DateInstanceCache.h" #include "ExecutableAllocator.h" #include "JITStubs.h" #include "JSValue.h" @@ -37,6 +38,7 @@ #include "NumericStrings.h" #include "SmallStrings.h" #include "TimeoutChecker.h" +#include "WeakRandom.h" #include <wtf/Forward.h> #include <wtf/HashMap.h> #include <wtf/RefCounted.h> @@ -60,7 +62,26 @@ namespace JSC { struct HashTable; struct Instruction; - struct VPtrSet; + + struct DSTOffsetCache { + DSTOffsetCache() + { + reset(); + } + + void reset() + { + offset = 0.0; + start = 0.0; + end = -1.0; + increment = 0.0; + } + + double offset; + double start; + double end; + double increment; + }; class JSGlobalData : public RefCounted<JSGlobalData> { public: @@ -74,8 +95,9 @@ namespace JSC { static bool sharedInstanceExists(); static JSGlobalData& sharedInstance(); - static PassRefPtr<JSGlobalData> create(bool isShared = false); + static PassRefPtr<JSGlobalData> create(); static PassRefPtr<JSGlobalData> createLeaked(); + static PassRefPtr<JSGlobalData> createNonDefault(); ~JSGlobalData(); #if ENABLE(JSC_MULTIPLE_THREADS) @@ -104,22 +126,25 @@ namespace JSC { RefPtr<Structure> propertyNameIteratorStructure; RefPtr<Structure> getterSetterStructure; RefPtr<Structure> apiWrapperStructure; + RefPtr<Structure> dummyMarkableCellStructure; #if USE(JSVALUE32) RefPtr<Structure> numberStructure; #endif - void* jsArrayVPtr; - void* jsByteArrayVPtr; - void* jsStringVPtr; - void* jsFunctionVPtr; + static void storeVPtrs(); + static JS_EXPORTDATA void* jsArrayVPtr; + static JS_EXPORTDATA void* jsByteArrayVPtr; + static JS_EXPORTDATA void* jsStringVPtr; + static JS_EXPORTDATA void* jsFunctionVPtr; IdentifierTable* identifierTable; CommonIdentifiers* propertyNames; const MarkedArgumentBuffer* emptyList; // Lists are supposed to be allocated on the stack to have their elements properly marked, which is not the case here - but this list has nothing to mark. SmallStrings smallStrings; NumericStrings numericStrings; - + DateInstanceCache dateInstanceCache; + #if ENABLE(ASSEMBLER) ExecutableAllocator executableAllocator; #endif @@ -154,16 +179,29 @@ namespace JSC { MarkStack markStack; + double cachedUTCOffset; + DSTOffsetCache dstOffsetCache; + + UString cachedDateString; + double cachedDateStringValue; + + WeakRandom weakRandom; + #ifndef NDEBUG bool mainThreadOnly; #endif + void resetDateCache(); + + void startSampling(); + void stopSampling(); + void dumpSampleData(ExecState* exec); private: - JSGlobalData(bool isShared, const VPtrSet&); + JSGlobalData(bool isShared); static JSGlobalData*& sharedInstanceInternal(); void createNativeThunk(); }; - + } // namespace JSC #endif // JSGlobalData_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.cpp index 60eb1b4..a2e9928 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -89,7 +89,7 @@ static inline void markIfNeeded(MarkStack& markStack, JSValue v) static inline void markIfNeeded(MarkStack& markStack, const RefPtr<Structure>& s) { if (s) - s->markAggregate(markStack); + markIfNeeded(markStack, s->storedPrototype()); } JSGlobalObject::~JSGlobalObject() @@ -121,15 +121,17 @@ JSGlobalObject::~JSGlobalObject() registerFile.setGlobalObject(0); registerFile.setNumGlobals(0); } - delete d(); + d()->destructor(d()); } void JSGlobalObject::init(JSObject* thisValue) { ASSERT(JSLock::currentThreadIsHoldingLock()); + structure()->disableSpecificFunctionTracking(); + d()->globalData = Heap::heap(this)->globalData(); - d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), thisValue); + d()->globalScopeChain = ScopeChain(this, d()->globalData.get(), this, thisValue); JSGlobalObject::globalExec()->init(0, 0, d()->globalScopeChain.node(), CallFrame::noCaller(), 0, 0, 0); @@ -396,6 +398,21 @@ void JSGlobalObject::markChildren(MarkStack& markStack) markIfNeeded(markStack, d()->methodCallDummy); markIfNeeded(markStack, d()->errorStructure); + markIfNeeded(markStack, d()->argumentsStructure); + markIfNeeded(markStack, d()->arrayStructure); + markIfNeeded(markStack, d()->booleanObjectStructure); + markIfNeeded(markStack, d()->callbackConstructorStructure); + markIfNeeded(markStack, d()->callbackFunctionStructure); + markIfNeeded(markStack, d()->callbackObjectStructure); + markIfNeeded(markStack, d()->dateStructure); + markIfNeeded(markStack, d()->emptyObjectStructure); + markIfNeeded(markStack, d()->errorStructure); + markIfNeeded(markStack, d()->functionStructure); + markIfNeeded(markStack, d()->numberObjectStructure); + markIfNeeded(markStack, d()->prototypeFunctionStructure); + markIfNeeded(markStack, d()->regExpMatchesArrayStructure); + markIfNeeded(markStack, d()->regExpStructure); + markIfNeeded(markStack, d()->stringObjectStructure); // No need to mark the other structures, because their prototypes are all // guaranteed to be referenced elsewhere. @@ -450,11 +467,12 @@ void JSGlobalObject::copyGlobalsTo(RegisterFile& registerFile) void* JSGlobalObject::operator new(size_t size, JSGlobalData* globalData) { -#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE - return globalData->heap.inlineAllocate(size); -#else return globalData->heap.allocate(size); -#endif +} + +void JSGlobalObject::destroyJSGlobalObjectData(void* jsGlobalObjectData) +{ + delete static_cast<JSGlobalObjectData*>(jsGlobalObjectData); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.h index 7459c2e..340e04d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObject.h @@ -22,6 +22,7 @@ #ifndef JSGlobalObject_h #define JSGlobalObject_h +#include "JSArray.h" #include "JSGlobalData.h" #include "JSVariableObject.h" #include "NativeFunctionWrapper.h" @@ -52,14 +53,22 @@ namespace JSC { struct HashTable; typedef Vector<ExecState*, 16> ExecStateStack; - + class JSGlobalObject : public JSVariableObject { protected: using JSVariableObject::JSVariableObjectData; struct JSGlobalObjectData : public JSVariableObjectData { - JSGlobalObjectData() + // We use an explicit destructor function pointer instead of a + // virtual destructor because we want to avoid adding a vtable + // pointer to this struct. Adding a vtable pointer would force the + // compiler to emit costly pointer fixup code when casting from + // JSVariableObjectData* to JSGlobalObjectData*. + typedef void (*Destructor)(void*); + + JSGlobalObjectData(Destructor destructor) : JSVariableObjectData(&symbolTable, 0) + , destructor(destructor) , registerArraySize(0) , globalScopeChain(NoScopeChain()) , regExpConstructor(0) @@ -85,10 +94,8 @@ namespace JSC { { } - virtual ~JSGlobalObjectData() - { - } - + Destructor destructor; + size_t registerArraySize; JSGlobalObject* next; @@ -153,13 +160,13 @@ namespace JSC { void* operator new(size_t, JSGlobalData*); explicit JSGlobalObject() - : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData) + : JSVariableObject(JSGlobalObject::createStructure(jsNull()), new JSGlobalObjectData(destroyJSGlobalObjectData)) { init(this); } protected: - JSGlobalObject(PassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue) + JSGlobalObject(NonNullPassRefPtr<Structure> structure, JSGlobalObjectData* data, JSObject* thisValue) : JSVariableObject(structure, data) { init(thisValue); @@ -229,10 +236,7 @@ namespace JSC { unsigned profileGroup() const { return d()->profileGroup; } Debugger* debugger() const { return d()->debugger; } - void setDebugger(Debugger* debugger) - { - d()->debugger = debugger; - } + void setDebugger(Debugger* debugger) { d()->debugger = debugger; } virtual bool supportsProfiling() const { return false; } @@ -264,10 +268,13 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } protected: + + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; + struct GlobalPropertyInfo { GlobalPropertyInfo(const Identifier& i, JSValue v, unsigned a) : identifier(i) @@ -283,6 +290,8 @@ namespace JSC { void addStaticGlobals(GlobalPropertyInfo*, int count); private: + static void destroyJSGlobalObjectData(void*); + // FIXME: Fold reset into init. void init(JSObject* thisValue); void reset(JSValue prototype); @@ -347,14 +356,6 @@ namespace JSC { return symbolTableGet(propertyName, slot, slotIsWriteable); } - inline JSGlobalObject* ScopeChainNode::globalObject() const - { - const ScopeChainNode* n = this; - while (n->next) - n = n->next; - return asGlobalObject(n->object); - } - inline JSValue Structure::prototypeForLookup(ExecState* exec) const { if (typeInfo().type() == ObjectType) @@ -409,13 +410,46 @@ namespace JSC { return globalData().dynamicGlobalObject; } + inline JSObject* constructEmptyObject(ExecState* exec) + { + return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure()); + } + + inline JSArray* constructEmptyArray(ExecState* exec) + { + return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure()); + } + + inline JSArray* constructEmptyArray(ExecState* exec, unsigned initialLength) + { + return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), initialLength); + } + + inline JSArray* constructArray(ExecState* exec, JSValue singleItemValue) + { + MarkedArgumentBuffer values; + values.append(singleItemValue); + return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); + } + + inline JSArray* constructArray(ExecState* exec, const ArgList& values) + { + return new (exec) JSArray(exec->lexicalGlobalObject()->arrayStructure(), values); + } + class DynamicGlobalObjectScope : public Noncopyable { public: DynamicGlobalObjectScope(CallFrame* callFrame, JSGlobalObject* dynamicGlobalObject) : m_dynamicGlobalObjectSlot(callFrame->globalData().dynamicGlobalObject) , m_savedDynamicGlobalObject(m_dynamicGlobalObjectSlot) { - m_dynamicGlobalObjectSlot = dynamicGlobalObject; + if (!m_dynamicGlobalObjectSlot) { + m_dynamicGlobalObjectSlot = dynamicGlobalObject; + + // Reset the date cache between JS invocations to force the VM + // to observe time zone changes. + callFrame->globalData().resetDateCache(); + } } ~DynamicGlobalObjectScope() diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 5ded370..0bc1274 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -27,14 +27,16 @@ #include "CallFrame.h" #include "GlobalEvalFunction.h" +#include "Interpreter.h" #include "JSGlobalObject.h" -#include "LiteralParser.h" #include "JSString.h" -#include "Interpreter.h" -#include "Parser.h" -#include "dtoa.h" #include "Lexer.h" +#include "LiteralParser.h" #include "Nodes.h" +#include "Parser.h" +#include "StringBuilder.h" +#include "StringExtras.h" +#include "dtoa.h" #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -55,24 +57,24 @@ static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEsc if (!cstr.c_str()) return throwError(exec, URIError, "String contained an illegal UTF-16 sequence."); - UString result = ""; + StringBuilder builder; const char* p = cstr.c_str(); for (size_t k = 0; k < cstr.size(); k++, p++) { char c = *p; if (c && strchr(doNotEscape, c)) - result.append(c); + builder.append(c); else { char tmp[4]; - sprintf(tmp, "%%%02X", static_cast<unsigned char>(c)); - result += tmp; + snprintf(tmp, 4, "%%%02X", static_cast<unsigned char>(c)); + builder.append((const char*)tmp); } } - return jsString(exec, result); + return jsString(exec, builder.release()); } static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUnescape, bool strict) { - UString result = ""; + StringBuilder builder; UString str = args.at(0).toString(exec); int k = 0; int len = str.size(); @@ -106,7 +108,7 @@ static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUne charLen = 0; else if (character >= 0x10000) { // Convert to surrogate pair. - result.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10))); + builder.append(static_cast<UChar>(0xD800 | ((character - 0x10000) >> 10))); u = static_cast<UChar>(0xDC00 | ((character - 0x10000) & 0x3FF)); } else u = static_cast<UChar>(character); @@ -131,9 +133,9 @@ static JSValue decode(ExecState* exec, const ArgList& args, const char* doNotUne } } k++; - result.append(c); + builder.append(c); } - return jsString(exec, result); + return jsString(exec, builder.release()); } bool isStrWhiteSpace(UChar c) @@ -286,12 +288,12 @@ JSValue JSC_HOST_CALL globalFuncEval(ExecState* exec, JSObject* function, JSValu if (JSValue parsedObject = preparser.tryLiteralParse()) return parsedObject; - EvalExecutable eval(exec, makeSource(s)); - JSObject* error = eval.compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node()); + RefPtr<EvalExecutable> eval = EvalExecutable::create(exec, makeSource(s)); + JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node()); if (error) return throwError(exec, error); - return exec->interpreter()->execute(&eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot()); + return exec->interpreter()->execute(eval.get(), exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain().node(), exec->exceptionSlot()); } JSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec, JSObject*, JSValue, const ArgList& args) @@ -376,7 +378,7 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons "0123456789" "*+-./@_"; - UString result = ""; + StringBuilder builder; UString s; UString str = args.at(0).toString(exec); const UChar* c = str.data(); @@ -393,15 +395,15 @@ JSValue JSC_HOST_CALL globalFuncEscape(ExecState* exec, JSObject*, JSValue, cons sprintf(tmp, "%%%02X", u); s = UString(tmp); } - result += s; + builder.append(s); } - return jsString(exec, result); + return jsString(exec, builder.release()); } JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - UString result = ""; + StringBuilder builder; UString str = args.at(0).toString(exec); int k = 0; int len = str.size(); @@ -420,10 +422,10 @@ JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, co k += 2; } k++; - result.append(*c); + builder.append(*c); } - return jsString(exec, result); + return jsString(exec, builder.release()); } #ifndef NDEBUG diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.cpp index 321762a..f4764e2 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.cpp @@ -121,7 +121,7 @@ bool JSNotAnObject::deleteProperty(ExecState* exec, unsigned) return false; } -void JSNotAnObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray&, bool) +void JSNotAnObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray&, EnumerationMode) { ASSERT_UNUSED(exec, exec->hadException() && exec->exception() == m_exception); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.h index 57347af..d5f430c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNotAnObject.h @@ -62,10 +62,13 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } private: + + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSObject::StructureFlags; + // JSValue methods virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue&); @@ -88,7 +91,7 @@ namespace JSC { virtual bool deleteProperty(ExecState*, const Identifier& propertyName); virtual bool deleteProperty(ExecState*, unsigned propertyName); - virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); JSNotAnObjectErrorStub* m_exception; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.h index 6a48081..e9e2470 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSNumberCell.h @@ -68,23 +68,15 @@ namespace JSC { void* operator new(size_t size, ExecState* exec) { - #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE - return exec->heap()->inlineAllocateNumber(size); - #else return exec->heap()->allocateNumber(size); - #endif } void* operator new(size_t size, JSGlobalData* globalData) { - #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE - return globalData->heap.inlineAllocateNumber(size); - #else return globalData->heap.allocateNumber(size); - #endif } - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, NeedsThisConversion | HasDefaultMark)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(NumberType, OverridesGetOwnPropertySlot | NeedsThisConversion)); } private: JSNumberCell(JSGlobalData* globalData, double value) @@ -117,6 +109,11 @@ namespace JSC { return static_cast<JSNumberCell*>(v.asCell()); } + ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState* exec, double d) + { + *this = jsNumberCell(exec, d); + } + inline JSValue::JSValue(ExecState* exec, double d) { JSValue v = JSImmediate::from(d); @@ -201,6 +198,11 @@ namespace JSC { #endif // USE(JSVALUE32) #if USE(JSVALUE64) + ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d) + { + *this = JSImmediate::fromNumberOutsideIntegerRange(d); + } + inline JSValue::JSValue(ExecState*, double d) { JSValue v = JSImmediate::from(d); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.cpp index 377c9d1..b089584 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.cpp @@ -32,6 +32,7 @@ #include "JSArray.h" #include "LiteralParser.h" #include "PropertyNameArray.h" +#include "StringBuilder.h" #include <wtf/MathExtras.h> namespace JSC { @@ -70,8 +71,6 @@ public: void markAggregate(MarkStack&); private: - typedef UString StringBuilder; - class Holder { public: Holder(JSObject*); @@ -156,7 +155,7 @@ static inline UString gap(ExecState* exec, JSValue space) } // If the space value is a string, use it as the gap string, otherwise use no gap string. - UString spaces = space.getString(); + UString spaces = space.getString(exec); if (spaces.size() > maxGapLength) { spaces = spaces.substr(0, maxGapLength); } @@ -213,7 +212,7 @@ Stringifier::Stringifier(ExecState* exec, JSValue replacer, JSValue space) break; UString propertyName; - if (name.getString(propertyName)) { + if (name.getString(exec, propertyName)) { m_arrayReplacerPropertyNames.add(Identifier(exec, propertyName)); continue; } @@ -269,7 +268,7 @@ JSValue Stringifier::stringify(JSValue value) if (m_exec->hadException()) return jsNull(); - return jsString(m_exec, result); + return jsString(m_exec, result.release()); } void Stringifier::appendQuotedString(StringBuilder& builder, const UString& value) @@ -389,7 +388,7 @@ Stringifier::StringifyResult Stringifier::appendStringifiedValue(StringBuilder& } UString stringValue; - if (value.getString(stringValue)) { + if (value.getString(m_exec, stringValue)) { appendQuotedString(builder, stringValue); return StringifySucceeded; } @@ -461,7 +460,7 @@ inline void Stringifier::indent() // Use a single shared string, m_repeatedGap, so we don't keep allocating new ones as we indent and unindent. int newSize = m_indent.size() + m_gap.size(); if (newSize > m_repeatedGap.size()) - m_repeatedGap.append(m_gap); + m_repeatedGap = makeString(m_repeatedGap, m_gap); ASSERT(newSize <= m_repeatedGap.size()); m_indent = m_repeatedGap.substr(0, newSize); } @@ -504,7 +503,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui m_propertyNames = stringifier.m_arrayReplacerPropertyNames.data(); else { PropertyNameArray objectPropertyNames(exec); - m_object->getPropertyNames(exec, objectPropertyNames); + m_object->getOwnPropertyNames(exec, objectPropertyNames); m_propertyNames = objectPropertyNames.releaseData(); } m_size = m_propertyNames->propertyNameVector().size(); @@ -588,7 +587,7 @@ bool Stringifier::Holder::appendNextProperty(Stringifier& stringifier, StringBui // This only occurs when get an undefined value for an object property. // In this case we don't want the separator and property name that we // already appended, so roll back. - builder = builder.substr(0, rollBackPoint); + builder.resize(rollBackPoint); break; } @@ -750,7 +749,7 @@ NEVER_INLINE JSValue Walker::walk(JSValue unfiltered) objectStack.append(object); indexStack.append(0); propertyStack.append(PropertyNameArray(m_exec)); - object->getPropertyNames(m_exec, propertyStack.last()); + object->getOwnPropertyNames(m_exec, propertyStack.last()); // fallthrough } objectStartVisitMember: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.h index 0705a69..ec3fa40 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSONObject.h @@ -34,18 +34,21 @@ namespace JSC { class JSONObject : public JSObject { public: - JSONObject(PassRefPtr<Structure> structure) + JSONObject(NonNullPassRefPtr<Structure> structure) : JSObject(structure) { } static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } static void markStringifiers(MarkStack&, Stringifier*); + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags; + private: virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.cpp index 01f74ac..0e3475f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.cpp @@ -42,6 +42,25 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSObject); +static inline void getClassPropertyNames(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, EnumerationMode mode) +{ + // Add properties from the static hashtables of properties + for (; classInfo; classInfo = classInfo->parentClass) { + const HashTable* table = classInfo->propHashTable(exec); + if (!table) + continue; + table->initializeIfNeeded(exec); + ASSERT(table->table); + + int hashSizeMask = table->compactSize - 1; + const HashEntry* entry = table->table; + for (int i = 0; i <= hashSizeMask; ++i, ++entry) { + if (entry->key() && (!(entry->attributes() & DontEnum) || (mode == IncludeDontEnumProperties))) + propertyNames.add(entry->key()); + } + } +} + void JSObject::markChildren(MarkStack& markStack) { #ifndef NDEBUG @@ -187,12 +206,12 @@ bool JSObject::hasProperty(ExecState* exec, unsigned propertyName) const } // ECMA 8.6.2.5 -bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) +bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName) { unsigned attributes; JSCell* specificValue; if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) { - if ((attributes & DontDelete) && checkDontDelete) + if ((attributes & DontDelete)) return false; removeDirect(propertyName); return true; @@ -200,7 +219,7 @@ bool JSObject::deleteProperty(ExecState* exec, const Identifier& propertyName, b // Look in the static hashtable of properties const HashEntry* entry = findPropertyHashEntry(exec, propertyName); - if (entry && (entry->attributes() & DontDelete) && checkDontDelete) + if (entry && entry->attributes() & DontDelete) return false; // this builtin property can't be deleted // FIXME: Should the code here actually do some deletion? @@ -213,9 +232,9 @@ bool JSObject::hasOwnProperty(ExecState* exec, const Identifier& propertyName) c return const_cast<JSObject*>(this)->getOwnPropertySlot(exec, propertyName, slot); } -bool JSObject::deleteProperty(ExecState* exec, unsigned propertyName, bool checkDontDelete) +bool JSObject::deleteProperty(ExecState* exec, unsigned propertyName) { - return deleteProperty(exec, Identifier::from(exec, propertyName), checkDontDelete); + return deleteProperty(exec, Identifier::from(exec, propertyName)); } static ALWAYS_INLINE JSValue callDefaultValueFunction(ExecState* exec, const JSObject* object, const Identifier& propertyName) @@ -395,26 +414,10 @@ bool JSObject::hasInstance(ExecState* exec, JSValue value, JSValue proto) bool JSObject::propertyIsEnumerable(ExecState* exec, const Identifier& propertyName) const { - unsigned attributes; - if (!getPropertyAttributes(exec, propertyName, attributes)) + PropertyDescriptor descriptor; + if (!const_cast<JSObject*>(this)->getOwnPropertyDescriptor(exec, propertyName, descriptor)) return false; - return !(attributes & DontEnum); -} - -bool JSObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const -{ - JSCell* specificValue; - if (m_structure->get(propertyName, attributes, specificValue) != WTF::notFound) - return true; - - // Look in the static hashtable of properties - const HashEntry* entry = findPropertyHashEntry(exec, propertyName); - if (entry) { - attributes = entry->attributes(); - return true; - } - - return false; + return descriptor.enumerable(); } bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyName, JSCell*& specificValue) const @@ -430,14 +433,31 @@ bool JSObject::getPropertySpecificValue(ExecState*, const Identifier& propertyNa return false; } -void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames) +void JSObject::getPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - m_structure->getEnumerablePropertyNames(exec, propertyNames, this); + getOwnPropertyNames(exec, propertyNames, mode); + + if (prototype().isNull()) + return; + + JSObject* prototype = asObject(this->prototype()); + while(1) { + if (prototype->structure()->typeInfo().overridesGetPropertyNames()) { + prototype->getPropertyNames(exec, propertyNames, mode); + break; + } + prototype->getOwnPropertyNames(exec, propertyNames, mode); + JSValue nextProto = prototype->prototype(); + if (nextProto.isNull()) + break; + prototype = asObject(nextProto); + } } -void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) +void JSObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - m_structure->getOwnPropertyNames(exec, propertyNames, this, includeNonEnumerable); + m_structure->getPropertyNames(propertyNames, mode); + getClassPropertyNames(exec, classInfo(), propertyNames, mode); } bool JSObject::toBoolean(ExecState*) const @@ -494,12 +514,12 @@ void JSObject::removeDirect(const Identifier& propertyName) void JSObject::putDirectFunction(ExecState* exec, InternalFunction* function, unsigned attr) { - putDirectFunction(Identifier(exec, function->name(&exec->globalData())), function, attr); + putDirectFunction(Identifier(exec, function->name(exec)), function, attr); } void JSObject::putDirectFunctionWithoutTransition(ExecState* exec, InternalFunction* function, unsigned attr) { - putDirectFunctionWithoutTransition(Identifier(exec, function->name(&exec->globalData())), function, attr); + putDirectFunctionWithoutTransition(Identifier(exec, function->name(exec)), function, attr); } NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, JSValue* location) @@ -514,7 +534,7 @@ Structure* JSObject::createInheritorID() { #ifdef QT_BUILD_SCRIPT_LIB // ### QtScript needs the hasOwnProperty() calls etc. for QScriptObject - m_inheritorID = Structure::create(this, TypeInfo(ObjectType, ImplementsHasInstance)); + m_inheritorID = Structure::create(this, TypeInfo(ObjectType, ImplementsHasInstance | JSC::OverridesHasInstance | JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames)); #else m_inheritorID = JSObject::createStructure(this); #endif @@ -526,11 +546,6 @@ void JSObject::allocatePropertyStorage(size_t oldSize, size_t newSize) allocatePropertyStorageInline(oldSize, newSize); } -JSObject* constructEmptyObject(ExecState* exec) -{ - return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure()); -} - bool JSObject::getOwnPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor& descriptor) { unsigned attributes = 0; @@ -581,7 +596,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName if (descriptor.isEmpty()) return true; - if (current.equalTo(descriptor)) + if (current.equalTo(exec, descriptor)) return true; // Filter out invalid changes @@ -627,7 +642,7 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName return false; } if (!current.writable()) { - if (descriptor.value() || !JSValue::strictEqual(current.value(), descriptor.value())) { + if (descriptor.value() || !JSValue::strictEqual(exec, current.value(), descriptor.value())) { if (throwException) throwError(exec, TypeError, "Attempting to change value of a readonly property."); return false; @@ -649,12 +664,12 @@ bool JSObject::defineOwnProperty(ExecState* exec, const Identifier& propertyName // Changing the accessor functions of an existing accessor property ASSERT(descriptor.isAccessorDescriptor()); if (!current.configurable()) { - if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(current.setter(), descriptor.setter()))) { + if (descriptor.setterPresent() && !(current.setter() && JSValue::strictEqual(exec, current.setter(), descriptor.setter()))) { if (throwException) throwError(exec, TypeError, "Attempting to change the setter of an unconfigurable property."); return false; } - if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(current.getter(), descriptor.getter()))) { + if (descriptor.getterPresent() && !(current.getter() && JSValue::strictEqual(exec, current.getter(), descriptor.getter()))) { if (throwException) throwError(exec, TypeError, "Attempting to change the getter of an unconfigurable property."); return false; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h index 9eb4e3e..21dbfe9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSObject.h @@ -74,7 +74,7 @@ namespace JSC { friend class JSCell; public: - explicit JSObject(PassRefPtr<Structure>); + explicit JSObject(NonNullPassRefPtr<Structure>); virtual void markChildren(MarkStack&); ALWAYS_INLINE void markChildrenDirect(MarkStack& markStack); @@ -86,7 +86,7 @@ namespace JSC { JSValue prototype() const; void setPrototype(JSValue prototype); - void setStructure(PassRefPtr<Structure>); + void setStructure(NonNullPassRefPtr<Structure>); Structure* inheritorID(); virtual UString className() const; @@ -115,15 +115,15 @@ namespace JSC { bool hasProperty(ExecState*, unsigned propertyName) const; bool hasOwnProperty(ExecState*, const Identifier& propertyName) const; - virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); - virtual bool deleteProperty(ExecState*, unsigned propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + virtual bool deleteProperty(ExecState*, unsigned propertyName); virtual JSValue defaultValue(ExecState*, PreferredPrimitiveType) const; virtual bool hasInstance(ExecState*, JSValue, JSValue prototypeProperty); - virtual void getPropertyNames(ExecState*, PropertyNameArray&); - virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); + virtual void getPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const; virtual bool getPrimitiveNumber(ExecState*, double& number, JSValue& value); @@ -135,7 +135,6 @@ namespace JSC { virtual JSObject* toThisObject(ExecState*) const; virtual JSObject* unwrappedObject(); - virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; bool getPropertySpecificValue(ExecState* exec, const Identifier& propertyName, JSCell*& specificFunction) const; // This get function only looks at the property map. @@ -197,7 +196,6 @@ namespace JSC { virtual bool isActivationObject() const { return false; } virtual bool isWatchdogException() const { return false; } virtual bool isNotAnObjectErrorStub() const { return false; } - #ifdef QT_BUILD_SCRIPT_LIB virtual bool compareToObject(ExecState*, JSObject *other) { return other == this; } #endif @@ -206,15 +204,22 @@ namespace JSC { void allocatePropertyStorageInline(size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); } - static const size_t inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3; - static const size_t nonInlineBaseStorageCapacity = 16; + static const unsigned inlineStorageCapacity = sizeof(EncodedJSValue) == 2 * sizeof(void*) ? 4 : 3; + static const unsigned nonInlineBaseStorageCapacity = 16; static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); + } + + void flattenDictionaryObject() + { + m_structure->flattenDictionaryStructure(this); } protected: + static const unsigned StructureFlags = 0; + void addAnonymousSlots(unsigned count); void putAnonymousValue(unsigned index, JSValue value) { @@ -231,7 +236,7 @@ namespace JSC { using JSCell::isGetterSetter; using JSCell::toObject; void getObject(); - void getString(); + void getString(ExecState* exec); void isObject(); void isString(); #if USE(JSVALUE32) @@ -268,8 +273,6 @@ namespace JSC { RefPtr<Structure> m_inheritorID; }; -JSObject* constructEmptyObject(ExecState*); - inline JSObject* asObject(JSCell* cell) { ASSERT(cell->isObject()); @@ -281,10 +284,9 @@ inline JSObject* asObject(JSValue value) return asObject(value.asCell()); } -inline JSObject::JSObject(PassRefPtr<Structure> structure) +inline JSObject::JSObject(NonNullPassRefPtr<Structure> structure) : JSCell(structure.releaseRef()) // ~JSObject balances this ref() { - ASSERT(m_structure); ASSERT(m_structure->propertyStorageCapacity() == inlineStorageCapacity); ASSERT(m_structure->isEmpty()); ASSERT(prototype().isNull() || Heap::heap(this) == Heap::heap(prototype())); @@ -313,7 +315,7 @@ inline void JSObject::setPrototype(JSValue prototype) setStructure(newStructure.release()); } -inline void JSObject::setStructure(PassRefPtr<Structure> structure) +inline void JSObject::setStructure(NonNullPassRefPtr<Structure> structure) { m_structure->deref(); m_structure = structure.releaseRef(); // ~JSObject balances this ref() @@ -375,14 +377,14 @@ ALWAYS_INLINE bool JSObject::getOwnPropertySlot(ExecState* exec, const Identifie ALWAYS_INLINE bool JSCell::fastGetOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - if (structure()->typeInfo().hasStandardGetOwnPropertySlot()) + if (!structure()->typeInfo().overridesGetOwnPropertySlot()) return asObject(this)->inlineGetOwnPropertySlot(exec, propertyName, slot); return getOwnPropertySlot(exec, propertyName, slot); } // It may seem crazy to inline a function this large but it makes a big difference // since this is function very hot in variable lookup -inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) +ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { JSObject* object = this; while (true) { @@ -395,7 +397,7 @@ inline bool JSObject::getPropertySlot(ExecState* exec, const Identifier& propert } } -inline bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) +ALWAYS_INLINE bool JSObject::getPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { JSObject* object = this; while (true) { @@ -689,7 +691,7 @@ ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack) { JSCell::markChildren(markStack); - m_structure->markAggregate(markStack); + markStack.append(prototype()); PropertyStorage storage = propertyStorage(); size_t storageSize = m_structure->propertyStorageSize(); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.cpp index e08a3d9..d3dcb83 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.cpp @@ -29,26 +29,62 @@ #include "config.h" #include "JSPropertyNameIterator.h" +#include "JSGlobalObject.h" + namespace JSC { ASSERT_CLASS_FITS_IN_CELL(JSPropertyNameIterator); -JSPropertyNameIterator::~JSPropertyNameIterator() +JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o) { + ASSERT(!o->structure()->enumerationCache() || + o->structure()->enumerationCache()->cachedStructure() != o->structure() || + o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec)); + + PropertyNameArray propertyNames(exec); + o->getPropertyNames(exec, propertyNames); + size_t numCacheableSlots = 0; + if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasAnonymousSlots() && + !o->structure()->hasGetterSetterProperties() && !o->structure()->isUncacheableDictionary() && + !o->structure()->typeInfo().overridesGetPropertyNames()) + numCacheableSlots = o->structure()->propertyStorageSize(); + + JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots); + + if (o->structure()->isDictionary()) + return jsPropertyNameIterator; + + if (o->structure()->typeInfo().overridesGetPropertyNames()) + return jsPropertyNameIterator; + + size_t count = normalizePrototypeChain(exec, o); + StructureChain* structureChain = o->structure()->prototypeChain(exec); + RefPtr<Structure>* structure = structureChain->head(); + for (size_t i = 0; i < count; ++i) { + if (structure[i]->typeInfo().overridesGetPropertyNames()) + return jsPropertyNameIterator; + } + + jsPropertyNameIterator->setCachedPrototypeChain(structureChain); + jsPropertyNameIterator->setCachedStructure(o->structure()); + o->structure()->setEnumerationCache(jsPropertyNameIterator); + return jsPropertyNameIterator; } -void JSPropertyNameIterator::markChildren(MarkStack& markStack) +JSValue JSPropertyNameIterator::get(ExecState* exec, JSObject* base, size_t i) { - JSCell::markChildren(markStack); - if (m_object) - markStack.append(m_object); + JSValue& identifier = m_jsStrings[i]; + if (m_cachedStructure == base->structure() && m_cachedPrototypeChain == base->structure()->prototypeChain(exec)) + return identifier; + + if (!base->hasProperty(exec, Identifier(exec, asString(identifier)->value(exec)))) + return JSValue(); + return identifier; } -void JSPropertyNameIterator::invalidate() +void JSPropertyNameIterator::markChildren(MarkStack& markStack) { - ASSERT(m_position == m_end); - m_object = 0; - m_data.clear(); + markStack.appendValues(m_jsStrings.get(), m_jsStringsSize, MayContainNullValues); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.h index d2849a8..f5c64bb 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -31,7 +31,9 @@ #include "JSObject.h" #include "JSString.h" +#include "Operations.h" #include "PropertyNameArray.h" +#include "StructureChain.h" namespace JSC { @@ -39,73 +41,63 @@ namespace JSC { class JSObject; class JSPropertyNameIterator : public JSCell { + friend class JIT; + public: - static JSPropertyNameIterator* create(ExecState*, JSValue); + static JSPropertyNameIterator* create(ExecState*, JSObject*); + + static PassRefPtr<Structure> createStructure(JSValue prototype) + { + return Structure::create(prototype, TypeInfo(CompoundType, OverridesMarkChildren)); + } - virtual ~JSPropertyNameIterator(); + virtual bool isPropertyNameIterator() const { return true; } virtual void markChildren(MarkStack&); - JSValue next(ExecState*); - void invalidate(); - - static PassRefPtr<Structure> createStructure(JSValue prototype) + bool getOffset(size_t i, int& offset) { - return Structure::create(prototype, TypeInfo(CompoundType)); + if (i >= m_numCacheableSlots) + return false; + offset = i; + return true; } + + JSValue get(ExecState*, JSObject*, size_t i); + size_t size() { return m_jsStringsSize; } + + void setCachedStructure(Structure* structure) { m_cachedStructure = structure; } + Structure* cachedStructure() { return m_cachedStructure; } + + void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } + StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); } + private: - JSPropertyNameIterator(ExecState*); - JSPropertyNameIterator(ExecState*, JSObject*, PassRefPtr<PropertyNameArrayData> propertyNameArrayData); + JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot); - JSObject* m_object; - RefPtr<PropertyNameArrayData> m_data; - PropertyNameArrayData::const_iterator m_position; - PropertyNameArrayData::const_iterator m_end; + Structure* m_cachedStructure; + RefPtr<StructureChain> m_cachedPrototypeChain; + uint32_t m_numCacheableSlots; + uint32_t m_jsStringsSize; + OwnArrayPtr<JSValue> m_jsStrings; }; -inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec) +inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlots) : JSCell(exec->globalData().propertyNameIteratorStructure.get()) - , m_object(0) - , m_position(0) - , m_end(0) + , m_cachedStructure(0) + , m_numCacheableSlots(numCacheableSlots) + , m_jsStringsSize(propertyNameArrayData->propertyNameVector().size()) + , m_jsStrings(new JSValue[m_jsStringsSize]) { + PropertyNameArrayData::PropertyNameVector& propertyNameVector = propertyNameArrayData->propertyNameVector(); + for (size_t i = 0; i < m_jsStringsSize; ++i) + m_jsStrings[i] = jsOwnedString(exec, propertyNameVector[i].ustring()); } -inline JSPropertyNameIterator::JSPropertyNameIterator(ExecState* exec, JSObject* object, PassRefPtr<PropertyNameArrayData> propertyNameArrayData) - : JSCell(exec->globalData().propertyNameIteratorStructure.get()) - , m_object(object) - , m_data(propertyNameArrayData) - , m_position(m_data->begin()) - , m_end(m_data->end()) -{ -} - -inline JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSValue v) +inline void Structure::setEnumerationCache(JSPropertyNameIterator* enumerationCache) { - if (v.isUndefinedOrNull()) - return new (exec) JSPropertyNameIterator(exec); - - JSObject* o = v.toObject(exec); - PropertyNameArray propertyNames(exec); - o->getPropertyNames(exec, propertyNames); - return new (exec) JSPropertyNameIterator(exec, o, propertyNames.releaseData()); -} - -inline JSValue JSPropertyNameIterator::next(ExecState* exec) -{ - if (m_position == m_end) - return JSValue(); - - if (m_data->cachedStructure() == m_object->structure() && m_data->cachedPrototypeChain() == m_object->structure()->prototypeChain(exec)) - return jsOwnedString(exec, (*m_position++).ustring()); - - do { - if (m_object->hasProperty(exec, *m_position)) - return jsOwnedString(exec, (*m_position++).ustring()); - m_position++; - } while (m_position != m_end); - - return JSValue(); + ASSERT(!isDictionary()); + m_enumerationCache = enumerationCache; } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.h index 5eb0e4b..2542878 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSStaticScopeObject.h @@ -57,7 +57,10 @@ namespace JSC{ virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes); - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, NeedsThisConversion)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); } + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | NeedsThisConversion | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; private: JSStaticScopeObjectData* d() { return static_cast<JSStaticScopeObjectData*>(JSVariableObject::d); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.cpp index a30f729..1e23a15 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.cpp @@ -25,41 +25,150 @@ #include "JSGlobalObject.h" #include "JSObject.h" +#include "Operations.h" #include "StringObject.h" #include "StringPrototype.h" namespace JSC { +void JSString::Rope::destructNonRecursive() +{ + Vector<Rope*, 32> workQueue; + Rope* rope = this; + + while (true) { + unsigned length = rope->ropeLength(); + for (unsigned i = 0; i < length; ++i) { + Fiber& fiber = rope->fibers(i); + if (fiber.isString()) + fiber.string()->deref(); + else { + Rope* nextRope = fiber.rope(); + if (nextRope->hasOneRef()) + workQueue.append(nextRope); + else + nextRope->deref(); + } + } + if (rope != this) + fastFree(rope); + + if (workQueue.isEmpty()) + return; + + rope = workQueue.last(); + workQueue.removeLast(); + } +} + +JSString::Rope::~Rope() +{ + destructNonRecursive(); +} + +// Overview: this methods converts a JSString from holding a string in rope form +// down to a simple UString representation. It does so by building up the string +// backwards, since we want to avoid recursion, we expect that the tree structure +// representing the rope is likely imbalanced with more nodes down the left side +// (since appending to the string is likely more common) - and as such resolving +// in this fashion should minimize work queue size. (If we built the queue forwards +// we would likely have to place all of the constituent UString::Reps into the +// Vector before performing any concatenation, but by working backwards we likely +// only fill the queue with the number of substrings at any given level in a +// rope-of-ropes.) +void JSString::resolveRope(ExecState* exec) const +{ + ASSERT(isRope()); + + // Allocate the buffer to hold the final string, position initially points to the end. + UChar* buffer; + if (PassRefPtr<UStringImpl> newImpl = UStringImpl::tryCreateUninitialized(m_stringLength, buffer)) + m_value = newImpl; + else { + for (unsigned i = 0; i < m_ropeLength; ++i) { + m_fibers[i].deref(); + m_fibers[i] = static_cast<void*>(0); + } + m_ropeLength = 0; + ASSERT(!isRope()); + ASSERT(m_value == UString()); + throwOutOfMemoryError(exec); + return; + } + UChar* position = buffer + m_stringLength; + + // Start with the current Rope. + Vector<Rope::Fiber, 32> workQueue; + Rope::Fiber currentFiber; + for (unsigned i = 0; i < (m_ropeLength - 1); ++i) + workQueue.append(m_fibers[i]); + currentFiber = m_fibers[m_ropeLength - 1]; + while (true) { + if (currentFiber.isRope()) { + Rope* rope = currentFiber.rope(); + // Copy the contents of the current rope into the workQueue, with the last item in 'currentFiber' + // (we will be working backwards over the rope). + unsigned ropeLengthMinusOne = rope->ropeLength() - 1; + for (unsigned i = 0; i < ropeLengthMinusOne; ++i) + workQueue.append(rope->fibers(i)); + currentFiber = rope->fibers(ropeLengthMinusOne); + } else { + UString::Rep* string = currentFiber.string(); + unsigned length = string->size(); + position -= length; + UStringImpl::copyChars(position, string->data(), length); + + // Was this the last item in the work queue? + if (workQueue.isEmpty()) { + // Create a string from the UChar buffer, clear the rope RefPtr. + ASSERT(buffer == position); + for (unsigned i = 0; i < m_ropeLength; ++i) { + m_fibers[i].deref(); + m_fibers[i] = static_cast<void*>(0); + } + m_ropeLength = 0; + + ASSERT(!isRope()); + return; + } + + // No! - set the next item up to process. + currentFiber = workQueue.last(); + workQueue.removeLast(); + } + } +} + JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const { return const_cast<JSString*>(this); } -bool JSString::getPrimitiveNumber(ExecState*, double& number, JSValue& value) +bool JSString::getPrimitiveNumber(ExecState* exec, double& number, JSValue& result) { - value = this; - number = m_value.toDouble(); + result = this; + number = value(exec).toDouble(); return false; } bool JSString::toBoolean(ExecState*) const { - return !m_value.isEmpty(); + return m_stringLength; } -double JSString::toNumber(ExecState*) const +double JSString::toNumber(ExecState* exec) const { - return m_value.toDouble(); + return value(exec).toDouble(); } -UString JSString::toString(ExecState*) const +UString JSString::toString(ExecState* exec) const { - return m_value; + return value(exec); } -UString JSString::toThisString(ExecState*) const +UString JSString::toThisString(ExecState* exec) const { - return m_value; + return value(exec); } JSString* JSString::toThisJSString(ExecState*) @@ -106,14 +215,14 @@ bool JSString::getOwnPropertySlot(ExecState* exec, const Identifier& propertyNam bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { if (propertyName == exec->propertyNames().length) { - descriptor.setDescriptor(jsNumber(exec, m_value.size()), DontEnum | DontDelete | ReadOnly); + descriptor.setDescriptor(jsNumber(exec, m_stringLength), DontEnum | DontDelete | ReadOnly); return true; } bool isStrictUInt32; unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); - if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) { - descriptor.setDescriptor(jsSingleCharacterSubstring(exec, m_value, i), DontDelete | ReadOnly); + if (isStrictUInt32 && i < m_stringLength) { + descriptor.setDescriptor(jsSingleCharacterSubstring(exec, value(exec), i), DontDelete | ReadOnly); return true; } @@ -139,60 +248,4 @@ bool JSString::getOwnPropertySlot(ExecState* exec, unsigned propertyName, Proper return JSString::getOwnPropertySlot(exec, Identifier::from(exec, propertyName), slot); } -bool JSString::getStringPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const -{ - if (propertyName == exec->propertyNames().length) { - attributes = DontEnum | DontDelete | ReadOnly; - return true; - } - bool isStrictUInt32; - unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); - if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) { - attributes = DontDelete | ReadOnly; - return true; - } - return false; -} - -JSString* jsString(JSGlobalData* globalData, const UString& s) -{ - int size = s.size(); - if (!size) - return globalData->smallStrings.emptyString(globalData); - if (size == 1) { - UChar c = s.data()[0]; - if (c <= 0xFF) - return globalData->smallStrings.singleCharacterString(globalData, c); - } - return new (globalData) JSString(globalData, s); -} - -JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length) -{ - ASSERT(offset <= static_cast<unsigned>(s.size())); - ASSERT(length <= static_cast<unsigned>(s.size())); - ASSERT(offset + length <= static_cast<unsigned>(s.size())); - if (!length) - return globalData->smallStrings.emptyString(globalData); - if (length == 1) { - UChar c = s.data()[offset]; - if (c <= 0xFF) - return globalData->smallStrings.singleCharacterString(globalData, c); - } - return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, length)); -} - -JSString* jsOwnedString(JSGlobalData* globalData, const UString& s) -{ - int size = s.size(); - if (!size) - return globalData->smallStrings.emptyString(globalData); - if (size == 1) { - UChar c = s.data()[0]; - if (c <= 0xFF) - return globalData->smallStrings.singleCharacterString(globalData, c); - } - return new (globalData) JSString(globalData, s, JSString::HasOtherOwner); -} - } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.h index eeada2e..e1c6aba 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSString.h @@ -59,14 +59,117 @@ namespace JSC { JSString* jsOwnedString(JSGlobalData*, const UString&); JSString* jsOwnedString(ExecState*, const UString&); - class JSString : public JSCell { - friend class JIT; - friend struct VPtrSet; + typedef void (*JSStringFinalizerCallback)(JSString*, void* context); + JSString* jsStringWithFinalizer(ExecState*, const UString&, JSStringFinalizerCallback callback, void* context); + class JS_EXPORTCLASS JSString : public JSCell { public: - JSString(JSGlobalData* globalData, const UString& value) + friend class JIT; + friend class JSGlobalData; + + // A Rope is a string composed of a set of substrings. + class Rope : public RefCounted<Rope> { + public: + // A Rope is composed from a set of smaller strings called Fibers. + // Each Fiber in a rope is either UString::Rep or another Rope. + class Fiber { + public: + Fiber() : m_value(0) {} + Fiber(UString::Rep* string) : m_value(reinterpret_cast<intptr_t>(string)) {} + Fiber(Rope* rope) : m_value(reinterpret_cast<intptr_t>(rope) | 1) {} + + Fiber(void* nonFiber) : m_value(reinterpret_cast<intptr_t>(nonFiber)) {} + + void deref() + { + if (isRope()) + rope()->deref(); + else + string()->deref(); + } + + Fiber& ref() + { + if (isString()) + string()->ref(); + else + rope()->ref(); + return *this; + } + + unsigned refAndGetLength() + { + if (isString()) { + UString::Rep* rep = string(); + return rep->ref()->size(); + } else { + Rope* r = rope(); + r->ref(); + return r->stringLength(); + } + } + + bool isRope() { return m_value & 1; } + Rope* rope() { return reinterpret_cast<Rope*>(m_value & ~1); } + bool isString() { return !isRope(); } + UString::Rep* string() { return reinterpret_cast<UString::Rep*>(m_value); } + + void* nonFiber() { return reinterpret_cast<void*>(m_value); } + private: + intptr_t m_value; + }; + + // Creates a Rope comprising of 'ropeLength' Fibers. + // The Rope is constructed in an uninitialized state - initialize must be called for each Fiber in the Rope. + static PassRefPtr<Rope> createOrNull(unsigned ropeLength) + { + void* allocation; + if (tryFastMalloc(sizeof(Rope) + (ropeLength - 1) * sizeof(Fiber)).getValue(allocation)) + return adoptRef(new (allocation) Rope(ropeLength)); + return 0; + } + + ~Rope(); + void destructNonRecursive(); + + void append(unsigned &index, Fiber& fiber) + { + m_fibers[index++] = fiber; + m_stringLength += fiber.refAndGetLength(); + } + void append(unsigned &index, const UString& string) + { + UString::Rep* rep = string.rep(); + m_fibers[index++] = Fiber(rep); + m_stringLength += rep->ref()->size(); + } + void append(unsigned& index, JSString* jsString) + { + if (jsString->isRope()) { + for (unsigned i = 0; i < jsString->m_ropeLength; ++i) + append(index, jsString->m_fibers[i]); + } else + append(index, jsString->string()); + } + + unsigned ropeLength() { return m_ropeLength; } + unsigned stringLength() { return m_stringLength; } + Fiber& fibers(unsigned index) { return m_fibers[index]; } + + private: + Rope(unsigned ropeLength) : m_ropeLength(ropeLength), m_stringLength(0) {} + void* operator new(size_t, void* inPlace) { return inPlace; } + + unsigned m_ropeLength; + unsigned m_stringLength; + Fiber m_fibers[1]; + }; + + ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value) : JSCell(globalData->stringStructure.get()) + , m_stringLength(value.size()) , m_value(value) + , m_ropeLength(0) { Heap::heap(this)->reportExtraMemoryCost(value.cost()); } @@ -74,33 +177,164 @@ namespace JSC { enum HasOtherOwnerType { HasOtherOwner }; JSString(JSGlobalData* globalData, const UString& value, HasOtherOwnerType) : JSCell(globalData->stringStructure.get()) + , m_stringLength(value.size()) , m_value(value) + , m_ropeLength(0) { } JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType) : JSCell(globalData->stringStructure.get()) + , m_stringLength(value->size()) , m_value(value) + , m_ropeLength(0) { } - - const UString& value() const { return m_value; } + JSString(JSGlobalData* globalData, PassRefPtr<JSString::Rope> rope) + : JSCell(globalData->stringStructure.get()) + , m_stringLength(rope->stringLength()) + , m_ropeLength(1) + { + m_fibers[0] = rope.releaseRef(); + } + // This constructor constructs a new string by concatenating s1 & s2. + // This should only be called with ropeLength <= 3. + JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, JSString* s2) + : JSCell(globalData->stringStructure.get()) + , m_stringLength(s1->length() + s2->length()) + , m_ropeLength(ropeLength) + { + ASSERT(ropeLength <= s_maxInternalRopeLength); + unsigned index = 0; + appendStringInConstruct(index, s1); + appendStringInConstruct(index, s2); + ASSERT(ropeLength == index); + } + // This constructor constructs a new string by concatenating s1 & s2. + // This should only be called with ropeLength <= 3. + JSString(JSGlobalData* globalData, unsigned ropeLength, JSString* s1, const UString& u2) + : JSCell(globalData->stringStructure.get()) + , m_stringLength(s1->length() + u2.size()) + , m_ropeLength(ropeLength) + { + ASSERT(ropeLength <= s_maxInternalRopeLength); + unsigned index = 0; + appendStringInConstruct(index, s1); + appendStringInConstruct(index, u2); + ASSERT(ropeLength == index); + } + // This constructor constructs a new string by concatenating s1 & s2. + // This should only be called with ropeLength <= 3. + JSString(JSGlobalData* globalData, unsigned ropeLength, const UString& u1, JSString* s2) + : JSCell(globalData->stringStructure.get()) + , m_stringLength(u1.size() + s2->length()) + , m_ropeLength(ropeLength) + { + ASSERT(ropeLength <= s_maxInternalRopeLength); + unsigned index = 0; + appendStringInConstruct(index, u1); + appendStringInConstruct(index, s2); + ASSERT(ropeLength == index); + } + // This constructor constructs a new string by concatenating v1, v2 & v3. + // This should only be called with ropeLength <= 3 ... which since every + // value must require a ropeLength of at least one implies that the length + // for each value must be exactly 1! + JSString(ExecState* exec, JSValue v1, JSValue v2, JSValue v3) + : JSCell(exec->globalData().stringStructure.get()) + , m_stringLength(0) + , m_ropeLength(s_maxInternalRopeLength) + { + unsigned index = 0; + appendValueInConstructAndIncrementLength(exec, index, v1); + appendValueInConstructAndIncrementLength(exec, index, v2); + appendValueInConstructAndIncrementLength(exec, index, v3); + ASSERT(index == s_maxInternalRopeLength); + } + + JSString(JSGlobalData* globalData, const UString& value, JSStringFinalizerCallback finalizer, void* context) + : JSCell(globalData->stringStructure.get()) + , m_stringLength(value.size()) + , m_value(value) + , m_ropeLength(0) + { + // nasty hack because we can't union non-POD types + m_fibers[0] = reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(finalizer)); + m_fibers[1] = context; + Heap::heap(this)->reportExtraMemoryCost(value.cost()); + } + + ~JSString() + { + ASSERT(vptr() == JSGlobalData::jsStringVPtr); + for (unsigned i = 0; i < m_ropeLength; ++i) + m_fibers[i].deref(); + + if (!m_ropeLength && m_fibers[0].nonFiber()) { + JSStringFinalizerCallback finalizer = (JSStringFinalizerCallback)(m_fibers[0].nonFiber()); + finalizer(this, m_fibers[1].nonFiber()); + } + } + + const UString& value(ExecState* exec) const + { + if (isRope()) + resolveRope(exec); + return m_value; + } + const UString tryGetValue() const + { + if (isRope()) + UString(); + return m_value; + } + unsigned length() { return m_stringLength; } bool getStringPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); bool getStringPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); bool getStringPropertyDescriptor(ExecState*, const Identifier& propertyName, PropertyDescriptor&); - bool getStringPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned&) const; - - bool canGetIndex(unsigned i) { return i < static_cast<unsigned>(m_value.size()); } - JSString* getIndex(JSGlobalData*, unsigned); + bool canGetIndex(unsigned i) { return i < m_stringLength; } + JSString* getIndex(ExecState*, unsigned); - static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, NeedsThisConversion | HasDefaultMark)); } + static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion)); } private: enum VPtrStealingHackType { VPtrStealingHack }; JSString(VPtrStealingHackType) : JSCell(0) + , m_ropeLength(0) + { + } + + void resolveRope(ExecState*) const; + + void appendStringInConstruct(unsigned& index, const UString& string) + { + m_fibers[index++] = Rope::Fiber(string.rep()->ref()); + } + + void appendStringInConstruct(unsigned& index, JSString* jsString) { + if (jsString->isRope()) { + for (unsigned i = 0; i < jsString->m_ropeLength; ++i) + m_fibers[index++] = jsString->m_fibers[i].ref(); + } else + appendStringInConstruct(index, jsString->string()); + } + + void appendValueInConstructAndIncrementLength(ExecState* exec, unsigned& index, JSValue v) + { + if (v.isString()) { + ASSERT(asCell(v)->isString()); + JSString* s = static_cast<JSString*>(asCell(v)); + ASSERT(s->ropeLength() == 1); + appendStringInConstruct(index, s); + m_stringLength += s->length(); + } else { + UString u(v.toString(exec)); + m_fibers[index++] = Rope::Fiber(u.rep()->ref()); + m_stringLength += u.size(); + } } virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; @@ -119,11 +353,38 @@ namespace JSC { virtual bool getOwnPropertySlot(ExecState*, unsigned propertyName, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); - UString m_value; + static const unsigned s_maxInternalRopeLength = 3; + + // A string is represented either by a UString or a Rope. + unsigned m_stringLength; + mutable UString m_value; + mutable unsigned m_ropeLength; + mutable Rope::Fiber m_fibers[s_maxInternalRopeLength]; + + bool isRope() const { return m_ropeLength; } + UString& string() { ASSERT(!isRope()); return m_value; } + unsigned ropeLength() { return m_ropeLength ? m_ropeLength : 1; } + + friend JSValue jsString(ExecState* exec, JSString* s1, JSString* s2); + friend JSValue jsString(ExecState* exec, const UString& u1, JSString* s2); + friend JSValue jsString(ExecState* exec, JSString* s1, const UString& u2); + friend JSValue jsString(ExecState* exec, Register* strings, unsigned count); + friend JSValue jsString(ExecState* exec, JSValue thisValue, const ArgList& args); + friend JSString* jsStringWithFinalizer(ExecState*, const UString&, JSStringFinalizerCallback callback, void* context); }; JSString* asString(JSValue); + // When an object is created from a different DLL, MSVC changes vptr to a "local" one right after invoking a constructor, + // see <http://groups.google.com/group/microsoft.public.vc.language/msg/55cdcefeaf770212>. + // This breaks isJSString(), and we don't need that hack anyway, so we change vptr back to primary one. + // The below function must be called by any inline function that invokes a JSString constructor. +#if COMPILER(MSVC) && !defined(BUILDING_JavaScriptCore) + inline JSString* fixupVPtr(JSGlobalData* globalData, JSString* string) { string->setVPtr(globalData->jsStringVPtr); return string; } +#else + inline JSString* fixupVPtr(JSGlobalData*, JSString* string) { return string; } +#endif + inline JSString* asString(JSValue value) { ASSERT(asCell(value)->isString()); @@ -139,7 +400,7 @@ namespace JSC { { if (c <= 0xFF) return globalData->smallStrings.singleCharacterString(globalData, c); - return new (globalData) JSString(globalData, UString(&c, 1)); + return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1))); } inline JSString* jsSingleCharacterSubstring(JSGlobalData* globalData, const UString& s, unsigned offset) @@ -148,7 +409,7 @@ namespace JSC { UChar c = s.data()[offset]; if (c <= 0xFF) return globalData->smallStrings.singleCharacterString(globalData, c); - return new (globalData) JSString(globalData, UString::Rep::create(s.rep(), offset, 1)); + return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, 1)))); } inline JSString* jsNontrivialString(JSGlobalData* globalData, const char* s) @@ -156,19 +417,67 @@ namespace JSC { ASSERT(s); ASSERT(s[0]); ASSERT(s[1]); - return new (globalData) JSString(globalData, s); + return fixupVPtr(globalData, new (globalData) JSString(globalData, s)); } inline JSString* jsNontrivialString(JSGlobalData* globalData, const UString& s) { ASSERT(s.size() > 1); - return new (globalData) JSString(globalData, s); + return fixupVPtr(globalData, new (globalData) JSString(globalData, s)); } - inline JSString* JSString::getIndex(JSGlobalData* globalData, unsigned i) + inline JSString* JSString::getIndex(ExecState* exec, unsigned i) { ASSERT(canGetIndex(i)); - return jsSingleCharacterSubstring(globalData, m_value, i); + return jsSingleCharacterSubstring(&exec->globalData(), value(exec), i); + } + + inline JSString* jsString(JSGlobalData* globalData, const UString& s) + { + int size = s.size(); + if (!size) + return globalData->smallStrings.emptyString(globalData); + if (size == 1) { + UChar c = s.data()[0]; + if (c <= 0xFF) + return globalData->smallStrings.singleCharacterString(globalData, c); + } + return fixupVPtr(globalData, new (globalData) JSString(globalData, s)); + } + + inline JSString* jsStringWithFinalizer(ExecState* exec, const UString& s, JSStringFinalizerCallback callback, void* context) + { + ASSERT(s.size() && (s.size() > 1 || s.data()[0] > 0xFF)); + JSGlobalData* globalData = &exec->globalData(); + return fixupVPtr(globalData, new (globalData) JSString(globalData, s, callback, context)); + } + + inline JSString* jsSubstring(JSGlobalData* globalData, const UString& s, unsigned offset, unsigned length) + { + ASSERT(offset <= static_cast<unsigned>(s.size())); + ASSERT(length <= static_cast<unsigned>(s.size())); + ASSERT(offset + length <= static_cast<unsigned>(s.size())); + if (!length) + return globalData->smallStrings.emptyString(globalData); + if (length == 1) { + UChar c = s.data()[offset]; + if (c <= 0xFF) + return globalData->smallStrings.singleCharacterString(globalData, c); + } + return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(UString::Rep::create(s.rep(), offset, length)), JSString::HasOtherOwner)); + } + + inline JSString* jsOwnedString(JSGlobalData* globalData, const UString& s) + { + int size = s.size(); + if (!size) + return globalData->smallStrings.emptyString(globalData); + if (size == 1) { + UChar c = s.data()[0]; + if (c <= 0xFF) + return globalData->smallStrings.singleCharacterString(globalData, c); + } + return fixupVPtr(globalData, new (globalData) JSString(globalData, s, JSString::HasOtherOwner)); } inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); } @@ -183,14 +492,14 @@ namespace JSC { ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { if (propertyName == exec->propertyNames().length) { - slot.setValue(jsNumber(exec, m_value.size())); + slot.setValue(jsNumber(exec, m_stringLength)); return true; } bool isStrictUInt32; unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); - if (isStrictUInt32 && i < static_cast<unsigned>(m_value.size())) { - slot.setValue(jsSingleCharacterSubstring(exec, m_value, i)); + if (isStrictUInt32 && i < m_stringLength) { + slot.setValue(jsSingleCharacterSubstring(exec, value(exec), i)); return true; } @@ -199,8 +508,8 @@ namespace JSC { ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { - if (propertyName < static_cast<unsigned>(m_value.size())) { - slot.setValue(jsSingleCharacterSubstring(exec, m_value, propertyName)); + if (propertyName < m_stringLength) { + slot.setValue(jsSingleCharacterSubstring(exec, value(exec), propertyName)); return true; } @@ -219,7 +528,7 @@ namespace JSC { inline UString JSValue::toString(ExecState* exec) const { if (isString()) - return static_cast<JSString*>(asCell())->value(); + return static_cast<JSString*>(asCell())->value(exec); if (isInt32()) return exec->globalData().numericStrings.add(asInt32()); if (isDouble()) @@ -236,6 +545,26 @@ namespace JSC { return asCell()->toString(exec); } + inline UString JSValue::toPrimitiveString(ExecState* exec) const + { + if (isString()) + return static_cast<JSString*>(asCell())->value(exec); + if (isInt32()) + return exec->globalData().numericStrings.add(asInt32()); + if (isDouble()) + return exec->globalData().numericStrings.add(asDouble()); + if (isTrue()) + return "true"; + if (isFalse()) + return "false"; + if (isNull()) + return "null"; + if (isUndefined()) + return "undefined"; + ASSERT(isCell()); + return asCell()->toPrimitive(exec, NoPreference).toString(exec); + } + } // namespace JSC #endif // JSString_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSTypeInfo.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSTypeInfo.h index 279510b..7c89600 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSTypeInfo.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSTypeInfo.h @@ -40,9 +40,9 @@ namespace JSC { static const unsigned OverridesHasInstance = 1 << 2; static const unsigned ImplementsDefaultHasInstance = 1 << 3; static const unsigned NeedsThisConversion = 1 << 4; - static const unsigned HasStandardGetOwnPropertySlot = 1 << 5; - static const unsigned HasDefaultMark = 1 << 6; - static const unsigned HasDefaultGetPropertyNames = 1 << 7; + static const unsigned OverridesGetOwnPropertySlot = 1 << 5; + static const unsigned OverridesMarkChildren = 1 << 6; + static const unsigned OverridesGetPropertyNames = 1 << 7; class TypeInfo { friend class JIT; @@ -63,9 +63,9 @@ namespace JSC { bool implementsHasInstance() const { return m_flags & ImplementsHasInstance; } bool overridesHasInstance() const { return m_flags & OverridesHasInstance; } bool needsThisConversion() const { return m_flags & NeedsThisConversion; } - bool hasStandardGetOwnPropertySlot() const { return m_flags & HasStandardGetOwnPropertySlot; } - bool hasDefaultMark() const { return m_flags & HasDefaultMark; } - bool hasDefaultGetPropertyNames() const { return m_flags & HasDefaultGetPropertyNames; } + bool overridesGetOwnPropertySlot() const { return m_flags & OverridesGetOwnPropertySlot; } + bool overridesMarkChildren() const { return m_flags & OverridesMarkChildren; } + bool overridesGetPropertyNames() const { return m_flags & OverridesGetPropertyNames; } unsigned flags() const { return m_flags; } private: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.h index 3c511d8..6da921f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSValue.h @@ -80,6 +80,7 @@ namespace JSC { enum JSUndefinedTag { JSUndefined }; enum JSTrueTag { JSTrue }; enum JSFalseTag { JSFalse }; + enum EncodeAsDoubleTag { EncodeAsDouble }; JSValue(); JSValue(JSNullTag); @@ -90,6 +91,7 @@ namespace JSC { JSValue(const JSCell* ptr); // Numbers + JSValue(EncodeAsDoubleTag, ExecState*, double); JSValue(ExecState*, double); JSValue(ExecState*, char); JSValue(ExecState*, unsigned char); @@ -135,8 +137,8 @@ namespace JSC { bool getBoolean() const; // false if not a boolean bool getNumber(double&) const; double uncheckedGetNumber() const; - bool getString(UString&) const; - UString getString() const; // null string if not a string + bool getString(ExecState* exec, UString&) const; + UString getString(ExecState* exec) const; // null string if not a string JSObject* getObject() const; // 0 if not an object CallType getCallData(CallData&); @@ -156,6 +158,7 @@ namespace JSC { double toNumber(ExecState*) const; JSValue toJSNumber(ExecState*) const; // Fast path for when you expect that the value is an immediate number. UString toString(ExecState*) const; + UString toPrimitiveString(ExecState*) const; JSObject* toObject(ExecState*) const; // Integer conversions. @@ -166,6 +169,10 @@ namespace JSC { uint32_t toUInt32(ExecState*) const; uint32_t toUInt32(ExecState*, bool& ok) const; +#if ENABLE(JSC_ZOMBIES) + bool isZombie() const; +#endif + // Floating point conversions (this is a convenience method for webcore; // signle precision float is not a representation used in JS or JSC). float toFloat(ExecState* exec) const { return static_cast<float>(toNumber(exec)); } @@ -186,9 +193,9 @@ namespace JSC { static bool equal(ExecState* exec, JSValue v1, JSValue v2); static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2); static bool equalSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2); - static bool strictEqual(JSValue v1, JSValue v2); - static bool strictEqualSlowCase(JSValue v1, JSValue v2); - static bool strictEqualSlowCaseInline(JSValue v1, JSValue v2); + static bool strictEqual(ExecState* exec, JSValue v1, JSValue v2); + static bool strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2); + static bool strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2); JSValue getJSNumber(); // JSValue() if this is not a JSNumber or number object @@ -228,7 +235,7 @@ namespace JSC { union { EncodedJSValue asEncodedJSValue; double asDouble; -#if PLATFORM(BIG_ENDIAN) +#if CPU(BIG_ENDIAN) struct { int32_t tag; int32_t payload; @@ -279,6 +286,11 @@ namespace JSC { return b ? JSValue(JSValue::JSTrue) : JSValue(JSValue::JSFalse); } + ALWAYS_INLINE JSValue jsDoubleNumber(ExecState* exec, double d) + { + return JSValue(JSValue::EncodeAsDouble, exec, d); + } + ALWAYS_INLINE JSValue jsNumber(ExecState* exec, double d) { return JSValue(exec, d); @@ -373,6 +385,14 @@ namespace JSC { return static_cast<uint32_t>(val); } + // FIXME: We should deprecate this and just use JSValue::asCell() instead. + JSCell* asCell(JSValue); + + inline JSCell* asCell(JSValue value) + { + return value.asCell(); + } + ALWAYS_INLINE int32_t JSValue::toInt32(ExecState* exec) const { if (isInt32()) @@ -423,6 +443,9 @@ namespace JSC { { JSValue v; v.u.asEncodedJSValue = encodedJSValue; +#if ENABLE(JSC_ZOMBIES) + ASSERT(!v.isZombie()); +#endif return v; } @@ -469,6 +492,9 @@ namespace JSC { else u.asBits.tag = EmptyValueTag; u.asBits.payload = reinterpret_cast<int32_t>(ptr); +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie()); +#endif } inline JSValue::JSValue(const JSCell* ptr) @@ -478,6 +504,9 @@ namespace JSC { else u.asBits.tag = EmptyValueTag; u.asBits.payload = reinterpret_cast<int32_t>(const_cast<JSCell*>(ptr)); +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie()); +#endif } inline JSValue::operator bool() const @@ -575,6 +604,11 @@ namespace JSC { return reinterpret_cast<JSCell*>(u.asBits.payload); } + ALWAYS_INLINE JSValue::JSValue(EncodeAsDoubleTag, ExecState*, double d) + { + u.asDouble = d; + } + inline JSValue::JSValue(ExecState* exec, double d) { const int32_t asInt32 = static_cast<int32_t>(d); @@ -773,11 +807,17 @@ namespace JSC { inline JSValue::JSValue(JSCell* ptr) : m_ptr(ptr) { +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie()); +#endif } inline JSValue::JSValue(const JSCell* ptr) : m_ptr(const_cast<JSCell*>(ptr)) { +#if ENABLE(JSC_ZOMBIES) + ASSERT(!isZombie()); +#endif } inline JSValue::operator bool() const diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.cpp index ac193ca..7365001 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.cpp @@ -34,33 +34,23 @@ namespace JSC { -bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) +bool JSVariableObject::deleteProperty(ExecState* exec, const Identifier& propertyName) { if (symbolTable().contains(propertyName.ustring().rep())) return false; - return JSObject::deleteProperty(exec, propertyName, checkDontDelete); + return JSObject::deleteProperty(exec, propertyName); } -void JSVariableObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) +void JSVariableObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { SymbolTable::const_iterator end = symbolTable().end(); for (SymbolTable::const_iterator it = symbolTable().begin(); it != end; ++it) { - if (!(it->second.getAttributes() & DontEnum) || includeNonEnumerable) + if (!(it->second.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties)) propertyNames.add(Identifier(exec, it->first.get())); } - JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); -} - -bool JSVariableObject::getPropertyAttributes(ExecState* exec, const Identifier& propertyName, unsigned& attributes) const -{ - SymbolTableEntry entry = symbolTable().get(propertyName.ustring().rep()); - if (!entry.isNull()) { - attributes = entry.getAttributes() | DontDelete; - return true; - } - return JSObject::getPropertyAttributes(exec, propertyName, attributes); + JSObject::getOwnPropertyNames(exec, propertyNames, mode); } bool JSVariableObject::isVariableObject() const diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.h index fe92729..737816d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSVariableObject.h @@ -48,22 +48,21 @@ namespace JSC { virtual void putWithAttributes(ExecState*, const Identifier&, JSValue, unsigned attributes) = 0; - virtual bool deleteProperty(ExecState*, const Identifier&, bool checkDontDelete = true); - virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); + virtual bool deleteProperty(ExecState*, const Identifier&); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual bool isVariableObject() const; virtual bool isDynamicScope() const = 0; - virtual bool getPropertyAttributes(ExecState*, const Identifier& propertyName, unsigned& attributes) const; - Register& registerAt(int index) const { return d->registers[index]; } static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } protected: + static const unsigned StructureFlags = OverridesGetPropertyNames | JSObject::StructureFlags; // Subclasses of JSVariableObject can subclass this struct to add data // without increasing their own size (since there's a hard limit on the // size of a JSCell). @@ -84,7 +83,7 @@ namespace JSC { JSVariableObjectData& operator=(const JSVariableObjectData&); }; - JSVariableObject(PassRefPtr<Structure> structure, JSVariableObjectData* data) + JSVariableObject(NonNullPassRefPtr<Structure> structure, JSVariableObjectData* data) : JSObject(structure) , d(data) // Subclass owns this pointer. { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.h index b56a58d..191ff3b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSWrapperObject.h @@ -30,7 +30,7 @@ namespace JSC { // Number, Boolean and Date which are wrappers for primitive types. class JSWrapperObject : public JSObject { protected: - explicit JSWrapperObject(PassRefPtr<Structure>); + explicit JSWrapperObject(NonNullPassRefPtr<Structure>); public: JSValue internalValue() const { return m_internalValue; } @@ -38,7 +38,7 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultGetPropertyNames | HasDefaultMark)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } private: @@ -47,7 +47,7 @@ namespace JSC { JSValue m_internalValue; }; - inline JSWrapperObject::JSWrapperObject(PassRefPtr<Structure> structure) + inline JSWrapperObject::JSWrapperObject(NonNullPassRefPtr<Structure> structure) : JSObject(structure) { addAnonymousSlots(1); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSZombie.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSZombie.cpp new file mode 100644 index 0000000..072d29b --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSZombie.cpp @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2009 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. + */ + +#include "config.h" +#include "JSZombie.h" +#include "ClassInfo.h" + +#if ENABLE(JSC_ZOMBIES) + +namespace JSC { + +const ClassInfo JSZombie::s_info = { "Zombie", 0, 0, 0 }; + +Structure* JSZombie::leakedZombieStructure() { + static Structure* structure = 0; + if (!structure) { + Structure::startIgnoringLeaks(); + structure = Structure::create(jsNull(), TypeInfo(UnspecifiedType)).releaseRef(); + Structure::stopIgnoringLeaks(); + } + return structure; +} + +} + +#endif // ENABLE(JSC_ZOMBIES) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSZombie.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSZombie.h new file mode 100644 index 0000000..8b33ea6 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/JSZombie.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009 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 JSZombie_h +#define JSZombie_h + +#include "JSCell.h" + +#if ENABLE(JSC_ZOMBIES) +namespace JSC { + +class JSZombie : public JSCell { +public: + JSZombie(const ClassInfo* oldInfo, Structure* structure) + : JSCell(structure) + , m_oldInfo(oldInfo) + { + } + virtual bool isZombie() const { return true; } + virtual const ClassInfo* classInfo() const { return &s_info; } + static Structure* leakedZombieStructure(); + + virtual bool isGetterSetter() const { ASSERT_NOT_REACHED(); return false; } + virtual bool isAPIValueWrapper() const { ASSERT_NOT_REACHED(); return false; } + virtual bool isPropertyNameIterator() const { ASSERT_NOT_REACHED(); return false; } + virtual CallType getCallData(CallData&) { ASSERT_NOT_REACHED(); return CallTypeNone; } + virtual ConstructType getConstructData(ConstructData&) { ASSERT_NOT_REACHED(); return ConstructTypeNone; } + virtual bool getUInt32(uint32_t&) const { ASSERT_NOT_REACHED(); return false; } + virtual JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const { ASSERT_NOT_REACHED(); return jsNull(); } + virtual bool getPrimitiveNumber(ExecState*, double&, JSValue&) { ASSERT_NOT_REACHED(); return false; } + virtual bool toBoolean(ExecState*) const { ASSERT_NOT_REACHED(); return false; } + virtual double toNumber(ExecState*) const { ASSERT_NOT_REACHED(); return 0.0; } + virtual UString toString(ExecState*) const { ASSERT_NOT_REACHED(); return ""; } + virtual JSObject* toObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; } + virtual void markChildren(MarkStack&) { ASSERT_NOT_REACHED(); } + virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&) { ASSERT_NOT_REACHED(); } + virtual void put(ExecState*, unsigned, JSValue) { ASSERT_NOT_REACHED(); } + virtual bool deleteProperty(ExecState*, const Identifier&) { ASSERT_NOT_REACHED(); return false; } + virtual bool deleteProperty(ExecState*, unsigned) { ASSERT_NOT_REACHED(); return false; } + virtual JSObject* toThisObject(ExecState*) const { ASSERT_NOT_REACHED(); return 0; } + virtual UString toThisString(ExecState*) const { ASSERT_NOT_REACHED(); return ""; } + virtual JSString* toThisJSString(ExecState*) { ASSERT_NOT_REACHED(); return 0; } + virtual JSValue getJSNumber() { ASSERT_NOT_REACHED(); return jsNull(); } + virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } + virtual bool getOwnPropertySlot(ExecState*, unsigned, PropertySlot&) { ASSERT_NOT_REACHED(); return false; } + + static const ClassInfo s_info; +private: + const ClassInfo* m_oldInfo; +}; + +} + +#endif // ENABLE(JSC_ZOMBIES) + +#endif // JSZombie_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.cpp index d242282..aa1e5ed 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/LiteralParser.cpp @@ -29,6 +29,7 @@ #include "JSArray.h" #include "JSString.h" #include "Lexer.h" +#include "StringBuilder.h" #include <wtf/ASCIICType.h> #include <wtf/dtoa.h> @@ -134,48 +135,48 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera { ++m_ptr; const UChar* runStart; - token.stringToken = UString(); + StringBuilder builder; do { runStart = m_ptr; while (m_ptr < m_end && isSafeStringCharacter<mode>(*m_ptr)) ++m_ptr; if (runStart < m_ptr) - token.stringToken.append(runStart, m_ptr - runStart); + builder.append(runStart, m_ptr - runStart); if ((mode == StrictJSON) && m_ptr < m_end && *m_ptr == '\\') { ++m_ptr; if (m_ptr >= m_end) return TokError; switch (*m_ptr) { case '"': - token.stringToken.append('"'); + builder.append('"'); m_ptr++; break; case '\\': - token.stringToken.append('\\'); + builder.append('\\'); m_ptr++; break; case '/': - token.stringToken.append('/'); + builder.append('/'); m_ptr++; break; case 'b': - token.stringToken.append('\b'); + builder.append('\b'); m_ptr++; break; case 'f': - token.stringToken.append('\f'); + builder.append('\f'); m_ptr++; break; case 'n': - token.stringToken.append('\n'); + builder.append('\n'); m_ptr++; break; case 'r': - token.stringToken.append('\r'); + builder.append('\r'); m_ptr++; break; case 't': - token.stringToken.append('\t'); + builder.append('\t'); m_ptr++; break; @@ -186,7 +187,7 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera if (!isASCIIHexDigit(m_ptr[i])) return TokError; } - token.stringToken.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4])); + builder.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4])); m_ptr += 5; break; @@ -199,6 +200,7 @@ template <LiteralParser::ParserMode mode> inline LiteralParser::TokenType Litera if (m_ptr >= m_end || *m_ptr != '"') return TokError; + token.stringToken = builder.release(); token.type = TokString; token.end = ++m_ptr; return TokString; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.cpp index 8359ff7..4e9e086 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.cpp @@ -34,7 +34,7 @@ void HashTable::createTable(JSGlobalData* globalData) const entries[i].setKey(0); for (int i = 0; values[i].key; ++i) { UString::Rep* identifier = Identifier::add(globalData, values[i].key).releaseRef(); - int hashIndex = identifier->computedHash() & compactHashSizeMask; + int hashIndex = identifier->existingHash() & compactHashSizeMask; HashEntry* entry = &entries[hashIndex]; if (entry->key()) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.h index 4d70689..e673c09 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Lookup.h @@ -144,7 +144,7 @@ namespace JSC { { ASSERT(table); - const HashEntry* entry = &table[identifier.ustring().rep()->computedHash() & compactHashSizeMask]; + const HashEntry* entry = &table[identifier.ustring().rep()->existingHash() & compactHashSizeMask]; if (!entry->key()) return 0; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStack.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStack.h index 5bc85fa..c551bac 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStack.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStack.h @@ -47,7 +47,7 @@ namespace JSC { } ALWAYS_INLINE void append(JSValue); - ALWAYS_INLINE void append(JSCell*); + void append(JSCell*); ALWAYS_INLINE void appendValues(Register* values, size_t count, MarkSetProperties properties = NoNullValues) { @@ -153,7 +153,7 @@ namespace JSC { ASSERT(0 == (size % MarkStack::pageSize())); if (size == m_allocated) return; -#if PLATFORM(WIN) +#if OS(WINDOWS) || OS(SYMBIAN) || PLATFORM(BREWMP) // We cannot release a part of a region with VirtualFree. To get around this, // we'll release the entire region and reallocate the size that we want. releaseStack(m_data, m_allocated); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackNone.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackNone.cpp new file mode 100644 index 0000000..b1ff48b --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackNone.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 Company 100, 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. + */ + +#include "config.h" + +#include "MarkStack.h" + +#include "FastMalloc.h" + +namespace JSC { + +void MarkStack::initializePagesize() +{ + MarkStack::s_pageSize = 4096; +} + +void* MarkStack::allocateStack(size_t size) +{ + return fastMalloc(size); +} + +void MarkStack::releaseStack(void* addr, size_t) +{ + return fastFree(addr); +} + +} diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackPosix.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackPosix.cpp index aec968e..de5e8ba 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackPosix.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackPosix.cpp @@ -24,49 +24,29 @@ */ #include "config.h" - - #include "MarkStack.h" +#if OS(UNIX) && !OS(SYMBIAN) + #include <unistd.h> -#if defined (__SYMBIAN32__) -#include "wtf/FastMalloc.h" -#include <e32base.h> -#include <e32std.h> -#include <e32hal.h> -#include <hal.h> -#else #include <sys/mman.h> -#endif namespace JSC { void MarkStack::initializePagesize() { -#if defined (__SYMBIAN32__) - TInt page_size; - UserHal::PageSizeInBytes(page_size); - MarkStack::s_pageSize = page_size; -#else MarkStack::s_pageSize = getpagesize(); -#endif } void* MarkStack::allocateStack(size_t size) { -#if defined (__SYMBIAN32__) - return fastMalloc(size); -#else return mmap(0, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); -#endif } void MarkStack::releaseStack(void* addr, size_t size) { -#if defined (__SYMBIAN32__) - fastFree(addr); -#else munmap(reinterpret_cast<char*>(addr), size); -#endif } } + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackSymbian.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackSymbian.cpp new file mode 100644 index 0000000..bda14ac --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackSymbian.cpp @@ -0,0 +1,48 @@ +/* + Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "config.h" +#include "MarkStack.h" + +#if OS(SYMBIAN) + +#include <e32hal.h> + +namespace JSC { + +void MarkStack::initializePagesize() +{ + TInt page_size; + UserHal::PageSizeInBytes(page_size); + MarkStack::s_pageSize = page_size; +} + +void* MarkStack::allocateStack(size_t size) +{ + return fastMalloc(size); +} + +void MarkStack::releaseStack(void* addr, size_t size) +{ + return fastFree(addr); +} + +} + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackWin.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackWin.cpp index 1fdd06a..a171c78 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackWin.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MarkStackWin.cpp @@ -24,10 +24,10 @@ */ #include "config.h" - - #include "MarkStack.h" +#if OS(WINDOWS) + #include "windows.h" namespace JSC { @@ -51,3 +51,5 @@ void MarkStack::releaseStack(void* addr, size_t) } } + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.cpp index 36771ab..98ff3ba 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.cpp @@ -85,7 +85,7 @@ const ClassInfo MathObject::info = { "Math", 0, 0, ExecState::mathTable }; @end */ -MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure) +MathObject::MathObject(ExecState* exec, NonNullPassRefPtr<Structure> structure) : JSObject(structure) { putDirectWithoutTransition(Identifier(exec, "E"), jsNumber(exec, exp(1.0)), DontDelete | DontEnum | ReadOnly); @@ -96,7 +96,6 @@ MathObject::MathObject(ExecState* exec, PassRefPtr<Structure> structure) putDirectWithoutTransition(Identifier(exec, "PI"), jsNumber(exec, piDouble), DontDelete | DontEnum | ReadOnly); putDirectWithoutTransition(Identifier(exec, "SQRT1_2"), jsNumber(exec, sqrt(0.5)), DontDelete | DontEnum | ReadOnly); putDirectWithoutTransition(Identifier(exec, "SQRT2"), jsNumber(exec, sqrt(2.0)), DontDelete | DontEnum | ReadOnly); - WTF::initializeWeakRandomNumberGenerator(); } // ECMA 15.8 @@ -120,22 +119,22 @@ JSValue JSC_HOST_CALL mathProtoFuncAbs(ExecState* exec, JSObject*, JSValue, cons JSValue JSC_HOST_CALL mathProtoFuncACos(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, acos(args.at(0).toNumber(exec))); + return jsDoubleNumber(exec, acos(args.at(0).toNumber(exec))); } JSValue JSC_HOST_CALL mathProtoFuncASin(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, asin(args.at(0).toNumber(exec))); + return jsDoubleNumber(exec, asin(args.at(0).toNumber(exec))); } JSValue JSC_HOST_CALL mathProtoFuncATan(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, atan(args.at(0).toNumber(exec))); + return jsDoubleNumber(exec, atan(args.at(0).toNumber(exec))); } JSValue JSC_HOST_CALL mathProtoFuncATan2(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, atan2(args.at(0).toNumber(exec), args.at(1).toNumber(exec))); + return jsDoubleNumber(exec, atan2(args.at(0).toNumber(exec), args.at(1).toNumber(exec))); } JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, const ArgList& args) @@ -145,12 +144,12 @@ JSValue JSC_HOST_CALL mathProtoFuncCeil(ExecState* exec, JSObject*, JSValue, con JSValue JSC_HOST_CALL mathProtoFuncCos(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, cos(args.at(0).toNumber(exec))); + return jsDoubleNumber(exec, cos(args.at(0).toNumber(exec))); } JSValue JSC_HOST_CALL mathProtoFuncExp(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, exp(args.at(0).toNumber(exec))); + return jsDoubleNumber(exec, exp(args.at(0).toNumber(exec))); } JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, const ArgList& args) @@ -160,7 +159,7 @@ JSValue JSC_HOST_CALL mathProtoFuncFloor(ExecState* exec, JSObject*, JSValue, co JSValue JSC_HOST_CALL mathProtoFuncLog(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, log(args.at(0).toNumber(exec))); + return jsDoubleNumber(exec, log(args.at(0).toNumber(exec))); } JSValue JSC_HOST_CALL mathProtoFuncMax(ExecState* exec, JSObject*, JSValue, const ArgList& args) @@ -211,7 +210,7 @@ JSValue JSC_HOST_CALL mathProtoFuncPow(ExecState* exec, JSObject*, JSValue, cons JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue, const ArgList&) { - return jsNumber(exec, WTF::weakRandomNumber()); + return jsDoubleNumber(exec, exec->globalData().weakRandom.get()); } JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, const ArgList& args) @@ -224,17 +223,17 @@ JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, co JSValue JSC_HOST_CALL mathProtoFuncSin(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, sin(args.at(0).toNumber(exec))); + return jsDoubleNumber(exec, sin(args.at(0).toNumber(exec))); } JSValue JSC_HOST_CALL mathProtoFuncSqrt(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, sqrt(args.at(0).toNumber(exec))); + return jsDoubleNumber(exec, sqrt(args.at(0).toNumber(exec))); } JSValue JSC_HOST_CALL mathProtoFuncTan(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - return jsNumber(exec, tan(args.at(0).toNumber(exec))); + return jsDoubleNumber(exec, tan(args.at(0).toNumber(exec))); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.h index a2e065f..7f474b8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/MathObject.h @@ -27,7 +27,7 @@ namespace JSC { class MathObject : public JSObject { public: - MathObject(ExecState*, PassRefPtr<Structure>); + MathObject(ExecState*, NonNullPassRefPtr<Structure>); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); @@ -37,8 +37,11 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } + + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags; }; } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorConstructor.cpp index 0205fc5..403fc7e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorConstructor.cpp @@ -32,8 +32,8 @@ ASSERT_CLASS_FITS_IN_CELL(NativeErrorConstructor); const ClassInfo NativeErrorConstructor::info = { "Function", &InternalFunction::info, 0, 0 }; -NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, PassRefPtr<Structure> structure, NativeErrorPrototype* nativeErrorPrototype) - : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name).getString())) +NativeErrorConstructor::NativeErrorConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, NativeErrorPrototype* nativeErrorPrototype) + : InternalFunction(&exec->globalData(), structure, Identifier(exec, nativeErrorPrototype->getDirect(exec->propertyNames().name).getString(exec))) , m_errorStructure(ErrorInstance::createStructure(nativeErrorPrototype)) { putDirect(exec->propertyNames().length, jsNumber(exec, 1), DontDelete | ReadOnly | DontEnum); // ECMA 15.11.7.5 diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorConstructor.h index 118d1f4..152dbac 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorConstructor.h @@ -31,7 +31,7 @@ namespace JSC { class NativeErrorConstructor : public InternalFunction { public: - NativeErrorConstructor(ExecState*, PassRefPtr<Structure>, NativeErrorPrototype*); + NativeErrorConstructor(ExecState*, NonNullPassRefPtr<Structure>, NativeErrorPrototype*); static const ClassInfo info; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorPrototype.cpp index 650a0fd..ca12798 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorPrototype.cpp @@ -29,7 +29,7 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(NativeErrorPrototype); -NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, PassRefPtr<Structure> structure, const UString& name, const UString& message) +NativeErrorPrototype::NativeErrorPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& name, const UString& message) #ifdef QT_BUILD_SCRIPT_LIB : ErrorInstance(structure) #else diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorPrototype.h index 48a9d7e..39a02c8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NativeErrorPrototype.h @@ -36,7 +36,7 @@ namespace JSC { #endif { public: - NativeErrorPrototype(ExecState*, PassRefPtr<Structure>, const UString& name, const UString& message); + NativeErrorPrototype(ExecState*, NonNullPassRefPtr<Structure>, const UString& name, const UString& message); }; } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.cpp index a95106d..cc6c51d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.cpp @@ -53,7 +53,7 @@ const ClassInfo NumberConstructor::info = { "Function", &InternalFunction::info, @end */ -NumberConstructor::NumberConstructor(ExecState* exec, PassRefPtr<Structure> structure, NumberPrototype* numberPrototype) +NumberConstructor::NumberConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, NumberPrototype* numberPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, numberPrototype->info.className)) { // Number.Prototype diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.h index 710ac86..cf19b6f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class NumberConstructor : public InternalFunction { public: - NumberConstructor(ExecState*, PassRefPtr<Structure>, NumberPrototype*); + NumberConstructor(ExecState*, NonNullPassRefPtr<Structure>, NumberPrototype*); virtual bool getOwnPropertySlot(ExecState*, const Identifier&, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); @@ -39,11 +39,14 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark | HasDefaultGetPropertyNames)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); } enum { NaNValue, NegInfinity, PosInfinity, MaxValue, MinValue }; + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags; + private: virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.cpp index 0e8df17..1a7e44c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.cpp @@ -31,7 +31,7 @@ ASSERT_CLASS_FITS_IN_CELL(NumberObject); const ClassInfo NumberObject::info = { "Number", 0, 0, 0 }; -NumberObject::NumberObject(PassRefPtr<Structure> structure) +NumberObject::NumberObject(NonNullPassRefPtr<Structure> structure) : JSWrapperObject(structure) { } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.h index f502bee..8223a90 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberObject.h @@ -27,20 +27,22 @@ namespace JSC { class NumberObject : public JSWrapperObject { public: - explicit NumberObject(PassRefPtr<Structure>); + explicit NumberObject(NonNullPassRefPtr<Structure>); static const ClassInfo info; -#if USE(JSVALUE32) + static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultGetPropertyNames)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } + + protected: +#if USE(JSVALUE32) + static const unsigned StructureFlags = OverridesMarkChildren | JSWrapperObject::StructureFlags; #else - static PassRefPtr<Structure> createStructure(JSValue prototype) - { - return Structure::create(prototype, TypeInfo(ObjectType, HasStandardGetOwnPropertySlot | HasDefaultMark | HasDefaultGetPropertyNames)); - } + static const unsigned StructureFlags = JSWrapperObject::StructureFlags; #endif + private: virtual const ClassInfo* classInfo() const { return &info; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberPrototype.cpp index 947324c..67210fa 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberPrototype.cpp @@ -25,9 +25,10 @@ #include "Error.h" #include "JSFunction.h" #include "JSString.h" +#include "Operations.h" #include "PrototypeFunction.h" +#include "StringBuilder.h" #include "dtoa.h" -#include "Operations.h" #include <wtf/Assertions.h> #include <wtf/MathExtras.h> #include <wtf/Vector.h> @@ -45,7 +46,7 @@ static JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState*, JSObject*, J // ECMA 15.7.4 -NumberPrototype::NumberPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) +NumberPrototype::NumberPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) : NumberObject(structure) { setInternalValue(jsNumber(exec, 0)); @@ -73,11 +74,12 @@ static UString integerPartNoExp(double d) bool resultIsInfOrNan = (decimalPoint == 9999); size_t length = strlen(result); - UString str = sign ? "-" : ""; + StringBuilder builder; + builder.append(sign ? "-" : ""); if (resultIsInfOrNan) - str += result; + builder.append((const char*)result); else if (decimalPoint <= 0) - str += "0"; + builder.append("0"); else { Vector<char, 1024> buf(decimalPoint + 1); @@ -89,10 +91,10 @@ static UString integerPartNoExp(double d) strncpy(buf.data(), result, decimalPoint); buf[decimalPoint] = '\0'; - str.append(buf.data()); + builder.append((const char*)(buf.data())); } - return str; + return builder.release(); } static UString charSequence(char c, int count) @@ -236,13 +238,16 @@ JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue UString s; if (x < 0) { - s.append('-'); + s = "-"; x = -x; - } else if (x == -0.0) - x = 0; + } else { + s = ""; + if (x == -0.0) + x = 0; + } if (x >= pow(10.0, 21.0)) - return jsString(exec, s + UString::from(x)); + return jsString(exec, makeString(s, UString::from(x))); const double tenToTheF = pow(10.0, f); double n = floor(x * tenToTheF); @@ -253,17 +258,19 @@ JSValue JSC_HOST_CALL numberProtoFuncToFixed(ExecState* exec, JSObject*, JSValue int k = m.size(); if (k <= f) { - UString z; + StringBuilder z; for (int i = 0; i < f + 1 - k; i++) z.append('0'); - m = z + m; + z.append(m); + m = z.release(); k = f + 1; ASSERT(k == m.size()); } int kMinusf = k - f; + if (kMinusf < m.size()) - return jsString(exec, s + m.substr(0, kMinusf) + "." + m.substr(kMinusf)); - return jsString(exec, s + m.substr(0, kMinusf)); + return jsString(exec, makeString(s, m.substr(0, kMinusf), ".", m.substr(kMinusf))); + return jsString(exec, makeString(s, m.substr(0, kMinusf))); } static void fractionalPartToString(char* buf, int& i, const char* result, int resultLength, int fractionalDigits) @@ -391,7 +398,8 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV if (x < 0) { s = "-"; x = -x; - } + } else + s = ""; if (!(doublePrecision >= 1 && doublePrecision <= 21)) // true for NaN return throwError(exec, RangeError, "toPrecision() argument must be between 1 and 21"); @@ -422,10 +430,10 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV m = integerPartNoExp(n); if (e < -6 || e >= precision) { if (m.size() > 1) - m = m.substr(0, 1) + "." + m.substr(1); + m = makeString(m.substr(0, 1), ".", m.substr(1)); if (e >= 0) - return jsNontrivialString(exec, s + m + "e+" + UString::from(e)); - return jsNontrivialString(exec, s + m + "e-" + UString::from(-e)); + return jsNontrivialString(exec, makeString(s, m, "e+", UString::from(e))); + return jsNontrivialString(exec, makeString(s, m, "e-", UString::from(-e))); } } else { m = charSequence('0', precision); @@ -433,13 +441,13 @@ JSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec, JSObject*, JSV } if (e == precision - 1) - return jsString(exec, s + m); + return jsString(exec, makeString(s, m)); if (e >= 0) { if (e + 1 < m.size()) - return jsString(exec, s + m.substr(0, e + 1) + "." + m.substr(e + 1)); - return jsString(exec, s + m); + return jsString(exec, makeString(s, m.substr(0, e + 1), ".", m.substr(e + 1))); + return jsString(exec, makeString(s, m)); } - return jsNontrivialString(exec, s + "0." + charSequence('0', -(e + 1)) + m); + return jsNontrivialString(exec, makeString(s, "0.", charSequence('0', -(e + 1)), m)); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberPrototype.h index 0a3a544..1fb2077 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/NumberPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class NumberPrototype : public NumberObject { public: - NumberPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); + NumberPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure); }; } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.cpp index 2992f1b..0838eb4 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.cpp @@ -36,12 +36,13 @@ ASSERT_CLASS_FITS_IN_CELL(ObjectConstructor); static JSValue JSC_HOST_CALL objectConstructorGetPrototypeOf(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL objectConstructorKeys(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL objectConstructorDefineProperty(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL objectConstructorDefineProperties(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL objectConstructorCreate(ExecState*, JSObject*, JSValue, const ArgList&); -ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure) +ObjectConstructor::ObjectConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, ObjectPrototype* objectPrototype, Structure* prototypeFunctionStructure) : InternalFunction(&exec->globalData(), structure, Identifier(exec, "Object")) { // ECMA 15.2.3.1 @@ -52,6 +53,7 @@ ObjectConstructor::ObjectConstructor(ExecState* exec, PassRefPtr<Structure> stru putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getPrototypeOf, objectConstructorGetPrototypeOf), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().getOwnPropertyDescriptor, objectConstructorGetOwnPropertyDescriptor), DontEnum); + putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().getOwnPropertyNames, objectConstructorGetOwnPropertyNames), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 1, exec->propertyNames().keys, objectConstructorKeys), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 3, exec->propertyNames().defineProperty, objectConstructorDefineProperty), DontEnum); putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 2, exec->propertyNames().defineProperties, objectConstructorDefineProperties), DontEnum); @@ -125,6 +127,21 @@ JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyDescriptor(ExecState* exec, return description; } +// FIXME: Use the enumeration cache. +JSValue JSC_HOST_CALL objectConstructorGetOwnPropertyNames(ExecState* exec, JSObject*, JSValue, const ArgList& args) +{ + if (!args.at(0).isObject()) + return throwError(exec, TypeError, "Requested property names of a value that is not an object."); + PropertyNameArray properties(exec); + asObject(args.at(0))->getOwnPropertyNames(exec, properties, IncludeDontEnumProperties); + JSArray* names = constructEmptyArray(exec); + size_t numProperties = properties.size(); + for (size_t i = 0; i < numProperties; i++) + names->push(exec, jsOwnedString(exec, properties[i].ustring())); + return names; +} + +// FIXME: Use the enumeration cache. JSValue JSC_HOST_CALL objectConstructorKeys(ExecState* exec, JSObject*, JSValue, const ArgList& args) { if (!args.at(0).isObject()) @@ -147,14 +164,14 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor } JSObject* description = asObject(in); - PropertySlot enumerableSlot; + PropertySlot enumerableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().enumerable, enumerableSlot)) { desc.setEnumerable(enumerableSlot.getValue(exec, exec->propertyNames().enumerable).toBoolean(exec)); if (exec->hadException()) return false; } - PropertySlot configurableSlot; + PropertySlot configurableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().configurable, configurableSlot)) { desc.setConfigurable(configurableSlot.getValue(exec, exec->propertyNames().configurable).toBoolean(exec)); if (exec->hadException()) @@ -162,21 +179,21 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor } JSValue value; - PropertySlot valueSlot; + PropertySlot valueSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().value, valueSlot)) { desc.setValue(valueSlot.getValue(exec, exec->propertyNames().value)); if (exec->hadException()) return false; } - PropertySlot writableSlot; + PropertySlot writableSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().writable, writableSlot)) { desc.setWritable(writableSlot.getValue(exec, exec->propertyNames().writable).toBoolean(exec)); if (exec->hadException()) return false; } - PropertySlot getSlot; + PropertySlot getSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().get, getSlot)) { JSValue get = getSlot.getValue(exec, exec->propertyNames().get); if (exec->hadException()) @@ -192,7 +209,7 @@ static bool toPropertyDescriptor(ExecState* exec, JSValue in, PropertyDescriptor desc.setGetter(get); } - PropertySlot setSlot; + PropertySlot setSlot(description); if (description->getPropertySlot(exec, exec->propertyNames().set, setSlot)) { JSValue set = setSlot.getValue(exec, exec->propertyNames().set); if (exec->hadException()) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.h index 9373781..1d2cdde 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class ObjectConstructor : public InternalFunction { public: - ObjectConstructor(ExecState*, PassRefPtr<Structure>, ObjectPrototype*, Structure* prototypeFunctionStructure); + ObjectConstructor(ExecState*, NonNullPassRefPtr<Structure>, ObjectPrototype*, Structure* prototypeFunctionStructure); private: virtual ConstructType getConstructData(ConstructData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.cpp index fccc44a..3065c6d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -40,7 +40,7 @@ static JSValue JSC_HOST_CALL objectProtoFuncLookupSetter(ExecState*, JSObject*, static JSValue JSC_HOST_CALL objectProtoFuncPropertyIsEnumerable(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState*, JSObject*, JSValue, const ArgList&); -ObjectPrototype::ObjectPrototype(ExecState* exec, PassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure) +ObjectPrototype::ObjectPrototype(ExecState* exec, NonNullPassRefPtr<Structure> stucture, Structure* prototypeFunctionStructure) : JSObject(stucture) , m_hasNoPropertiesWithUInt32Names(true) { @@ -148,7 +148,7 @@ JSValue JSC_HOST_CALL objectProtoFuncToLocaleString(ExecState* exec, JSObject*, JSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { - return jsNontrivialString(exec, "[object " + thisValue.toThisObject(exec)->className() + "]"); + return jsNontrivialString(exec, makeString("[object ", thisValue.toThisObject(exec)->className(), "]")); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.h index 6dd3c28..489d962 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ObjectPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class ObjectPrototype : public JSObject { public: - ObjectPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); + ObjectPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure); private: virtual void put(ExecState*, const Identifier&, JSValue, PutPropertySlot&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.cpp index 093bbec..0e1887c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.cpp @@ -29,10 +29,6 @@ #include <stdio.h> #include <wtf/MathExtras.h> -#if HAVE(FLOAT_H) -#include <float.h> -#endif - namespace JSC { bool JSValue::equalSlowCase(ExecState* exec, JSValue v1, JSValue v2) @@ -40,9 +36,9 @@ bool JSValue::equalSlowCase(ExecState* exec, JSValue v1, JSValue v2) return equalSlowCaseInline(exec, v1, v2); } -bool JSValue::strictEqualSlowCase(JSValue v1, JSValue v2) +bool JSValue::strictEqualSlowCase(ExecState* exec, JSValue v1, JSValue v2) { - return strictEqualSlowCaseInline(v1, v2); + return strictEqualSlowCaseInline(exec, v1, v2); } NEVER_INLINE JSValue throwOutOfMemoryError(ExecState* exec) @@ -58,12 +54,13 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2) JSValue p1 = v1.toPrimitive(callFrame); JSValue p2 = v2.toPrimitive(callFrame); - if (p1.isString() || p2.isString()) { - RefPtr<UString::Rep> value = concatenate(p1.toString(callFrame).rep(), p2.toString(callFrame).rep()); - if (!value) - return throwOutOfMemoryError(callFrame); - return jsString(callFrame, value.release()); + if (p1.isString()) { + return p2.isString() + ? jsString(callFrame, asString(p1), asString(p2)) + : jsString(callFrame, asString(p1), p2.toString(callFrame)); } + if (p2.isString()) + return jsString(callFrame, p1.toString(callFrame), asString(p2)); return jsNumber(callFrame, p1.toNumber(callFrame) + p2.toNumber(callFrame)); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h index 21120f5..d1d6eaa 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Operations.h @@ -35,6 +35,136 @@ namespace JSC { bool jsIsObjectType(JSValue); bool jsIsFunctionType(JSValue); + ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, JSString* s2) + { + if (!s1->length()) + return s2; + if (!s2->length()) + return s1; + + unsigned ropeLength = s1->ropeLength() + s2->ropeLength(); + JSGlobalData* globalData = &exec->globalData(); + + if (ropeLength <= JSString::s_maxInternalRopeLength) + return new (globalData) JSString(globalData, ropeLength, s1, s2); + + unsigned index = 0; + RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength); + if (UNLIKELY(!rope)) + return throwOutOfMemoryError(exec); + rope->append(index, s1); + rope->append(index, s2); + ASSERT(index == ropeLength); + return new (globalData) JSString(globalData, rope.release()); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, JSString* s2) + { + unsigned ropeLength = 1 + s2->ropeLength(); + JSGlobalData* globalData = &exec->globalData(); + + if (ropeLength <= JSString::s_maxInternalRopeLength) + return new (globalData) JSString(globalData, ropeLength, u1, s2); + + unsigned index = 0; + RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength); + if (UNLIKELY(!rope)) + return throwOutOfMemoryError(exec); + rope->append(index, u1); + rope->append(index, s2); + ASSERT(index == ropeLength); + return new (globalData) JSString(globalData, rope.release()); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, JSString* s1, const UString& u2) + { + unsigned ropeLength = s1->ropeLength() + 1; + JSGlobalData* globalData = &exec->globalData(); + + if (ropeLength <= JSString::s_maxInternalRopeLength) + return new (globalData) JSString(globalData, ropeLength, s1, u2); + + unsigned index = 0; + RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength); + if (UNLIKELY(!rope)) + return throwOutOfMemoryError(exec); + rope->append(index, s1); + rope->append(index, u2); + ASSERT(index == ropeLength); + return new (globalData) JSString(globalData, rope.release()); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count) + { + ASSERT(count >= 3); + + unsigned ropeLength = 0; + for (unsigned i = 0; i < count; ++i) { + JSValue v = strings[i].jsValue(); + if (LIKELY(v.isString())) + ropeLength += asString(v)->ropeLength(); + else + ++ropeLength; + } + + JSGlobalData* globalData = &exec->globalData(); + if (ropeLength == 3) + return new (globalData) JSString(exec, strings[0].jsValue(), strings[1].jsValue(), strings[2].jsValue()); + + RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength); + if (UNLIKELY(!rope)) + return throwOutOfMemoryError(exec); + + unsigned index = 0; + for (unsigned i = 0; i < count; ++i) { + JSValue v = strings[i].jsValue(); + if (LIKELY(v.isString())) + rope->append(index, asString(v)); + else + rope->append(index, v.toString(exec)); + } + + ASSERT(index == ropeLength); + return new (globalData) JSString(globalData, rope.release()); + } + + ALWAYS_INLINE JSValue jsString(ExecState* exec, JSValue thisValue, const ArgList& args) + { + unsigned ropeLength = 0; + if (LIKELY(thisValue.isString())) + ropeLength += asString(thisValue)->ropeLength(); + else + ++ropeLength; + for (unsigned i = 0; i < args.size(); ++i) { + JSValue v = args.at(i); + if (LIKELY(v.isString())) + ropeLength += asString(v)->ropeLength(); + else + ++ropeLength; + } + + RefPtr<JSString::Rope> rope = JSString::Rope::createOrNull(ropeLength); + if (UNLIKELY(!rope)) + return throwOutOfMemoryError(exec); + + unsigned index = 0; + if (LIKELY(thisValue.isString())) + rope->append(index, asString(thisValue)); + else + rope->append(index, thisValue.toString(exec)); + for (unsigned i = 0; i < args.size(); ++i) { + JSValue v = args.at(i); + if (LIKELY(v.isString())) + rope->append(index, asString(v)); + else + rope->append(index, v.toString(exec)); + } + ASSERT(index == ropeLength); + + JSGlobalData* globalData = &exec->globalData(); + return new (globalData) JSString(globalData, rope.release()); + } + // ECMA 11.9.3 inline bool JSValue::equal(ExecState* exec, JSValue v1, JSValue v2) { @@ -53,7 +183,7 @@ namespace JSC { bool s1 = v1.isString(); bool s2 = v2.isString(); if (s1 && s2) - return asString(v1)->value() == asString(v2)->value(); + return asString(v1)->value(exec) == asString(v2)->value(exec); if (v1.isUndefinedOrNull()) { if (v2.isUndefinedOrNull()) @@ -70,13 +200,12 @@ namespace JSC { } if (v1.isObject()) { - if (v2.isObject()) { + if (v2.isObject()) return v1 == v2 #ifdef QT_BUILD_SCRIPT_LIB || asObject(v1)->compareToObject(exec, asObject(v2)) #endif ; - } JSValue p1 = v1.toPrimitive(exec); if (exec->hadException()) return false; @@ -115,17 +244,17 @@ namespace JSC { } // ECMA 11.9.3 - ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(JSValue v1, JSValue v2) + ALWAYS_INLINE bool JSValue::strictEqualSlowCaseInline(ExecState* exec, JSValue v1, JSValue v2) { ASSERT(v1.isCell() && v2.isCell()); if (v1.asCell()->isString() && v2.asCell()->isString()) - return asString(v1)->value() == asString(v2)->value(); + return asString(v1)->value(exec) == asString(v2)->value(exec); return v1 == v2; } - inline bool JSValue::strictEqual(JSValue v1, JSValue v2) + inline bool JSValue::strictEqual(ExecState* exec, JSValue v1, JSValue v2) { if (v1.isInt32() && v2.isInt32()) return v1 == v2; @@ -136,10 +265,10 @@ namespace JSC { if (!v1.isCell() || !v2.isCell()) return v1 == v2; - return strictEqualSlowCaseInline(v1, v2); + return strictEqualSlowCaseInline(exec, v1, v2); } - inline bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2) + ALWAYS_INLINE bool jsLess(CallFrame* callFrame, JSValue v1, JSValue v2) { if (v1.isInt32() && v2.isInt32()) return v1.asInt32() < v2.asInt32(); @@ -151,7 +280,7 @@ namespace JSC { JSGlobalData* globalData = &callFrame->globalData(); if (isJSString(globalData, v1) && isJSString(globalData, v2)) - return asString(v1)->value() < asString(v2)->value(); + return asString(v1)->value(callFrame) < asString(v2)->value(callFrame); JSValue p1; JSValue p2; @@ -161,7 +290,7 @@ namespace JSC { if (wasNotString1 | wasNotString2) return n1 < n2; - return asString(p1)->value() < asString(p2)->value(); + return asString(p1)->value(callFrame) < asString(p2)->value(callFrame); } inline bool jsLessEq(CallFrame* callFrame, JSValue v1, JSValue v2) @@ -176,7 +305,7 @@ namespace JSC { JSGlobalData* globalData = &callFrame->globalData(); if (isJSString(globalData, v1) && isJSString(globalData, v2)) - return !(asString(v2)->value() < asString(v1)->value()); + return !(asString(v2)->value(callFrame) < asString(v1)->value(callFrame)); JSValue p1; JSValue p2; @@ -186,7 +315,7 @@ namespace JSC { if (wasNotString1 | wasNotString2) return n1 <= n2; - return !(asString(p2)->value() < asString(p1)->value()); + return !(asString(p2)->value(callFrame) < asString(p1)->value(callFrame)); } // Fast-path choices here are based on frequency data from SunSpider: @@ -200,44 +329,29 @@ namespace JSC { ALWAYS_INLINE JSValue jsAdd(CallFrame* callFrame, JSValue v1, JSValue v2) { - double left; - double right = 0.0; - - bool rightIsNumber = v2.getNumber(right); - if (rightIsNumber && v1.getNumber(left)) + double left = 0.0, right; + if (v1.getNumber(left) && v2.getNumber(right)) return jsNumber(callFrame, left + right); - bool leftIsString = v1.isString(); - if (leftIsString && v2.isString()) { - RefPtr<UString::Rep> value = concatenate(asString(v1)->value().rep(), asString(v2)->value().rep()); - if (!value) - return throwOutOfMemoryError(callFrame); - return jsString(callFrame, value.release()); - } - - if (rightIsNumber & leftIsString) { - RefPtr<UString::Rep> value = v2.isInt32() ? - concatenate(asString(v1)->value().rep(), v2.asInt32()) : - concatenate(asString(v1)->value().rep(), right); - - if (!value) - return throwOutOfMemoryError(callFrame); - return jsString(callFrame, value.release()); + if (v1.isString()) { + return v2.isString() + ? jsString(callFrame, asString(v1), asString(v2)) + : jsString(callFrame, asString(v1), v2.toPrimitiveString(callFrame)); } // All other cases are pretty uncommon return jsAddSlowCase(callFrame, v1, v2); } - inline size_t countPrototypeChainEntriesAndCheckForProxies(CallFrame* callFrame, JSValue baseValue, const PropertySlot& slot) + inline size_t normalizePrototypeChain(CallFrame* callFrame, JSValue base, JSValue slotBase, const Identifier& propertyName, size_t& slotOffset) { - JSCell* cell = asCell(baseValue); + JSCell* cell = asCell(base); size_t count = 0; - while (slot.slotBase() != cell) { + while (slotBase != cell) { JSValue v = cell->structure()->prototypeForLookup(callFrame); - // If we didn't find slotBase in baseValue's prototype chain, then baseValue + // If we didn't find slotBase in base's prototype chain, then base // must be a proxy for another object. if (v.isNull()) @@ -247,8 +361,11 @@ namespace JSC { // Since we're accessing a prototype in a loop, it's a good bet that it // should not be treated as a dictionary. - if (cell->structure()->isDictionary()) - asObject(cell)->setStructure(Structure::fromDictionaryTransition(cell->structure())); + if (cell->structure()->isDictionary()) { + asObject(cell)->flattenDictionaryObject(); + if (slotBase == cell) + slotOffset = cell->structure()->get(propertyName); + } ++count; } @@ -257,6 +374,25 @@ namespace JSC { return count; } + inline size_t normalizePrototypeChain(CallFrame* callFrame, JSCell* base) + { + size_t count = 0; + while (1) { + JSValue v = base->structure()->prototypeForLookup(callFrame); + if (v.isNull()) + return count; + + base = asCell(v); + + // Since we're accessing a prototype in a loop, it's a good bet that it + // should not be treated as a dictionary. + if (base->structure()->isDictionary()) + asObject(base)->flattenDictionaryObject(); + + ++count; + } + } + ALWAYS_INLINE JSValue resolveBase(CallFrame* callFrame, Identifier& property, ScopeChainNode* scopeChain) { ScopeChainIterator iter = scopeChain->begin(); @@ -279,52 +415,6 @@ namespace JSC { ASSERT_NOT_REACHED(); return JSValue(); } - - ALWAYS_INLINE JSValue concatenateStrings(CallFrame* callFrame, Register* strings, unsigned count) - { - ASSERT(count >= 3); - - // Estimate the amount of space required to hold the entire string. If all - // arguments are strings, we can easily calculate the exact amount of space - // required. For any other arguments, for now let's assume they may require - // 11 UChars of storage. This is enouch to hold any int, and likely is also - // reasonable for the other immediates. We may want to come back and tune - // this value at some point. - unsigned bufferSize = 0; - for (unsigned i = 0; i < count; ++i) { - JSValue v = strings[i].jsValue(); - if (LIKELY(v.isString())) - bufferSize += asString(v)->value().size(); - else - bufferSize += 11; - } - - // Allocate an output string to store the result. - // If the first argument is a String, and if it has the capacity (or can grow - // its capacity) to hold the entire result then use this as a base to concatenate - // onto. Otherwise, allocate a new empty output buffer. - JSValue firstValue = strings[0].jsValue(); - RefPtr<UString::Rep> resultRep; - if (firstValue.isString() && (resultRep = asString(firstValue)->value().rep())->reserveCapacity(bufferSize)) { - // We're going to concatenate onto the first string - remove it from the list of items to be appended. - ++strings; - --count; - } else - resultRep = UString::Rep::createEmptyBuffer(bufferSize); - UString result(resultRep); - - // Loop over the operands, writing them into the output buffer. - for (unsigned i = 0; i < count; ++i) { - JSValue v = strings[i].jsValue(); - if (LIKELY(v.isString())) - result.append(asString(v)->value()); - else - result.append(v.toString(callFrame)); - } - - return jsString(callFrame, result); - } - } // namespace JSC #endif // Operations_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.cpp index 4db814f..558ae28 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.cpp @@ -153,15 +153,15 @@ void PropertyDescriptor::setGetter(JSValue getter) m_attributes &= ~ReadOnly; } -bool PropertyDescriptor::equalTo(const PropertyDescriptor& other) const +bool PropertyDescriptor::equalTo(ExecState* exec, const PropertyDescriptor& other) const { if (!other.m_value == m_value || !other.m_getter == m_getter || !other.m_setter == m_setter) return false; - return (!m_value || JSValue::strictEqual(other.m_value, m_value)) && - (!m_getter || JSValue::strictEqual(other.m_getter, m_getter)) && - (!m_setter || JSValue::strictEqual(other.m_setter, m_setter)) && + return (!m_value || JSValue::strictEqual(exec, other.m_value, m_value)) && + (!m_getter || JSValue::strictEqual(exec, other.m_getter, m_getter)) && + (!m_setter || JSValue::strictEqual(exec, other.m_setter, m_setter)) && attributesEqual(other); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.h index 40bec86..ff9f160 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyDescriptor.h @@ -61,7 +61,7 @@ namespace JSC { bool configurablePresent() const { return m_seenAttributes & ConfigurablePresent; } bool setterPresent() const { return m_setter; } bool getterPresent() const { return m_getter; } - bool equalTo(const PropertyDescriptor& other) const; + bool equalTo(ExecState* exec, const PropertyDescriptor& other) const; bool attributesEqual(const PropertyDescriptor& other) const; unsigned attributesWithOverride(const PropertyDescriptor& other) const; private: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyNameArray.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyNameArray.cpp index 0878e73..5108272 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyNameArray.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyNameArray.cpp @@ -21,13 +21,16 @@ #include "config.h" #include "PropertyNameArray.h" +#include "Structure.h" +#include "StructureChain.h" + namespace JSC { static const size_t setThreshold = 20; void PropertyNameArray::add(UString::Rep* identifier) { - ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->identifierTable()); + ASSERT(identifier == &UString::Rep::null() || identifier == &UString::Rep::empty() || identifier->isIdentifier()); size_t size = m_data->propertyNameVector().size(); if (size < setThreshold) { @@ -44,7 +47,7 @@ void PropertyNameArray::add(UString::Rep* identifier) return; } - m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); + addKnownUnique(identifier); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyNameArray.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyNameArray.h index 67ee9c8..3dbcc9d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyNameArray.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PropertyNameArray.h @@ -23,46 +23,35 @@ #include "CallFrame.h" #include "Identifier.h" -#include "Structure.h" -#include "StructureChain.h" #include <wtf/HashSet.h> +#include <wtf/OwnArrayPtr.h> #include <wtf/Vector.h> namespace JSC { + + class Structure; + class StructureChain; + // FIXME: Rename to PropertyNameArray. class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> { public: typedef Vector<Identifier, 20> PropertyNameVector; - typedef PropertyNameVector::const_iterator const_iterator; static PassRefPtr<PropertyNameArrayData> create() { return adoptRef(new PropertyNameArrayData); } - const_iterator begin() const { return m_propertyNameVector.begin(); } - const_iterator end() const { return m_propertyNameVector.end(); } - PropertyNameVector& propertyNameVector() { return m_propertyNameVector; } - void setCachedStructure(Structure* structure) { m_cachedStructure = structure; } - Structure* cachedStructure() const { return m_cachedStructure; } - - void setCachedPrototypeChain(PassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } - StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); } - private: PropertyNameArrayData() - : m_cachedStructure(0) { } PropertyNameVector m_propertyNameVector; - Structure* m_cachedStructure; - RefPtr<StructureChain> m_cachedPrototypeChain; }; + // FIXME: Rename to PropertyNameArrayBuilder. class PropertyNameArray { public: - typedef PropertyNameArrayData::const_iterator const_iterator; - PropertyNameArray(JSGlobalData* globalData) : m_data(PropertyNameArrayData::create()) , m_globalData(globalData) @@ -83,21 +72,18 @@ namespace JSC { void add(UString::Rep*); void addKnownUnique(UString::Rep* identifier) { m_data->propertyNameVector().append(Identifier(m_globalData, identifier)); } - size_t size() const { return m_data->propertyNameVector().size(); } - Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; } const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; } - const_iterator begin() const { return m_data->begin(); } - const_iterator end() const { return m_data->end(); } - void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; } PropertyNameArrayData* data() { return m_data.get(); } - PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); } - void setShouldCache(bool shouldCache) { m_shouldCache = shouldCache; } - bool shouldCache() const { return m_shouldCache; } + // FIXME: Remove these functions. + typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator; + size_t size() const { return m_data->propertyNameVector().size(); } + const_iterator begin() const { return m_data->propertyNameVector().begin(); } + const_iterator end() const { return m_data->propertyNameVector().end(); } private: typedef HashSet<UString::Rep*, PtrHash<UString::Rep*> > IdentifierSet; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Protect.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Protect.h index 6e7984c..c2d7f0c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Protect.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Protect.h @@ -22,8 +22,8 @@ #ifndef Protect_h #define Protect_h -#include "JSCell.h" #include "Collector.h" +#include "JSValue.h" namespace JSC { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PrototypeFunction.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PrototypeFunction.cpp index 8e3d107..38f8adb 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PrototypeFunction.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PrototypeFunction.cpp @@ -40,7 +40,7 @@ PrototypeFunction::PrototypeFunction(ExecState* exec, int length, const Identifi putDirect(exec->propertyNames().length, jsNumber(exec, length), DontDelete | ReadOnly | DontEnum); } -PrototypeFunction::PrototypeFunction(ExecState* exec, PassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function) +PrototypeFunction::PrototypeFunction(ExecState* exec, NonNullPassRefPtr<Structure> prototypeFunctionStructure, int length, const Identifier& name, NativeFunction function) : InternalFunction(&exec->globalData(), prototypeFunctionStructure, name) , m_function(function) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PrototypeFunction.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PrototypeFunction.h index 99ab327..70ee034 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PrototypeFunction.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/PrototypeFunction.h @@ -32,7 +32,7 @@ namespace JSC { class PrototypeFunction : public InternalFunction { public: PrototypeFunction(ExecState*, int length, const Identifier&, NativeFunction); - PrototypeFunction(ExecState*, PassRefPtr<Structure>, int length, const Identifier&, NativeFunction); + PrototypeFunction(ExecState*, NonNullPassRefPtr<Structure>, int length, const Identifier&, NativeFunction); private: virtual CallType getCallData(CallData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExp.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExp.cpp index b366b58..430a5c0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExp.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExp.cpp @@ -65,7 +65,6 @@ inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern) inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern, const UString& flags) : m_pattern(pattern) - , m_flags(flags) , m_flagBits(0) , m_constructionError(0) , m_numSubpatterns(0) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExp.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExp.h index 24d4199..61ab0bc 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExp.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExp.h @@ -49,7 +49,6 @@ namespace JSC { bool multiline() const { return m_flagBits & Multiline; } const UString& pattern() const { return m_pattern; } - const UString& flags() const { return m_flags; } bool isValid() const { return !m_constructionError; } const char* errorMessage() const { return m_constructionError; } @@ -66,7 +65,6 @@ namespace JSC { enum FlagBits { Global = 1, IgnoreCase = 2, Multiline = 4 }; UString m_pattern; // FIXME: Just decompile m_regExp instead of storing this. - UString m_flags; // FIXME: Just decompile m_regExp instead of storing this. int m_flagBits; const char* m_constructionError; unsigned m_numSubpatterns; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.cpp index 1c95175..6f00142 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -90,29 +90,7 @@ const ClassInfo RegExpConstructor::info = { "Function", &InternalFunction::info, @end */ -struct RegExpConstructorPrivate : FastAllocBase { - // Global search cache / settings - RegExpConstructorPrivate() - : lastNumSubPatterns(0) - , multiline(false) - , lastOvectorIndex(0) - { - } - - const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; } - Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; } - Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; } - void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; } - - UString input; - UString lastInput; - Vector<int, 32> ovector[2]; - unsigned lastNumSubPatterns : 30; - bool multiline : 1; - unsigned lastOvectorIndex : 1; -}; - -RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype) +RegExpConstructor::RegExpConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, RegExpPrototype* regExpPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, "RegExp")) , d(new RegExpConstructorPrivate) { @@ -123,30 +101,6 @@ RegExpConstructor::RegExpConstructor(ExecState* exec, PassRefPtr<Structure> stru putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 2), ReadOnly | DontDelete | DontEnum); } -/* - To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular - expression matching through the performMatch function. We use cached results to calculate, - e.g., RegExp.lastMatch and RegExp.leftParen. -*/ -void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector) -{ - position = r->match(s, startOffset, &d->tempOvector()); - - if (ovector) - *ovector = d->tempOvector().data(); - - if (position != -1) { - ASSERT(!d->tempOvector().isEmpty()); - - length = d->tempOvector()[1] - d->tempOvector()[0]; - - d->input = s; - d->lastInput = s; - d->changeLastOvector(); - d->lastNumSubPatterns = r->numSubpatterns(); - } -} - RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate* data) : JSArray(exec->lexicalGlobalObject()->regExpMatchesArrayStructure(), data->lastNumSubPatterns + 1) { @@ -178,6 +132,8 @@ void RegExpMatchesArray::fillArrayInstance(ExecState* exec) int start = d->lastOvector()[2 * i]; if (start >= 0) JSArray::put(exec, i, jsSubstring(exec, d->lastInput, start, d->lastOvector()[2 * i + 1] - start)); + else + JSArray::put(exec, i, jsUndefined()); } PutPropertySlot slot; @@ -346,7 +302,7 @@ JSObject* constructRegExp(ExecState* exec, const ArgList& args) RefPtr<RegExp> regExp = RegExp::create(&exec->globalData(), pattern, flags); if (!regExp->isValid()) - return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage())); + return throwError(exec, SyntaxError, makeString("Invalid regular expression: ", regExp->errorMessage())); return new (exec) RegExpObject(exec->lexicalGlobalObject()->regExpStructure(), regExp.release()); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.h index 4b06b51..f9ca9cf 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpConstructor.h @@ -22,6 +22,7 @@ #define RegExpConstructor_h #include "InternalFunction.h" +#include "RegExp.h" #include <wtf/OwnPtr.h> namespace JSC { @@ -30,13 +31,35 @@ namespace JSC { class RegExpPrototype; struct RegExpConstructorPrivate; + struct RegExpConstructorPrivate : FastAllocBase { + // Global search cache / settings + RegExpConstructorPrivate() + : lastNumSubPatterns(0) + , multiline(false) + , lastOvectorIndex(0) + { + } + + const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; } + Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; } + Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; } + void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; } + + UString input; + UString lastInput; + Vector<int, 32> ovector[2]; + unsigned lastNumSubPatterns : 30; + bool multiline : 1; + unsigned lastOvectorIndex : 1; + }; + class RegExpConstructor : public InternalFunction { public: - RegExpConstructor(ExecState*, PassRefPtr<Structure>, RegExpPrototype*); + RegExpConstructor(ExecState*, NonNullPassRefPtr<Structure>, RegExpPrototype*); static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, ImplementsHasInstance | HasDefaultMark | HasDefaultGetPropertyNames)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } virtual void put(ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&); @@ -59,6 +82,9 @@ namespace JSC { JSValue getLeftContext(ExecState*) const; JSValue getRightContext(ExecState*) const; + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags; + private: virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); @@ -78,6 +104,30 @@ namespace JSC { return static_cast<RegExpConstructor*>(asObject(value)); } + /* + To facilitate result caching, exec(), test(), match(), search(), and replace() dipatch regular + expression matching through the performMatch function. We use cached results to calculate, + e.g., RegExp.lastMatch and RegExp.leftParen. + */ + inline void RegExpConstructor::performMatch(RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector) + { + position = r->match(s, startOffset, &d->tempOvector()); + + if (ovector) + *ovector = d->tempOvector().data(); + + if (position != -1) { + ASSERT(!d->tempOvector().isEmpty()); + + length = d->tempOvector()[1] - d->tempOvector()[0]; + + d->input = s; + d->lastInput = s; + d->changeLastOvector(); + d->lastNumSubPatterns = r->numSubpatterns(); + } + } + } // namespace JSC #endif // RegExpConstructor_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpMatchesArray.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpMatchesArray.h index c1a5a25..38d3cb4 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -65,25 +65,25 @@ namespace JSC { JSArray::put(exec, propertyName, v); } - virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete = true) + virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName) { if (lazyCreationData()) fillArrayInstance(exec); - return JSArray::deleteProperty(exec, propertyName, checkDontDelete); + return JSArray::deleteProperty(exec, propertyName); } - virtual bool deleteProperty(ExecState* exec, unsigned propertyName, bool checkDontDelete = true) + virtual bool deleteProperty(ExecState* exec, unsigned propertyName) { if (lazyCreationData()) fillArrayInstance(exec); - return JSArray::deleteProperty(exec, propertyName, checkDontDelete); + return JSArray::deleteProperty(exec, propertyName); } - virtual void getOwnPropertyNames(ExecState* exec, PropertyNameArray& arr, bool includeNonEnumerable = false) + virtual void getOwnPropertyNames(ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties) { if (lazyCreationData()) fillArrayInstance(exec); - JSArray::getOwnPropertyNames(exec, arr, includeNonEnumerable); + JSArray::getOwnPropertyNames(exec, arr, mode); } void fillArrayInstance(ExecState*); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.cpp index 9d9dd7d..42bfcef 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.cpp @@ -57,7 +57,7 @@ const ClassInfo RegExpObject::info = { "RegExp", 0, 0, ExecState::regExpTable }; @end */ -RegExpObject::RegExpObject(PassRefPtr<Structure> structure, PassRefPtr<RegExp> regExp) +RegExpObject::RegExpObject(NonNullPassRefPtr<Structure> structure, NonNullPassRefPtr<RegExp> regExp) : JSObject(structure) , d(new RegExpObjectData(regExp, 0)) { @@ -142,7 +142,7 @@ bool RegExpObject::match(ExecState* exec, const ArgList& args) UString input = args.isEmpty() ? regExpConstructor->input() : args.at(0).toString(exec); if (input.isNull()) { - throwError(exec, GeneralError, "No input to " + toString(exec) + "."); + throwError(exec, GeneralError, makeString("No input to ", toString(exec), ".")); return false; } @@ -159,7 +159,7 @@ bool RegExpObject::match(ExecState* exec, const ArgList& args) } int position; - int length; + int length = 0; regExpConstructor->performMatch(d->regExp.get(), input, static_cast<int>(d->lastIndex), position, length); if (position < 0) { d->lastIndex = 0; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.h index 67113b6..3117c86 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpObject.h @@ -28,7 +28,7 @@ namespace JSC { class RegExpObject : public JSObject { public: - RegExpObject(PassRefPtr<Structure>, PassRefPtr<RegExp>); + RegExpObject(NonNullPassRefPtr<Structure>, NonNullPassRefPtr<RegExp>); virtual ~RegExpObject(); void setRegExp(PassRefPtr<RegExp> r) { d->regExp = r; } @@ -49,16 +49,19 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType, HasDefaultMark | HasDefaultGetPropertyNames)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } + protected: + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags; + private: bool match(ExecState*, const ArgList&); virtual CallType getCallData(CallData&); struct RegExpObjectData : FastAllocBase { - RegExpObjectData(PassRefPtr<RegExp> regExp, double lastIndex) + RegExpObjectData(NonNullPassRefPtr<RegExp> regExp, double lastIndex) : regExp(regExp) , lastIndex(lastIndex) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.cpp index 4714171..5f9d357 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -46,7 +46,7 @@ static JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState*, JSObject*, JSVa const ClassInfo RegExpPrototype::info = { "RegExpPrototype", 0, 0, 0 }; -RegExpPrototype::RegExpPrototype(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) +RegExpPrototype::RegExpPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure) : JSObject(structure) { putDirectFunctionWithoutTransition(exec, new (exec) NativeFunctionWrapper(exec, prototypeFunctionStructure, 0, exec->propertyNames().compile, regExpProtoFuncCompile), DontEnum); @@ -91,7 +91,7 @@ JSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec, JSObject*, JSValue } if (!regExp->isValid()) - return throwError(exec, SyntaxError, UString("Invalid regular expression: ").append(regExp->errorMessage())); + return throwError(exec, SyntaxError, makeString("Invalid regular expression: ", regExp->errorMessage())); asRegExpObject(thisValue)->setRegExp(regExp.release()); asRegExpObject(thisValue)->setLastIndex(0); @@ -106,19 +106,17 @@ JSValue JSC_HOST_CALL regExpProtoFuncToString(ExecState* exec, JSObject*, JSValu return throwError(exec, TypeError); } - UString result = "/" + asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec); -#ifdef QT_BUILD_SCRIPT_LIB - if (result.size() == 1) - result.append("(?:)"); -#endif - result.append('/'); + char postfix[5] = { '/', 0, 0, 0, 0 }; + int index = 1; if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().global).toBoolean(exec)) - result.append('g'); + postfix[index++] = 'g'; if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().ignoreCase).toBoolean(exec)) - result.append('i'); + postfix[index++] = 'i'; if (asRegExpObject(thisValue)->get(exec, exec->propertyNames().multiline).toBoolean(exec)) - result.append('m'); - return jsNontrivialString(exec, result); + postfix[index] = 'm'; + UString source = asRegExpObject(thisValue)->get(exec, exec->propertyNames().source).toString(exec); + // If source is empty, use "/(?:)/" to avoid colliding with comment syntax + return jsNontrivialString(exec, makeString("/", source.size() ? source : UString("(?:)"), postfix)); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.h index f5db720..d3979bd 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/RegExpPrototype.h @@ -27,7 +27,7 @@ namespace JSC { class RegExpPrototype : public JSObject { public: - RegExpPrototype(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure); + RegExpPrototype(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure); virtual const ClassInfo* classInfo() const { return &info; } static const ClassInfo info; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.cpp index 960c525..981794b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.cpp @@ -36,8 +36,8 @@ void ScopeChainNode::print() const ScopeChainIterator scopeEnd = end(); for (ScopeChainIterator scopeIter = begin(); scopeIter != scopeEnd; ++scopeIter) { JSObject* o = *scopeIter; - PropertyNameArray propertyNames(globalObject()->globalExec()); - o->getPropertyNames(globalObject()->globalExec(), propertyNames); + PropertyNameArray propertyNames(globalObject->globalExec()); + o->getPropertyNames(globalObject->globalExec(), propertyNames); PropertyNameArray::const_iterator propEnd = propertyNames.end(); fprintf(stderr, "----- [scope %p] -----\n", o); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.h index c5e16c9..0b15b67 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/ScopeChain.h @@ -33,14 +33,16 @@ namespace JSC { class ScopeChainNode : public FastAllocBase { public: - ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSObject* globalThis) + ScopeChainNode(ScopeChainNode* next, JSObject* object, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) : next(next) , object(object) , globalData(globalData) + , globalObject(globalObject) , globalThis(globalThis) , refCount(1) { ASSERT(globalData); + ASSERT(globalObject); } #ifndef NDEBUG // Due to the number of subtle and timing dependent bugs that have occurred due @@ -51,6 +53,7 @@ namespace JSC { next = 0; object = 0; globalData = 0; + globalObject = 0; globalThis = 0; } #endif @@ -58,6 +61,7 @@ namespace JSC { ScopeChainNode* next; JSObject* object; JSGlobalData* globalData; + JSGlobalObject* globalObject; JSObject* globalThis; int refCount; @@ -82,9 +86,6 @@ namespace JSC { ScopeChainIterator begin() const; ScopeChainIterator end() const; - JSGlobalObject* globalObject() const; // defined in JSGlobalObject.h - JSObject* globalThisObject() const { return globalThis; } - #ifndef NDEBUG void print() const; #endif @@ -93,7 +94,7 @@ namespace JSC { inline ScopeChainNode* ScopeChainNode::push(JSObject* o) { ASSERT(o); - return new ScopeChainNode(this, o, globalData, globalThis); + return new ScopeChainNode(this, o, globalData, globalObject, globalThis); } inline ScopeChainNode* ScopeChainNode::pop() @@ -163,8 +164,8 @@ namespace JSC { { } - ScopeChain(JSObject* o, JSGlobalData* globalData, JSObject* globalThis) - : m_node(new ScopeChainNode(0, o, globalData, globalThis)) + ScopeChain(JSObject* o, JSGlobalData* globalData, JSGlobalObject* globalObject, JSObject* globalThis) + : m_node(new ScopeChainNode(0, o, globalData, globalObject, globalThis)) { } @@ -203,7 +204,7 @@ namespace JSC { void pop() { m_node = m_node->pop(); } void clear() { m_node->deref(); m_node = 0; } - JSGlobalObject* globalObject() const { return m_node->globalObject(); } + JSGlobalObject* globalObject() const { return m_node->globalObject; } void markAggregate(MarkStack&) const; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.cpp index 04701cb..ac71735 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/SmallStrings.cpp @@ -41,30 +41,16 @@ public: UString::Rep* rep(unsigned char character) { return &m_reps[character]; } private: - UChar m_characters[numCharactersToStore]; - UString::BaseString m_base; UString::Rep m_reps[numCharactersToStore]; }; SmallStringsStorage::SmallStringsStorage() - : m_base(m_characters, numCharactersToStore) { - m_base.rc = numCharactersToStore + 1; - // make sure UString doesn't try to reuse the buffer by pretending we have one more character in it - m_base.usedCapacity = numCharactersToStore + 1; - m_base.capacity = numCharactersToStore + 1; - m_base.checkConsistency(); - - for (unsigned i = 0; i < numCharactersToStore; ++i) - m_characters[i] = i; - - memset(&m_reps, 0, sizeof(m_reps)); + UChar* characterBuffer = 0; + RefPtr<UStringImpl> baseString = UStringImpl::createUninitialized(numCharactersToStore, characterBuffer); for (unsigned i = 0; i < numCharactersToStore; ++i) { - m_reps[i].offset = i; - m_reps[i].len = 1; - m_reps[i].rc = 1; - m_reps[i].setBaseString(&m_base); - m_reps[i].checkConsistency(); + characterBuffer[i] = i; + new (&m_reps[i]) UString::Rep(&characterBuffer[i], 1, PassRefPtr<UStringImpl>(baseString)); } } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringBuilder.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringBuilder.h new file mode 100644 index 0000000..8e18d37 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringBuilder.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2009 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 StringBuilder_h +#define StringBuilder_h + +#include <wtf/Vector.h> + +namespace JSC { + +class StringBuilder { +public: + void append(const UChar u) + { + buffer.append(u); + } + + void append(const char* str) + { + buffer.append(str, strlen(str)); + } + + void append(const char* str, size_t len) + { + buffer.reserveCapacity(buffer.size() + len); + for (size_t i = 0; i < len; i++) + buffer.append(static_cast<unsigned char>(str[i])); + } + + void append(const UChar* str, size_t len) + { + buffer.append(str, len); + } + + void append(const UString& str) + { + buffer.append(str.data(), str.size()); + } + + bool isEmpty() { return buffer.isEmpty(); } + void reserveCapacity(size_t newCapacity) { buffer.reserveCapacity(newCapacity); } + void resize(size_t size) { buffer.resize(size); } + size_t size() const { return buffer.size(); } + + UChar operator[](size_t i) const { return buffer.at(i); } + + UString release() + { + buffer.shrinkToFit(); + return UString::adopt(buffer); + } + +private: + Vector<UChar, 64> buffer; +}; + +} + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringConstructor.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringConstructor.cpp index 6380445..c7b62bf 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringConstructor.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringConstructor.cpp @@ -30,12 +30,12 @@ namespace JSC { static NEVER_INLINE JSValue stringFromCharCodeSlowCase(ExecState* exec, const ArgList& args) { - UChar* buf = static_cast<UChar*>(fastMalloc(args.size() * sizeof(UChar))); - UChar* p = buf; - ArgList::const_iterator end = args.end(); - for (ArgList::const_iterator it = args.begin(); it != end; ++it) - *p++ = static_cast<UChar>((*it).toUInt32(exec)); - return jsString(exec, UString(buf, p - buf, false)); + unsigned length = args.size(); + UChar* buf; + PassRefPtr<UStringImpl> impl = UStringImpl::createUninitialized(length, buf); + for (unsigned i = 0; i < length; ++i) + buf[i] = static_cast<UChar>(args.at(i).toUInt32(exec)); + return jsString(exec, impl); } static JSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec, JSObject*, JSValue, const ArgList& args) @@ -47,7 +47,7 @@ static JSValue JSC_HOST_CALL stringFromCharCode(ExecState* exec, JSObject*, JSVa ASSERT_CLASS_FITS_IN_CELL(StringConstructor); -StringConstructor::StringConstructor(ExecState* exec, PassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype) +StringConstructor::StringConstructor(ExecState* exec, NonNullPassRefPtr<Structure> structure, Structure* prototypeFunctionStructure, StringPrototype* stringPrototype) : InternalFunction(&exec->globalData(), structure, Identifier(exec, stringPrototype->classInfo()->className)) { // ECMA 15.5.3.1 String.prototype diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringConstructor.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringConstructor.h index 7d52c69..e511f7b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringConstructor.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringConstructor.h @@ -29,7 +29,7 @@ namespace JSC { class StringConstructor : public InternalFunction { public: - StringConstructor(ExecState*, PassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*); + StringConstructor(ExecState*, NonNullPassRefPtr<Structure>, Structure* prototypeFunctionStructure, StringPrototype*); virtual ConstructType getConstructData(ConstructData&); virtual CallType getCallData(CallData&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.cpp index dd1ac5d..f8e0e87 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.cpp @@ -29,19 +29,19 @@ ASSERT_CLASS_FITS_IN_CELL(StringObject); const ClassInfo StringObject::info = { "String", 0, 0, 0 }; -StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure) +StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure) : JSWrapperObject(structure) { setInternalValue(jsEmptyString(exec)); } -StringObject::StringObject(PassRefPtr<Structure> structure, JSString* string) +StringObject::StringObject(NonNullPassRefPtr<Structure> structure, JSString* string) : JSWrapperObject(structure) { setInternalValue(string); } -StringObject::StringObject(ExecState* exec, PassRefPtr<Structure> structure, const UString& string) +StringObject::StringObject(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string) : JSWrapperObject(structure) { setInternalValue(jsString(exec, string)); @@ -75,7 +75,7 @@ void StringObject::put(ExecState* exec, const Identifier& propertyName, JSValue JSObject::put(exec, propertyName, value, slot); } -bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyName, bool checkDontDelete) +bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyName) { if (propertyName == exec->propertyNames().length) return false; @@ -83,15 +83,17 @@ bool StringObject::deleteProperty(ExecState* exec, const Identifier& propertyNam unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); if (isStrictUInt32 && internalValue()->canGetIndex(i)) return false; - return JSObject::deleteProperty(exec, propertyName, checkDontDelete); + return JSObject::deleteProperty(exec, propertyName); } -void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, bool includeNonEnumerable) +void StringObject::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) { - int size = internalValue()->value().size(); + int size = internalValue()->length(); for (int i = 0; i < size; ++i) propertyNames.add(Identifier(exec, UString::from(i))); - return JSObject::getOwnPropertyNames(exec, propertyNames); + if (mode == IncludeDontEnumProperties) + propertyNames.add(exec->propertyNames().length); + return JSObject::getOwnPropertyNames(exec, propertyNames, mode); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.h index 2f5927a..b720b90 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObject.h @@ -28,8 +28,8 @@ namespace JSC { class StringObject : public JSWrapperObject { public: - StringObject(ExecState*, PassRefPtr<Structure>); - StringObject(ExecState*, PassRefPtr<Structure>, const UString&); + StringObject(ExecState*, NonNullPassRefPtr<Structure>); + StringObject(ExecState*, NonNullPassRefPtr<Structure>, const UString&); static StringObject* create(ExecState*, JSString*); @@ -38,8 +38,8 @@ namespace JSC { virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); virtual void put(ExecState* exec, const Identifier& propertyName, JSValue, PutPropertySlot&); - virtual bool deleteProperty(ExecState*, const Identifier& propertyName, bool checkDontDelete = true); - virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, bool includeNonEnumerable = false); + virtual bool deleteProperty(ExecState*, const Identifier& propertyName); + virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual const ClassInfo* classInfo() const { return &info; } static const JS_EXPORTDATA ClassInfo info; @@ -48,11 +48,12 @@ namespace JSC { static PassRefPtr<Structure> createStructure(JSValue prototype) { - return Structure::create(prototype, TypeInfo(ObjectType)); + return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags)); } protected: - StringObject(PassRefPtr<Structure>, JSString*); + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSWrapperObject::StructureFlags; + StringObject(NonNullPassRefPtr<Structure>, JSString*); }; StringObject* asStringObject(JSValue); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h index 1d2e03f..69e1939 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringObjectThatMasqueradesAsUndefined.h @@ -37,16 +37,18 @@ namespace JSC { } private: - StringObjectThatMasqueradesAsUndefined(ExecState* exec, PassRefPtr<Structure> structure, const UString& string) + StringObjectThatMasqueradesAsUndefined(ExecState* exec, NonNullPassRefPtr<Structure> structure, const UString& string) : StringObject(exec, structure, string) { } static PassRefPtr<Structure> createStructure(JSValue proto) { - return Structure::create(proto, TypeInfo(ObjectType, MasqueradesAsUndefined | HasDefaultMark)); + return Structure::create(proto, TypeInfo(ObjectType, StructureFlags)); } + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | MasqueradesAsUndefined | OverridesGetPropertyNames | StringObject::StructureFlags; + virtual bool toBoolean(ExecState*) const { return false; } }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.cpp index c9a32b6..d002e07 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.cpp @@ -25,9 +25,11 @@ #include "CachedCall.h" #include "Error.h" #include "Executable.h" +#include "JSGlobalObjectFunctions.h" #include "JSArray.h" #include "JSFunction.h" #include "ObjectPrototype.h" +#include "Operations.h" #include "PropertyNameArray.h" #include "RegExpConstructor.h" #include "RegExpObject.h" @@ -72,6 +74,10 @@ static JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState*, JSObject*, JSVa static JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState*, JSObject*, JSValue, const ArgList&); +static JSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*, JSObject*, JSValue, const ArgList&); + } #include "StringPrototype.lut.h" @@ -117,11 +123,14 @@ const ClassInfo StringPrototype::info = { "String", &StringObject::info, 0, Exec fontsize stringProtoFuncFontsize DontEnum|Function 1 anchor stringProtoFuncAnchor DontEnum|Function 1 link stringProtoFuncLink DontEnum|Function 1 + trim stringProtoFuncTrim DontEnum|Function 0 + trimLeft stringProtoFuncTrimLeft DontEnum|Function 0 + trimRight stringProtoFuncTrimRight DontEnum|Function 0 @end */ // ECMA 15.5.4 -StringPrototype::StringPrototype(ExecState* exec, PassRefPtr<Structure> structure) +StringPrototype::StringPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure) : StringObject(exec, structure) { // The constructor will be added later, after StringConstructor has been built @@ -140,12 +149,11 @@ bool StringPrototype::getOwnPropertyDescriptor(ExecState* exec, const Identifier // ------------------------------ Functions -------------------------- -static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg) +static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacement, const UString& source, const int* ovector, RegExp* reg, int i) { - UString substitutedReplacement; + Vector<UChar> substitutedReplacement; int offset = 0; - int i = -1; - while ((i = replacement.find('$', i + 1)) != -1) { + do { if (i + 1 == replacement.size()) break; @@ -197,15 +205,21 @@ static inline UString substituteBackreferences(const UString& replacement, const i += 1 + advance; offset = i + 1; substitutedReplacement.append(source.data() + backrefStart, backrefLength); - } - - if (!offset) - return replacement; + } while ((i = replacement.find('$', i + 1)) != -1); if (replacement.size() - offset) substitutedReplacement.append(replacement.data() + offset, replacement.size() - offset); - return substitutedReplacement; + substitutedReplacement.shrinkToFit(); + return UString::adopt(substitutedReplacement); +} + +static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg) +{ + int i = replacement.find('$', 0); + if (UNLIKELY(i != -1)) + return substituteBackreferencesSlow(replacement, source, ovector, reg, i); + return replacement; } static inline int localeCompare(const UString& a, const UString& b) @@ -216,7 +230,7 @@ static inline int localeCompare(const UString& a, const UString& b) JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { JSString* sourceVal = thisValue.toThisJSString(exec); - const UString& source = sourceVal->value(); + const UString& source = sourceVal->value(exec); JSValue pattern = args.at(0); @@ -249,7 +263,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue return jsNull(); while (true) { int matchIndex; - int matchLen; + int matchLen = 0; int* ovector; regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); if (matchIndex < 0) @@ -273,7 +287,8 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue cachedCall.setArgument(i++, sourceVal); cachedCall.setThis(exec->globalThisValue()); - replacements.append(cachedCall.call().toString(cachedCall.newCallFrame())); + JSValue result = cachedCall.call(); + replacements.append(result.toString(cachedCall.newCallFrame(exec))); if (exec->hadException()) break; @@ -290,7 +305,7 @@ JSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec, JSObject*, JSValue } else { do { int matchIndex; - int matchLen; + int matchLen = 0; int* ovector; regExpConstructor->performMatch(reg, source, startPosition, matchIndex, matchLen, &ovector); if (matchIndex < 0) @@ -414,12 +429,14 @@ JSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState* exec, JSObject*, JSVa JSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { - UString s = thisValue.toThisString(exec); + if (thisValue.isString() && (args.size() == 1)) { + JSValue v = args.at(0); + return v.isString() + ? jsString(exec, asString(thisValue), asString(v)) + : jsString(exec, asString(thisValue), v.toString(exec)); + } - ArgList::const_iterator end = args.end(); - for (ArgList::const_iterator it = args.begin(); it != end; ++it) - s += (*it).toString(exec); - return jsString(exec, s); + return jsString(exec, thisValue, args); } JSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -461,6 +478,11 @@ JSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState* exec, JSObject*, JSV dpos = 0; else if (!(dpos <= len)) // true for NaN dpos = len; +#if OS(SYMBIAN) + // Work around for broken NaN compare operator + else if (isnan(dpos)) + dpos = len; +#endif return jsNumber(exec, s.rfind(u2, static_cast<int>(dpos))); } @@ -485,7 +507,7 @@ JSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec, JSObject*, JSValue t } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; - int matchLength; + int matchLength = 0; regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); if (!(reg->global())) { // case without 'g' flag is handled like RegExp.prototype.exec @@ -535,7 +557,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec, JSObject*, JSValue } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); int pos; - int matchLength; + int matchLength = 0; regExpConstructor->performMatch(reg.get(), u, 0, pos, matchLength); return jsNumber(exec, pos); } @@ -683,7 +705,7 @@ JSValue JSC_HOST_CALL stringProtoFuncSubstring(ExecState* exec, JSObject*, JSVal JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { JSString* sVal = thisValue.toThisJSString(exec); - const UString& s = sVal->value(); + const UString& s = sVal->value(exec); int sSize = s.size(); if (!sSize) @@ -699,7 +721,7 @@ JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSV buffer[i] = toASCIILower(c); } if (!(ored & ~0x7f)) - return jsString(exec, UString(buffer.releaseBuffer(), sSize, false)); + return jsString(exec, UString::adopt(buffer)); bool error; int length = Unicode::toLower(buffer.data(), sSize, sData, sSize, &error); @@ -709,15 +731,18 @@ JSValue JSC_HOST_CALL stringProtoFuncToLowerCase(ExecState* exec, JSObject*, JSV if (error) return sVal; } - if (length == sSize && memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0) - return sVal; - return jsString(exec, UString(buffer.releaseBuffer(), length, false)); + if (length == sSize) { + if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0) + return sVal; + } else + buffer.resize(length); + return jsString(exec, UString::adopt(buffer)); } JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { JSString* sVal = thisValue.toThisJSString(exec); - const UString& s = sVal->value(); + const UString& s = sVal->value(exec); int sSize = s.size(); if (!sSize) @@ -733,7 +758,7 @@ JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSV buffer[i] = toASCIIUpper(c); } if (!(ored & ~0x7f)) - return jsString(exec, UString(buffer.releaseBuffer(), sSize, false)); + return jsString(exec, UString::adopt(buffer)); bool error; int length = Unicode::toUpper(buffer.data(), sSize, sData, sSize, &error); @@ -743,9 +768,12 @@ JSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState* exec, JSObject*, JSV if (error) return sVal; } - if (length == sSize && memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0) - return sVal; - return jsString(exec, UString(buffer.releaseBuffer(), length, false)); + if (length == sSize) { + if (memcmp(buffer.data(), sData, length * sizeof(UChar)) == 0) + return sVal; + } else + buffer.resize(length); + return jsString(exec, UString::adopt(buffer)); } JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -761,62 +789,62 @@ JSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState* exec, JSObject*, J JSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, "<big>" + s + "</big>"); + return jsNontrivialString(exec, makeString("<big>", s, "</big>")); } JSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, "<small>" + s + "</small>"); + return jsNontrivialString(exec, makeString("<small>", s, "</small>")); } JSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, "<blink>" + s + "</blink>"); + return jsNontrivialString(exec, makeString("<blink>", s, "</blink>")); } JSValue JSC_HOST_CALL stringProtoFuncBold(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, "<b>" + s + "</b>"); + return jsNontrivialString(exec, makeString("<b>", s, "</b>")); } JSValue JSC_HOST_CALL stringProtoFuncFixed(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsString(exec, "<tt>" + s + "</tt>"); + return jsString(exec, makeString("<tt>", s, "</tt>")); } JSValue JSC_HOST_CALL stringProtoFuncItalics(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, "<i>" + s + "</i>"); + return jsNontrivialString(exec, makeString("<i>", s, "</i>")); } JSValue JSC_HOST_CALL stringProtoFuncStrike(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, "<strike>" + s + "</strike>"); + return jsNontrivialString(exec, makeString("<strike>", s, "</strike>")); } JSValue JSC_HOST_CALL stringProtoFuncSub(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, "<sub>" + s + "</sub>"); + return jsNontrivialString(exec, makeString("<sub>", s, "</sub>")); } JSValue JSC_HOST_CALL stringProtoFuncSup(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) { UString s = thisValue.toThisString(exec); - return jsNontrivialString(exec, "<sup>" + s + "</sup>"); + return jsNontrivialString(exec, makeString("<sup>", s, "</sup>")); } JSValue JSC_HOST_CALL stringProtoFuncFontcolor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); - return jsNontrivialString(exec, "<font color=\"" + a0.toString(exec) + "\">" + s + "</font>"); + return jsNontrivialString(exec, makeString("<font color=\"", a0.toString(exec), "\">", s, "</font>")); } JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -829,7 +857,8 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu unsigned stringSize = s.size(); unsigned bufferSize = 22 + stringSize; UChar* buffer; - if (!tryFastMalloc(bufferSize * sizeof(UChar)).getValue(buffer)) + PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer); + if (!impl) return jsUndefined(); buffer[0] = '<'; buffer[1] = 'f'; @@ -854,17 +883,17 @@ JSValue JSC_HOST_CALL stringProtoFuncFontsize(ExecState* exec, JSObject*, JSValu buffer[19 + stringSize] = 'n'; buffer[20 + stringSize] = 't'; buffer[21 + stringSize] = '>'; - return jsNontrivialString(exec, UString(buffer, bufferSize, false)); + return jsNontrivialString(exec, impl); } - return jsNontrivialString(exec, "<font size=\"" + a0.toString(exec) + "\">" + s + "</font>"); + return jsNontrivialString(exec, makeString("<font size=\"", a0.toString(exec), "\">", s, "</font>")); } JSValue JSC_HOST_CALL stringProtoFuncAnchor(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) { UString s = thisValue.toThisString(exec); JSValue a0 = args.at(0); - return jsNontrivialString(exec, "<a name=\"" + a0.toString(exec) + "\">" + s + "</a>"); + return jsNontrivialString(exec, makeString("<a name=\"", a0.toString(exec), "\">", s, "</a>")); } JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue thisValue, const ArgList& args) @@ -877,7 +906,8 @@ JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue th unsigned stringSize = s.size(); unsigned bufferSize = 15 + linkTextSize + stringSize; UChar* buffer; - if (!tryFastMalloc(bufferSize * sizeof(UChar)).getValue(buffer)) + PassRefPtr<UStringImpl> impl = UStringImpl::tryCreateUninitialized(bufferSize, buffer); + if (!impl) return jsUndefined(); buffer[0] = '<'; buffer[1] = 'a'; @@ -896,7 +926,54 @@ JSValue JSC_HOST_CALL stringProtoFuncLink(ExecState* exec, JSObject*, JSValue th buffer[12 + linkTextSize + stringSize] = '/'; buffer[13 + linkTextSize + stringSize] = 'a'; buffer[14 + linkTextSize + stringSize] = '>'; - return jsNontrivialString(exec, UString(buffer, bufferSize, false)); + return jsNontrivialString(exec, impl); } +enum { + TrimLeft = 1, + TrimRight = 2 +}; + +static inline bool isTrimWhitespace(UChar c) +{ + return isStrWhiteSpace(c) || c == 0x200b; +} + +static inline JSValue trimString(ExecState* exec, JSValue thisValue, int trimKind) +{ + UString str = thisValue.toThisString(exec); + int left = 0; + if (trimKind & TrimLeft) { + while (left < str.size() && isTrimWhitespace(str[left])) + left++; + } + int right = str.size(); + if (trimKind & TrimRight) { + while (right > left && isTrimWhitespace(str[right - 1])) + right--; + } + + // Don't gc allocate a new string if we don't have to. + if (left == 0 && right == str.size() && thisValue.isString()) + return thisValue; + + return jsString(exec, str.substr(left, right - left)); +} + +JSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) +{ + return trimString(exec, thisValue, TrimLeft | TrimRight); +} + +JSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) +{ + return trimString(exec, thisValue, TrimLeft); +} + +JSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState* exec, JSObject*, JSValue thisValue, const ArgList&) +{ + return trimString(exec, thisValue, TrimRight); +} + + } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.h index 580e13d..3a6a2a3 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StringPrototype.h @@ -29,7 +29,7 @@ namespace JSC { class StringPrototype : public StringObject { public: - StringPrototype(ExecState*, PassRefPtr<Structure>); + StringPrototype(ExecState*, NonNullPassRefPtr<Structure>); virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); virtual bool getOwnPropertyDescriptor(ExecState*, const Identifier&, PropertyDescriptor&); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.cpp index be817c3..8e50dd1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.cpp @@ -28,9 +28,10 @@ #include "Identifier.h" #include "JSObject.h" +#include "JSPropertyNameIterator.h" +#include "Lookup.h" #include "PropertyNameArray.h" #include "StructureChain.h" -#include "Lookup.h" #include <wtf/RefCountedLeakCounter.h> #include <wtf/RefPtr.h> @@ -75,6 +76,8 @@ static HashSet<Structure*>& ignoreSet = *(new HashSet<Structure*>); static HashSet<Structure*>& liveStructureSet = *(new HashSet<Structure*>); #endif +static int comparePropertyMapEntryIndices(const void* a, const void* b); + void Structure::dumpStatistics() { #if DUMP_STRUCTURE_ID_STATISTICS @@ -130,6 +133,7 @@ Structure::Structure(JSValue prototype, const TypeInfo& typeInfo) , m_isPinnedPropertyTable(false) , m_hasGetterSetterProperties(false) , m_attributesInPrevious(0) + , m_specificFunctionThrashCount(0) { ASSERT(m_prototype); ASSERT(m_prototype.isObject() || m_prototype.isNull()); @@ -158,9 +162,9 @@ Structure::~Structure() m_previous->table.removeAnonymousSlotTransition(m_anonymousSlotsInPrevious); } - - if (m_cachedPropertyNameArrayData) - m_cachedPropertyNameArrayData->setCachedStructure(0); + + if (m_enumerationCache) + m_enumerationCache->setCachedStructure(0); if (m_propertyTable) { unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; @@ -281,59 +285,6 @@ void Structure::materializePropertyMap() } } -void Structure::getOwnPropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject, bool includeNonEnumerable) -{ - getNamesFromPropertyTable(propertyNames, includeNonEnumerable); - getNamesFromClassInfoTable(exec, baseObject->classInfo(), propertyNames, includeNonEnumerable); -} - -void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject) -{ - bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary()); - - if (shouldCache && m_cachedPropertyNameArrayData) { - if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) { - propertyNames.setData(m_cachedPropertyNameArrayData); - return; - } - clearEnumerationCache(); - } - - baseObject->getOwnPropertyNames(exec, propertyNames); - - if (m_prototype.isObject()) { - propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly. - JSObject* prototype = asObject(m_prototype); - while(1) { - if (!prototype->structure()->typeInfo().hasDefaultGetPropertyNames()) { - prototype->getPropertyNames(exec, propertyNames); - break; - } - prototype->getOwnPropertyNames(exec, propertyNames); - JSValue nextProto = prototype->prototype(); - if (!nextProto.isObject()) - break; - prototype = asObject(nextProto); - } - } - - if (shouldCache) { - StructureChain* protoChain = prototypeChain(exec); - m_cachedPropertyNameArrayData = propertyNames.data(); - if (!protoChain->isCacheable()) - return; - m_cachedPropertyNameArrayData->setCachedPrototypeChain(protoChain); - m_cachedPropertyNameArrayData->setCachedStructure(this); - } -} - -void Structure::clearEnumerationCache() -{ - if (m_cachedPropertyNameArrayData) - m_cachedPropertyNameArrayData->setCachedStructure(0); - m_cachedPropertyNameArrayData.clear(); -} - void Structure::growPropertyStorageCapacity() { if (m_propertyStorageCapacity == JSObject::inlineStorageCapacity) @@ -351,7 +302,7 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName) ASSERT(isDictionary()); ASSERT(m_propertyTable); - unsigned i = rep->computedHash(); + unsigned i = rep->existingHash(); #if DUMP_PROPERTYMAP_STATS ++numProbes; @@ -369,7 +320,7 @@ void Structure::despecifyDictionaryFunction(const Identifier& propertyName) ++numCollisions; #endif - unsigned k = 1 | doubleHash(rep->computedHash()); + unsigned k = 1 | doubleHash(rep->existingHash()); while (1) { i += k; @@ -407,6 +358,9 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con ASSERT(!structure->isDictionary()); ASSERT(structure->typeInfo().type() == ObjectType); ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset)); + + if (structure->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount) + specificValue = 0; if (structure->transitionCount() > s_maxTransitionLength) { RefPtr<Structure> transition = toCacheableDictionaryTransition(structure); @@ -426,6 +380,8 @@ PassRefPtr<Structure> Structure::addPropertyTransition(Structure* structure, con transition->m_specificValueInPrevious = specificValue; transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties; + transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount; if (structure->m_propertyTable) { if (structure->m_isPinnedPropertyTable) @@ -468,6 +424,8 @@ PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties; + transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount; // Don't set m_offset, as one can not transition to this. @@ -480,10 +438,13 @@ PassRefPtr<Structure> Structure::changePrototypeTransition(Structure* structure, PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structure, const Identifier& replaceFunction) { + ASSERT(structure->m_specificFunctionThrashCount < maxSpecificFunctionThrashCount); RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo()); transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties; + transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount + 1; // Don't set m_offset, as one can not transition to this. @@ -491,8 +452,12 @@ PassRefPtr<Structure> Structure::despecifyFunctionTransition(Structure* structur transition->m_propertyTable = structure->copyPropertyTable(); transition->m_isPinnedPropertyTable = true; - bool removed = transition->despecifyFunction(replaceFunction); - ASSERT_UNUSED(removed, removed); + if (transition->m_specificFunctionThrashCount == maxSpecificFunctionThrashCount) + transition->despecifyAllFunctions(); + else { + bool removed = transition->despecifyFunction(replaceFunction); + ASSERT_UNUSED(removed, removed); + } return transition.release(); } @@ -515,6 +480,8 @@ PassRefPtr<Structure> Structure::addAnonymousSlotsTransition(Structure* structur transition->m_specificValueInPrevious = 0; transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties; + transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount; if (structure->m_propertyTable) { if (structure->m_isPinnedPropertyTable) @@ -543,6 +510,8 @@ PassRefPtr<Structure> Structure::getterSetterTransition(Structure* structure) RefPtr<Structure> transition = create(structure->storedPrototype(), structure->typeInfo()); transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = transition->m_hasGetterSetterProperties; + transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties; + transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount; // Don't set m_offset, as one can not transition to this. @@ -561,6 +530,8 @@ PassRefPtr<Structure> Structure::toDictionaryTransition(Structure* structure, Di transition->m_dictionaryKind = kind; transition->m_propertyStorageCapacity = structure->m_propertyStorageCapacity; transition->m_hasGetterSetterProperties = structure->m_hasGetterSetterProperties; + transition->m_hasNonEnumerableProperties = structure->m_hasNonEnumerableProperties; + transition->m_specificFunctionThrashCount = structure->m_specificFunctionThrashCount; structure->materializePropertyMapIfNecessary(); transition->m_propertyTable = structure->copyPropertyTable(); @@ -579,43 +550,75 @@ PassRefPtr<Structure> Structure::toUncacheableDictionaryTransition(Structure* st return toDictionaryTransition(structure, UncachedDictionaryKind); } -PassRefPtr<Structure> Structure::fromDictionaryTransition(Structure* structure) +PassRefPtr<Structure> Structure::flattenDictionaryStructure(JSObject* object) { - ASSERT(structure->isDictionary()); - - // Since dictionary Structures are not shared, and no opcodes specialize - // for them, we don't need to allocate a new Structure when transitioning - // to non-dictionary status. - - // FIMXE: We can make this more efficient by canonicalizing the Structure (draining the - // deleted offsets vector) before transitioning from dictionary. - if (!structure->m_propertyTable || !structure->m_propertyTable->deletedOffsets || structure->m_propertyTable->deletedOffsets->isEmpty()) - structure->m_dictionaryKind = NoneDictionaryKind; + ASSERT(isDictionary()); + if (isUncacheableDictionary()) { + ASSERT(m_propertyTable); + Vector<PropertyMapEntry*> sortedPropertyEntries(m_propertyTable->keyCount); + PropertyMapEntry** p = sortedPropertyEntries.data(); + unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; + for (unsigned i = 1; i <= entryCount; i++) { + if (m_propertyTable->entries()[i].key) + *p++ = &m_propertyTable->entries()[i]; + } + size_t propertyCount = p - sortedPropertyEntries.data(); + qsort(sortedPropertyEntries.data(), propertyCount, sizeof(PropertyMapEntry*), comparePropertyMapEntryIndices); + sortedPropertyEntries.resize(propertyCount); + + // We now have the properties currently defined on this object + // in the order that they are expected to be in, but we need to + // reorder the storage, so we have to copy the current values out + Vector<JSValue> values(propertyCount); + unsigned anonymousSlotCount = m_propertyTable->anonymousSlotCount; + for (unsigned i = 0; i < propertyCount; i++) { + PropertyMapEntry* entry = sortedPropertyEntries[i]; + values[i] = object->getDirectOffset(entry->offset); + // Update property table to have the new property offsets + entry->offset = anonymousSlotCount + i; + entry->index = i; + } + + // Copy the original property values into their final locations + for (unsigned i = 0; i < propertyCount; i++) + object->putDirectOffset(anonymousSlotCount + i, values[i]); + + if (m_propertyTable->deletedOffsets) { + delete m_propertyTable->deletedOffsets; + m_propertyTable->deletedOffsets = 0; + } + } - return structure; + m_dictionaryKind = NoneDictionaryKind; + return this; } size_t Structure::addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue) { + ASSERT(!m_enumerationCache); + + if (m_specificFunctionThrashCount == maxSpecificFunctionThrashCount) + specificValue = 0; + materializePropertyMapIfNecessary(); m_isPinnedPropertyTable = true; + size_t offset = put(propertyName, attributes, specificValue); if (propertyStorageSize() > propertyStorageCapacity()) growPropertyStorageCapacity(); - clearEnumerationCache(); return offset; } size_t Structure::removePropertyWithoutTransition(const Identifier& propertyName) { ASSERT(isUncacheableDictionary()); + ASSERT(!m_enumerationCache); materializePropertyMapIfNecessary(); m_isPinnedPropertyTable = true; size_t offset = remove(propertyName); - clearEnumerationCache(); return offset; } @@ -682,7 +685,7 @@ size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& sp if (!m_propertyTable) return notFound; - unsigned i = rep->computedHash(); + unsigned i = rep->existingHash(); #if DUMP_PROPERTYMAP_STATS ++numProbes; @@ -702,7 +705,7 @@ size_t Structure::get(const UString::Rep* rep, unsigned& attributes, JSCell*& sp ++numCollisions; #endif - unsigned k = 1 | doubleHash(rep->computedHash()); + unsigned k = 1 | doubleHash(rep->existingHash()); while (1) { i += k; @@ -733,7 +736,7 @@ bool Structure::despecifyFunction(const Identifier& propertyName) UString::Rep* rep = propertyName._ustring.rep(); - unsigned i = rep->computedHash(); + unsigned i = rep->existingHash(); #if DUMP_PROPERTYMAP_STATS ++numProbes; @@ -753,7 +756,7 @@ bool Structure::despecifyFunction(const Identifier& propertyName) ++numCollisions; #endif - unsigned k = 1 | doubleHash(rep->computedHash()); + unsigned k = 1 | doubleHash(rep->existingHash()); while (1) { i += k; @@ -774,6 +777,17 @@ bool Structure::despecifyFunction(const Identifier& propertyName) } } +void Structure::despecifyAllFunctions() +{ + materializePropertyMapIfNecessary(); + if (!m_propertyTable) + return; + + unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; + for (unsigned i = 1; i <= entryCount; ++i) + m_propertyTable->entries()[i].specificValue = 0; +} + size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue) { ASSERT(!propertyName.isNull()); @@ -781,6 +795,9 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel checkConsistency(); + if (attributes & DontEnum) + m_hasNonEnumerableProperties = true; + UString::Rep* rep = propertyName._ustring.rep(); if (!m_propertyTable) @@ -788,7 +805,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel // FIXME: Consider a fast case for tables with no deleted sentinels. - unsigned i = rep->computedHash(); + unsigned i = rep->existingHash(); unsigned k = 0; bool foundDeletedElement = false; unsigned deletedElementIndex = 0; // initialize to make the compiler happy @@ -811,7 +828,7 @@ size_t Structure::put(const Identifier& propertyName, unsigned attributes, JSCel } if (k == 0) { - k = 1 | doubleHash(rep->computedHash()); + k = 1 | doubleHash(rep->existingHash()); #if DUMP_PROPERTYMAP_STATS ++numCollisions; #endif @@ -891,7 +908,7 @@ size_t Structure::remove(const Identifier& propertyName) #endif // Find the thing to remove. - unsigned i = rep->computedHash(); + unsigned i = rep->existingHash(); unsigned k = 0; unsigned entryIndex; UString::Rep* key = 0; @@ -905,7 +922,7 @@ size_t Structure::remove(const Identifier& propertyName) break; if (k == 0) { - k = 1 | doubleHash(rep->computedHash()); + k = 1 | doubleHash(rep->existingHash()); #if DUMP_PROPERTYMAP_STATS ++numCollisions; #endif @@ -949,7 +966,7 @@ void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry) { ASSERT(m_propertyTable); - unsigned i = entry.key->computedHash(); + unsigned i = entry.key->existingHash(); unsigned k = 0; #if DUMP_PROPERTYMAP_STATS @@ -962,7 +979,7 @@ void Structure::insertIntoPropertyMapHashTable(const PropertyMapEntry& entry) break; if (k == 0) { - k = 1 | doubleHash(entry.key->computedHash()); + k = 1 | doubleHash(entry.key->existingHash()); #if DUMP_PROPERTYMAP_STATS ++numCollisions; #endif @@ -1045,7 +1062,7 @@ void Structure::rehashPropertyMapHashTable(unsigned newTableSize) checkConsistency(); } -static int comparePropertyMapEntryIndices(const void* a, const void* b) +int comparePropertyMapEntryIndices(const void* a, const void* b) { unsigned ia = static_cast<PropertyMapEntry* const*>(a)[0]->index; unsigned ib = static_cast<PropertyMapEntry* const*>(b)[0]->index; @@ -1056,7 +1073,7 @@ static int comparePropertyMapEntryIndices(const void* a, const void* b) return 0; } -void Structure::getNamesFromPropertyTable(PropertyNameArray& propertyNames, bool includeNonEnumerable) +void Structure::getPropertyNames(PropertyNameArray& propertyNames, EnumerationMode mode) { materializePropertyMapIfNecessary(); if (!m_propertyTable) @@ -1067,7 +1084,8 @@ void Structure::getNamesFromPropertyTable(PropertyNameArray& propertyNames, bool int i = 0; unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned k = 1; k <= entryCount; k++) { - if (m_propertyTable->entries()[k].key && (!(m_propertyTable->entries()[k].attributes & DontEnum) || includeNonEnumerable)) { + ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[k].attributes & DontEnum)); + if (m_propertyTable->entries()[k].key && (!(m_propertyTable->entries()[k].attributes & DontEnum) || (mode == IncludeDontEnumProperties))) { PropertyMapEntry* value = &m_propertyTable->entries()[k]; int j; for (j = i - 1; j >= 0 && a[j]->index > value->index; --j) @@ -1094,7 +1112,7 @@ void Structure::getNamesFromPropertyTable(PropertyNameArray& propertyNames, bool PropertyMapEntry** p = sortedEnumerables.data(); unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; for (unsigned i = 1; i <= entryCount; i++) { - if (m_propertyTable->entries()[i].key && (!(m_propertyTable->entries()[i].attributes & DontEnum) || includeNonEnumerable)) + if (m_propertyTable->entries()[i].key && (!(m_propertyTable->entries()[i].attributes & DontEnum) || (mode == IncludeDontEnumProperties))) *p++ = &m_propertyTable->entries()[i]; } @@ -1113,25 +1131,6 @@ void Structure::getNamesFromPropertyTable(PropertyNameArray& propertyNames, bool } } -void Structure::getNamesFromClassInfoTable(ExecState* exec, const ClassInfo* classInfo, PropertyNameArray& propertyNames, bool includeNonEnumerable) -{ - // Add properties from the static hashtables of properties - for (; classInfo; classInfo = classInfo->parentClass) { - const HashTable* table = classInfo->propHashTable(exec); - if (!table) - continue; - table->initializeIfNeeded(exec); - ASSERT(table->table); - - int hashSizeMask = table->compactSize - 1; - const HashEntry* entry = table->table; - for (int i = 0; i <= hashSizeMask; ++i, ++entry) { - if (entry->key() && (!(entry->attributes() & DontEnum) || includeNonEnumerable)) - propertyNames.add(entry->key()); - } - } -} - #if DO_PROPERTYMAP_CONSTENCY_CHECK void Structure::checkConsistency() @@ -1173,11 +1172,12 @@ void Structure::checkConsistency() unsigned nonEmptyEntryCount = 0; for (unsigned c = 1; c <= m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; ++c) { + ASSERT(m_hasNonEnumerableProperties || !(m_propertyTable->entries()[c].attributes & DontEnum)); UString::Rep* rep = m_propertyTable->entries()[c].key; if (!rep) continue; ++nonEmptyEntryCount; - unsigned i = rep->computedHash(); + unsigned i = rep->existingHash(); unsigned k = 0; unsigned entryIndex; while (1) { @@ -1186,7 +1186,7 @@ void Structure::checkConsistency() if (rep == m_propertyTable->entries()[entryIndex - 1].key) break; if (k == 0) - k = 1 | doubleHash(rep->computedHash()); + k = 1 | doubleHash(rep->existingHash()); i += k; } ASSERT(entryIndex == c + 1); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.h index d012ba9..5284258 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Structure.h @@ -30,6 +30,8 @@ #include "JSType.h" #include "JSValue.h" #include "PropertyMapHashTable.h" +#include "PropertyNameArray.h" +#include "Protect.h" #include "StructureTransitionTable.h" #include "JSTypeInfo.h" #include "UString.h" @@ -49,6 +51,11 @@ namespace JSC { class PropertyNameArrayData; class StructureChain; + enum EnumerationMode { + ExcludeDontEnumProperties, + IncludeDontEnumProperties + }; + class Structure : public RefCounted<Structure> { public: friend class JIT; @@ -72,11 +79,10 @@ namespace JSC { static PassRefPtr<Structure> getterSetterTransition(Structure*); static PassRefPtr<Structure> toCacheableDictionaryTransition(Structure*); static PassRefPtr<Structure> toUncacheableDictionaryTransition(Structure*); - static PassRefPtr<Structure> fromDictionaryTransition(Structure*); - ~Structure(); + PassRefPtr<Structure> flattenDictionaryStructure(JSObject*); - void markAggregate(MarkStack&); + ~Structure(); // These should be used with caution. size_t addPropertyWithoutTransition(const Identifier& propertyName, unsigned attributes, JSCell* specificValue); @@ -95,8 +101,8 @@ namespace JSC { Structure* previousID() const { return m_previous.get(); } void growPropertyStorageCapacity(); - size_t propertyStorageCapacity() const { return m_propertyStorageCapacity; } - size_t propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; } + unsigned propertyStorageCapacity() const { return m_propertyStorageCapacity; } + unsigned propertyStorageSize() const { return m_propertyTable ? m_propertyTable->keyCount + m_propertyTable->anonymousSlotCount + (m_propertyTable->deletedOffsets ? m_propertyTable->deletedOffsets->size() : 0) : m_offset + 1; } bool isUsingInlineStorage() const; size_t get(const Identifier& propertyName); @@ -116,17 +122,22 @@ namespace JSC { return hasTransition(propertyName._ustring.rep(), attributes); } - void getEnumerablePropertyNames(ExecState*, PropertyNameArray&, JSObject*); - void getOwnPropertyNames(ExecState*, PropertyNameArray&, JSObject*, bool includeNonEnumerable = false); - bool hasGetterSetterProperties() const { return m_hasGetterSetterProperties; } void setHasGetterSetterProperties(bool hasGetterSetterProperties) { m_hasGetterSetterProperties = hasGetterSetterProperties; } + bool hasNonEnumerableProperties() const { return m_hasNonEnumerableProperties; } + + bool hasAnonymousSlots() const { return m_propertyTable && m_propertyTable->anonymousSlotCount; } + bool isEmpty() const { return m_propertyTable ? !m_propertyTable->keyCount : m_offset == noOffset; } - JSCell* specificValue() { return m_specificValueInPrevious; } void despecifyDictionaryFunction(const Identifier& propertyName); + void disableSpecificFunctionTracking() { m_specificFunctionThrashCount = maxSpecificFunctionThrashCount; } + void setEnumerationCache(JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h. + JSPropertyNameIterator* enumerationCache() { return m_enumerationCache.get(); } + void getPropertyNames(PropertyNameArray&, EnumerationMode mode); + private: Structure(JSValue prototype, const TypeInfo&); @@ -140,8 +151,6 @@ namespace JSC { size_t put(const Identifier& propertyName, unsigned attributes, JSCell* specificValue); size_t remove(const Identifier& propertyName); void addAnonymousSlots(unsigned slotCount); - void getNamesFromPropertyTable(PropertyNameArray&, bool includeNonEnumerable = false); - void getNamesFromClassInfoTable(ExecState*, const ClassInfo*, PropertyNameArray&, bool includeNonEnumerable = false); void expandPropertyMapHashTable(); void rehashPropertyMapHashTable(); @@ -152,6 +161,7 @@ namespace JSC { void checkConsistency(); bool despecifyFunction(const Identifier&); + void despecifyAllFunctions(); PropertyMapHashTable* copyPropertyTable(); void materializePropertyMap(); @@ -162,8 +172,6 @@ namespace JSC { materializePropertyMap(); } - void clearEnumerationCache(); - signed char transitionCount() const { // Since the number of transitions is always the same as m_offset, we keep the size of Structure down by not storing both. @@ -178,6 +186,8 @@ namespace JSC { static const signed char noOffset = -1; + static const unsigned maxSpecificFunctionThrashCount = 3; + TypeInfo m_typeInfo; JSValue m_prototype; @@ -189,16 +199,17 @@ namespace JSC { StructureTransitionTable table; - RefPtr<PropertyNameArrayData> m_cachedPropertyNameArrayData; + ProtectedPtr<JSPropertyNameIterator> m_enumerationCache; PropertyMapHashTable* m_propertyTable; - size_t m_propertyStorageCapacity; + uint32_t m_propertyStorageCapacity; signed char m_offset; unsigned m_dictionaryKind : 2; bool m_isPinnedPropertyTable : 1; bool m_hasGetterSetterProperties : 1; + bool m_hasNonEnumerableProperties : 1; #if COMPILER(WINSCW) // Workaround for Symbian WINSCW compiler that cannot resolve unsigned type of the declared // bitfield, when used as argument in make_pair() function calls in structure.ccp. @@ -208,6 +219,8 @@ namespace JSC { unsigned m_attributesInPrevious : 7; #endif unsigned m_anonymousSlotsInPrevious : 6; + unsigned m_specificFunctionThrashCount : 2; + // 4 free bits }; inline size_t Structure::get(const Identifier& propertyName) @@ -220,7 +233,7 @@ namespace JSC { UString::Rep* rep = propertyName._ustring.rep(); - unsigned i = rep->computedHash(); + unsigned i = rep->existingHash(); #if DUMP_PROPERTYMAP_STATS ++numProbes; @@ -237,7 +250,7 @@ namespace JSC { ++numCollisions; #endif - unsigned k = 1 | WTF::doubleHash(rep->computedHash()); + unsigned k = 1 | WTF::doubleHash(rep->existingHash()); while (1) { i += k; @@ -304,7 +317,7 @@ namespace JSC { TransitionTable* transitionTable = new TransitionTable; setTransitionTable(transitionTable); if (existingTransition) - add(make_pair(RefPtr<UString::Rep>(existingTransition->m_nameInPrevious.get()), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious); + add(std::make_pair(RefPtr<UString::Rep>(existingTransition->m_nameInPrevious.get()), existingTransition->m_attributesInPrevious), existingTransition, existingTransition->m_specificValueInPrevious); } } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.cpp index 2c38b67..76e5518 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.cpp @@ -25,7 +25,6 @@ #include "config.h" #include "StructureChain.h" -#include "Structure.h" #include "JSObject.h" #include "Structure.h" @@ -47,23 +46,11 @@ StructureChain::StructureChain(Structure* head) m_vector[i] = 0; } +#if OS(HPUX) PassRefPtr<StructureChain> StructureChain::create(Structure* head) { return adoptRef(new StructureChain(head)); } - -bool StructureChain::isCacheable() const -{ - uint32_t i = 0; - - while (m_vector[i]) { - // Both classes of dictionary structure may change arbitrarily so we can't cache them - if (m_vector[i]->isDictionary()) - return false; - if (!m_vector[i++]->typeInfo().hasDefaultGetPropertyNames()) - return false; - } - return true; -} +#endif } // namespace JSC diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.h index 5990e17..3496400 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureChain.h @@ -36,10 +36,15 @@ namespace JSC { class Structure; class StructureChain : public RefCounted<StructureChain> { + friend class JIT; + public: +#if OS(HPUX) static PassRefPtr<StructureChain> create(Structure* head); +#else + static PassRefPtr<StructureChain> create(Structure* head) { return adoptRef(new StructureChain(head)); } +#endif RefPtr<Structure>* head() { return m_vector.get(); } - bool isCacheable() const; private: StructureChain(Structure* head); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureTransitionTable.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureTransitionTable.h index 0fa7b73..35fb7e4 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureTransitionTable.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/StructureTransitionTable.h @@ -42,7 +42,7 @@ namespace JSC { typedef std::pair<RefPtr<UString::Rep>, unsigned> Key; static unsigned hash(const Key& p) { - return p.first->computedHash(); + return p.first->existingHash(); } static bool equal(const Key& a, const Key& b) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.cpp index 0a8bbd3..9e1f8b4 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/TimeoutChecker.cpp @@ -33,9 +33,9 @@ #include "CallFrame.h" #include "JSGlobalObject.h" -#if PLATFORM(DARWIN) +#if OS(DARWIN) #include <mach/mach.h> -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) #include <windows.h> #else #include "CurrentTime.h" @@ -54,7 +54,7 @@ static const int defaultIntervalBetweenChecks = 1000; // Returns the time the current thread has spent executing, in milliseconds. static inline unsigned getCPUTime() { -#if PLATFORM(DARWIN) +#if OS(DARWIN) mach_msg_type_number_t infoCount = THREAD_BASIC_INFO_COUNT; thread_basic_info_data_t info; @@ -67,7 +67,7 @@ static inline unsigned getCPUTime() time += info.system_time.seconds * 1000 + info.system_time.microseconds / 1000; return time; -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) union { FILETIME fileTime; unsigned long long fileTimeAsLong; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Tracing.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Tracing.h index e544f66..c28c85f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Tracing.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Tracing.h @@ -33,7 +33,7 @@ #define JAVASCRIPTCORE_GC_BEGIN() #define JAVASCRIPTCORE_GC_BEGIN_ENABLED() 0 -#define JAVASCRIPTCORE_GC_END(arg0, arg1) +#define JAVASCRIPTCORE_GC_END() #define JAVASCRIPTCORE_GC_END_ENABLED() 0 #define JAVASCRIPTCORE_GC_MARKED() diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.cpp index e66ca93..a6b66cb 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.cpp @@ -30,12 +30,12 @@ #include "Identifier.h" #include "Operations.h" #include <ctype.h> -#include <float.h> #include <limits.h> #include <limits> #include <math.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <wtf/ASCIICType.h> #include <wtf/Assertions.h> #include <wtf/MathExtras.h> @@ -44,9 +44,6 @@ #include <wtf/unicode/UTF8.h> #include <wtf/StringExtras.h> -#if HAVE(STRING_H) -#include <string.h> -#endif #if HAVE(STRINGS_H) #include <strings.h> #endif @@ -55,52 +52,11 @@ using namespace WTF; using namespace WTF::Unicode; using namespace std; -// This can be tuned differently per platform by putting platform #ifs right here. -// If you don't define this macro at all, then copyChars will just call directly -// to memcpy. -#define USTRING_COPY_CHARS_INLINE_CUTOFF 20 - namespace JSC { extern const double NaN; extern const double Inf; -// This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. -static const int minLengthToShare = 10; - -static inline size_t overflowIndicator() { return std::numeric_limits<size_t>::max(); } -static inline size_t maxUChars() { return std::numeric_limits<size_t>::max() / sizeof(UChar); } - -static inline PossiblyNull<UChar*> allocChars(size_t length) -{ - ASSERT(length); - if (length > maxUChars()) - return 0; - return tryFastMalloc(sizeof(UChar) * length); -} - -static inline PossiblyNull<UChar*> reallocChars(UChar* buffer, size_t length) -{ - ASSERT(length); - if (length > maxUChars()) - return 0; - return tryFastRealloc(buffer, sizeof(UChar) * length); -} - -static inline void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) -{ -#ifdef USTRING_COPY_CHARS_INLINE_CUTOFF - if (numCharacters <= USTRING_COPY_CHARS_INLINE_CUTOFF) { - for (unsigned i = 0; i < numCharacters; ++i) - destination[i] = source[i]; - return; - } -#endif - memcpy(destination, source, numCharacters * sizeof(UChar)); -} - -COMPILE_ASSERT(sizeof(UChar) == 2, uchar_is_2_bytes); - CString::CString(const char* c) : m_length(strlen(c)) , m_data(new char[m_length + 1]) @@ -193,389 +149,52 @@ bool operator==(const CString& c1, const CString& c2) // These static strings are immutable, except for rc, whose initial value is chosen to // reduce the possibility of it becoming zero due to ref/deref not being thread-safe. static UChar sharedEmptyChar; -UString::BaseString* UString::Rep::nullBaseString; -UString::BaseString* UString::Rep::emptyBaseString; +UStringImpl* UStringImpl::s_null; +UStringImpl* UStringImpl::s_empty; UString* UString::nullUString; -static void initializeStaticBaseString(UString::BaseString& base) -{ - base.rc = INT_MAX / 2; - base.m_identifierTableAndFlags.setFlag(UString::Rep::StaticFlag); - base.checkConsistency(); -} - void initializeUString() { - UString::Rep::nullBaseString = new UString::BaseString(0, 0); - initializeStaticBaseString(*UString::Rep::nullBaseString); - - UString::Rep::emptyBaseString = new UString::BaseString(&sharedEmptyChar, 0); - initializeStaticBaseString(*UString::Rep::emptyBaseString); - + UStringImpl::s_null = new UStringImpl(0, 0, UStringImpl::ConstructStaticString); + UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString); UString::nullUString = new UString; } -static char* statBuffer = 0; // Only used for debugging via UString::ascii(). - -PassRefPtr<UString::Rep> UString::Rep::createCopying(const UChar* d, int l) -{ - UChar* copyD = static_cast<UChar*>(fastMalloc(l * sizeof(UChar))); - copyChars(copyD, d, l); - return create(copyD, l); -} - -PassRefPtr<UString::Rep> UString::Rep::createFromUTF8(const char* string) +static PassRefPtr<UString::Rep> createRep(const char* c) { - if (!string) - return &UString::Rep::null(); - - size_t length = strlen(string); - Vector<UChar, 1024> buffer(length); - UChar* p = buffer.data(); - if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length)) + if (!c) return &UString::Rep::null(); - return UString::Rep::createCopying(buffer.data(), p - buffer.data()); -} - -PassRefPtr<UString::Rep> UString::Rep::create(UChar* string, int length, PassRefPtr<UString::SharedUChar> sharedBuffer) -{ - PassRefPtr<UString::Rep> rep = create(string, length); - rep->baseString()->setSharedBuffer(sharedBuffer); - rep->checkConsistency(); - return rep; -} - -UString::SharedUChar* UString::Rep::sharedBuffer() -{ - UString::BaseString* base = baseString(); - if (len < minLengthToShare) - return 0; - - return base->sharedBuffer(); -} - -void UString::Rep::destroy() -{ - checkConsistency(); - - // Static null and empty strings can never be destroyed, but we cannot rely on - // reference counting, because ref/deref are not thread-safe. - if (!isStatic()) { - if (identifierTable()) - Identifier::remove(this); - - UString::BaseString* base = baseString(); - if (base == this) { - if (m_sharedBuffer) - m_sharedBuffer->deref(); - else - fastFree(base->buf); - } else - base->deref(); - - delete this; - } -} - -// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's -// or anything like that. -const unsigned PHI = 0x9e3779b9U; - -// Paul Hsieh's SuperFastHash -// http://www.azillionmonkeys.com/qed/hash.html -unsigned UString::Rep::computeHash(const UChar* s, int len) -{ - unsigned l = len; - uint32_t hash = PHI; - uint32_t tmp; - - int rem = l & 1; - l >>= 1; - - // Main loop - for (; l > 0; l--) { - hash += s[0]; - tmp = (s[1] << 11) ^ hash; - hash = (hash << 16) ^ tmp; - s += 2; - hash += hash >> 11; - } - - // Handle end case - if (rem) { - hash += s[0]; - hash ^= hash << 11; - hash += hash >> 17; - } - - // Force "avalanching" of final 127 bits - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 2; - hash += hash >> 15; - hash ^= hash << 10; - - // this avoids ever returning a hash code of 0, since that is used to - // signal "hash not computed yet", using a value that is likely to be - // effectively the same as 0 when the low bits are masked - if (hash == 0) - hash = 0x80000000; - - return hash; -} - -// Paul Hsieh's SuperFastHash -// http://www.azillionmonkeys.com/qed/hash.html -unsigned UString::Rep::computeHash(const char* s, int l) -{ - // This hash is designed to work on 16-bit chunks at a time. But since the normal case - // (above) is to hash UTF-16 characters, we just treat the 8-bit chars as if they - // were 16-bit chunks, which should give matching results - - uint32_t hash = PHI; - uint32_t tmp; - - size_t rem = l & 1; - l >>= 1; - - // Main loop - for (; l > 0; l--) { - hash += static_cast<unsigned char>(s[0]); - tmp = (static_cast<unsigned char>(s[1]) << 11) ^ hash; - hash = (hash << 16) ^ tmp; - s += 2; - hash += hash >> 11; - } - - // Handle end case - if (rem) { - hash += static_cast<unsigned char>(s[0]); - hash ^= hash << 11; - hash += hash >> 17; - } - - // Force "avalanching" of final 127 bits - hash ^= hash << 3; - hash += hash >> 5; - hash ^= hash << 2; - hash += hash >> 15; - hash ^= hash << 10; - - // this avoids ever returning a hash code of 0, since that is used to - // signal "hash not computed yet", using a value that is likely to be - // effectively the same as 0 when the low bits are masked - if (hash == 0) - hash = 0x80000000; - - return hash; -} - -#ifndef NDEBUG -void UString::Rep::checkConsistency() const -{ - const UString::BaseString* base = baseString(); - - // There is no recursion for base strings. - ASSERT(base == base->baseString()); - - if (isStatic()) { - // There are only two static strings: null and empty. - ASSERT(!len); - - // Static strings cannot get in identifier tables, because they are globally shared. - ASSERT(!identifierTable()); - } - - // The string fits in buffer. - ASSERT(base->usedPreCapacity <= base->preCapacity); - ASSERT(base->usedCapacity <= base->capacity); - ASSERT(-offset <= base->usedPreCapacity); - ASSERT(offset + len <= base->usedCapacity); -} -#endif - -UString::SharedUChar* UString::BaseString::sharedBuffer() -{ - if (!m_sharedBuffer) - setSharedBuffer(SharedUChar::create(new OwnFastMallocPtr<UChar>(buf))); - return m_sharedBuffer; -} - -void UString::BaseString::setSharedBuffer(PassRefPtr<UString::SharedUChar> sharedBuffer) -{ - // The manual steps below are because m_sharedBuffer can't be a RefPtr. m_sharedBuffer - // is in a union with another variable to avoid making BaseString any larger. - if (m_sharedBuffer) - m_sharedBuffer->deref(); - m_sharedBuffer = sharedBuffer.releaseRef(); -} - -bool UString::BaseString::slowIsBufferReadOnly() -{ - // The buffer may not be modified as soon as the underlying data has been shared with another class. - if (m_sharedBuffer->isShared()) - return true; - - // At this point, we know it that the underlying buffer isn't shared outside of this base class, - // so get rid of m_sharedBuffer. - OwnPtr<OwnFastMallocPtr<UChar> > mallocPtr(m_sharedBuffer->release()); - UChar* unsharedBuf = const_cast<UChar*>(mallocPtr->release()); - setSharedBuffer(0); - preCapacity += (buf - unsharedBuf); - buf = unsharedBuf; - return false; -} - -// Put these early so they can be inlined. -static inline size_t expandedSize(size_t capacitySize, size_t precapacitySize) -{ - // Combine capacitySize & precapacitySize to produce a single size to allocate, - // check that doing so does not result in overflow. - size_t size = capacitySize + precapacitySize; - if (size < capacitySize) - return overflowIndicator(); - - // Small Strings (up to 4 pages): - // Expand the allocation size to 112.5% of the amount requested. This is largely sicking - // to our previous policy, however 112.5% is cheaper to calculate. - if (size < 0x4000) { - size_t expandedSize = ((size + (size >> 3)) | 15) + 1; - // Given the limited range within which we calculate the expansion in this - // fashion the above calculation should never overflow. - ASSERT(expandedSize >= size); - ASSERT(expandedSize < maxUChars()); - return expandedSize; - } - - // Medium Strings (up to 128 pages): - // For pages covering multiple pages over-allocation is less of a concern - any unused - // space will not be paged in if it is not used, so this is purely a VM overhead. For - // these strings allocate 2x the requested size. - if (size < 0x80000) { - size_t expandedSize = ((size + size) | 0xfff) + 1; - // Given the limited range within which we calculate the expansion in this - // fashion the above calculation should never overflow. - ASSERT(expandedSize >= size); - ASSERT(expandedSize < maxUChars()); - return expandedSize; - } - - // Large Strings (to infinity and beyond!): - // Revert to our 112.5% policy - probably best to limit the amount of unused VM we allow - // any individual string be responsible for. - size_t expandedSize = ((size + (size >> 3)) | 0xfff) + 1; - - // Check for overflow - any result that is at least as large as requested (but - // still below the limit) is okay. - if ((expandedSize >= size) && (expandedSize < maxUChars())) - return expandedSize; - return overflowIndicator(); -} - -static inline bool expandCapacity(UString::Rep* rep, int requiredLength) -{ - rep->checkConsistency(); - ASSERT(!rep->baseString()->isBufferReadOnly()); - - UString::BaseString* base = rep->baseString(); - - if (requiredLength > base->capacity) { - size_t newCapacity = expandedSize(requiredLength, base->preCapacity); - UChar* oldBuf = base->buf; - if (!reallocChars(base->buf, newCapacity).getValue(base->buf)) { - base->buf = oldBuf; - return false; - } - base->capacity = newCapacity - base->preCapacity; - } - if (requiredLength > base->usedCapacity) - base->usedCapacity = requiredLength; - - rep->checkConsistency(); - return true; -} - -bool UString::Rep::reserveCapacity(int capacity) -{ - // If this is an empty string there is no point 'growing' it - just allocate a new one. - // If the BaseString is shared with another string that is using more capacity than this - // string is, then growing the buffer won't help. - // If the BaseString's buffer is readonly, then it isn't allowed to grow. - UString::BaseString* base = baseString(); - if (!base->buf || !base->capacity || (offset + len) != base->usedCapacity || base->isBufferReadOnly()) - return false; - - // If there is already sufficient capacity, no need to grow! - if (capacity <= base->capacity) - return true; - - checkConsistency(); - - size_t newCapacity = expandedSize(capacity, base->preCapacity); - UChar* oldBuf = base->buf; - if (!reallocChars(base->buf, newCapacity).getValue(base->buf)) { - base->buf = oldBuf; - return false; - } - base->capacity = newCapacity - base->preCapacity; - - checkConsistency(); - return true; -} - -void UString::expandCapacity(int requiredLength) -{ - if (!JSC::expandCapacity(m_rep.get(), requiredLength)) - makeNull(); -} - -void UString::expandPreCapacity(int requiredPreCap) -{ - m_rep->checkConsistency(); - ASSERT(!m_rep->baseString()->isBufferReadOnly()); - - BaseString* base = m_rep->baseString(); - - if (requiredPreCap > base->preCapacity) { - size_t newCapacity = expandedSize(requiredPreCap, base->capacity); - int delta = newCapacity - base->capacity - base->preCapacity; - - UChar* newBuf; - if (!allocChars(newCapacity).getValue(newBuf)) { - makeNull(); - return; - } - copyChars(newBuf + delta, base->buf, base->capacity + base->preCapacity); - fastFree(base->buf); - base->buf = newBuf; + if (!c[0]) + return &UString::Rep::empty(); - base->preCapacity = newCapacity - base->capacity; - } - if (requiredPreCap > base->usedPreCapacity) - base->usedPreCapacity = requiredPreCap; + size_t length = strlen(c); + UChar* d; + PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d); + if (!result) + return &UString::Rep::null(); - m_rep->checkConsistency(); + for (size_t i = 0; i < length; i++) + d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend + return result; } -static PassRefPtr<UString::Rep> createRep(const char* c) +static inline PassRefPtr<UString::Rep> createRep(const char* c, int length) { if (!c) return &UString::Rep::null(); - if (!c[0]) + if (!length) return &UString::Rep::empty(); - size_t length = strlen(c); UChar* d; - if (!allocChars(length).getValue(d)) + PassRefPtr<UStringImpl> result = UStringImpl::tryCreateUninitialized(length, d); + if (!result) return &UString::Rep::null(); - else { - for (size_t i = 0; i < length; i++) - d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend - return UString::Rep::create(d, static_cast<int>(length)); - } + for (int i = 0; i < length; i++) + d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend + return result; } UString::UString(const char* c) @@ -583,335 +202,31 @@ UString::UString(const char* c) { } -UString::UString(const UChar* c, int length) +UString::UString(const char* c, int length) + : m_rep(createRep(c, length)) { - if (length == 0) - m_rep = &Rep::empty(); - else - m_rep = Rep::createCopying(c, length); } -UString::UString(UChar* c, int length, bool copy) +UString::UString(const UChar* c, int length) { - if (length == 0) + if (length == 0) m_rep = &Rep::empty(); - else if (copy) - m_rep = Rep::createCopying(c, length); else m_rep = Rep::create(c, length); } -UString::UString(const Vector<UChar>& buffer) -{ - if (!buffer.size()) - m_rep = &Rep::empty(); - else - m_rep = Rep::createCopying(buffer.data(), buffer.size()); -} - -static ALWAYS_INLINE int newCapacityWithOverflowCheck(const int currentCapacity, const int extendLength, const bool plusOne = false) -{ - ASSERT_WITH_MESSAGE(extendLength >= 0, "extendedLength = %d", extendLength); - - const int plusLength = plusOne ? 1 : 0; - if (currentCapacity > std::numeric_limits<int>::max() - extendLength - plusLength) - CRASH(); - - return currentCapacity + extendLength + plusLength; -} - -static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const UChar* tData, int tSize) -{ - RefPtr<UString::Rep> rep = r; - - rep->checkConsistency(); - - int thisSize = rep->size(); - int thisOffset = rep->offset; - int length = thisSize + tSize; - UString::BaseString* base = rep->baseString(); - - // possible cases: - if (tSize == 0) { - // t is empty - } else if (thisSize == 0) { - // this is empty - rep = UString::Rep::createCopying(tData, tSize); - } else if (rep == base && !base->isShared()) { - // this is direct and has refcount of 1 (so we can just alter it directly) - if (!expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length))) - rep = &UString::Rep::null(); - if (rep->data()) { - copyChars(rep->data() + thisSize, tData, tSize); - rep->len = length; - rep->_hash = 0; - } - } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) { - // this reaches the end of the buffer - extend it if it's long enough to append to - if (!expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length))) - rep = &UString::Rep::null(); - if (rep->data()) { - copyChars(rep->data() + thisSize, tData, tSize); - rep = UString::Rep::create(rep, 0, length); - } - } else { - // This is shared in some way that prevents us from modifying base, so we must make a whole new string. - size_t newCapacity = expandedSize(length, 0); - UChar* d; - if (!allocChars(newCapacity).getValue(d)) - rep = &UString::Rep::null(); - else { - copyChars(d, rep->data(), thisSize); - copyChars(d + thisSize, tData, tSize); - rep = UString::Rep::create(d, length); - rep->baseString()->capacity = newCapacity; - } - } - - rep->checkConsistency(); - - return rep.release(); -} - -static ALWAYS_INLINE PassRefPtr<UString::Rep> concatenate(PassRefPtr<UString::Rep> r, const char* t) -{ - RefPtr<UString::Rep> rep = r; - - rep->checkConsistency(); - - int thisSize = rep->size(); - int thisOffset = rep->offset; - int tSize = static_cast<int>(strlen(t)); - int length = thisSize + tSize; - UString::BaseString* base = rep->baseString(); - - // possible cases: - if (thisSize == 0) { - // this is empty - rep = createRep(t); - } else if (tSize == 0) { - // t is empty, we'll just return *this below. - } else if (rep == base && !base->isShared()) { - // this is direct and has refcount of 1 (so we can just alter it directly) - expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length)); - UChar* d = rep->data(); - if (d) { - for (int i = 0; i < tSize; ++i) - d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend - rep->len = length; - rep->_hash = 0; - } - } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) { - // this string reaches the end of the buffer - extend it - expandCapacity(rep.get(), newCapacityWithOverflowCheck(thisOffset, length)); - UChar* d = rep->data(); - if (d) { - for (int i = 0; i < tSize; ++i) - d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend - rep = UString::Rep::create(rep, 0, length); - } - } else { - // This is shared in some way that prevents us from modifying base, so we must make a whole new string. - size_t newCapacity = expandedSize(length, 0); - UChar* d; - if (!allocChars(newCapacity).getValue(d)) - rep = &UString::Rep::null(); - else { - copyChars(d, rep->data(), thisSize); - for (int i = 0; i < tSize; ++i) - d[thisSize + i] = static_cast<unsigned char>(t[i]); // use unsigned char to zero-extend instead of sign-extend - rep = UString::Rep::create(d, length); - rep->baseString()->capacity = newCapacity; - } - } - - rep->checkConsistency(); - - return rep.release(); -} - -PassRefPtr<UString::Rep> concatenate(UString::Rep* a, UString::Rep* b) -{ - a->checkConsistency(); - b->checkConsistency(); - - int aSize = a->size(); - int bSize = b->size(); - int aOffset = a->offset; - - // possible cases: - - UString::BaseString* aBase = a->baseString(); - if (bSize == 1 && aOffset + aSize == aBase->usedCapacity && aOffset + aSize < aBase->capacity && !aBase->isBufferReadOnly()) { - // b is a single character (common fast case) - ++aBase->usedCapacity; - a->data()[aSize] = b->data()[0]; - return UString::Rep::create(a, 0, aSize + 1); - } - - // a is empty - if (aSize == 0) - return b; - // b is empty - if (bSize == 0) - return a; - - int bOffset = b->offset; - int length = aSize + bSize; - - UString::BaseString* bBase = b->baseString(); - if (aOffset + aSize == aBase->usedCapacity && aSize >= minShareSize && 4 * aSize >= bSize - && (-bOffset != bBase->usedPreCapacity || aSize >= bSize) && !aBase->isBufferReadOnly()) { - // - a reaches the end of its buffer so it qualifies for shared append - // - also, it's at least a quarter the length of b - appending to a much shorter - // string does more harm than good - // - however, if b qualifies for prepend and is longer than a, we'd rather prepend - - UString x(a); - x.expandCapacity(newCapacityWithOverflowCheck(aOffset, length)); - if (!a->data() || !x.data()) - return 0; - copyChars(a->data() + aSize, b->data(), bSize); - PassRefPtr<UString::Rep> result = UString::Rep::create(a, 0, length); - - a->checkConsistency(); - b->checkConsistency(); - result->checkConsistency(); - - return result; - } - - if (-bOffset == bBase->usedPreCapacity && bSize >= minShareSize && 4 * bSize >= aSize && !bBase->isBufferReadOnly()) { - // - b reaches the beginning of its buffer so it qualifies for shared prepend - // - also, it's at least a quarter the length of a - prepending to a much shorter - // string does more harm than good - UString y(b); - y.expandPreCapacity(-bOffset + aSize); - if (!b->data() || !y.data()) - return 0; - copyChars(b->data() - aSize, a->data(), aSize); - PassRefPtr<UString::Rep> result = UString::Rep::create(b, -aSize, length); - - a->checkConsistency(); - b->checkConsistency(); - result->checkConsistency(); - - return result; - } - - // a does not qualify for append, and b does not qualify for prepend, gotta make a whole new string - size_t newCapacity = expandedSize(length, 0); - UChar* d; - if (!allocChars(newCapacity).getValue(d)) - return 0; - copyChars(d, a->data(), aSize); - copyChars(d + aSize, b->data(), bSize); - PassRefPtr<UString::Rep> result = UString::Rep::create(d, length); - result->baseString()->capacity = newCapacity; - - a->checkConsistency(); - b->checkConsistency(); - result->checkConsistency(); - - return result; -} - -PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, int i) -{ - UChar buf[1 + sizeof(i) * 3]; - UChar* end = buf + sizeof(buf) / sizeof(UChar); - UChar* p = end; - - if (i == 0) - *--p = '0'; - else if (i == INT_MIN) { - char minBuf[1 + sizeof(i) * 3]; - sprintf(minBuf, "%d", INT_MIN); - return concatenate(rep, minBuf); - } else { - bool negative = false; - if (i < 0) { - negative = true; - i = -i; - } - while (i) { - *--p = static_cast<unsigned short>((i % 10) + '0'); - i /= 10; - } - if (negative) - *--p = '-'; - } - - return concatenate(rep, p, static_cast<int>(end - p)); - -} - -PassRefPtr<UString::Rep> concatenate(UString::Rep* rep, double d) +UString UString::createFromUTF8(const char* string) { - // avoid ever printing -NaN, in JS conceptually there is only one NaN value - if (isnan(d)) - return concatenate(rep, "NaN"); - - if (d == 0.0) // stringify -0 as 0 - d = 0.0; + if (!string) + return null(); - char buf[80]; - int decimalPoint; - int sign; + size_t length = strlen(string); + Vector<UChar, 1024> buffer(length); + UChar* p = buffer.data(); + if (conversionOK != convertUTF8ToUTF16(&string, string + length, &p, p + length)) + return null(); - char result[80]; - WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL); - int length = static_cast<int>(strlen(result)); - - int i = 0; - if (sign) - buf[i++] = '-'; - - if (decimalPoint <= 0 && decimalPoint > -6) { - buf[i++] = '0'; - buf[i++] = '.'; - for (int j = decimalPoint; j < 0; j++) - buf[i++] = '0'; - strcpy(buf + i, result); - } else if (decimalPoint <= 21 && decimalPoint > 0) { - if (length <= decimalPoint) { - strcpy(buf + i, result); - i += length; - for (int j = 0; j < decimalPoint - length; j++) - buf[i++] = '0'; - buf[i] = '\0'; - } else { - strncpy(buf + i, result, decimalPoint); - i += decimalPoint; - buf[i++] = '.'; - strcpy(buf + i, result + decimalPoint); - } - } else if (result[0] < '0' || result[0] > '9') - strcpy(buf + i, result); - else { - buf[i++] = result[0]; - if (length > 1) { - buf[i++] = '.'; - strcpy(buf + i, result + 1); - i += length - 1; - } - - buf[i++] = 'e'; - buf[i++] = (decimalPoint >= 0) ? '+' : '-'; - // decimalPoint can't be more than 3 digits decimal given the - // nature of float representation - int exponential = decimalPoint - 1; - if (exponential < 0) - exponential = -exponential; - if (exponential >= 100) - buf[i++] = static_cast<char>('0' + exponential / 100); - if (exponential >= 10) - buf[i++] = static_cast<char>('0' + (exponential % 100) / 10); - buf[i++] = static_cast<char>('0' + exponential % 10); - buf[i++] = '\0'; - } - - return concatenate(rep, buf); + return UString(buffer.data(), p - buffer.data()); } UString UString::from(int i) @@ -953,7 +268,7 @@ UString UString::from(long long i) *--p = '0'; else if (i == std::numeric_limits<long long>::min()) { char minBuf[1 + sizeof(i) * 3]; -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) snprintf(minBuf, sizeof(minBuf) - 1, "%I64d", std::numeric_limits<long long>::min()); #else snprintf(minBuf, sizeof(minBuf) - 1, "%lld", std::numeric_limits<long long>::min()); @@ -1025,69 +340,10 @@ UString UString::from(long l) UString UString::from(double d) { - // avoid ever printing -NaN, in JS conceptually there is only one NaN value - if (isnan(d)) - return "NaN"; - if (!d) - return "0"; // -0 -> "0" - - char buf[80]; - int decimalPoint; - int sign; - - char result[80]; - WTF::dtoa(result, d, 0, &decimalPoint, &sign, NULL); - int length = static_cast<int>(strlen(result)); - - int i = 0; - if (sign) - buf[i++] = '-'; - - if (decimalPoint <= 0 && decimalPoint > -6) { - buf[i++] = '0'; - buf[i++] = '.'; - for (int j = decimalPoint; j < 0; j++) - buf[i++] = '0'; - strcpy(buf + i, result); - } else if (decimalPoint <= 21 && decimalPoint > 0) { - if (length <= decimalPoint) { - strcpy(buf + i, result); - i += length; - for (int j = 0; j < decimalPoint - length; j++) - buf[i++] = '0'; - buf[i] = '\0'; - } else { - strncpy(buf + i, result, decimalPoint); - i += decimalPoint; - buf[i++] = '.'; - strcpy(buf + i, result + decimalPoint); - } - } else if (result[0] < '0' || result[0] > '9') - strcpy(buf + i, result); - else { - buf[i++] = result[0]; - if (length > 1) { - buf[i++] = '.'; - strcpy(buf + i, result + 1); - i += length - 1; - } - - buf[i++] = 'e'; - buf[i++] = (decimalPoint >= 0) ? '+' : '-'; - // decimalPoint can't be more than 3 digits decimal given the - // nature of float representation - int exponential = decimalPoint - 1; - if (exponential < 0) - exponential = -exponential; - if (exponential >= 100) - buf[i++] = static_cast<char>('0' + exponential / 100); - if (exponential >= 10) - buf[i++] = static_cast<char>('0' + (exponential % 100) / 10); - buf[i++] = static_cast<char>('0' + exponential % 10); - buf[i++] = '\0'; - } - - return UString(buf); + DtoaBuffer buffer; + unsigned length; + doubleToStringInJavaScriptFormat(d, buffer, &length); + return UString(buffer, length); } UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, int rangeCount, const UString* separators, int separatorCount) const @@ -1113,23 +369,24 @@ UString UString::spliceSubstringsWithSeparators(const Range* substringRanges, in return ""; UChar* buffer; - if (!allocChars(totalLength).getValue(buffer)) + PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer); + if (!rep) return null(); int maxCount = max(rangeCount, separatorCount); int bufferPos = 0; for (int i = 0; i < maxCount; i++) { if (i < rangeCount) { - copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length); + UStringImpl::copyChars(buffer + bufferPos, data() + substringRanges[i].position, substringRanges[i].length); bufferPos += substringRanges[i].length; } if (i < separatorCount) { - copyChars(buffer + bufferPos, separators[i].data(), separators[i].size()); + UStringImpl::copyChars(buffer + bufferPos, separators[i].data(), separators[i].size()); bufferPos += separators[i].size(); } } - return UString::Rep::create(buffer, totalLength); + return rep; } UString UString::replaceRange(int rangeStart, int rangeLength, const UString& replacement) const @@ -1142,136 +399,16 @@ UString UString::replaceRange(int rangeStart, int rangeLength, const UString& re return ""; UChar* buffer; - if (!allocChars(totalLength).getValue(buffer)) + PassRefPtr<Rep> rep = Rep::tryCreateUninitialized(totalLength, buffer); + if (!rep) return null(); - copyChars(buffer, data(), rangeStart); - copyChars(buffer + rangeStart, replacement.data(), replacementLength); + UStringImpl::copyChars(buffer, data(), rangeStart); + UStringImpl::copyChars(buffer + rangeStart, replacement.data(), replacementLength); int rangeEnd = rangeStart + rangeLength; - copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd); - - return UString::Rep::create(buffer, totalLength); -} - - -UString& UString::append(const UString &t) -{ - m_rep->checkConsistency(); - t.rep()->checkConsistency(); - - int thisSize = size(); - int thisOffset = m_rep->offset; - int tSize = t.size(); - int length = thisSize + tSize; - BaseString* base = m_rep->baseString(); - - // possible cases: - if (thisSize == 0) { - // this is empty - *this = t; - } else if (tSize == 0) { - // t is empty - } else if (m_rep == base && !base->isShared()) { - // this is direct and has refcount of 1 (so we can just alter it directly) - expandCapacity(newCapacityWithOverflowCheck(thisOffset, length)); - if (data()) { - copyChars(m_rep->data() + thisSize, t.data(), tSize); - m_rep->len = length; - m_rep->_hash = 0; - } - } else if (thisOffset + thisSize == base->usedCapacity && thisSize >= minShareSize && !base->isBufferReadOnly()) { - // this reaches the end of the buffer - extend it if it's long enough to append to - expandCapacity(newCapacityWithOverflowCheck(thisOffset, length)); - if (data()) { - copyChars(m_rep->data() + thisSize, t.data(), tSize); - m_rep = Rep::create(m_rep, 0, length); - } - } else { - // This is shared in some way that prevents us from modifying base, so we must make a whole new string. - size_t newCapacity = expandedSize(length, 0); - UChar* d; - if (!allocChars(newCapacity).getValue(d)) - makeNull(); - else { - copyChars(d, data(), thisSize); - copyChars(d + thisSize, t.data(), tSize); - m_rep = Rep::create(d, length); - m_rep->baseString()->capacity = newCapacity; - } - } - - m_rep->checkConsistency(); - t.rep()->checkConsistency(); - - return *this; -} - -UString& UString::append(const UChar* tData, int tSize) -{ - m_rep = concatenate(m_rep.release(), tData, tSize); - return *this; -} - -UString& UString::append(const char* t) -{ - m_rep = concatenate(m_rep.release(), t); - return *this; -} - -UString& UString::append(UChar c) -{ - m_rep->checkConsistency(); + UStringImpl::copyChars(buffer + rangeStart + replacementLength, data() + rangeEnd, size() - rangeEnd); - int thisOffset = m_rep->offset; - int length = size(); - BaseString* base = m_rep->baseString(); - - // possible cases: - if (length == 0) { - // this is empty - must make a new m_rep because we don't want to pollute the shared empty one - size_t newCapacity = expandedSize(1, 0); - UChar* d; - if (!allocChars(newCapacity).getValue(d)) - makeNull(); - else { - d[0] = c; - m_rep = Rep::create(d, 1); - m_rep->baseString()->capacity = newCapacity; - } - } else if (m_rep == base && !base->isShared()) { - // this is direct and has refcount of 1 (so we can just alter it directly) - expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true)); - UChar* d = m_rep->data(); - if (d) { - d[length] = c; - m_rep->len = length + 1; - m_rep->_hash = 0; - } - } else if (thisOffset + length == base->usedCapacity && length >= minShareSize && !base->isBufferReadOnly()) { - // this reaches the end of the string - extend it and share - expandCapacity(newCapacityWithOverflowCheck(thisOffset, length, true)); - UChar* d = m_rep->data(); - if (d) { - d[length] = c; - m_rep = Rep::create(m_rep, 0, length + 1); - } - } else { - // This is shared in some way that prevents us from modifying base, so we must make a whole new string. - size_t newCapacity = expandedSize(length + 1, 0); - UChar* d; - if (!allocChars(newCapacity).getValue(d)) - makeNull(); - else { - copyChars(d, data(), length); - d[length] = c; - m_rep = Rep::create(d, length + 1); - m_rep->baseString()->capacity = newCapacity; - } - } - - m_rep->checkConsistency(); - - return *this; + return rep; } bool UString::getCString(CStringBuffer& buffer) const @@ -1299,13 +436,15 @@ bool UString::getCString(CStringBuffer& buffer) const char* UString::ascii() const { + static char* asciiBuffer = 0; + int length = size(); int neededSize = length + 1; - delete[] statBuffer; - statBuffer = new char[neededSize]; + delete[] asciiBuffer; + asciiBuffer = new char[neededSize]; const UChar* p = data(); - char* q = statBuffer; + char* q = asciiBuffer; const UChar* limit = p + length; while (p != limit) { *q = static_cast<char>(p[0]); @@ -1314,7 +453,7 @@ char* UString::ascii() const } *q = '\0'; - return statBuffer; + return asciiBuffer; } UString& UString::operator=(const char* c) @@ -1330,21 +469,13 @@ UString& UString::operator=(const char* c) } int l = static_cast<int>(strlen(c)); - UChar* d; - BaseString* base = m_rep->baseString(); - if (!base->isShared() && l <= base->capacity && m_rep == base && m_rep->offset == 0 && base->preCapacity == 0) { - d = base->buf; - m_rep->_hash = 0; - m_rep->len = l; - } else { - if (!allocChars(l).getValue(d)) { - makeNull(); - return *this; - } - m_rep = Rep::create(d, l); - } - for (int i = 0; i < l; i++) - d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend + UChar* d = 0; + m_rep = Rep::tryCreateUninitialized(l, d); + if (m_rep) { + for (int i = 0; i < l; i++) + d[i] = static_cast<unsigned char>(c[i]); // use unsigned char to zero-extend instead of sign-extend + } else + makeNull(); return *this; } @@ -1502,7 +633,7 @@ uint32_t UString::toStrictUInt32(bool* ok) const *ok = false; // Empty string is not OK. - int len = m_rep->len; + int len = m_rep->size(); if (len == 0) return 0; const UChar* p = m_rep->data(); @@ -1727,10 +858,15 @@ int compare(const UString& s1, const UString& s2) return (l1 > l2) ? 1 : -1; } +#if OS(SOLARIS) && COMPILER(SUNCC) +// Signature must match that of UStringImpl.h, otherwise the linker complains about undefined symbol. +bool equal(const UStringImpl* r, const UStringImpl* b) +#else bool equal(const UString::Rep* r, const UString::Rep* b) +#endif { - int length = r->len; - if (length != b->len) + int length = r->size(); + if (length != b->size()) return false; const UChar* d = r->data(); const UChar* s = b->data(); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.h index 58c3615..c1f32db 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UString.h @@ -24,6 +24,7 @@ #define UString_h #include "Collector.h" +#include "UStringImpl.h" #include <stdint.h> #include <string.h> #include <wtf/Assertions.h> @@ -35,13 +36,15 @@ #include <wtf/Vector.h> #include <wtf/unicode/Unicode.h> +#if PLATFORM(QT) +#include <QtCore/qstring.h> +#endif + namespace JSC { using WTF::PlacementNewAdoptType; using WTF::PlacementNewAdopt; - class IdentifierTable; - class CString { public: CString() @@ -71,192 +74,58 @@ namespace JSC { char* m_data; }; + bool operator==(const CString&, const CString&); + typedef Vector<char, 32> CStringBuffer; class UString { friend class JIT; public: +#if PLATFORM(QT) + operator QT_PREPEND_NAMESPACE(QString)() const + { + return QT_PREPEND_NAMESPACE(QString)(reinterpret_cast<const QT_PREPEND_NAMESPACE(QChar)*>(this->data()), this->size()); + } - typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; - struct BaseString; - struct Rep : Noncopyable { - friend class JIT; - - static PassRefPtr<Rep> create(UChar* buffer, int length) - { - return adoptRef(new BaseString(buffer, length)); - } - - static PassRefPtr<Rep> createEmptyBuffer(size_t size) - { - // Guard against integer overflow - if (size < (std::numeric_limits<size_t>::max() / sizeof(UChar))) { - void* buf = 0; - if (tryFastMalloc(size * sizeof(UChar)).getValue(buf)) - return adoptRef(new BaseString(static_cast<UChar*>(buf), 0, size)); - } - return adoptRef(new BaseString(0, 0, 0)); - } - - static PassRefPtr<Rep> createCopying(const UChar*, int); - static PassRefPtr<Rep> create(PassRefPtr<Rep> base, int offset, int length); - - // Constructs a string from a UTF-8 string, using strict conversion (see comments in UTF8.h). - // Returns UString::Rep::null for null input or conversion failure. - static PassRefPtr<Rep> createFromUTF8(const char*); - - // Uses SharedUChar to have joint ownership over the UChar*. - static PassRefPtr<Rep> create(UChar*, int, PassRefPtr<SharedUChar>); - - SharedUChar* sharedBuffer(); - void destroy(); - - bool baseIsSelf() const { return m_identifierTableAndFlags.isFlagSet(BaseStringFlag); } - UChar* data() const; - int size() const { return len; } - - unsigned hash() const { if (_hash == 0) _hash = computeHash(data(), len); return _hash; } - unsigned computedHash() const { ASSERT(_hash); return _hash; } // fast path for Identifiers - - static unsigned computeHash(const UChar*, int length); - static unsigned computeHash(const char*, int length); - static unsigned computeHash(const char* s) { return computeHash(s, strlen(s)); } - - IdentifierTable* identifierTable() const { return m_identifierTableAndFlags.get(); } - void setIdentifierTable(IdentifierTable* table) { ASSERT(!isStatic()); m_identifierTableAndFlags.set(table); } - - bool isStatic() const { return m_identifierTableAndFlags.isFlagSet(StaticFlag); } - void setStatic(bool); - void setBaseString(PassRefPtr<BaseString>); - BaseString* baseString(); - const BaseString* baseString() const; - - Rep* ref() { ++rc; return this; } - ALWAYS_INLINE void deref() { if (--rc == 0) destroy(); } - - void checkConsistency() const; - enum UStringFlags { - StaticFlag, - BaseStringFlag - }; - - // unshared data - int offset; - int len; - int rc; // For null and empty static strings, this field does not reflect a correct count, because ref/deref are not thread-safe. A special case in destroy() guarantees that these do not get deleted. - mutable unsigned _hash; - PtrAndFlags<IdentifierTable, UStringFlags> m_identifierTableAndFlags; - - static BaseString& null() { return *nullBaseString; } - static BaseString& empty() { return *emptyBaseString; } - - bool reserveCapacity(int capacity); - - protected: - // Constructor for use by BaseString subclass; they use the union with m_baseString for another purpose. - Rep(int length) - : offset(0) - , len(length) - , rc(1) - , _hash(0) - , m_baseString(0) - { - } - - Rep(PassRefPtr<BaseString> base, int offsetInBase, int length) - : offset(offsetInBase) - , len(length) - , rc(1) - , _hash(0) - , m_baseString(base.releaseRef()) - { - checkConsistency(); - } - - union { - // If !baseIsSelf() - BaseString* m_baseString; - // If baseIsSelf() - SharedUChar* m_sharedBuffer; - }; - - private: - // For SmallStringStorage which allocates an array and does initialization manually. - Rep() { } - - friend class SmallStringsStorage; - friend void initializeUString(); - JS_EXPORTDATA static BaseString* nullBaseString; - JS_EXPORTDATA static BaseString* emptyBaseString; - }; - - - struct BaseString : public Rep { - bool isShared() { return rc != 1 || isBufferReadOnly(); } - void setSharedBuffer(PassRefPtr<SharedUChar>); - - bool isBufferReadOnly() - { - if (!m_sharedBuffer) - return false; - return slowIsBufferReadOnly(); - } - - // potentially shared data. - UChar* buf; - int preCapacity; - int usedPreCapacity; - int capacity; - int usedCapacity; - - size_t reportedCost; - - private: - BaseString(UChar* buffer, int length, int additionalCapacity = 0) - : Rep(length) - , buf(buffer) - , preCapacity(0) - , usedPreCapacity(0) - , capacity(length + additionalCapacity) - , usedCapacity(length) - , reportedCost(0) - { - m_identifierTableAndFlags.setFlag(BaseStringFlag); - checkConsistency(); - } - - SharedUChar* sharedBuffer(); - bool slowIsBufferReadOnly(); - - friend struct Rep; - friend class SmallStringsStorage; - friend void initializeUString(); - }; - + UString(const QT_PREPEND_NAMESPACE(QString)& str) + { + *this = JSC::UString(reinterpret_cast<const UChar*>(str.constData()), str.length()); + } +#endif + typedef UStringImpl Rep; + public: + // UString constructors passed char*s assume ISO Latin-1 encoding; for UTF8 use 'createFromUTF8', below. UString(); - UString(const char*); + UString(const char*); // Constructor for null-terminated string. + UString(const char*, int length); UString(const UChar*, int length); - UString(UChar*, int length, bool copy); + UString(const Vector<UChar>& buffer); UString(const UString& s) : m_rep(s.m_rep) { } - UString(const Vector<UChar>& buffer); + // Special constructor for cases where we overwrite an object in place. + UString(PlacementNewAdoptType) + : m_rep(PlacementNewAdopt) + { + } ~UString() { } - // Special constructor for cases where we overwrite an object in place. - UString(PlacementNewAdoptType) - : m_rep(PlacementNewAdopt) + template<size_t inlineCapacity> + static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) { + return Rep::adopt(vector); } + static UString createFromUTF8(const char*); + static UString from(int); static UString from(long long); static UString from(unsigned int); @@ -283,12 +152,6 @@ namespace JSC { UString replaceRange(int rangeStart, int RangeEnd, const UString& replacement) const; - UString& append(const UString&); - UString& append(const char*); - UString& append(UChar); - UString& append(char c) { return append(static_cast<UChar>(static_cast<unsigned char>(c))); } - UString& append(const UChar*, int size); - bool getCString(CStringBuffer&) const; // NOTE: This method should only be used for *debugging* purposes as it @@ -307,13 +170,10 @@ namespace JSC { UString& operator=(const char*c); - UString& operator+=(const UString& s) { return append(s); } - UString& operator+=(const char* s) { return append(s); } - const UChar* data() const { return m_rep->data(); } - bool isNull() const { return (m_rep == &Rep::null()); } - bool isEmpty() const { return (!m_rep->len); } + bool isNull() const { return m_rep == &Rep::null(); } + bool isEmpty() const { return !m_rep->size(); } bool is8Bit() const; @@ -349,36 +209,9 @@ namespace JSC { ASSERT(m_rep); } - size_t cost() const; - - // Attempt to grow this string such that it can grow to a total length of 'capacity' - // without reallocation. This may fail a number of reasons - if the BasicString is - // shared and another string is using part of the capacity beyond our end point, if - // the realloc fails, or if this string is empty and has no storage. - // - // This method returns a boolean indicating success. - bool reserveCapacity(int capacity) - { - return m_rep->reserveCapacity(capacity); - } - -#if PLATFORM(QT) - operator QT_PREPEND_NAMESPACE(QString)() const - { - QT_USE_NAMESPACE; - return QString(reinterpret_cast<const QChar*>(this->data()), this->size()); - } - - UString(const QT_PREPEND_NAMESPACE(QString)& str) - { - *this = JSC::UString(reinterpret_cast<const UChar*>(str.constData()), str.length()); - } -#endif - + size_t cost() const { return m_rep->cost(); } private: - void expandCapacity(int requiredLength); - void expandPreCapacity(int requiredPreCap); void makeNull(); RefPtr<Rep> m_rep; @@ -386,13 +219,9 @@ namespace JSC { friend void initializeUString(); friend bool operator==(const UString&, const UString&); - friend PassRefPtr<Rep> concatenate(Rep*, Rep*); // returns 0 if out of memory }; - PassRefPtr<UString::Rep> concatenate(UString::Rep*, UString::Rep*); - PassRefPtr<UString::Rep> concatenate(UString::Rep*, int); - PassRefPtr<UString::Rep> concatenate(UString::Rep*, double); - inline bool operator==(const UString& s1, const UString& s2) + ALWAYS_INLINE bool operator==(const UString& s1, const UString& s2) { int size = s1.size(); switch (size) { @@ -438,72 +267,8 @@ namespace JSC { return !JSC::operator==(s1, s2); } - bool operator==(const CString&, const CString&); - - inline UString operator+(const UString& s1, const UString& s2) - { - RefPtr<UString::Rep> result = concatenate(s1.rep(), s2.rep()); - return UString(result ? result.release() : UString::nullRep()); - } - int compare(const UString&, const UString&); - bool equal(const UString::Rep*, const UString::Rep*); - - inline PassRefPtr<UString::Rep> UString::Rep::create(PassRefPtr<UString::Rep> rep, int offset, int length) - { - ASSERT(rep); - rep->checkConsistency(); - - int repOffset = rep->offset; - - PassRefPtr<BaseString> base = rep->baseString(); - - ASSERT(-(offset + repOffset) <= base->usedPreCapacity); - ASSERT(offset + repOffset + length <= base->usedCapacity); - - // Steal the single reference this Rep was created with. - return adoptRef(new Rep(base, repOffset + offset, length)); - } - - inline UChar* UString::Rep::data() const - { - const BaseString* base = baseString(); - return base->buf + base->preCapacity + offset; - } - - inline void UString::Rep::setStatic(bool v) - { - ASSERT(!identifierTable()); - if (v) - m_identifierTableAndFlags.setFlag(StaticFlag); - else - m_identifierTableAndFlags.clearFlag(StaticFlag); - } - - inline void UString::Rep::setBaseString(PassRefPtr<BaseString> base) - { - ASSERT(base != this); - ASSERT(!baseIsSelf()); - m_baseString = base.releaseRef(); - } - - inline UString::BaseString* UString::Rep::baseString() - { - return !baseIsSelf() ? m_baseString : reinterpret_cast<BaseString*>(this) ; - } - - inline const UString::BaseString* UString::Rep::baseString() const - { - return const_cast<Rep*>(this)->baseString(); - } - -#ifdef NDEBUG - inline void UString::Rep::checkConsistency() const - { - } -#endif - inline UString::UString() : m_rep(&Rep::null()) { @@ -524,45 +289,288 @@ namespace JSC { // huge buffer. // FIXME: this should be size_t but that would cause warnings until we // fix UString sizes to be size_t instead of int - static const int minShareSize = Heap::minExtraCostSize / sizeof(UChar); + static const int minShareSize = Heap::minExtraCost / sizeof(UChar); - inline size_t UString::cost() const - { - BaseString* base = m_rep->baseString(); - size_t capacity = (base->capacity + base->preCapacity) * sizeof(UChar); - size_t reportedCost = base->reportedCost; - ASSERT(capacity >= reportedCost); + struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > { + static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->existingHash(); } + static unsigned hash(JSC::UString::Rep* key) { return key->existingHash(); } + }; - size_t capacityDelta = capacity - reportedCost; + void initializeUString(); + + template<typename StringType> + class StringTypeAdapter { + }; - if (capacityDelta < static_cast<size_t>(minShareSize)) - return 0; + template<> + class StringTypeAdapter<char*> { + public: + StringTypeAdapter<char*>(char* buffer) + : m_buffer((unsigned char*)buffer) + , m_length(strlen(buffer)) + { + } - base->reportedCost = capacity; + unsigned length() { return m_length; } - return capacityDelta; - } + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_buffer[i]; + } -#if PLATFORM(QT) + private: + const unsigned char* m_buffer; + unsigned m_length; + }; - inline UString operator+(const char* s1, const UString& s2) + template<> + class StringTypeAdapter<const char*> { + public: + StringTypeAdapter<const char*>(const char* buffer) + : m_buffer((unsigned char*)buffer) + , m_length(strlen(buffer)) { - return operator+(UString(s1), s2); } - inline UString operator+(const UString& s1, const char* s2) + unsigned length() { return m_length; } + + void writeTo(UChar* destination) { - return operator+(s1, UString(s2)); + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_buffer[i]; } -#endif + private: + const unsigned char* m_buffer; + unsigned m_length; + }; - struct IdentifierRepHash : PtrHash<RefPtr<JSC::UString::Rep> > { - static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->computedHash(); } - static unsigned hash(JSC::UString::Rep* key) { return key->computedHash(); } + template<> + class StringTypeAdapter<UString> { + public: + StringTypeAdapter<UString>(UString& string) + : m_data(string.data()) + , m_length(string.size()) + { + } + + unsigned length() { return m_length; } + + void writeTo(UChar* destination) + { + for (unsigned i = 0; i < m_length; ++i) + destination[i] = m_data[i]; + } + + private: + const UChar* m_data; + unsigned m_length; }; - void initializeUString(); + template<typename StringType1, typename StringType2> + UString makeString(StringType1 string1, StringType2 string2) + { + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + + UChar* buffer; + unsigned length = adapter1.length() + adapter2.length(); + PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return UString(); + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + + return resultImpl; + } + + template<typename StringType1, typename StringType2, typename StringType3> + UString makeString(StringType1 string1, StringType2 string2, StringType3 string3) + { + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + + UChar* buffer; + unsigned length = adapter1.length() + adapter2.length() + adapter3.length(); + PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return UString(); + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + + return resultImpl; + } + + template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> + UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) + { + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + + UChar* buffer; + unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length(); + PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return UString(); + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + + return resultImpl; + } + + template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> + UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) + { + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + StringTypeAdapter<StringType5> adapter5(string5); + + UChar* buffer; + unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length(); + PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return UString(); + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + + return resultImpl; + } + + template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> + UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) + { + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + StringTypeAdapter<StringType5> adapter5(string5); + StringTypeAdapter<StringType6> adapter6(string6); + + UChar* buffer; + unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length(); + PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return UString(); + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + + return resultImpl; + } + + template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> + UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) + { + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + StringTypeAdapter<StringType5> adapter5(string5); + StringTypeAdapter<StringType6> adapter6(string6); + StringTypeAdapter<StringType7> adapter7(string7); + + UChar* buffer; + unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length(); + PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return UString(); + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + + return resultImpl; + } + + template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> + UString makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) + { + StringTypeAdapter<StringType1> adapter1(string1); + StringTypeAdapter<StringType2> adapter2(string2); + StringTypeAdapter<StringType3> adapter3(string3); + StringTypeAdapter<StringType4> adapter4(string4); + StringTypeAdapter<StringType5> adapter5(string5); + StringTypeAdapter<StringType6> adapter6(string6); + StringTypeAdapter<StringType7> adapter7(string7); + StringTypeAdapter<StringType8> adapter8(string8); + + UChar* buffer; + unsigned length = adapter1.length() + adapter2.length() + adapter3.length() + adapter4.length() + adapter5.length() + adapter6.length() + adapter7.length() + adapter8.length(); + PassRefPtr<UStringImpl> resultImpl = UStringImpl::tryCreateUninitialized(length, buffer); + if (!resultImpl) + return UString(); + + UChar* result = buffer; + adapter1.writeTo(result); + result += adapter1.length(); + adapter2.writeTo(result); + result += adapter2.length(); + adapter3.writeTo(result); + result += adapter3.length(); + adapter4.writeTo(result); + result += adapter4.length(); + adapter5.writeTo(result); + result += adapter5.length(); + adapter6.writeTo(result); + result += adapter6.length(); + adapter7.writeTo(result); + result += adapter7.length(); + adapter8.writeTo(result); + + return resultImpl; + } + } // namespace JSC namespace WTF { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp new file mode 100644 index 0000000..4b0d1c9 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.cpp @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2009 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. + */ + +#include "config.h" +#include "UStringImpl.h" + +#include "Identifier.h" +#include "UString.h" +#include <wtf/unicode/UTF8.h> + +using namespace WTF::Unicode; +using namespace std; + +namespace JSC { + +SharedUChar* UStringImpl::baseSharedBuffer() +{ + ASSERT((bufferOwnership() == BufferShared) + || ((bufferOwnership() == BufferOwned) && !m_dataBuffer.asPtr<void*>())); + + if (bufferOwnership() != BufferShared) + m_dataBuffer = UntypedPtrAndBitfield(SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(), BufferShared); + + return m_dataBuffer.asPtr<SharedUChar*>(); +} + +SharedUChar* UStringImpl::sharedBuffer() +{ + if (m_length < s_minLengthToShare) + return 0; + ASSERT(!isStatic()); + + UStringImpl* owner = bufferOwnerString(); + if (owner->bufferOwnership() == BufferInternal) + return 0; + + return owner->baseSharedBuffer(); +} + +UStringImpl::~UStringImpl() +{ + ASSERT(!isStatic()); + checkConsistency(); + + if (isIdentifier()) + Identifier::remove(this); + + if (bufferOwnership() != BufferInternal) { + if (bufferOwnership() == BufferOwned) + fastFree(m_data); + else if (bufferOwnership() == BufferSubstring) + m_dataBuffer.asPtr<UStringImpl*>()->deref(); + else { + ASSERT(bufferOwnership() == BufferShared); + m_dataBuffer.asPtr<SharedUChar*>()->deref(); + } + } +} + +} diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h new file mode 100644 index 0000000..4e1ddc7 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/UStringImpl.h @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2009 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 UStringImpl_h +#define UStringImpl_h + +#include <limits> +#include <wtf/CrossThreadRefCounted.h> +#include <wtf/OwnFastMallocPtr.h> +#include <wtf/PossiblyNull.h> +#include <wtf/StringHashFunctions.h> +#include <wtf/Vector.h> +#include <wtf/unicode/Unicode.h> + +namespace JSC { + +class IdentifierTable; + +typedef CrossThreadRefCounted<OwnFastMallocPtr<UChar> > SharedUChar; + +class UntypedPtrAndBitfield { +public: + UntypedPtrAndBitfield() {} + + UntypedPtrAndBitfield(void* ptrValue, uintptr_t bitValue) + : m_value(reinterpret_cast<uintptr_t>(ptrValue) | bitValue) +#ifndef NDEBUG + , m_leaksPtr(ptrValue) +#endif + { + ASSERT(ptrValue == asPtr<void*>()); + ASSERT((*this & ~s_alignmentMask) == bitValue); + } + + template<typename T> + T asPtr() const { return reinterpret_cast<T>(m_value & s_alignmentMask); } + + UntypedPtrAndBitfield& operator&=(uintptr_t bits) + { + m_value &= bits | s_alignmentMask; + return *this; + } + + UntypedPtrAndBitfield& operator|=(uintptr_t bits) + { + m_value |= bits & ~s_alignmentMask; + return *this; + } + + uintptr_t operator&(uintptr_t mask) const + { + return m_value & mask & ~s_alignmentMask; + } + +private: + static const uintptr_t s_alignmentMask = ~static_cast<uintptr_t>(0x7); + uintptr_t m_value; +#ifndef NDEBUG + void* m_leaksPtr; // Only used to allow tools like leaks on OSX to detect that the memory is referenced. +#endif +}; + +class UStringImpl : Noncopyable { +public: + template<size_t inlineCapacity> + static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) + { + if (unsigned length = vector.size()) + return adoptRef(new UStringImpl(vector.releaseBuffer(), length, BufferOwned)); + return &empty(); + } + + static PassRefPtr<UStringImpl> create(const UChar* buffer, int length) + { + UChar* newBuffer; + if (PassRefPtr<UStringImpl> impl = tryCreateUninitialized(length, newBuffer)) { + copyChars(newBuffer, buffer, length); + return impl; + } + return &null(); + } + + static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, int offset, int length) + { + ASSERT(rep); + rep->checkConsistency(); + return adoptRef(new UStringImpl(rep->m_data + offset, length, rep->bufferOwnerString())); + } + + static PassRefPtr<UStringImpl> create(PassRefPtr<SharedUChar> sharedBuffer, UChar* buffer, int length) + { + return adoptRef(new UStringImpl(buffer, length, sharedBuffer)); + } + + static PassRefPtr<UStringImpl> createUninitialized(unsigned length, UChar*& output) + { + if (!length) { + output = 0; + return &empty(); + } + + if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar))) + CRASH(); + UStringImpl* resultImpl = static_cast<UStringImpl*>(fastMalloc(sizeof(UChar) * length + sizeof(UStringImpl))); + output = reinterpret_cast<UChar*>(resultImpl + 1); + return adoptRef(new(resultImpl) UStringImpl(output, length, BufferInternal)); + } + + static PassRefPtr<UStringImpl> tryCreateUninitialized(unsigned length, UChar*& output) + { + if (!length) { + output = 0; + return &empty(); + } + + if (length > ((std::numeric_limits<size_t>::max() - sizeof(UStringImpl)) / sizeof(UChar))) + return 0; + UStringImpl* resultImpl; + if (!tryFastMalloc(sizeof(UChar) * length + sizeof(UStringImpl)).getValue(resultImpl)) + return 0; + output = reinterpret_cast<UChar*>(resultImpl + 1); + return adoptRef(new(resultImpl) UStringImpl(output, length, BufferInternal)); + } + + SharedUChar* sharedBuffer(); + UChar* data() const { return m_data; } + int size() const { return m_length; } + size_t cost() + { + // For substrings, return the cost of the base string. + if (bufferOwnership() == BufferSubstring) + return m_dataBuffer.asPtr<UStringImpl*>()->cost(); + + if (m_dataBuffer & s_reportedCostBit) + return 0; + m_dataBuffer |= s_reportedCostBit; + return m_length; + } + unsigned hash() const { if (!m_hash) m_hash = computeHash(data(), m_length); return m_hash; } + unsigned existingHash() const { ASSERT(m_hash); return m_hash; } // fast path for Identifiers + void setHash(unsigned hash) { ASSERT(hash == computeHash(data(), m_length)); m_hash = hash; } // fast path for Identifiers + bool isIdentifier() const { return m_isIdentifier; } + void setIsIdentifier(bool isIdentifier) { m_isIdentifier = isIdentifier; } + + UStringImpl* ref() { m_refCount += s_refCountIncrement; return this; } + ALWAYS_INLINE void deref() { if (!(m_refCount -= s_refCountIncrement)) delete this; } + + static void copyChars(UChar* destination, const UChar* source, unsigned numCharacters) + { + if (numCharacters <= s_copyCharsInlineCutOff) { + for (unsigned i = 0; i < numCharacters; ++i) + destination[i] = source[i]; + } else + memcpy(destination, source, numCharacters * sizeof(UChar)); + } + + static unsigned computeHash(const UChar* s, int length) { ASSERT(length >= 0); return WTF::stringHash(s, length); } + static unsigned computeHash(const char* s, int length) { ASSERT(length >= 0); return WTF::stringHash(s, length); } + static unsigned computeHash(const char* s) { return WTF::stringHash(s); } + + static UStringImpl& null() { return *s_null; } + static UStringImpl& empty() { return *s_empty; } + + ALWAYS_INLINE void checkConsistency() const + { + // There is no recursion of substrings. + ASSERT(bufferOwnerString()->bufferOwnership() != BufferSubstring); + // Static strings cannot be put in identifier tables, because they are globally shared. + ASSERT(!isStatic() || !isIdentifier()); + } + +private: + enum BufferOwnership { + BufferInternal, + BufferOwned, + BufferSubstring, + BufferShared, + }; + + // For SmallStringStorage, which allocates an array and uses an in-place new. + UStringImpl() { } + + // Used to construct normal strings with an internal or external buffer. + UStringImpl(UChar* data, int length, BufferOwnership ownership) + : m_data(data) + , m_length(length) + , m_refCount(s_refCountIncrement) + , m_hash(0) + , m_isIdentifier(false) + , m_dataBuffer(0, ownership) + { + ASSERT((ownership == BufferInternal) || (ownership == BufferOwned)); + checkConsistency(); + } + + // Used to construct static strings, which have an special refCount that can never hit zero. + // This means that the static string will never be destroyed, which is important because + // static strings will be shared across threads & ref-counted in a non-threadsafe manner. + enum StaticStringConstructType { ConstructStaticString }; + UStringImpl(UChar* data, int length, StaticStringConstructType) + : m_data(data) + , m_length(length) + , m_refCount(s_staticRefCountInitialValue) + , m_hash(0) + , m_isIdentifier(false) + , m_dataBuffer(0, BufferOwned) + { + checkConsistency(); + } + + // Used to create new strings that are a substring of an existing string. + UStringImpl(UChar* data, int length, PassRefPtr<UStringImpl> base) + : m_data(data) + , m_length(length) + , m_refCount(s_refCountIncrement) + , m_hash(0) + , m_isIdentifier(false) + , m_dataBuffer(base.releaseRef(), BufferSubstring) + { + // Do use static strings as a base for substrings; UntypedPtrAndBitfield assumes + // that all pointers will be at least 8-byte aligned, we cannot guarantee that of + // UStringImpls that are not heap allocated. + ASSERT(m_dataBuffer.asPtr<UStringImpl*>()->size()); + ASSERT(!m_dataBuffer.asPtr<UStringImpl*>()->isStatic()); + checkConsistency(); + } + + // Used to construct new strings sharing an existing shared buffer. + UStringImpl(UChar* data, int length, PassRefPtr<SharedUChar> sharedBuffer) + : m_data(data) + , m_length(length) + , m_refCount(s_refCountIncrement) + , m_hash(0) + , m_isIdentifier(false) + , m_dataBuffer(sharedBuffer.releaseRef(), BufferShared) + { + checkConsistency(); + } + +#if OS(SOLARIS) && COMPILER(SUNCC) +public: // Otherwise the compiler complains about operator new not being accessible. +#endif +#if COMPILER(WINSCW) || COMPILER(XLC) + void* operator new(size_t size) { return Noncopyable::operator new(size); } +#else + using Noncopyable::operator new; +#endif +#if OS(SOLARIS) && COMPILER(SUNCC) +private: +#endif + void* operator new(size_t, void* p) { return p; } + + ~UStringImpl(); + + // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. + static const int s_minLengthToShare = 10; + static const unsigned s_copyCharsInlineCutOff = 20; + static const uintptr_t s_bufferOwnershipMask = 3; + static const uintptr_t s_reportedCostBit = 4; + // We initialize and increment/decrement the refCount for all normal (non-static) strings by the value 2. + // We initialize static strings with an odd number (specifically, 1), such that the refCount cannot reach zero. + static const int s_refCountIncrement = 2; + static const int s_staticRefCountInitialValue = 1; + + UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() : this; } + const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_dataBuffer.asPtr<UStringImpl*>() : this; } + SharedUChar* baseSharedBuffer(); + unsigned bufferOwnership() const { return m_dataBuffer & s_bufferOwnershipMask; } + bool isStatic() const { return m_refCount & 1; } + + // unshared data + UChar* m_data; + int m_length; + unsigned m_refCount; + mutable unsigned m_hash : 31; + mutable unsigned m_isIdentifier : 1; + UntypedPtrAndBitfield m_dataBuffer; + + JS_EXPORTDATA static UStringImpl* s_null; + JS_EXPORTDATA static UStringImpl* s_empty; + + friend class JIT; + friend class SmallStringsStorage; + friend void initializeUString(); +}; + +bool equal(const UStringImpl*, const UStringImpl*); + +} + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/WeakGCMap.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/WeakGCMap.h new file mode 100644 index 0000000..39a91c5 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/WeakGCMap.h @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2009 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. AND ITS CONTRIBUTORS ``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 ITS 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 WeakGCMap_h +#define WeakGCMap_h + +#include "Collector.h" +#include <wtf/HashMap.h> + +namespace JSC { + +class JSCell; + +// A HashMap whose get() function returns emptyValue() for cells awaiting destruction. +template<typename KeyType, typename MappedType> +class WeakGCMap : public FastAllocBase { + /* + Invariants: + * A value enters the WeakGCMap marked. (Guaranteed by set().) + * A value that becomes unmarked leaves the WeakGCMap before being recycled. (Guaranteed by the value's destructor removing it from the WeakGCMap.) + * A value that becomes unmarked leaves the WeakGCMap before becoming marked again. (Guaranteed by all destructors running before the mark phase begins.) + * During the mark phase, all values in the WeakGCMap are valid. (Guaranteed by all destructors running before the mark phase begins.) + */ + +public: + typedef typename HashMap<KeyType, MappedType>::iterator iterator; + typedef typename HashMap<KeyType, MappedType>::const_iterator const_iterator; + + bool isEmpty() { return m_map.isEmpty(); } + + MappedType get(const KeyType& key) const; + pair<iterator, bool> set(const KeyType&, const MappedType&); + MappedType take(const KeyType& key); + + // These unchecked functions provide access to a value even if the value's + // mark bit is not set. This is used, among other things, to retrieve values + // during the GC mark phase, which begins by clearing all mark bits. + + MappedType uncheckedGet(const KeyType& key) const { return m_map.get(key); } + bool uncheckedRemove(const KeyType&, const MappedType&); + + iterator uncheckedBegin() { return m_map.begin(); } + iterator uncheckedEnd() { return m_map.end(); } + + const_iterator uncheckedBegin() const { return m_map.begin(); } + const_iterator uncheckedEnd() const { return m_map.end(); } + +private: + HashMap<KeyType, MappedType> m_map; +}; + +template<typename KeyType, typename MappedType> +inline MappedType WeakGCMap<KeyType, MappedType>::get(const KeyType& key) const +{ + MappedType result = m_map.get(key); + if (result == HashTraits<MappedType>::emptyValue()) + return result; + if (!Heap::isCellMarked(result)) + return HashTraits<MappedType>::emptyValue(); + return result; +} + +template<typename KeyType, typename MappedType> +MappedType WeakGCMap<KeyType, MappedType>::take(const KeyType& key) +{ + MappedType result = m_map.take(key); + if (result == HashTraits<MappedType>::emptyValue()) + return result; + if (!Heap::isCellMarked(result)) + return HashTraits<MappedType>::emptyValue(); + return result; +} + +template<typename KeyType, typename MappedType> +pair<typename HashMap<KeyType, MappedType>::iterator, bool> WeakGCMap<KeyType, MappedType>::set(const KeyType& key, const MappedType& value) +{ + Heap::markCell(value); // If value is newly allocated, it's not marked, so mark it now. + pair<iterator, bool> result = m_map.add(key, value); + if (!result.second) { // pre-existing entry + result.second = !Heap::isCellMarked(result.first->second); + result.first->second = value; + } + return result; +} + +template<typename KeyType, typename MappedType> +bool WeakGCMap<KeyType, MappedType>::uncheckedRemove(const KeyType& key, const MappedType& value) +{ + iterator it = m_map.find(key); + if (it == m_map.end()) + return false; + if (it->second != value) + return false; + m_map.remove(it); + return true; +} + +} // namespace JSC + +#endif // WeakGCMap_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/WeakGCPtr.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/WeakGCPtr.h new file mode 100644 index 0000000..8653721 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/WeakGCPtr.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2009 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. AND ITS CONTRIBUTORS ``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 ITS 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 WeakGCPtr_h +#define WeakGCPtr_h + +#include "Collector.h" +#include <wtf/Noncopyable.h> + +namespace JSC { + +// A smart pointer whose get() function returns 0 for cells awaiting destruction. +template <typename T> class WeakGCPtr : Noncopyable { +public: + WeakGCPtr() : m_ptr(0) { } + WeakGCPtr(T* ptr) { assign(ptr); } + + T* get() const + { + if (!m_ptr || !Heap::isCellMarked(m_ptr)) + return 0; + return m_ptr; + } + + void clear() { m_ptr = 0; } + + T& operator*() const { return *get(); } + T* operator->() const { return get(); } + + bool operator!() const { return !get(); } + + // This conversion operator allows implicit conversion to bool but not to other integer types. +#if COMPILER(WINSCW) + operator bool() const { return m_ptr; } +#else + typedef T* WeakGCPtr::*UnspecifiedBoolType; + operator UnspecifiedBoolType() const { return get() ? &WeakGCPtr::m_ptr : 0; } +#endif + + WeakGCPtr& operator=(T*); + +private: + void assign(T* ptr) + { + if (ptr) + Heap::markCell(ptr); + m_ptr = ptr; + } + + T* m_ptr; +}; + +template <typename T> inline WeakGCPtr<T>& WeakGCPtr<T>::operator=(T* optr) +{ + assign(optr); + return *this; +} + +template <typename T, typename U> inline bool operator==(const WeakGCPtr<T>& a, const WeakGCPtr<U>& b) +{ + return a.get() == b.get(); +} + +template <typename T, typename U> inline bool operator==(const WeakGCPtr<T>& a, U* b) +{ + return a.get() == b; +} + +template <typename T, typename U> inline bool operator==(T* a, const WeakGCPtr<U>& b) +{ + return a == b.get(); +} + +template <typename T, typename U> inline bool operator!=(const WeakGCPtr<T>& a, const WeakGCPtr<U>& b) +{ + return a.get() != b.get(); +} + +template <typename T, typename U> inline bool operator!=(const WeakGCPtr<T>& a, U* b) +{ + return a.get() != b; +} + +template <typename T, typename U> inline bool operator!=(T* a, const WeakGCPtr<U>& b) +{ + return a != b.get(); +} + +template <typename T, typename U> inline WeakGCPtr<T> static_pointer_cast(const WeakGCPtr<U>& p) +{ + return WeakGCPtr<T>(static_cast<T*>(p.get())); +} + +template <typename T, typename U> inline WeakGCPtr<T> const_pointer_cast(const WeakGCPtr<U>& p) +{ + return WeakGCPtr<T>(const_cast<T*>(p.get())); +} + +template <typename T> inline T* getPtr(const WeakGCPtr<T>& p) +{ + return p.get(); +} + +} // namespace JSC + +#endif // WeakGCPtr_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/WeakRandom.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/WeakRandom.h new file mode 100644 index 0000000..ff3995e --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/WeakRandom.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2009 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. + * + * + * Copyright (c) 2009 Ian C. Bullard + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef WeakRandom_h +#define WeakRandom_h + +#include <limits.h> +#include <wtf/StdLibExtras.h> + +namespace JSC { + +class WeakRandom { +public: + WeakRandom(unsigned seed) + : m_low(seed ^ 0x49616E42) + , m_high(seed) + { + } + + double get() + { + return advance() / (UINT_MAX + 1.0); + } + +private: + unsigned advance() + { + m_high = (m_high << 16) + (m_high >> 16); + m_high += m_low; + m_low += m_high; + return m_high; + } + + unsigned m_low; + unsigned m_high; +}; + +} // namespace JSC + +#endif // WeakRandom_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WREC.h b/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WREC.h index 483dce0..13324e7 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WREC.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WREC.h @@ -32,7 +32,7 @@ #include <wtf/unicode/Unicode.h> -#if COMPILER(GCC) && PLATFORM(X86) +#if COMPILER(GCC) && CPU(X86) #define WREC_CALL __attribute__ ((regparm (3))) #else #define WREC_CALL diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WRECGenerator.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WRECGenerator.cpp index e62add3..7105984 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WRECGenerator.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WRECGenerator.cpp @@ -40,7 +40,7 @@ namespace JSC { namespace WREC { void Generator::generateEnter() { -#if PLATFORM(X86) +#if CPU(X86) // On x86 edi & esi are callee preserved registers. push(X86Registers::edi); push(X86Registers::esi); @@ -71,7 +71,7 @@ void Generator::generateReturnSuccess() store32(index, Address(output, 4)); // match end // Restore callee save registers. -#if PLATFORM(X86) +#if CPU(X86) pop(X86Registers::esi); pop(X86Registers::edi); #endif @@ -110,7 +110,7 @@ void Generator::generateReturnFailure() pop(); move(Imm32(-1), returnRegister); -#if PLATFORM(X86) +#if CPU(X86) pop(X86Registers::esi); pop(X86Registers::edi); #endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WRECGenerator.h b/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WRECGenerator.h index 294c3d0..d707a6e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WRECGenerator.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wrec/WRECGenerator.h @@ -62,7 +62,7 @@ namespace JSC { { } -#if PLATFORM(X86) +#if CPU(X86) static const RegisterID input = X86Registers::eax; static const RegisterID index = X86Registers::edx; static const RegisterID length = X86Registers::ecx; @@ -73,7 +73,7 @@ namespace JSC { static const RegisterID returnRegister = X86Registers::eax; #endif -#if PLATFORM(X86_64) +#if CPU(X86_64) static const RegisterID input = X86Registers::edi; static const RegisterID index = X86Registers::esi; static const RegisterID length = X86Registers::edx; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wscript b/src/3rdparty/javascriptcore/JavaScriptCore/wscript index 9dd37c9..356950f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wscript +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wscript @@ -29,8 +29,8 @@ import commands from settings import * -jscore_excludes = ['jsc.cpp', 'ucptable.cpp', 'GOwnPtr.cpp'] -jscore_excludes.extend(get_excludes(jscore_dir, ['*CF.cpp'])) +jscore_excludes = ['jsc.cpp', 'ucptable.cpp'] +jscore_excludes.extend(get_excludes(jscore_dir, ['*CF.cpp', '*Symbian.cpp'])) sources = [] diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/AlwaysInline.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/AlwaysInline.h index 64fdd99..4e7224c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/AlwaysInline.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/AlwaysInline.h @@ -23,7 +23,7 @@ #ifndef ALWAYS_INLINE #if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW) #define ALWAYS_INLINE inline __attribute__((__always_inline__)) -#elif COMPILER(MSVC) && defined(NDEBUG) +#elif (COMPILER(MSVC) || COMPILER(RVCT)) && defined(NDEBUG) #define ALWAYS_INLINE __forceinline #else #define ALWAYS_INLINE inline diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Assertions.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Assertions.cpp index 5af1377..4615810 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Assertions.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Assertions.cpp @@ -35,7 +35,7 @@ #include <CoreFoundation/CFString.h> #endif -#if COMPILER(MSVC) && !PLATFORM(WINCE) +#if COMPILER(MSVC) && !OS(WINCE) #ifndef WINVER #define WINVER 0x0500 #endif @@ -46,7 +46,7 @@ #include <crtdbg.h> #endif -#if PLATFORM(WINCE) +#if OS(WINCE) #include <winbase.h> #endif @@ -85,7 +85,7 @@ static void vprintf_stderr_common(const char* format, va_list args) break; if (_vsnprintf(buffer, size, format, args) != -1) { -#if PLATFORM(WINCE) +#if OS(WINCE) // WinCE only supports wide chars wchar_t* wideBuffer = (wchar_t*)malloc(size * sizeof(wchar_t)); if (wideBuffer == NULL) @@ -108,7 +108,7 @@ static void vprintf_stderr_common(const char* format, va_list args) } while (size > 1024); } #endif -#if PLATFORM(SYMBIAN) +#if OS(SYMBIAN) vfprintf(stdout, format, args); #else vfprintf(stderr, format, args); @@ -126,7 +126,7 @@ static void printf_stderr_common(const char* format, ...) static void printCallSite(const char* file, int line, const char* function) { -#if PLATFORM(WIN) && !PLATFORM(WINCE) && defined _DEBUG +#if OS(WIN) && !OS(WINCE) && defined _DEBUG _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function); #else printf_stderr_common("(%s:%d %s)\n", file, line, function); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Assertions.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Assertions.h index f529a62..352a74b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Assertions.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Assertions.h @@ -50,7 +50,7 @@ #include <inttypes.h> #endif -#if PLATFORM(SYMBIAN) +#if OS(SYMBIAN) #include <e32def.h> #include <e32debug.h> #endif @@ -61,24 +61,50 @@ #define ASSERTIONS_DISABLED_DEFAULT 0 #endif +#if COMPILER(MSVC7) || COMPILER(WINSCW) +#define HAVE_VARIADIC_MACRO 0 +#else +#define HAVE_VARIADIC_MACRO 1 +#endif + #ifndef ASSERT_DISABLED #define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT #endif +#ifndef ASSERT_MSG_DISABLED +#if HAVE(VARIADIC_MACRO) +#define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT +#else +#define ASSERT_MSG_DISABLED 1 +#endif +#endif + #ifndef ASSERT_ARG_DISABLED #define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT #endif #ifndef FATAL_DISABLED +#if HAVE(VARIADIC_MACRO) #define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT +#else +#define FATAL_DISABLED 1 +#endif #endif #ifndef ERROR_DISABLED +#if HAVE(VARIADIC_MACRO) #define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT +#else +#define ERROR_DISABLED 1 +#endif #endif #ifndef LOG_DISABLED +#if HAVE(VARIADIC_MACRO) #define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT +#else +#define LOG_DISABLED 1 +#endif #endif #if COMPILER(GCC) @@ -125,7 +151,7 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann /* CRASH -- gets us into the debugger or the crash reporter -- signals are ignored by the crash reporter so we must do better */ #ifndef CRASH -#if PLATFORM(SYMBIAN) +#if OS(SYMBIAN) #define CRASH() do { \ __DEBUGGER(); \ User::Panic(_L("Webkit CRASH"),0); \ @@ -138,9 +164,9 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann #endif #endif -/* ASSERT, ASSERT_WITH_MESSAGE, ASSERT_NOT_REACHED */ +/* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED */ -#if PLATFORM(WINCE) && !PLATFORM(TORCHMOBILE) +#if OS(WINCE) && !PLATFORM(TORCHMOBILE) /* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */ #include <windows.h> #undef min @@ -148,7 +174,7 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann #undef ERROR #endif -#if PLATFORM(WIN_OS) || PLATFORM(SYMBIAN) +#if OS(WINDOWS) || OS(SYMBIAN) /* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */ #undef ASSERT #endif @@ -156,13 +182,6 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann #if ASSERT_DISABLED #define ASSERT(assertion) ((void)0) -#if COMPILER(MSVC7) -#define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif PLATFORM(SYMBIAN) -#define ASSERT_WITH_MESSAGE(assertion...) ((void)0) -#else -#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) -#endif /* COMPILER(MSVC7) */ #define ASSERT_NOT_REACHED() ((void)0) #define ASSERT_UNUSED(variable, assertion) ((void)variable) @@ -174,10 +193,24 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann CRASH(); \ } \ while (0) + +#define ASSERT_NOT_REACHED() do { \ + WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \ + CRASH(); \ +} while (0) + +#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion) + +#endif + +/* ASSERT_WITH_MESSAGE */ + #if COMPILER(MSVC7) #define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif PLATFORM(SYMBIAN) -#define ASSERT_WITH_MESSAGE(assertion...) ((void)0) +#elif COMPILER(WINSCW) +#define ASSERT_WITH_MESSAGE(assertion, arg...) ((void)0) +#elif ASSERT_MSG_DISABLED +#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) #else #define ASSERT_WITH_MESSAGE(assertion, ...) do \ if (!(assertion)) { \ @@ -185,16 +218,9 @@ while (0) CRASH(); \ } \ while (0) -#endif /* COMPILER(MSVC7) */ -#define ASSERT_NOT_REACHED() do { \ - WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \ - CRASH(); \ -} while (0) - -#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion) - #endif - + + /* ASSERT_ARG */ #if ASSERT_ARG_DISABLED @@ -219,12 +245,12 @@ while (0) /* FATAL */ -#if FATAL_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) -#define FATAL(...) ((void)0) -#elif COMPILER(MSVC7) +#if COMPILER(MSVC7) #define FATAL() ((void)0) -#elif PLATFORM(SYMBIAN) -#define FATAL(args...) ((void)0) +#elif COMPILER(WINSCW) +#define FATAL(arg...) ((void)0) +#elif FATAL_DISABLED +#define FATAL(...) ((void)0) #else #define FATAL(...) do { \ WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \ @@ -234,24 +260,24 @@ while (0) /* LOG_ERROR */ -#if ERROR_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) -#define LOG_ERROR(...) ((void)0) -#elif COMPILER(MSVC7) +#if COMPILER(MSVC7) #define LOG_ERROR() ((void)0) -#elif PLATFORM(SYMBIAN) -#define LOG_ERROR(args...) ((void)0) +#elif COMPILER(WINSCW) +#define LOG_ERROR(arg...) ((void)0) +#elif ERROR_DISABLED +#define LOG_ERROR(...) ((void)0) #else #define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__) #endif /* LOG */ -#if LOG_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) -#define LOG(channel, ...) ((void)0) -#elif COMPILER(MSVC7) +#if COMPILER(MSVC7) #define LOG() ((void)0) -#elif PLATFORM(SYMBIAN) -#define LOG(channel, args...) ((void)0) +#elif COMPILER(WINSCW) +#define LOG(arg...) ((void)0) +#elif LOG_DISABLED +#define LOG(channel, ...) ((void)0) #else #define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) #define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) @@ -260,12 +286,12 @@ while (0) /* LOG_VERBOSE */ -#if LOG_DISABLED && !COMPILER(MSVC7) && !PLATFORM(SYMBIAN) -#define LOG_VERBOSE(channel, ...) ((void)0) -#elif COMPILER(MSVC7) +#if COMPILER(MSVC7) #define LOG_VERBOSE(channel) ((void)0) -#elif PLATFORM(SYMBIAN) -#define LOG_VERBOSE(channel, args...) ((void)0) +#elif COMPILER(WINSCW) +#define LOG_VERBOSE(channel, arg...) ((void)0) +#elif LOG_DISABLED +#define LOG_VERBOSE(channel, ...) ((void)0) #else #define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) #endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CrossThreadRefCounted.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CrossThreadRefCounted.h index 6a05211..f682f0d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CrossThreadRefCounted.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CrossThreadRefCounted.h @@ -70,10 +70,6 @@ namespace WTF { return !m_refCounter.hasOneRef() || (m_threadSafeRefCounter && !m_threadSafeRefCounter->hasOneRef()); } -#ifndef NDEBUG - bool mayBePassedToAnotherThread() const { ASSERT(!m_threadId); return m_refCounter.hasOneRef(); } -#endif - private: CrossThreadRefCounted(T* data, ThreadSafeSharedBase* threadedCounter) : m_threadSafeRefCounter(threadedCounter) @@ -92,6 +88,10 @@ namespace WTF { void threadSafeDeref(); +#ifndef NDEBUG + bool isOwnedByCurrentThread() const { return !m_threadId || m_threadId == currentThread(); } +#endif + RefCountedBase m_refCounter; ThreadSafeSharedBase* m_threadSafeRefCounter; T* m_data; @@ -103,7 +103,7 @@ namespace WTF { template<class T> void CrossThreadRefCounted<T>::ref() { - ASSERT(!m_threadId || m_threadId == currentThread()); + ASSERT(isOwnedByCurrentThread()); m_refCounter.ref(); #ifndef NDEBUG // Store the threadId as soon as the ref count gets to 2. @@ -119,7 +119,7 @@ namespace WTF { template<class T> void CrossThreadRefCounted<T>::deref() { - ASSERT(!m_threadId || m_threadId == currentThread()); + ASSERT(isOwnedByCurrentThread()); if (m_refCounter.derefBase()) { threadSafeDeref(); delete this; @@ -146,10 +146,12 @@ namespace WTF { template<class T> PassRefPtr<CrossThreadRefCounted<T> > CrossThreadRefCounted<T>::crossThreadCopy() { + ASSERT(isOwnedByCurrentThread()); if (m_threadSafeRefCounter) m_threadSafeRefCounter->ref(); else m_threadSafeRefCounter = new ThreadSafeSharedBase(2); + return adoptRef(new CrossThreadRefCounted<T>(m_data, m_threadSafeRefCounter)); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CurrentTime.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CurrentTime.cpp index a3d5290..b272874 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CurrentTime.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CurrentTime.cpp @@ -33,7 +33,7 @@ #include "config.h" #include "CurrentTime.h" -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) // Windows is first since we want to use hires timers, despite PLATFORM(CF) // being defined. @@ -45,7 +45,7 @@ #include <time.h> #if USE(QUERY_PERFORMANCE_COUNTER) -#if PLATFORM(WINCE) +#if OS(WINCE) extern "C" time_t mktime(struct tm *t); #else #include <sys/timeb.h> @@ -63,11 +63,15 @@ extern "C" time_t mktime(struct tm *t); #include <sys/time.h> #endif +#if PLATFORM(CHROMIUM) +#error Chromium uses a different timer implementation +#endif + namespace WTF { const double msPerSecond = 1000.0; -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #if USE(QUERY_PERFORMANCE_COUNTER) @@ -119,7 +123,7 @@ static double highResUpTime() static double lowResUTCTime() { -#if PLATFORM(WINCE) +#if OS(WINCE) SYSTEMTIME systemTime; GetSystemTime(&systemTime); struct tm tmtime; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CurrentTime.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CurrentTime.h index 31f1ec8..334a6e9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CurrentTime.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/CurrentTime.h @@ -32,13 +32,32 @@ #ifndef CurrentTime_h #define CurrentTime_h +#include <time.h> + namespace WTF { - // Returns the current system (UTC) time in seconds, starting January 1, 1970. - // Precision varies depending on a platform but usually is as good or better + // Returns the current UTC time in seconds, counted from January 1, 1970. + // Precision varies depending on platform but is usually as good or better // than a millisecond. double currentTime(); + // Same thing, in milliseconds. + inline double currentTimeMS() + { + return currentTime() * 1000.0; + } + + inline void getLocalTime(const time_t* localTime, struct tm* localTM) + { + #if COMPILER(MSVC7) || COMPILER(MINGW) || OS(WINCE) + *localTM = *localtime(localTime); + #elif COMPILER(MSVC) + localtime_s(localTM, localTime); + #else + localtime_r(localTime, localTM); + #endif + } + } // namespace WTF using WTF::currentTime; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/DateMath.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/DateMath.cpp index 0386494..b9a0207 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/DateMath.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/DateMath.cpp @@ -39,6 +39,33 @@ * other provisions required by the MPL or the GPL, as the case may be. * If you do not delete the provisions above, a recipient may use your * version of this file under any of the LGPL, the MPL or the GPL. + + * Copyright 2006-2008 the V8 project authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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. */ #include "config.h" @@ -61,11 +88,7 @@ #include <errno.h> #endif -#if PLATFORM(DARWIN) -#include <notify.h> -#endif - -#if PLATFORM(WINCE) +#if OS(WINCE) extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); extern "C" struct tm * localtime(const time_t *timer); #endif @@ -78,8 +101,14 @@ extern "C" struct tm * localtime(const time_t *timer); #include <sys/timeb.h> #endif +#if USE(JSC) +#include "CallFrame.h" +#endif + #define NaN std::numeric_limits<double>::quiet_NaN() +using namespace WTF; + namespace WTF { /* Constants */ @@ -91,6 +120,10 @@ static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0; static const double usecPerSec = 1000000.0; static const double maxUnixTime = 2145859200.0; // 12/31/2037 +// ECMAScript asks not to support for a date of which total +// millisecond value is larger than the following value. +// See 15.9.1.14 of ECMA-262 5th edition. +static const double maxECMAScriptTime = 8.64E15; // Day of year for the first day of each month, where index 0 is January, and day 0 is January 1. // First for non-leap years, then for leap years. @@ -139,7 +172,7 @@ static inline double msToDays(double ms) return floor(ms / msPerDay); } -static inline int msToYear(double ms) +int msToYear(double ms) { int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970); double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear); @@ -150,7 +183,7 @@ static inline int msToYear(double ms) return approxYear; } -static inline int dayInYear(double ms, int year) +int dayInYear(double ms, int year) { return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year)); } @@ -196,7 +229,7 @@ static inline int msToHours(double ms) return static_cast<int>(result); } -static inline int monthFromDayInYear(int dayInYear, bool leapYear) +int monthFromDayInYear(int dayInYear, bool leapYear) { const int d = dayInYear; int step; @@ -234,7 +267,7 @@ static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& star return (dayInYear <= startDayOfNextMonth); } -static inline int dayInMonthFromDayInYear(int dayInYear, bool leapYear) +int dayInMonthFromDayInYear(int dayInYear, bool leapYear) { const int d = dayInYear; int step; @@ -277,7 +310,7 @@ static inline double timeToMS(double hour, double min, double sec, double ms) return (((hour * minutesPerHour + min) * secondsPerMinute + sec) * msPerSecond + ms); } -static int dateToDayInYear(int year, int month, int day) +double dateToDaysFrom1970(int year, int month, int day) { year += month / 12; @@ -287,34 +320,13 @@ static int dateToDayInYear(int year, int month, int day) --year; } - int yearday = static_cast<int>(floor(daysFrom1970ToYear(year))); + double yearday = floor(daysFrom1970ToYear(year)); + ASSERT((year >= 1970 && yearday >= 0) || (year < 1970 && yearday < 0)); int monthday = monthToDayInYear(month, isLeapYear(year)); return yearday + monthday + day - 1; } -double getCurrentUTCTime() -{ - return floor(getCurrentUTCTimeWithMicroseconds()); -} - -// Returns current time in milliseconds since 1 Jan 1970. -double getCurrentUTCTimeWithMicroseconds() -{ - return currentTime() * 1000.0; -} - -void getLocalTime(const time_t* localTime, struct tm* localTM) -{ -#if COMPILER(MSVC7) || COMPILER(MINGW) || PLATFORM(WINCE) - *localTM = *localtime(localTime); -#elif COMPILER(MSVC) - localtime_s(localTM, localTime); -#else - localtime_r(localTime, localTM); -#endif -} - // There is a hard limit at 2038 that we currently do not have a workaround // for (rdar://problem/5052975). static inline int maximumYearForDST() @@ -328,7 +340,7 @@ static inline int minimumYearForDST() // greater than the max year minus 27 (2010), we want to use the max year // minus 27 instead, to ensure there is a range of 28 years that all years // can map to. - return std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ; + return std::min(msToYear(jsCurrentTime()), maximumYearForDST() - 27) ; } /* @@ -367,7 +379,11 @@ int equivalentYearForDST(int year) static int32_t calculateUTCOffset() { +#if PLATFORM(BREWMP) + time_t localTime = static_cast<time_t>(currentTime()); +#else time_t localTime = time(0); +#endif tm localt; getLocalTime(&localTime, &localt); @@ -399,44 +415,10 @@ static int32_t calculateUTCOffset() return static_cast<int32_t>(utcOffset * 1000); } -#if PLATFORM(DARWIN) -static int32_t s_cachedUTCOffset; // In milliseconds. An assumption here is that access to an int32_t variable is atomic on platforms that take this code path. -static bool s_haveCachedUTCOffset; -static int s_notificationToken; -#endif - -/* - * Get the difference in milliseconds between this time zone and UTC (GMT) - * NOT including DST. - */ -double getUTCOffset() -{ -#if PLATFORM(DARWIN) - if (s_haveCachedUTCOffset) { - int notified; - uint32_t status = notify_check(s_notificationToken, ¬ified); - if (status == NOTIFY_STATUS_OK && !notified) - return s_cachedUTCOffset; - } -#endif - - int32_t utcOffset = calculateUTCOffset(); - -#if PLATFORM(DARWIN) - // Theoretically, it is possible that several threads will be executing this code at once, in which case we will have a race condition, - // and a newer value may be overwritten. In practice, time zones don't change that often. - s_cachedUTCOffset = utcOffset; -#endif - - return utcOffset; -} - /* - * Get the DST offset for the time passed in. Takes - * seconds (not milliseconds) and cannot handle dates before 1970 - * on some OS' + * Get the DST offset for the time passed in. */ -static double getDSTOffsetSimple(double localTimeSeconds, double utcOffset) +static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset) { if (localTimeSeconds > maxUnixTime) localTimeSeconds = maxUnixTime; @@ -465,9 +447,9 @@ static double getDSTOffsetSimple(double localTimeSeconds, double utcOffset) } // Get the DST offset, given a time in UTC -static double getDSTOffset(double ms, double utcOffset) +static double calculateDSTOffset(double ms, double utcOffset) { - // On Mac OS X, the call to localtime (see getDSTOffsetSimple) will return historically accurate + // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) will return historically accurate // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript // standard explicitly dictates that historical information should not be considered when // determining DST. For this reason we shift away from years that localtime can handle but would @@ -479,70 +461,22 @@ static double getDSTOffset(double ms, double utcOffset) int dayInYearLocal = dayInYear(ms, year); int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear); int month = monthFromDayInYear(dayInYearLocal, leapYear); - int day = dateToDayInYear(equivalentYear, month, dayInMonth); + double day = dateToDaysFrom1970(equivalentYear, month, dayInMonth); ms = (day * msPerDay) + msToMilliseconds(ms); } - return getDSTOffsetSimple(ms / msPerSecond, utcOffset); -} - -double gregorianDateTimeToMS(const GregorianDateTime& t, double milliSeconds, bool inputIsUTC) -{ - int day = dateToDayInYear(t.year + 1900, t.month, t.monthDay); - double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds); - double result = (day * msPerDay) + ms; - - if (!inputIsUTC) { // convert to UTC - double utcOffset = getUTCOffset(); - result -= utcOffset; - result -= getDSTOffset(result, utcOffset); - } - - return result; -} - -void msToGregorianDateTime(double ms, bool outputIsUTC, GregorianDateTime& tm) -{ - // input is UTC - double dstOff = 0.0; - const double utcOff = getUTCOffset(); - - if (!outputIsUTC) { // convert to local time - dstOff = getDSTOffset(ms, utcOff); - ms += dstOff + utcOff; - } - - const int year = msToYear(ms); - tm.second = msToSeconds(ms); - tm.minute = msToMinutes(ms); - tm.hour = msToHours(ms); - tm.weekDay = msToWeekDay(ms); - tm.yearDay = dayInYear(ms, year); - tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year)); - tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year)); - tm.year = year - 1900; - tm.isDST = dstOff != 0.0; - - tm.utcOffset = outputIsUTC ? 0 : static_cast<long>((dstOff + utcOff) / msPerSecond); - tm.timeZone = NULL; + return calculateDSTOffsetSimple(ms / msPerSecond, utcOffset); } void initializeDates() { #ifndef NDEBUG static bool alreadyInitialized; - ASSERT(!alreadyInitialized++); + ASSERT(!alreadyInitialized); + alreadyInitialized = true; #endif equivalentYearForDST(2000); // Need to call once to initialize a static used in this function. -#if PLATFORM(DARWIN) - // Register for a notification whenever the time zone changes. - uint32_t status = notify_register_check("com.apple.system.timezone", &s_notificationToken); - if (status == NOTIFY_STATUS_OK) { - s_cachedUTCOffset = calculateUTCOffset(); - s_haveCachedUTCOffset = true; - } -#endif } static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, int second) @@ -558,7 +492,7 @@ static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int // We follow the recommendation of RFC 2822 to consider all // obsolete time zones not listed here equivalent to "-0000". static const struct KnownZone { -#if !PLATFORM(WIN_OS) +#if !OS(WINDOWS) const #endif char tzName[4]; @@ -623,8 +557,12 @@ static bool parseLong(const char* string, char** stopPosition, int base, long* r return true; } -double parseDateFromNullTerminatedCharacters(const char* dateString) +// Odd case where 'exec' is allowed to be 0, to accomodate a caller in WebCore. +static double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset) { + haveTZ = false; + offset = 0; + // This parses a date in the form: // Tuesday, 09-Nov-99 23:12:40 GMT // or @@ -825,9 +763,6 @@ double parseDateFromNullTerminatedCharacters(const char* dateString) } } - bool haveTZ = false; - int offset = 0; - // Don't fail if the time zone is missing. // Some websites omit the time zone (4275206). if (*dateString) { @@ -890,33 +825,172 @@ double parseDateFromNullTerminatedCharacters(const char* dateString) else year += 1900; } + + return ymdhmsToSeconds(year, month + 1, day, hour, minute, second) * msPerSecond; +} + +double parseDateFromNullTerminatedCharacters(const char* dateString) +{ + bool haveTZ; + int offset; + double ms = parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); + if (isnan(ms)) + return NaN; // fall back to local timezone if (!haveTZ) { - GregorianDateTime t; - t.monthDay = day; - t.month = month; - t.year = year - 1900; - t.isDST = -1; - t.second = second; - t.minute = minute; - t.hour = hour; - - // Use our gregorianDateTimeToMS() rather than mktime() as the latter can't handle the full year range. - return gregorianDateTimeToMS(t, 0, false); + double utcOffset = calculateUTCOffset(); + double dstOffset = calculateDSTOffset(ms, utcOffset); + offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute); } - - return (ymdhmsToSeconds(year, month + 1, day, hour, minute, second) - (offset * 60.0)) * msPerSecond; + return ms - (offset * msPerMinute); } double timeClip(double t) { if (!isfinite(t)) return NaN; - if (fabs(t) > 8.64E15) + if (fabs(t) > maxECMAScriptTime) return NaN; return trunc(t); } +} // namespace WTF + +#if USE(JSC) +namespace JSC { + +// Get the DST offset for the time passed in. +// +// NOTE: The implementation relies on the fact that no time zones have +// more than one daylight savings offset change per month. +// If this function is called with NaN it returns NaN. +static double getDSTOffset(ExecState* exec, double ms, double utcOffset) +{ + DSTOffsetCache& cache = exec->globalData().dstOffsetCache; + double start = cache.start; + double end = cache.end; + + if (start <= ms) { + // If the time fits in the cached interval, return the cached offset. + if (ms <= end) return cache.offset; + + // Compute a possible new interval end. + double newEnd = end + cache.increment; + + if (ms <= newEnd) { + double endOffset = calculateDSTOffset(newEnd, utcOffset); + if (cache.offset == endOffset) { + // If the offset at the end of the new interval still matches + // the offset in the cache, we grow the cached time interval + // and return the offset. + cache.end = newEnd; + cache.increment = msPerMonth; + return endOffset; + } else { + double offset = calculateDSTOffset(ms, utcOffset); + if (offset == endOffset) { + // The offset at the given time is equal to the offset at the + // new end of the interval, so that means that we've just skipped + // the point in time where the DST offset change occurred. Updated + // the interval to reflect this and reset the increment. + cache.start = ms; + cache.end = newEnd; + cache.increment = msPerMonth; + } else { + // The interval contains a DST offset change and the given time is + // before it. Adjust the increment to avoid a linear search for + // the offset change point and change the end of the interval. + cache.increment /= 3; + cache.end = ms; + } + // Update the offset in the cache and return it. + cache.offset = offset; + return offset; + } + } + } + + // Compute the DST offset for the time and shrink the cache interval + // to only contain the time. This allows fast repeated DST offset + // computations for the same time. + double offset = calculateDSTOffset(ms, utcOffset); + cache.offset = offset; + cache.start = ms; + cache.end = ms; + cache.increment = msPerMonth; + return offset; +} + +/* + * Get the difference in milliseconds between this time zone and UTC (GMT) + * NOT including DST. + */ +double getUTCOffset(ExecState* exec) +{ + double utcOffset = exec->globalData().cachedUTCOffset; + if (!isnan(utcOffset)) + return utcOffset; + exec->globalData().cachedUTCOffset = calculateUTCOffset(); + return exec->globalData().cachedUTCOffset; +} +double gregorianDateTimeToMS(ExecState* exec, const GregorianDateTime& t, double milliSeconds, bool inputIsUTC) +{ + double day = dateToDaysFrom1970(t.year + 1900, t.month, t.monthDay); + double ms = timeToMS(t.hour, t.minute, t.second, milliSeconds); + double result = (day * WTF::msPerDay) + ms; -} // namespace WTF + if (!inputIsUTC) { // convert to UTC + double utcOffset = getUTCOffset(exec); + result -= utcOffset; + result -= getDSTOffset(exec, result, utcOffset); + } + + return result; +} + +// input is UTC +void msToGregorianDateTime(ExecState* exec, double ms, bool outputIsUTC, GregorianDateTime& tm) +{ + double dstOff = 0.0; + double utcOff = 0.0; + if (!outputIsUTC) { + utcOff = getUTCOffset(exec); + dstOff = getDSTOffset(exec, ms, utcOff); + ms += dstOff + utcOff; + } + + const int year = msToYear(ms); + tm.second = msToSeconds(ms); + tm.minute = msToMinutes(ms); + tm.hour = msToHours(ms); + tm.weekDay = msToWeekDay(ms); + tm.yearDay = dayInYear(ms, year); + tm.monthDay = dayInMonthFromDayInYear(tm.yearDay, isLeapYear(year)); + tm.month = monthFromDayInYear(tm.yearDay, isLeapYear(year)); + tm.year = year - 1900; + tm.isDST = dstOff != 0.0; + tm.utcOffset = static_cast<long>((dstOff + utcOff) / WTF::msPerSecond); + tm.timeZone = NULL; +} + +double parseDateFromNullTerminatedCharacters(ExecState* exec, const char* dateString) +{ + ASSERT(exec); + bool haveTZ; + int offset; + double ms = WTF::parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); + if (isnan(ms)) + return NaN; + + // fall back to local timezone + if (!haveTZ) { + double utcOffset = getUTCOffset(exec); + double dstOffset = getDSTOffset(exec, ms, utcOffset); + offset = static_cast<int>((utcOffset + dstOffset) / WTF::msPerMinute); + } + return ms - (offset * WTF::msPerMinute); +} + +} // namespace JSC +#endif // USE(JSC) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/DateMath.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/DateMath.h index 6110f76..033d25e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/DateMath.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/DateMath.h @@ -42,27 +42,27 @@ #ifndef DateMath_h #define DateMath_h -#include <time.h> +#include <math.h> #include <string.h> +#include <time.h> +#include <wtf/CurrentTime.h> #include <wtf/Noncopyable.h> +#include <wtf/UnusedParam.h> namespace WTF { - -struct GregorianDateTime; - void initializeDates(); -void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&); -double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC); -double getUTCOffset(); int equivalentYearForDST(int year); -double getCurrentUTCTime(); -double getCurrentUTCTimeWithMicroseconds(); -void getLocalTime(const time_t*, tm*); // Not really math related, but this is currently the only shared place to put these. -double parseDateFromNullTerminatedCharacters(const char*); +double parseDateFromNullTerminatedCharacters(const char* dateString); double timeClip(double); +inline double jsCurrentTime() +{ + // JavaScript doesn't recognize fractions of a millisecond. + return floor(WTF::currentTimeMS()); +} + const char * const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; const char * const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; @@ -74,9 +74,39 @@ const double msPerSecond = 1000.0; const double msPerMinute = 60.0 * 1000.0; const double msPerHour = 60.0 * 60.0 * 1000.0; const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0; +const double msPerMonth = 2592000000.0; -// Intentionally overridding the default tm of the system -// Tee members of tm differ on various operating systems. +// Returns the number of days from 1970-01-01 to the specified date. +double dateToDaysFrom1970(int year, int month, int day); +int msToYear(double ms); +int dayInYear(double ms, int year); +int monthFromDayInYear(int dayInYear, bool leapYear); +int dayInMonthFromDayInYear(int dayInYear, bool leapYear); + +} // namespace WTF + +using WTF::dateToDaysFrom1970; +using WTF::dayInMonthFromDayInYear; +using WTF::dayInYear; +using WTF::minutesPerHour; +using WTF::monthFromDayInYear; +using WTF::msPerDay; +using WTF::msPerSecond; +using WTF::msToYear; +using WTF::secondsPerMinute; + +#if USE(JSC) +namespace JSC { +class ExecState; +struct GregorianDateTime; + +void msToGregorianDateTime(ExecState*, double, bool outputIsUTC, GregorianDateTime&); +double gregorianDateTimeToMS(ExecState*, const GregorianDateTime&, double, bool inputIsUTC); +double getUTCOffset(ExecState*); +double parseDateFromNullTerminatedCharacters(ExecState*, const char* dateString); + +// Intentionally overridding the default tm of the system. +// The members of tm differ on various operating systems. struct GregorianDateTime : Noncopyable { GregorianDateTime() : second(0) @@ -98,7 +128,7 @@ struct GregorianDateTime : Noncopyable { delete [] timeZone; } - GregorianDateTime(const tm& inTm) + GregorianDateTime(ExecState* exec, const tm& inTm) : second(inTm.tm_sec) , minute(inTm.tm_min) , hour(inTm.tm_hour) @@ -109,10 +139,11 @@ struct GregorianDateTime : Noncopyable { , year(inTm.tm_year) , isDST(inTm.tm_isdst) { + UNUSED_PARAM(exec); #if HAVE(TM_GMTOFF) utcOffset = static_cast<int>(inTm.tm_gmtoff); #else - utcOffset = static_cast<int>(getUTCOffset() / msPerSecond + (isDST ? secondsPerHour : 0)); + utcOffset = static_cast<int>(getUTCOffset(exec) / WTF::msPerSecond + (isDST ? WTF::secondsPerHour : 0)); #endif #if HAVE(TM_ZONE) @@ -186,7 +217,7 @@ static inline int gmtoffset(const GregorianDateTime& t) { return t.utcOffset; } - -} // namespace WTF +} // namespace JSC +#endif // USE(JSC) #endif // DateMath_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/FastMalloc.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/FastMalloc.cpp index f3ded7e..d95f078 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/FastMalloc.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/FastMalloc.cpp @@ -119,11 +119,13 @@ static void initializeIsForbiddenKey() pthread_key_create(&isForbiddenKey, 0); } +#if !ASSERT_DISABLED static bool isForbidden() { pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey); return !!pthread_getspecific(isForbiddenKey); } +#endif void fastMallocForbid() { @@ -182,6 +184,17 @@ void* fastZeroedMalloc(size_t n) memset(result, 0, n); return result; } + +char* fastStrDup(const char* src) +{ + int len = strlen(src) + 1; + char* dup = static_cast<char*>(fastMalloc(len)); + + if (dup) + memcpy(dup, src, len); + + return dup; +} TryMallocReturnValue tryFastZeroedMalloc(size_t n) { @@ -196,13 +209,6 @@ TryMallocReturnValue tryFastZeroedMalloc(size_t n) #if FORCE_SYSTEM_MALLOC -#include <stdlib.h> -#if !PLATFORM(WIN_OS) - #include <pthread.h> -#else - #include "windows.h" -#endif - namespace WTF { TryMallocReturnValue tryFastMalloc(size_t n) @@ -354,7 +360,7 @@ FastMallocStatistics fastMallocStatistics() } // namespace WTF -#if PLATFORM(DARWIN) +#if OS(DARWIN) // This symbol is present in the JavaScriptCore exports file even when FastMalloc is disabled. // It will never be used in this case, so it's type and value are less interesting than its presence. extern "C" const int jscore_fastmalloc_introspection = 0; @@ -384,7 +390,7 @@ extern "C" const int jscore_fastmalloc_introspection = 0; #include <stdarg.h> #include <stddef.h> #include <stdio.h> -#if PLATFORM(UNIX) +#if OS(UNIX) #include <unistd.h> #endif #if COMPILER(MSVC) @@ -396,11 +402,15 @@ extern "C" const int jscore_fastmalloc_introspection = 0; #if WTF_CHANGES -#if PLATFORM(DARWIN) +#if OS(DARWIN) #include "MallocZoneSupport.h" #include <wtf/HashSet.h> #include <wtf/Vector.h> #endif +#if HAVE(DISPATCH_H) +#include <dispatch/dispatch.h> +#endif + #ifndef PRIuS #define PRIuS "zu" @@ -410,7 +420,7 @@ extern "C" const int jscore_fastmalloc_introspection = 0; // call to the function on Mac OS X, and it's used in performance-critical code. So we // use a function pointer. But that's not necessarily faster on other platforms, and we had // problems with this technique on Windows, so we'll do this only on Mac OS X. -#if PLATFORM(DARWIN) +#if OS(DARWIN) static void* (*pthread_getspecific_function_pointer)(pthread_key_t) = pthread_getspecific; #define pthread_getspecific(key) pthread_getspecific_function_pointer(key) #endif @@ -438,7 +448,7 @@ namespace WTF { #define MESSAGE LOG_ERROR #define CHECK_CONDITION ASSERT -#if PLATFORM(DARWIN) +#if OS(DARWIN) class Span; class TCMalloc_Central_FreeListPadded; class TCMalloc_PageHeap; @@ -995,7 +1005,7 @@ class PageHeapAllocator { int inuse() const { return inuse_; } -#if defined(WTF_CHANGES) && PLATFORM(DARWIN) +#if defined(WTF_CHANGES) && OS(DARWIN) template <class Recorder> void recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader) { @@ -1177,7 +1187,7 @@ template <int BITS> class MapSelector { }; #if defined(WTF_CHANGES) -#if PLATFORM(X86_64) +#if CPU(X86_64) // On all known X86-64 platforms, the upper 16 bits are always unused and therefore // can be excluded from the PageMap key. // See http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details @@ -1228,7 +1238,7 @@ static const int kScavengeTimerDelayInSeconds = 5; static const size_t kMinimumFreeCommittedPageCount = 512; // During a scavenge, we'll release up to a fraction of the free committed pages. -#if PLATFORM(WIN) +#if OS(WINDOWS) // We are slightly less aggressive in releasing memory on Windows due to performance reasons. static const int kMaxScavengeAmountFactor = 3; #else @@ -1377,26 +1387,34 @@ class TCMalloc_PageHeap { // Index of last free list we scavenged size_t scavenge_index_; -#if defined(WTF_CHANGES) && PLATFORM(DARWIN) +#if defined(WTF_CHANGES) && OS(DARWIN) friend class FastMallocZone; #endif #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - static NO_RETURN void* runScavengerThread(void*); + void initializeScavenger(); + ALWAYS_INLINE void signalScavenger(); + void scavenge(); + ALWAYS_INLINE bool shouldContinueScavenging() const; +#if !HAVE(DISPATCH_H) + static NO_RETURN void* runScavengerThread(void*); NO_RETURN void scavengerThread(); - void scavenge(); - - inline bool shouldContinueScavenging() const; + // Keeps track of whether the background thread is actively scavenging memory every kScavengeTimerDelayInSeconds, or + // it's blocked waiting for more pages to be deleted. + bool m_scavengeThreadActive; pthread_mutex_t m_scavengeMutex; - pthread_cond_t m_scavengeCondition; +#else // !HAVE(DISPATCH_H) + void periodicScavenge(); + + dispatch_queue_t m_scavengeQueue; + dispatch_source_t m_scavengeTimer; + bool m_scavengingScheduled; +#endif - // Keeps track of whether the background thread is actively scavenging memory every kScavengeTimerDelayInSeconds, or - // it's blocked waiting for more pages to be deleted. - bool m_scavengeThreadActive; #endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY }; @@ -1424,24 +1442,60 @@ void TCMalloc_PageHeap::init() } #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY + initializeScavenger(); +#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY +} + +#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY + +#if !HAVE(DISPATCH_H) + +void TCMalloc_PageHeap::initializeScavenger() +{ pthread_mutex_init(&m_scavengeMutex, 0); pthread_cond_init(&m_scavengeCondition, 0); m_scavengeThreadActive = true; pthread_t thread; pthread_create(&thread, 0, runScavengerThread, this); -#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY } -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY void* TCMalloc_PageHeap::runScavengerThread(void* context) { static_cast<TCMalloc_PageHeap*>(context)->scavengerThread(); -#if COMPILER(MSVC) || PLATFORM(SOLARIS) +#if COMPILER(MSVC) || OS(SOLARIS) // Without this, Visual Studio will complain that this method does not return a value. return 0; #endif } +ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger() +{ + if (!m_scavengeThreadActive && shouldContinueScavenging()) + pthread_cond_signal(&m_scavengeCondition); +} + +#else // !HAVE(DISPATCH_H) + +void TCMalloc_PageHeap::initializeScavenger() +{ + m_scavengeQueue = dispatch_queue_create("com.apple.JavaScriptCore.FastMallocSavenger", NULL); + m_scavengeTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, m_scavengeQueue); + dispatch_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, kScavengeTimerDelayInSeconds * NSEC_PER_SEC); + dispatch_source_set_timer(m_scavengeTimer, startTime, kScavengeTimerDelayInSeconds * NSEC_PER_SEC, 1000 * NSEC_PER_USEC); + dispatch_source_set_event_handler(m_scavengeTimer, ^{ periodicScavenge(); }); + m_scavengingScheduled = false; +} + +ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger() +{ + if (!m_scavengingScheduled && shouldContinueScavenging()) { + m_scavengingScheduled = true; + dispatch_resume(m_scavengeTimer); + } +} + +#endif + void TCMalloc_PageHeap::scavenge() { // If we have to commit memory in the last 5 seconds, it means we don't have enough free committed pages @@ -1477,7 +1531,7 @@ void TCMalloc_PageHeap::scavenge() free_committed_pages_ -= pagesDecommitted; } -inline bool TCMalloc_PageHeap::shouldContinueScavenging() const +ALWAYS_INLINE bool TCMalloc_PageHeap::shouldContinueScavenging() const { return free_committed_pages_ > kMinimumFreeCommittedPageCount; } @@ -1739,8 +1793,7 @@ inline void TCMalloc_PageHeap::Delete(Span* span) { } // Make sure the scavenge thread becomes active if we have enough freed pages to release some back to the system. - if (!m_scavengeThreadActive && shouldContinueScavenging()) - pthread_cond_signal(&m_scavengeCondition); + signalScavenger(); #else IncrementalScavenge(n); #endif @@ -2283,7 +2336,9 @@ static inline TCMalloc_PageHeap* getPageHeap() #define pageheap getPageHeap() #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY -#if PLATFORM(WIN_OS) + +#if !HAVE(DISPATCH_H) +#if OS(WINDOWS) static void sleep(unsigned seconds) { ::Sleep(seconds * 1000); @@ -2312,6 +2367,23 @@ void TCMalloc_PageHeap::scavengerThread() } } } + +#else + +void TCMalloc_PageHeap::periodicScavenge() +{ + { + SpinLockHolder h(&pageheap_lock); + pageheap->scavenge(); + } + + if (!shouldContinueScavenging()) { + m_scavengingScheduled = false; + dispatch_suspend(m_scavengeTimer); + } +} +#endif // HAVE(DISPATCH_H) + #endif // If TLS is available, we also store a copy @@ -2821,7 +2893,7 @@ void TCMalloc_ThreadCache::InitModule() { } pageheap->init(); phinited = 1; -#if defined(WTF_CHANGES) && PLATFORM(DARWIN) +#if defined(WTF_CHANGES) && OS(DARWIN) FastMallocZone::init(); #endif } @@ -3800,7 +3872,7 @@ void* realloc(void* old_ptr, size_t new_size) { return new_ptr; } else { #if ENABLE(FAST_MALLOC_MATCH_VALIDATION) - old_ptr = pByte + sizeof(AllocAlignmentInteger); // Set old_ptr back to the user pointer. + old_ptr = static_cast<AllocAlignmentInteger*>(old_ptr) + 1; // Set old_ptr back to the user pointer. #endif return old_ptr; } @@ -4019,7 +4091,7 @@ void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride; #endif -#if defined(WTF_CHANGES) && PLATFORM(DARWIN) +#if defined(WTF_CHANGES) && OS(DARWIN) class FreeObjectFinder { const RemoteMemoryReader& m_reader; @@ -4302,7 +4374,7 @@ extern "C" { malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, &FastMallocZone::goodSize, &FastMallocZone::check, &FastMallocZone::print, &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !PLATFORM(IPHONE) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !OS(IPHONE_OS) , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher. #endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/FastMalloc.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/FastMalloc.h index ca0961c..74d4307 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/FastMalloc.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/FastMalloc.h @@ -33,6 +33,7 @@ namespace WTF { void* fastZeroedMalloc(size_t); void* fastCalloc(size_t numElements, size_t elementSize); void* fastRealloc(void*, size_t); + char* fastStrDup(const char*); struct TryMallocReturnValue { TryMallocReturnValue(void* data) @@ -188,17 +189,18 @@ using WTF::tryFastZeroedMalloc; using WTF::tryFastCalloc; using WTF::tryFastRealloc; using WTF::fastFree; +using WTF::fastStrDup; #ifndef NDEBUG using WTF::fastMallocForbid; using WTF::fastMallocAllow; #endif -#if COMPILER(GCC) && PLATFORM(DARWIN) +#if COMPILER(GCC) && OS(DARWIN) #define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline)) #elif COMPILER(GCC) #define WTF_PRIVATE_INLINE inline __attribute__((always_inline)) -#elif COMPILER(MSVC) +#elif COMPILER(MSVC) || COMPILER(RVCT) #define WTF_PRIVATE_INLINE __forceinline #else #define WTF_PRIVATE_INLINE inline @@ -216,14 +218,21 @@ using WTF::fastMallocAllow; // We musn't customize the global operator new and delete for the Qt port. #if !PLATFORM(QT) -WTF_PRIVATE_INLINE void* operator new(size_t size) { return fastMalloc(size); } +#if COMPILER(MSVC) +#pragma warning(push) +#pragma warning(disable: 4290) // Disable the C++ exception specification ignored warning. +#endif +WTF_PRIVATE_INLINE void* operator new(size_t size) throw (std::bad_alloc) { return fastMalloc(size); } WTF_PRIVATE_INLINE void* operator new(size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } -WTF_PRIVATE_INLINE void operator delete(void* p) { fastFree(p); } +WTF_PRIVATE_INLINE void operator delete(void* p) throw() { fastFree(p); } WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); } -WTF_PRIVATE_INLINE void* operator new[](size_t size) { return fastMalloc(size); } +WTF_PRIVATE_INLINE void* operator new[](size_t size) throw (std::bad_alloc) { return fastMalloc(size); } WTF_PRIVATE_INLINE void* operator new[](size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } -WTF_PRIVATE_INLINE void operator delete[](void* p) { fastFree(p); } +WTF_PRIVATE_INLINE void operator delete[](void* p) throw() { fastFree(p); } WTF_PRIVATE_INLINE void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); } +#if COMPILER(MSVC) +#pragma warning(pop) +#endif #endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/GOwnPtr.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/GOwnPtr.cpp deleted file mode 100644 index 432885f..0000000 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/GOwnPtr.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2008 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include "GOwnPtr.h" - -namespace WTF { - -template <> void freeOwnedGPtr<GError>(GError* ptr) -{ - if (ptr) - g_error_free(ptr); -} - -template <> void freeOwnedGPtr<GList>(GList* ptr) -{ - g_list_free(ptr); -} - -template <> void freeOwnedGPtr<GCond>(GCond* ptr) -{ - if (ptr) - g_cond_free(ptr); -} - -template <> void freeOwnedGPtr<GMutex>(GMutex* ptr) -{ - if (ptr) - g_mutex_free(ptr); -} - -template <> void freeOwnedGPtr<GPatternSpec>(GPatternSpec* ptr) -{ - if (ptr) - g_pattern_spec_free(ptr); -} - -template <> void freeOwnedGPtr<GDir>(GDir* ptr) -{ - if (ptr) - g_dir_close(ptr); -} - -template <> void freeOwnedGPtr<GHashTable>(GHashTable* ptr) -{ - if (ptr) - g_hash_table_unref(ptr); -} - -} // namespace WTF diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/GOwnPtr.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/GOwnPtr.h deleted file mode 100644 index 4993348..0000000 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/GOwnPtr.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2008 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef GOwnPtr_h -#define GOwnPtr_h - -#include <algorithm> -#include <glib.h> -#include <wtf/Assertions.h> -#include <wtf/Noncopyable.h> - -namespace WTF { - template <typename T> inline void freeOwnedGPtr(T* ptr) { g_free(reinterpret_cast<void*>(ptr)); } - template<> void freeOwnedGPtr<GError>(GError*); - template<> void freeOwnedGPtr<GList>(GList*); - template<> void freeOwnedGPtr<GCond>(GCond*); - template<> void freeOwnedGPtr<GMutex>(GMutex*); - template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*); - template<> void freeOwnedGPtr<GDir>(GDir*); - template<> void freeOwnedGPtr<GHashTable>(GHashTable*); - - template <typename T> class GOwnPtr : public Noncopyable { - public: - explicit GOwnPtr(T* ptr = 0) : m_ptr(ptr) { } - ~GOwnPtr() { freeOwnedGPtr(m_ptr); } - - T* get() const { return m_ptr; } - T* release() { T* ptr = m_ptr; m_ptr = 0; return ptr; } - T*& outPtr() { ASSERT(!m_ptr); return m_ptr; } - - void set(T* ptr) { ASSERT(!ptr || m_ptr != ptr); freeOwnedGPtr(m_ptr); m_ptr = ptr; } - void clear() { freeOwnedGPtr(m_ptr); m_ptr = 0; } - - T& operator*() const { ASSERT(m_ptr); return *m_ptr; } - T* operator->() const { ASSERT(m_ptr); return m_ptr; } - - bool operator!() const { return !m_ptr; } - - // This conversion operator allows implicit conversion to bool but not to other integer types. - typedef T* GOwnPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &GOwnPtr::m_ptr : 0; } - - void swap(GOwnPtr& o) { std::swap(m_ptr, o.m_ptr); } - - private: - T* m_ptr; - }; - - template <typename T> inline void swap(GOwnPtr<T>& a, GOwnPtr<T>& b) { a.swap(b); } - - template <typename T, typename U> inline bool operator==(const GOwnPtr<T>& a, U* b) - { - return a.get() == b; - } - - template <typename T, typename U> inline bool operator==(T* a, const GOwnPtr<U>& b) - { - return a == b.get(); - } - - template <typename T, typename U> inline bool operator!=(const GOwnPtr<T>& a, U* b) - { - return a.get() != b; - } - - template <typename T, typename U> inline bool operator!=(T* a, const GOwnPtr<U>& b) - { - return a != b.get(); - } - - template <typename T> inline typename GOwnPtr<T>::PtrType getPtr(const GOwnPtr<T>& p) - { - return p.get(); - } - -} // namespace WTF - -using WTF::GOwnPtr; - -#endif // GOwnPtr_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashCountedSet.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashCountedSet.h index 5fb6da8..165eb41 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashCountedSet.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashCountedSet.h @@ -65,8 +65,8 @@ namespace WTF { void remove(iterator); // removes the value, regardless of its count - void clear(iterator); - void clear(const ValueType&); + void removeAll(iterator); + void removeAll(const ValueType&); // clears the whole set void clear(); @@ -171,13 +171,13 @@ namespace WTF { } template<typename Value, typename HashFunctions, typename Traits> - inline void HashCountedSet<Value, HashFunctions, Traits>::clear(const ValueType& value) + inline void HashCountedSet<Value, HashFunctions, Traits>::removeAll(const ValueType& value) { - clear(find(value)); + removeAll(find(value)); } template<typename Value, typename HashFunctions, typename Traits> - inline void HashCountedSet<Value, HashFunctions, Traits>::clear(iterator it) + inline void HashCountedSet<Value, HashFunctions, Traits>::removeAll(iterator it) { if (it == end()) return; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashFunctions.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashFunctions.h index 13afb72..2c66a2d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashFunctions.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashFunctions.h @@ -173,9 +173,6 @@ namespace WTF { template<typename P> struct DefaultHash<RefPtr<P> > { typedef PtrHash<RefPtr<P> > Hash; }; template<typename T, typename U> struct DefaultHash<std::pair<T, U> > { typedef PairHash<T, U> Hash; }; - - // Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's - static const unsigned stringHashingStartValue = 0x9e3779b9U; } // namespace WTF diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashMap.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashMap.h index 8ff9170..de4743a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashMap.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashMap.h @@ -83,6 +83,23 @@ namespace WTF { MappedType take(const KeyType&); // efficient combination of get with remove + // An alternate version of find() that finds the object by hashing and comparing + // with some other type, to avoid the cost of type conversion. HashTranslator + // must have the following function members: + // static unsigned hash(const T&); + // static bool equal(const ValueType&, const T&); + template<typename T, typename HashTranslator> iterator find(const T&); + template<typename T, typename HashTranslator> const_iterator find(const T&) const; + template<typename T, typename HashTranslator> bool contains(const T&) const; + + // An alternate version of add() that finds the object by hashing and comparing + // with some other type, to avoid the cost of type conversion if the object is already + // in the table. HashTranslator must have the following function members: + // static unsigned hash(const T&); + // static bool equal(const ValueType&, const T&); + // static translate(ValueType&, const T&, unsigned hashCode); + template<typename T, typename HashTranslator> pair<iterator, bool> add(const T&, const MappedType&); + private: pair<iterator, bool> inlineAdd(const KeyType&, const MappedType&); @@ -107,6 +124,19 @@ namespace WTF { } }; + template<typename ValueType, typename ValueTraits, typename T, typename Translator> + struct HashMapTranslatorAdapter { + typedef typename ValueType::first_type KeyType; + typedef typename ValueType::second_type MappedType; + + static unsigned hash(const T& key) { return Translator::hash(key); } + static bool equal(const KeyType& a, const T& b) { return Translator::equal(a, b); } + static void translate(ValueType& location, const T& key, const MappedType&, unsigned hashCode) + { + Translator::translate(location.first, key, hashCode); + } + }; + template<typename T, typename U, typename V, typename W, typename X> inline void HashMap<T, U, V, W, X>::swap(HashMap& other) { @@ -174,6 +204,33 @@ namespace WTF { } template<typename T, typename U, typename V, typename W, typename X> + template<typename TYPE, typename HashTranslator> + inline typename HashMap<T, U, V, W, X>::iterator + HashMap<T, U, V, W, X>::find(const TYPE& value) + { + typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter; + return m_impl.template find<TYPE, Adapter>(value); + } + + template<typename T, typename U, typename V, typename W, typename X> + template<typename TYPE, typename HashTranslator> + inline typename HashMap<T, U, V, W, X>::const_iterator + HashMap<T, U, V, W, X>::find(const TYPE& value) const + { + typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter; + return m_impl.template find<TYPE, Adapter>(value); + } + + template<typename T, typename U, typename V, typename W, typename X> + template<typename TYPE, typename HashTranslator> + inline bool + HashMap<T, U, V, W, X>::contains(const TYPE& value) const + { + typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter; + return m_impl.template contains<TYPE, Adapter>(value); + } + + template<typename T, typename U, typename V, typename W, typename X> inline pair<typename HashMap<T, U, V, W, X>::iterator, bool> HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, const MappedType& mapped) { @@ -197,6 +254,15 @@ namespace WTF { } template<typename T, typename U, typename V, typename W, typename X> + template<typename TYPE, typename HashTranslator> + pair<typename HashMap<T, U, V, W, X>::iterator, bool> + HashMap<T, U, V, W, X>::add(const TYPE& key, const MappedType& value) + { + typedef HashMapTranslatorAdapter<ValueType, ValueTraits, TYPE, HashTranslator> Adapter; + return m_impl.template addPassingHashCode<TYPE, MappedType, Adapter>(key, value); + } + + template<typename T, typename U, typename V, typename W, typename X> pair<typename HashMap<T, U, V, W, X>::iterator, bool> HashMap<T, U, V, W, X>::add(const KeyType& key, const MappedType& mapped) { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashSet.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashSet.h index 3906a36..e56e384 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashSet.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashSet.h @@ -81,7 +81,7 @@ namespace WTF { // An alternate version of add() that finds the object by hashing and comparing // with some other type, to avoid the cost of type conversion if the object is already - // in the table. HashTranslator must have the following methods: + // in the table. HashTranslator must have the following function members: // static unsigned hash(const T&); // static bool equal(const ValueType&, const T&); // static translate(ValueType&, const T&, unsigned hashCode); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashTable.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashTable.h index 3b283f8..92533fa 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashTable.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/HashTable.h @@ -197,7 +197,7 @@ namespace WTF { void checkValidity(const const_iterator& other) const { ASSERT(m_table); - ASSERT(other.m_table); + ASSERT_UNUSED(other, other.m_table); ASSERT(m_table == other.m_table); } #else diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ListHashSet.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ListHashSet.h index 38cc998..54ed36b 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ListHashSet.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ListHashSet.h @@ -51,7 +51,7 @@ namespace WTF { template<typename ValueArg> struct ListHashSetNodeAllocator; template<typename ValueArg, typename HashArg> struct ListHashSetNodeHashFunctions; - template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet { + template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet : public FastAllocBase { private: typedef ListHashSetNode<ValueArg> Node; typedef ListHashSetNodeAllocator<ValueArg> NodeAllocator; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ListRefPtr.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ListRefPtr.h index d863226..8bf6447 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ListRefPtr.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ListRefPtr.h @@ -44,6 +44,9 @@ namespace WTF { template <typename U> ListRefPtr& operator=(const PassRefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; } }; + // Remove inline for winscw compiler to prevent the compiler agressively resolving + // T::ref() in RefPtr<T>'s copy constructor. The bug is reported at: + // https://xdabug001.ext.nokia.com/bugzilla/show_bug.cgi?id=9812. template <typename T> #if !COMPILER(WINSCW) inline diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MainThread.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MainThread.cpp index e999094..40a4ae5 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MainThread.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MainThread.cpp @@ -39,10 +39,12 @@ namespace WTF { struct FunctionWithContext { MainThreadFunction* function; void* context; + ThreadCondition* syncFlag; - FunctionWithContext(MainThreadFunction* function = 0, void* context = 0) + FunctionWithContext(MainThreadFunction* function = 0, void* context = 0, ThreadCondition* syncFlag = 0) : function(function) , context(context) + , syncFlag(syncFlag) { } }; @@ -92,6 +94,8 @@ void dispatchFunctionsFromMainThread() } invocation.function(invocation.context); + if (invocation.syncFlag) + invocation.syncFlag->signal(); // If we are running accumulated functions for too long so UI may become unresponsive, we need to // yield so the user input can be processed. Otherwise user may not be able to even close the window. @@ -117,6 +121,24 @@ void callOnMainThread(MainThreadFunction* function, void* context) scheduleDispatchFunctionsOnMainThread(); } +void callOnMainThreadAndWait(MainThreadFunction* function, void* context) +{ + ASSERT(function); + + if (isMainThread()) { + function(context); + return; + } + + ThreadCondition syncFlag; + Mutex& functionQueueMutex = mainThreadFunctionQueueMutex(); + MutexLocker locker(functionQueueMutex); + functionQueue().append(FunctionWithContext(function, context, &syncFlag)); + if (functionQueue().size() == 1) + scheduleDispatchFunctionsOnMainThread(); + syncFlag.wait(functionQueueMutex); +} + void setMainThreadCallbacksPaused(bool paused) { ASSERT(isMainThread()); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MainThread.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MainThread.h index b8305b5..11a5eb1 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MainThread.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MainThread.h @@ -40,6 +40,9 @@ extern "C" { void callOnMainThread(MainThreadFunction*, void* context); +// Blocks the thread until the call finishes on the main thread. Misusing this can easily cause deadlocks. +void callOnMainThreadAndWait(MainThreadFunction*, void* context); + void setMainThreadCallbacksPaused(bool paused); // Must be called from the main thread (Darwin is an exception to this rule). @@ -54,6 +57,7 @@ void dispatchFunctionsFromMainThread(); } // namespace WTF using WTF::callOnMainThread; +using WTF::callOnMainThreadAndWait; using WTF::setMainThreadCallbacksPaused; #endif // MainThread_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MathExtras.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MathExtras.h index 324300d..9ea57fd 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MathExtras.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MathExtras.h @@ -26,28 +26,24 @@ #ifndef WTF_MathExtras_h #define WTF_MathExtras_h +#include <float.h> #include <math.h> #include <stdlib.h> -#if PLATFORM(SOLARIS) +#if OS(SOLARIS) #include <ieeefp.h> #endif -#if PLATFORM(OPENBSD) +#if OS(OPENBSD) #include <sys/types.h> #include <machine/ieee.h> #endif #if COMPILER(MSVC) -#if PLATFORM(WINCE) +#if OS(WINCE) #include <stdlib.h> #endif #include <limits> - -#if HAVE(FLOAT_H) -#include <float.h> -#endif - #endif #ifndef M_PI @@ -66,7 +62,7 @@ const double piOverFourDouble = M_PI_4; const float piOverFourFloat = static_cast<float>(M_PI_4); #endif -#if PLATFORM(DARWIN) +#if OS(DARWIN) // Work around a bug in the Mac OS X libc where ceil(-0.1) return +0. inline double wtf_ceil(double x) { return copysign(ceil(x), x); } @@ -75,7 +71,7 @@ inline double wtf_ceil(double x) { return copysign(ceil(x), x); } #endif -#if PLATFORM(SOLARIS) +#if OS(SOLARIS) #ifndef isfinite inline bool isfinite(double x) { return finite(x) && !isnand(x); } @@ -89,7 +85,7 @@ inline bool signbit(double x) { return x < 0.0; } // FIXME: Wrong for negative 0 #endif -#if PLATFORM(OPENBSD) +#if OS(OPENBSD) #ifndef isfinite inline bool isfinite(double x) { return finite(x); } @@ -102,6 +98,8 @@ inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x #if COMPILER(MSVC) || COMPILER(RVCT) +inline long long llround(double num) { return static_cast<long long>(num > 0 ? num + 0.5 : ceil(num - 0.5)); } +inline long long llroundf(float num) { return static_cast<long long>(num > 0 ? num + 0.5f : ceil(num - 0.5f)); } inline long lround(double num) { return static_cast<long>(num > 0 ? num + 0.5 : ceil(num - 0.5)); } inline long lroundf(float num) { return static_cast<long>(num > 0 ? num + 0.5f : ceilf(num - 0.5f)); } inline double round(double num) { return num > 0 ? floor(num + 0.5) : ceil(num - 0.5); } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MessageQueue.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MessageQueue.h index 070b76c..48bd10a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MessageQueue.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/MessageQueue.h @@ -41,23 +41,31 @@ namespace WTF { enum MessageQueueWaitResult { MessageQueueTerminated, // Queue was destroyed while waiting for message. MessageQueueTimeout, // Timeout was specified and it expired. - MessageQueueMessageReceived // A message was successfully received and returned. + MessageQueueMessageReceived, // A message was successfully received and returned. }; + // The queue takes ownership of messages and transfer it to the new owner + // when messages are fetched from the queue. + // Essentially, MessageQueue acts as a queue of OwnPtr<DataType>. template<typename DataType> class MessageQueue : public Noncopyable { public: MessageQueue() : m_killed(false) { } - - void append(const DataType&); - bool appendAndCheckEmpty(const DataType&); - void prepend(const DataType&); - bool waitForMessage(DataType&); + ~MessageQueue(); + + void append(PassOwnPtr<DataType>); + bool appendAndCheckEmpty(PassOwnPtr<DataType>); + void prepend(PassOwnPtr<DataType>); + + PassOwnPtr<DataType> waitForMessage(); + PassOwnPtr<DataType> tryGetMessage(); template<typename Predicate> - MessageQueueWaitResult waitForMessageFilteredWithTimeout(DataType&, Predicate&, double absoluteTime); - void kill(); + PassOwnPtr<DataType> waitForMessageFilteredWithTimeout(MessageQueueWaitResult&, Predicate&, double absoluteTime); + + template<typename Predicate> + void removeIf(Predicate&); - bool tryGetMessage(DataType&); + void kill(); bool killed() const; // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time. @@ -66,86 +74,115 @@ namespace WTF { static double infiniteTime() { return std::numeric_limits<double>::max(); } private: - static bool alwaysTruePredicate(DataType&) { return true; } + static bool alwaysTruePredicate(DataType*) { return true; } mutable Mutex m_mutex; ThreadCondition m_condition; - Deque<DataType> m_queue; + Deque<DataType*> m_queue; bool m_killed; }; template<typename DataType> - inline void MessageQueue<DataType>::append(const DataType& message) + MessageQueue<DataType>::~MessageQueue() + { + deleteAllValues(m_queue); + } + + template<typename DataType> + inline void MessageQueue<DataType>::append(PassOwnPtr<DataType> message) { MutexLocker lock(m_mutex); - m_queue.append(message); + m_queue.append(message.release()); m_condition.signal(); } // Returns true if the queue was empty before the item was added. template<typename DataType> - inline bool MessageQueue<DataType>::appendAndCheckEmpty(const DataType& message) + inline bool MessageQueue<DataType>::appendAndCheckEmpty(PassOwnPtr<DataType> message) { MutexLocker lock(m_mutex); bool wasEmpty = m_queue.isEmpty(); - m_queue.append(message); + m_queue.append(message.release()); m_condition.signal(); return wasEmpty; } template<typename DataType> - inline void MessageQueue<DataType>::prepend(const DataType& message) + inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message) { MutexLocker lock(m_mutex); - m_queue.prepend(message); + m_queue.prepend(message.release()); m_condition.signal(); } template<typename DataType> - inline bool MessageQueue<DataType>::waitForMessage(DataType& result) + inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessage() { - MessageQueueWaitResult exitReason = waitForMessageFilteredWithTimeout(result, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime()); + MessageQueueWaitResult exitReason; + PassOwnPtr<DataType> result = waitForMessageFilteredWithTimeout(exitReason, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime()); ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived); - return exitReason == MessageQueueMessageReceived; + return result; } template<typename DataType> template<typename Predicate> - inline MessageQueueWaitResult MessageQueue<DataType>::waitForMessageFilteredWithTimeout(DataType& result, Predicate& predicate, double absoluteTime) + inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessageFilteredWithTimeout(MessageQueueWaitResult& result, Predicate& predicate, double absoluteTime) { MutexLocker lock(m_mutex); bool timedOut = false; - DequeConstIterator<DataType> found = m_queue.end(); + DequeConstIterator<DataType*> found = m_queue.end(); while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end()) timedOut = !m_condition.timedWait(m_mutex, absoluteTime); ASSERT(!timedOut || absoluteTime != infiniteTime()); - if (m_killed) - return MessageQueueTerminated; + if (m_killed) { + result = MessageQueueTerminated; + return 0; + } - if (timedOut) - return MessageQueueTimeout; + if (timedOut) { + result = MessageQueueTimeout; + return 0; + } ASSERT(found != m_queue.end()); - result = *found; + DataType* message = *found; m_queue.remove(found); - return MessageQueueMessageReceived; + result = MessageQueueMessageReceived; + return message; } template<typename DataType> - inline bool MessageQueue<DataType>::tryGetMessage(DataType& result) + inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessage() { MutexLocker lock(m_mutex); if (m_killed) - return false; + return 0; if (m_queue.isEmpty()) - return false; + return 0; - result = m_queue.first(); + DataType* message = m_queue.first(); m_queue.removeFirst(); - return true; + return message; + } + + template<typename DataType> + template<typename Predicate> + inline void MessageQueue<DataType>::removeIf(Predicate& predicate) + { + MutexLocker lock(m_mutex); + // See bug 31657 for why this loop looks so weird + while (true) { + DequeConstIterator<DataType*> found = m_queue.findIf(predicate); + if (found == m_queue.end()) + break; + + DataType* message = *found; + m_queue.remove(found); + delete message; + } } template<typename DataType> diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/PassRefPtr.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/PassRefPtr.h index ae398d3..36ba78e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/PassRefPtr.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/PassRefPtr.h @@ -42,20 +42,10 @@ namespace WTF { ptr->deref(); } - template<typename T> -#if !COMPILER(WINSCW) - inline -#endif - void refIfNotNull(T* ptr) - { - if (UNLIKELY(ptr != 0)) - ptr->ref(); - } - template<typename T> class PassRefPtr { public: PassRefPtr() : m_ptr(0) {} - PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } + PassRefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); } // It somewhat breaks the type system to allow transfer of ownership out of // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr // temporaries, and we don't really have a need to use real const PassRefPtrs @@ -63,14 +53,14 @@ namespace WTF { PassRefPtr(const PassRefPtr& o) : m_ptr(o.releaseRef()) {} template <typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.releaseRef()) { } - ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); } + ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull<T>(m_ptr); } template <class U> - PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { T* ptr = m_ptr; refIfNotNull(ptr); } + PassRefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); } T* get() const { return m_ptr; } - void clear() { T* ptr = m_ptr; derefIfNotNull(ptr); m_ptr = 0; } + void clear() { if (T* ptr = m_ptr) ptr->deref(); m_ptr = 0; } T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; } T& operator*() const { return *m_ptr; } @@ -79,7 +69,6 @@ namespace WTF { bool operator!() const { return !m_ptr; } // This conversion operator allows implicit conversion to bool but not to other integer types. - // Parenthesis is needed for winscw compiler to resolve class qualifier in this case. typedef T* (PassRefPtr::*UnspecifiedBoolType); operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; } @@ -95,22 +84,82 @@ namespace WTF { mutable T* m_ptr; }; + // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr + // begins life non-null, and can only become null through a call to releaseRef() + // or clear(). + + // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However, + // if we use inheritance, GCC's optimizer fails to realize that destruction + // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the + // most important code from PassRefPtr. + template <typename T> class NonNullPassRefPtr { + public: + NonNullPassRefPtr(T* ptr) + : m_ptr(ptr) + { + ASSERT(m_ptr); + m_ptr->ref(); + } + + template <class U> NonNullPassRefPtr(const RefPtr<U>& o) + : m_ptr(o.get()) + { + ASSERT(m_ptr); + m_ptr->ref(); + } + + NonNullPassRefPtr(const NonNullPassRefPtr& o) + : m_ptr(o.releaseRef()) + { + ASSERT(m_ptr); + } + + template <class U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o) + : m_ptr(o.releaseRef()) + { + ASSERT(m_ptr); + } + + template <class U> NonNullPassRefPtr(const PassRefPtr<U>& o) + : m_ptr(o.releaseRef()) + { + ASSERT(m_ptr); + } + + ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); } + + T* get() const { return m_ptr; } + + void clear() { derefIfNotNull(m_ptr); m_ptr = 0; } + T* releaseRef() const { T* tmp = m_ptr; m_ptr = 0; return tmp; } + + T& operator*() const { return *m_ptr; } + T* operator->() const { return m_ptr; } + + private: + mutable T* m_ptr; + }; + template <typename T> template <typename U> inline PassRefPtr<T>& PassRefPtr<T>::operator=(const RefPtr<U>& o) { T* optr = o.get(); - refIfNotNull(optr); + if (optr) + optr->ref(); T* ptr = m_ptr; m_ptr = optr; - derefIfNotNull(ptr); + if (ptr) + ptr->deref(); return *this; } template <typename T> inline PassRefPtr<T>& PassRefPtr<T>::operator=(T* optr) { - refIfNotNull(optr); + if (optr) + optr->ref(); T* ptr = m_ptr; m_ptr = optr; - derefIfNotNull(ptr); + if (ptr) + ptr->deref(); return *this; } @@ -118,7 +167,8 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = ref.releaseRef(); - derefIfNotNull(ptr); + if (ptr) + ptr->deref(); return *this; } @@ -126,7 +176,8 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = ref.releaseRef(); - derefIfNotNull(ptr); + if (ptr) + ptr->deref(); return *this; } @@ -203,6 +254,7 @@ namespace WTF { } // namespace WTF using WTF::PassRefPtr; +using WTF::NonNullPassRefPtr; using WTF::adoptRef; using WTF::static_pointer_cast; using WTF::const_pointer_cast; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h index be74e2a..ec9a1e3 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h @@ -27,163 +27,451 @@ #ifndef WTF_Platform_h #define WTF_Platform_h -/* PLATFORM handles OS, operating environment, graphics API, and CPU */ +/* ==== PLATFORM handles OS, operating environment, graphics API, and + CPU. This macro will be phased out in favor of platform adaptation + macros, policy decision macros, and top-level port definitions. ==== */ #define PLATFORM(WTF_FEATURE) (defined WTF_PLATFORM_##WTF_FEATURE && WTF_PLATFORM_##WTF_FEATURE) + + +/* ==== Platform adaptation macros: these describe properties of the target environment. ==== */ + +/* COMPILER() - the compiler being used to build the project */ #define COMPILER(WTF_FEATURE) (defined WTF_COMPILER_##WTF_FEATURE && WTF_COMPILER_##WTF_FEATURE) +/* CPU() - the target CPU architecture */ +#define CPU(WTF_FEATURE) (defined WTF_CPU_##WTF_FEATURE && WTF_CPU_##WTF_FEATURE) +/* HAVE() - specific system features (headers, functions or similar) that are present or not */ #define HAVE(WTF_FEATURE) (defined HAVE_##WTF_FEATURE && HAVE_##WTF_FEATURE) +/* OS() - underlying operating system; only to be used for mandated low-level services like + virtual memory, not to choose a GUI toolkit */ +#define OS(WTF_FEATURE) (defined WTF_OS_##WTF_FEATURE && WTF_OS_##WTF_FEATURE) + + +/* ==== Policy decision macros: these define policy choices for a particular port. ==== */ + +/* USE() - use a particular third-party library or optional OS service */ #define USE(WTF_FEATURE) (defined WTF_USE_##WTF_FEATURE && WTF_USE_##WTF_FEATURE) +/* ENABLE() - turn on a specific feature of WebKit */ #define ENABLE(WTF_FEATURE) (defined ENABLE_##WTF_FEATURE && ENABLE_##WTF_FEATURE) -/* Operating systems - low-level dependencies */ -/* PLATFORM(DARWIN) */ -/* Operating system level dependencies for Mac OS X / Darwin that should */ -/* be used regardless of operating environment */ -#ifdef __APPLE__ -#define WTF_PLATFORM_DARWIN 1 -#include <AvailabilityMacros.h> -#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 -#define BUILDING_ON_TIGER 1 -#elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 -#define BUILDING_ON_LEOPARD 1 + +/* ==== COMPILER() - the compiler being used to build the project ==== */ + +/* COMPILER(MSVC) Microsoft Visual C++ */ +/* COMPILER(MSVC7) Microsoft Visual C++ v7 or lower*/ +#if defined(_MSC_VER) +#define WTF_COMPILER_MSVC 1 +#if _MSC_VER < 1400 +#define WTF_COMPILER_MSVC7 1 #endif -#include <TargetConditionals.h> #endif -/* PLATFORM(WIN_OS) */ -/* Operating system level dependencies for Windows that should be used */ -/* regardless of operating environment */ -#if defined(WIN32) || defined(_WIN32) -#define WTF_PLATFORM_WIN_OS 1 +/* COMPILER(RVCT) - ARM RealView Compilation Tools */ +#if defined(__CC_ARM) || defined(__ARMCC__) +#define WTF_COMPILER_RVCT 1 #endif -/* PLATFORM(WINCE) */ -/* Operating system level dependencies for Windows CE that should be used */ -/* regardless of operating environment */ -/* Note that for this platform PLATFORM(WIN_OS) is also defined. */ -#if defined(_WIN32_WCE) -#define WTF_PLATFORM_WINCE 1 +/* COMPILER(GCC) - GNU Compiler Collection */ +/* --gnu option of the RVCT compiler also defines __GNUC__ */ +#if defined(__GNUC__) && !COMPILER(RVCT) +#define WTF_COMPILER_GCC 1 +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #endif -/* PLATFORM(LINUX) */ -/* Operating system level dependencies for Linux-like systems that */ -/* should be used regardless of operating environment */ -#ifdef __linux__ -#define WTF_PLATFORM_LINUX 1 +/* COMPILER(MINGW) - MinGW GCC */ +#if defined(MINGW) || defined(__MINGW32__) +#define WTF_COMPILER_MINGW 1 #endif -/* PLATFORM(FREEBSD) */ -/* Operating system level dependencies for FreeBSD-like systems that */ -/* should be used regardless of operating environment */ -#ifdef __FreeBSD__ -#define WTF_PLATFORM_FREEBSD 1 +/* COMPILER(SUNCC) - Sun CC compiler, also known as Sun Studio or Sun Pro */ +#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) +#define WTF_COMPILER_SUNCC 1 #endif -/* PLATFORM(OPENBSD) */ -/* Operating system level dependencies for OpenBSD systems that */ -/* should be used regardless of operating environment */ -#ifdef __OpenBSD__ -#define WTF_PLATFORM_OPENBSD 1 +/* COMPILER(WINSCW) - CodeWarrior for Symbian emulator */ +#if defined(__WINSCW__) +#define WTF_COMPILER_WINSCW 1 #endif -/* PLATFORM(SOLARIS) */ -/* Operating system level dependencies for Solaris that should be used */ -/* regardless of operating environment */ -#if defined(sun) || defined(__sun) -#define WTF_PLATFORM_SOLARIS 1 +/* COMPILER(ACC) - HP aCC */ +#if defined(__HP_aCC) +#define WTF_COMPILER_ACC 1 +#endif + +/* COMPILER(XLC) - IBM XL */ +#if defined(__xlC__) +#define WTF_COMPILER_XLC 1 +#endif + + +/* ==== CPU() - the target CPU architecture ==== */ + +/* This also defines CPU(BIG_ENDIAN) or CPU(MIDDLE_ENDIAN) or neither, as appropriate. */ + +/* CPU(ALPHA) - DEC Alpha */ +#if defined(__alpha__) +#define WTF_CPU_ALPHA 1 +#endif + +/* CPU(IA64) - Itanium / IA-64 */ +#if defined(__ia64__) || defined(__ia64) || defined(_M_IA64) +#define WTF_CPU_IA64 1 +/* 32-bit mode on Itanium */ +#if !defined(__LP64__) +#define WTF_CPU_IA64_32 1 +#endif +/* Itanium can be both big- and little-endian; + we need to determine at compile time which one it is. + - HP's aCC compiler only compiles big-endian (so HP-UXi is always big-endian) + - GCC defines __BIG_ENDIAN__ for us (default on HP-UX) + - Linux is usually little-endian + - I've never seen AIX or Windows on IA-64, but they should be little-endian too +*/ +#if defined(__BIG_ENDIAN__) || defined(__HP_aCC) +# define WTF_CPU_BIG_ENDIAN 1 +#endif +#endif + +/* CPU(HPPA) - a.k.a. PA-RISC */ +#if defined(__hppa) || defined(__hppa__) +#define WTF_CPU_HPPA 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(PPC) - PowerPC 32-bit */ +#if defined(__ppc__) \ + || defined(__PPC__) \ + || defined(__powerpc__) \ + || defined(__powerpc) \ + || defined(__POWERPC__) \ + || defined(_M_PPC) \ + || defined(__PPC) +#define WTF_CPU_PPC 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(PPC64) - PowerPC 64-bit */ +#if defined(__ppc64__) \ + || defined(__PPC64__) +#define WTF_CPU_PPC64 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(SH4) - SuperH SH-4 */ +#if defined(__SH4__) +#define WTF_CPU_SH4 1 +#endif + +/* CPU(SPARC32) - SPARC 32-bit */ +#if defined(__sparc) && !defined(__arch64__) || defined(__sparcv8) +#define WTF_CPU_SPARC32 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(SPARC64) - SPARC 64-bit */ +#if defined(__sparc__) && defined(__arch64__) || defined (__sparcv9) +#define WTF_CPU_SPARC64 1 +#define WTF_CPU_BIG_ENDIAN 1 +#endif + +/* CPU(SPARC) - any SPARC, true for CPU(SPARC32) and CPU(SPARC64) */ +#if CPU(SPARC32) || CPU(SPARC64) +#define WTF_CPU_SPARC +#endif + +/* CPU(X86) - i386 / x86 32-bit */ +#if defined(__i386__) \ + || defined(i386) \ + || defined(_M_IX86) \ + || defined(_X86_) \ + || defined(__THW_INTEL) +#define WTF_CPU_X86 1 +#endif + +/* CPU(X86_64) - AMD64 / Intel64 / x86_64 64-bit */ +#if defined(__x86_64__) \ + || defined(_M_X64) +#define WTF_CPU_X86_64 1 #endif -/* PLATFORM(AIX) */ -/* Operating system level dependencies for AIX that should be used */ -/* regardless of operating environment */ -#if defined(_AIX) -#define WTF_PLATFORM_AIX 1 /* 64-bit mode on AIX */ #ifdef __64BIT__ -#define WTF_PLATFORM_AIX64 1 +#define WTF_CPU_AIX64 1 +#endif + +/* CPU(ARM) - ARM, any version*/ +#if defined(arm) \ + || defined(__arm__) \ + || defined(__MARM__) +#define WTF_CPU_ARM 1 + +#if defined(__ARMEB__) +#define WTF_CPU_BIG_ENDIAN 1 + +#elif !defined(__ARM_EABI__) \ + && !defined(__EABI__) \ + && !defined(__VFP_FP__) \ + && !defined(ANDROID) +#define WTF_CPU_MIDDLE_ENDIAN 1 + +#endif + +#define WTF_ARM_ARCH_AT_LEAST(N) (CPU(ARM) && WTF_ARM_ARCH_VERSION >= N) + +/* Set WTF_ARM_ARCH_VERSION */ +#if defined(__ARM_ARCH_4__) \ + || defined(__ARM_ARCH_4T__) \ + || defined(__MARM_ARMV4__) \ + || defined(_ARMV4I_) +#define WTF_ARM_ARCH_VERSION 4 + +#elif defined(__ARM_ARCH_5__) \ + || defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5E__) \ + || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) \ + || defined(__MARM_ARMV5__) +#define WTF_ARM_ARCH_VERSION 5 + +#elif defined(__ARM_ARCH_6__) \ + || defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6T2__) \ + || defined(__ARMV6__) +#define WTF_ARM_ARCH_VERSION 6 + +#elif defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) +#define WTF_ARM_ARCH_VERSION 7 + +/* RVCT sets _TARGET_ARCH_ARM */ +#elif defined(__TARGET_ARCH_ARM) +#define WTF_ARM_ARCH_VERSION __TARGET_ARCH_ARM + +#else +#define WTF_ARM_ARCH_VERSION 0 + +#endif + +/* Set WTF_THUMB_ARCH_VERSION */ +#if defined(__ARM_ARCH_4T__) +#define WTF_THUMB_ARCH_VERSION 1 + +#elif defined(__ARM_ARCH_5T__) \ + || defined(__ARM_ARCH_5TE__) \ + || defined(__ARM_ARCH_5TEJ__) +#define WTF_THUMB_ARCH_VERSION 2 + +#elif defined(__ARM_ARCH_6J__) \ + || defined(__ARM_ARCH_6K__) \ + || defined(__ARM_ARCH_6Z__) \ + || defined(__ARM_ARCH_6ZK__) \ + || defined(__ARM_ARCH_6M__) +#define WTF_THUMB_ARCH_VERSION 3 + +#elif defined(__ARM_ARCH_6T2__) \ + || defined(__ARM_ARCH_7__) \ + || defined(__ARM_ARCH_7A__) \ + || defined(__ARM_ARCH_7R__) \ + || defined(__ARM_ARCH_7M__) +#define WTF_THUMB_ARCH_VERSION 4 + +/* RVCT sets __TARGET_ARCH_THUMB */ +#elif defined(__TARGET_ARCH_THUMB) +#define WTF_THUMB_ARCH_VERSION __TARGET_ARCH_THUMB + +#else +#define WTF_THUMB_ARCH_VERSION 0 +#endif + + +/* CPU(ARMV5_OR_LOWER) - ARM instruction set v5 or earlier */ +/* On ARMv5 and below the natural alignment is required. + And there are some other differences for v5 or earlier. */ +#if !defined(ARMV5_OR_LOWER) && !WTF_ARM_ARCH_AT_LEAST(6) +#define WTF_CPU_ARMV5_OR_LOWER 1 +#endif + + +/* CPU(ARM_TRADITIONAL) - Thumb2 is not available, only traditional ARM (v4 or greater) */ +/* CPU(ARM_THUMB2) - Thumb2 instruction set is available */ +/* Only one of these will be defined. */ +#if !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2) +# if defined(thumb2) || defined(__thumb2__) \ + || ((defined(__thumb) || defined(__thumb__)) && WTF_THUMB_ARCH_VERSION == 4) +# define WTF_CPU_ARM_TRADITIONAL 0 +# define WTF_CPU_ARM_THUMB2 1 +# elif WTF_ARM_ARCH_AT_LEAST(4) +# define WTF_CPU_ARM_TRADITIONAL 1 +# define WTF_CPU_ARM_THUMB2 0 +# else +# error "Not supported ARM architecture" +# endif +#elif CPU(ARM_TRADITIONAL) && CPU(ARM_THUMB2) /* Sanity Check */ +# error "Cannot use both of WTF_CPU_ARM_TRADITIONAL and WTF_CPU_ARM_THUMB2 platforms" +#endif /* !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2) */ + +#endif /* ARM */ + + + +/* ==== OS() - underlying operating system; only to be used for mandated low-level services like + virtual memory, not to choose a GUI toolkit ==== */ + +/* OS(ANDROID) - Android */ +#ifdef ANDROID +#define WTF_OS_ANDROID 1 +#endif + +/* OS(AIX) - AIX */ +#ifdef _AIX +#define WTF_OS_AIX 1 +#endif + +/* OS(DARWIN) - Any Darwin-based OS, including Mac OS X and iPhone OS */ +#ifdef __APPLE__ +#define WTF_OS_DARWIN 1 + +/* FIXME: BUILDING_ON_.., and TARGETING... macros should be folded into the OS() system */ +#include <AvailabilityMacros.h> +#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5 +#define BUILDING_ON_TIGER 1 +#elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 +#define BUILDING_ON_LEOPARD 1 +#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 +#define BUILDING_ON_SNOW_LEOPARD 1 #endif +#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 +#define TARGETING_TIGER 1 +#elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 +#define TARGETING_LEOPARD 1 +#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 +#define TARGETING_SNOW_LEOPARD 1 +#endif +#include <TargetConditionals.h> + +#endif + +/* OS(IPHONE_OS) - iPhone OS */ +/* OS(MAC_OS_X) - Mac OS X (not including iPhone OS) */ +#if OS(DARWIN) && ((defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) \ + || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) \ + || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR)) +#define WTF_OS_IPHONE_OS 1 +#elif OS(DARWIN) && defined(TARGET_OS_MAC) && TARGET_OS_MAC +#define WTF_OS_MAC_OS_X 1 +#endif + +/* OS(FREEBSD) - FreeBSD */ +#ifdef __FreeBSD__ +#define WTF_OS_FREEBSD 1 +#endif + +/* OS(HAIKU) - Haiku */ +#ifdef __HAIKU__ +#define WTF_OS_HAIKU 1 #endif -/* PLATFORM(HPUX) */ -/* Operating system level dependencies for HP-UX that should be used */ -/* regardless of operating environment */ +/* OS(HPUX) - HP-UX */ #if defined(hpux) || defined(__hpux) -#define WTF_PLATFORM_HPUX 1 +#define WTF_OS_HPUX 1 #ifndef MAP_ANON #define MAP_ANON MAP_ANONYMOUS #endif #endif -#if defined (__SYMBIAN32__) -/* we are cross-compiling, it is not really windows */ -#undef WTF_PLATFORM_WIN_OS -#undef WTF_PLATFORM_WIN -#define WTF_PLATFORM_SYMBIAN 1 +/* OS(LINUX) - Linux */ +#ifdef __linux__ +#define WTF_OS_LINUX 1 #endif - -/* PLATFORM(NETBSD) */ -/* Operating system level dependencies for NetBSD that should be used */ -/* regardless of operating environment */ +/* OS(NETBSD) - NetBSD */ #if defined(__NetBSD__) #define WTF_PLATFORM_NETBSD 1 #endif -/* PLATFORM(QNX) */ -/* Operating system level dependencies for QNX that should be used */ -/* regardless of operating environment */ +/* OS(OPENBSD) - OpenBSD */ +#ifdef __OpenBSD__ +#define WTF_OS_OPENBSD 1 +#endif + +/* OS(QNX) - QNX */ #if defined(__QNXNTO__) -#define WTF_PLATFORM_QNX 1 -#endif - -/* PLATFORM(UNIX) */ -/* Operating system level dependencies for Unix-like systems that */ -/* should be used regardless of operating environment */ -#if PLATFORM(DARWIN) \ - || PLATFORM(FREEBSD) \ - || PLATFORM(SYMBIAN) \ - || PLATFORM(NETBSD) \ - || PLATFORM(SOLARIS) \ - || PLATFORM(HPUX) \ - || defined(unix) \ - || defined(__unix) \ - || defined(__unix__) \ - || PLATFORM(AIX) \ - || defined(__HAIKU__) \ - || defined(__QNXNTO__) -#define WTF_PLATFORM_UNIX 1 +#define WTF_OS_QNX 1 +#endif + +/* OS(SOLARIS) - Solaris */ +#if defined(sun) || defined(__sun) +#define WTF_OS_SOLARIS 1 +#endif + +/* OS(WINCE) - Windows CE; note that for this platform OS(WINDOWS) is also defined */ +#if defined(_WIN32_WCE) +#define WTF_OS_WINCE 1 +#endif + +/* OS(WINDOWS) - Any version of Windows */ +#if defined(WIN32) || defined(_WIN32) +#define WTF_OS_WINDOWS 1 +#endif + +/* OS(SYMBIAN) - Symbian */ +#if defined (__SYMBIAN32__) +/* we are cross-compiling, it is not really windows */ +#undef WTF_OS_WINDOWS +#undef WTF_PLATFORM_WIN +#define WTF_OS_SYMBIAN 1 +#endif + +/* OS(UNIX) - Any Unix-like system */ +#if OS(AIX) \ + || OS(ANDROID) \ + || OS(DARWIN) \ + || OS(FREEBSD) \ + || OS(HAIKU) \ + || OS(HPUX) \ + || OS(LINUX) \ + || OS(NETBSD) \ + || OS(OPENBSD) \ + || OS(QNX) \ + || OS(SOLARIS) \ + || OS(SYMBIAN) \ + || defined(unix) \ + || defined(__unix) \ + || defined(__unix__) +#define WTF_OS_UNIX 1 #endif /* Operating environments */ +/* FIXME: these are all mixes of OS, operating environment and policy choices. */ /* PLATFORM(CHROMIUM) */ /* PLATFORM(QT) */ +/* PLATFORM(WX) */ /* PLATFORM(GTK) */ +/* PLATFORM(HAIKU) */ /* PLATFORM(MAC) */ /* PLATFORM(WIN) */ #if defined(BUILDING_CHROMIUM__) #define WTF_PLATFORM_CHROMIUM 1 #elif defined(BUILDING_QT__) #define WTF_PLATFORM_QT 1 - -/* PLATFORM(KDE) */ -#if defined(BUILDING_KDE__) -#define WTF_PLATFORM_KDE 1 -#endif - #elif defined(BUILDING_WX__) #define WTF_PLATFORM_WX 1 #elif defined(BUILDING_GTK__) #define WTF_PLATFORM_GTK 1 #elif defined(BUILDING_HAIKU__) #define WTF_PLATFORM_HAIKU 1 -#elif PLATFORM(DARWIN) +#elif OS(DARWIN) #define WTF_PLATFORM_MAC 1 -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) #define WTF_PLATFORM_WIN 1 #endif /* PLATFORM(IPHONE) */ +/* FIXME: this is sometimes used as an OS switch and sometimes for higher-level things */ #if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) #define WTF_PLATFORM_IPHONE 1 #endif @@ -200,6 +488,13 @@ #define WTF_PLATFORM_IPHONE 0 #endif +/* PLATFORM(ANDROID) */ +/* FIXME: this is sometimes used as an OS() switch, and other times to drive + policy choices */ +#if defined(ANDROID) +#define WTF_PLATFORM_ANDROID 1 +#endif + /* Graphics engines */ /* PLATFORM(CG) and PLATFORM(CI) */ @@ -212,251 +507,48 @@ /* PLATFORM(SKIA) for Win/Linux, CG/CI for Mac */ #if PLATFORM(CHROMIUM) -#if PLATFORM(DARWIN) +#define ENABLE_HISTORY_ALWAYS_ASYNC 1 +#if OS(DARWIN) #define WTF_PLATFORM_CG 1 #define WTF_PLATFORM_CI 1 #define WTF_USE_ATSUI 1 +#define WTF_USE_CORE_TEXT 1 #else #define WTF_PLATFORM_SKIA 1 #endif #endif -/* Makes PLATFORM(WIN) default to PLATFORM(CAIRO) */ -/* FIXME: This should be changed from a blacklist to a whitelist */ -#if !PLATFORM(MAC) && !PLATFORM(QT) && !PLATFORM(WX) && !PLATFORM(CHROMIUM) && !PLATFORM(WINCE) && !PLATFORM(HAIKU) +#if PLATFORM(GTK) #define WTF_PLATFORM_CAIRO 1 #endif -/* CPU */ - -/* PLATFORM(PPC) */ -#if defined(__ppc__) \ - || defined(__PPC__) \ - || defined(__powerpc__) \ - || defined(__powerpc) \ - || defined(__POWERPC__) \ - || defined(_M_PPC) \ - || defined(__PPC) -#define WTF_PLATFORM_PPC 1 -#define WTF_PLATFORM_BIG_ENDIAN 1 -#endif - -/* PLATFORM(PPC64) */ -#if defined(__ppc64__) \ - || defined(__PPC64__) -#define WTF_PLATFORM_PPC64 1 -#define WTF_PLATFORM_BIG_ENDIAN 1 -#endif - -/* PLATFORM(ARM) */ -#define PLATFORM_ARM_ARCH(N) (PLATFORM(ARM) && ARM_ARCH_VERSION >= N) - -#if defined(arm) \ - || defined(__arm__) \ - || defined(__MARM__) -#define WTF_PLATFORM_ARM 1 -#if defined(__ARMEB__) -#define WTF_PLATFORM_BIG_ENDIAN 1 -#elif !defined(__ARM_EABI__) && !defined(__EABI__) && !defined(__VFP_FP__) -#define WTF_PLATFORM_MIDDLE_ENDIAN 1 -#endif -#define ARM_ARCH_VERSION 3 -#if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__) || defined(ARMV4I) \ - || defined(_ARMV4I_) || defined(armv4i) -#undef ARM_ARCH_VERSION -#define ARM_ARCH_VERSION 4 -#endif -#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \ - || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \ - || defined(__ARM_ARCH_5TEJ__) || defined(__MARM_ARMV5__) -#undef ARM_ARCH_VERSION -#define ARM_ARCH_VERSION 5 -#endif -#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \ - || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \ - || defined(__ARM_ARCH_6ZK__) || defined(__ARMV6__) -#undef ARM_ARCH_VERSION -#define ARM_ARCH_VERSION 6 -#endif -#if defined(__ARM_ARCH_7A__) || defined(__ARMV7__) -#undef ARM_ARCH_VERSION -#define ARM_ARCH_VERSION 7 -#endif -/* On ARMv5 and below the natural alignment is required. */ -#if !defined(ARM_REQUIRE_NATURAL_ALIGNMENT) && ARM_ARCH_VERSION <= 5 -#define ARM_REQUIRE_NATURAL_ALIGNMENT 1 -#endif -/* Defines two pseudo-platforms for ARM and Thumb-2 instruction set. */ -#if !defined(WTF_PLATFORM_ARM_TRADITIONAL) && !defined(WTF_PLATFORM_ARM_THUMB2) -# if defined(thumb2) || defined(__thumb2__) -# define WTF_PLATFORM_ARM_TRADITIONAL 0 -# define WTF_PLATFORM_ARM_THUMB2 1 -# elif PLATFORM_ARM_ARCH(4) || PLATFORM_ARM_ARCH(5) -# define WTF_PLATFORM_ARM_TRADITIONAL 1 -# define WTF_PLATFORM_ARM_THUMB2 0 -# else -# error "Not supported ARM architecture" -# endif -#elif PLATFORM(ARM_TRADITIONAL) && PLATFORM(ARM_THUMB2) /* Sanity Check */ -# error "Cannot use both of WTF_PLATFORM_ARM_TRADITIONAL and WTF_PLATFORM_ARM_THUMB2 platforms" -#endif // !defined(ARM_TRADITIONAL) && !defined(ARM_THUMB2) -#endif /* ARM */ - -/* PLATFORM(X86) */ -#if defined(__i386__) \ - || defined(i386) \ - || defined(_M_IX86) \ - || defined(_X86_) \ - || defined(__THW_INTEL) -#define WTF_PLATFORM_X86 1 -#endif - -/* PLATFORM(X86_64) */ -#if defined(__x86_64__) \ - || defined(_M_X64) -#define WTF_PLATFORM_X86_64 1 -#endif - -/* PLATFORM(SH4) */ -#if defined(__SH4__) -#define WTF_PLATFORM_SH4 1 -#endif - -/* PLATFORM(SPARC64) */ -#if defined(__sparc__) && defined(__arch64__) || defined (__sparcv9) -#define WTF_PLATFORM_SPARC64 1 -#define WTF_PLATFORM_BIG_ENDIAN 1 -#endif - -/* PLATFORM(SPARC32) */ -#if defined(__sparc) && !defined(__arch64__) || defined(__sparcv8) -#define WTF_PLATFORM_SPARC32 1 -#define WTF_PLATFORM_BIG_ENDIAN 1 -#endif - -#if PLATFORM(SPARC32) || PLATFORM(SPARC64) -#define WTF_PLATFORM_SPARC -#endif -/* PLATFORM(HPPA) */ -/* a.k.a. PA-RISC */ -#if defined(__hppa) || defined(__hppa__) -#define WTF_PLATFORM_HPPA 1 -#define WTF_PLATFORM_BIG_ENDIAN 1 -#endif - -/* PLATFORM(IA64) */ -/* a.k.a. Itanium Processor Family, IPF */ -#if defined(__ia64) || defined(__ia64__) || defined(_M_IA64) -#define WTF_PLATFORM_IA64 1 - -/* 32-bit mode on Itanium */ -#if !defined(__LP64__) -#define WTF_PLATFORM_IA64_32 1 -#endif - -/* Itanium can be both big- and little-endian - we need to determine at compile time which one it is. - - HP's aCC compiler only compiles big-endian (so HP-UXi is always big-endian) - - GCC defines __BIG_ENDIAN__ for us (default on HP-UX) - - Linux is usually little-endian - - I've never seen AIX or Windows on IA-64, but they should be little-endian too -*/ -#if defined(__BIG_ENDIAN__) || defined(__HP_aCC) -# define WTF_PLATFORM_BIG_ENDIAN 1 -#endif -#endif - -/* PLATFORM(WINCE) && PLATFORM(QT) +/* OS(WINCE) && PLATFORM(QT) We can not determine the endianess at compile time. For Qt for Windows CE the endianess is specified in the device specific makespec */ -#if PLATFORM(WINCE) && PLATFORM(QT) +#if OS(WINCE) && PLATFORM(QT) # include <QtGlobal> # undef WTF_PLATFORM_BIG_ENDIAN # undef WTF_PLATFORM_MIDDLE_ENDIAN # if Q_BYTE_ORDER == Q_BIG_EDIAN # define WTF_PLATFORM_BIG_ENDIAN 1 # endif -#endif -#if PLATFORM(WINCE) && PLATFORM(QT) # include <ce_time.h> #endif -/* Compiler */ - -/* COMPILER(MSVC) */ -#if defined(_MSC_VER) -#define WTF_COMPILER_MSVC 1 -#if _MSC_VER < 1400 -#define WTF_COMPILER_MSVC7 1 -#endif -#endif - -/* COMPILER(RVCT) */ -#if defined(__CC_ARM) || defined(__ARMCC__) -#define WTF_COMPILER_RVCT 1 -#endif - -/* COMPILER(GCC) */ -/* --gnu option of the RVCT compiler also defines __GNUC__ */ -#if defined(__GNUC__) && !COMPILER(RVCT) -#define WTF_COMPILER_GCC 1 -#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#endif - -/* COMPILER(MINGW) */ -#if defined(MINGW) || defined(__MINGW32__) -#define WTF_COMPILER_MINGW 1 -#endif - -/* COMPILER(BORLAND) */ -/* not really fully supported - is this relevant any more? */ -#if defined(__BORLANDC__) -#define WTF_COMPILER_BORLAND 1 -#endif - -/* COMPILER(CYGWIN) */ -/* not really fully supported - is this relevant any more? */ -#if defined(__CYGWIN__) -#define WTF_COMPILER_CYGWIN 1 -#endif - -/* COMPILER(WINSCW) */ -#if defined(__WINSCW__) -#define WTF_COMPILER_WINSCW 1 -#endif - -/* COMPILER(SUNCC) */ -/* This is the Sun CC compiler, also known as Sun Studio or Sun Pro */ -#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) -#define WTF_COMPILER_SUNCC 1 -#endif - -/* COMPILER(XLC) */ -/* IBM Visual Age C/C++ compiler, a.k.a. xlC */ -#if defined(__xlC__) -#define WTF_COMPILER_XLC 1 -#endif - -/* COMPILER(ACC) */ -/* HP's aC++/ANSI C compiler, a.k.a. aCC */ -#if defined(__HP_aCC) -#define WTF_COMPILER_ACC -#endif - -#if (PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN)) && !defined(ENABLE_JSC_MULTIPLE_THREADS) +#if (PLATFORM(IPHONE) || PLATFORM(MAC) || PLATFORM(WIN) || (PLATFORM(QT) && OS(DARWIN) && !ENABLE(SINGLE_THREADED))) && !defined(ENABLE_JSC_MULTIPLE_THREADS) #define ENABLE_JSC_MULTIPLE_THREADS 1 #endif /* On Windows, use QueryPerformanceCounter by default */ -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #define WTF_USE_QUERY_PERFORMANCE_COUNTER 1 #endif -#if PLATFORM(WINCE) && !PLATFORM(QT) +#if OS(WINCE) && !PLATFORM(QT) #undef ENABLE_JSC_MULTIPLE_THREADS #define ENABLE_JSC_MULTIPLE_THREADS 0 #define USE_SYSTEM_MALLOC 0 @@ -467,26 +559,25 @@ #define ENABLE_WML 1 #define HAVE_ACCESSIBILITY 0 -#define NOMINMAX // Windows min and max conflict with standard macros -#define NOSHLWAPI // shlwapi.h not available on WinCe +#define NOMINMAX /* Windows min and max conflict with standard macros */ +#define NOSHLWAPI /* shlwapi.h not available on WinCe */ -// MSDN documentation says these functions are provided with uspce.lib. But we cannot find this file. -#define __usp10__ // disable "usp10.h" +/* MSDN documentation says these functions are provided with uspce.lib. But we cannot find this file. */ +#define __usp10__ /* disable "usp10.h" */ -#define _INC_ASSERT // disable "assert.h" +#define _INC_ASSERT /* disable "assert.h" */ #define assert(x) -// _countof is only included in CE6; for CE5 we need to define it ourself +/* _countof is only included in CE6; for CE5 we need to define it ourself */ #ifndef _countof #define _countof(x) (sizeof(x) / sizeof((x)[0])) #endif -#endif /* PLATFORM(WINCE) && !PLATFORM(QT) */ +#endif /* OS(WINCE) && !PLATFORM(QT) */ -/* for Unicode, KDE uses Qt */ -#if PLATFORM(KDE) || PLATFORM(QT) +#if PLATFORM(QT) #define WTF_USE_QT4_UNICODE 1 -#elif PLATFORM(WINCE) +#elif OS(WINCE) #define WTF_USE_WINCE_UNICODE 1 #elif PLATFORM(GTK) /* The GTK+ Unicode backend is configurable */ @@ -497,6 +588,10 @@ #if PLATFORM(MAC) && !PLATFORM(IPHONE) #define WTF_PLATFORM_CF 1 #define WTF_USE_PTHREADS 1 +#define HAVE_PTHREAD_RWLOCK 1 +#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_TIGER) && CPU(X86_64) +#define WTF_USE_PLUGIN_HOST_PROCESS 1 +#endif #if !defined(ENABLE_MAC_JAVA_BRIDGE) #define ENABLE_MAC_JAVA_BRIDGE 1 #endif @@ -505,26 +600,45 @@ #endif #define HAVE_READLINE 1 #define HAVE_RUNLOOP_TIMER 1 -#endif +#endif /* PLATFORM(MAC) && !PLATFORM(IPHONE) */ -#if PLATFORM(CHROMIUM) && PLATFORM(DARWIN) +#if PLATFORM(CHROMIUM) && OS(DARWIN) #define WTF_PLATFORM_CF 1 #define WTF_USE_PTHREADS 1 +#define HAVE_PTHREAD_RWLOCK 1 #endif -#if PLATFORM(IPHONE) +#if PLATFORM(QT) && OS(DARWIN) #define WTF_PLATFORM_CF 1 -#define WTF_USE_PTHREADS 1 +#endif + +#if PLATFORM(IPHONE) #define ENABLE_CONTEXT_MENUS 0 #define ENABLE_DRAG_SUPPORT 0 #define ENABLE_FTPDIR 1 +#define ENABLE_GEOLOCATION 1 +#define ENABLE_ICONDATABASE 0 #define ENABLE_INSPECTOR 0 #define ENABLE_MAC_JAVA_BRIDGE 0 -#define ENABLE_ICONDATABASE 0 -#define ENABLE_GEOLOCATION 1 #define ENABLE_NETSCAPE_PLUGIN_API 0 -#define HAVE_READLINE 1 +#define ENABLE_ORIENTATION_EVENTS 1 #define ENABLE_REPAINT_THROTTLING 1 +#define HAVE_READLINE 1 +#define WTF_PLATFORM_CF 1 +#define WTF_USE_PTHREADS 1 +#define HAVE_PTHREAD_RWLOCK 1 +#endif + +#if PLATFORM(ANDROID) +#define WTF_USE_PTHREADS 1 +#define WTF_PLATFORM_SGL 1 +#define USE_SYSTEM_MALLOC 1 +#define ENABLE_MAC_JAVA_BRIDGE 1 +#define LOG_DISABLED 1 +/* Prevents Webkit from drawing the caret in textfields and textareas + This prevents unnecessary invals. */ +#define ENABLE_TEXT_CARET 1 +#define ENABLE_JAVASCRIPT_DEBUGGER 0 #endif #if PLATFORM(WIN) @@ -533,11 +647,15 @@ #if PLATFORM(WX) #define ENABLE_ASSEMBLER 1 +#if OS(DARWIN) +#define WTF_PLATFORM_CF 1 +#endif #endif #if PLATFORM(GTK) #if HAVE(PTHREAD_H) #define WTF_USE_PTHREADS 1 +#define HAVE_PTHREAD_RWLOCK 1 #endif #endif @@ -545,6 +663,7 @@ #define HAVE_POSIX_MEMALIGN 1 #define WTF_USE_CURL 1 #define WTF_USE_PTHREADS 1 +#define HAVE_PTHREAD_RWLOCK 1 #define USE_SYSTEM_MALLOC 1 #define ENABLE_NETSCAPE_PLUGIN_API 0 #endif @@ -555,19 +674,19 @@ #endif #endif /* !defined(HAVE_ACCESSIBILITY) */ -#if PLATFORM(UNIX) && !PLATFORM(SYMBIAN) +#if OS(UNIX) && !OS(SYMBIAN) #define HAVE_SIGNAL_H 1 #endif -#if !PLATFORM(WIN_OS) && !PLATFORM(SOLARIS) && !PLATFORM(QNX) \ - && !PLATFORM(SYMBIAN) && !PLATFORM(HAIKU) && !COMPILER(RVCT) && !PLATFORM(AIX) \ - && !PLATFORM(HPUX) +#if !OS(WINDOWS) && !OS(SOLARIS) && !OS(QNX) \ + && !OS(SYMBIAN) && !OS(HAIKU) && !OS(RVCT) \ + && !OS(ANDROID) && !OS(AIX) && !OS(HPUX) #define HAVE_TM_GMTOFF 1 #define HAVE_TM_ZONE 1 #define HAVE_TIMEGM 1 -#endif +#endif -#if PLATFORM(DARWIN) +#if OS(DARWIN) #define HAVE_ERRNO_H 1 #define HAVE_LANGINFO_H 1 @@ -579,27 +698,32 @@ #define HAVE_SYS_TIME_H 1 #define HAVE_SYS_TIMEB_H 1 -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !PLATFORM(IPHONE) && !PLATFORM(QT) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) + +#define HAVE_DISPATCH_H 1 + +#if !PLATFORM(IPHONE) && !PLATFORM(QT) #define HAVE_MADV_FREE_REUSE 1 #define HAVE_MADV_FREE 1 #define HAVE_PTHREAD_SETNAME_NP 1 #endif +#endif + #if PLATFORM(IPHONE) #define HAVE_MADV_FREE 1 #endif -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) -#define HAVE_FLOAT_H 1 -#if PLATFORM(WINCE) +#if OS(WINCE) #define HAVE_ERRNO_H 0 #else #define HAVE_SYS_TIMEB_H 1 #endif #define HAVE_VIRTUALALLOC 1 -#elif PLATFORM(SYMBIAN) +#elif OS(SYMBIAN) #define HAVE_ERRNO_H 1 #define HAVE_MMAP 0 @@ -612,9 +736,19 @@ #define HAVE_SYS_PARAM_H 1 #endif -#elif PLATFORM(QNX) +#elif OS(QNX) + +#define HAVE_ERRNO_H 1 +#define HAVE_MMAP 1 +#define HAVE_SBRK 1 +#define HAVE_STRINGS_H 1 +#define HAVE_SYS_PARAM_H 1 +#define HAVE_SYS_TIME_H 1 + +#elif OS(ANDROID) #define HAVE_ERRNO_H 1 +#define HAVE_LANGINFO_H 0 #define HAVE_MMAP 1 #define HAVE_SBRK 1 #define HAVE_STRINGS_H 1 @@ -627,7 +761,7 @@ #define HAVE_ERRNO_H 1 /* As long as Haiku doesn't have a complete support of locale this will be disabled. */ -#if !PLATFORM(HAIKU) +#if !OS(HAIKU) #define HAVE_LANGINFO_H 1 #endif #define HAVE_MMAP 1 @@ -686,6 +820,14 @@ #define ENABLE_NETSCAPE_PLUGIN_API 1 #endif +#if !defined(WTF_USE_PLUGIN_HOST_PROCESS) +#define WTF_USE_PLUGIN_HOST_PROCESS 0 +#endif + +#if !defined(ENABLE_ORIENTATION_EVENTS) +#define ENABLE_ORIENTATION_EVENTS 0 +#endif + #if !defined(ENABLE_OPCODE_STATS) #define ENABLE_OPCODE_STATS 0 #endif @@ -718,15 +860,11 @@ #endif #if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64) -#if PLATFORM(X86_64) && (PLATFORM(DARWIN) || PLATFORM(LINUX) || PLATFORM(SOLARIS) || PLATFORM(HPUX)) -#define WTF_USE_JSVALUE64 1 -#elif (PLATFORM(IA64) && !PLATFORM(IA64_32)) || PLATFORM(SPARC64) -#define WTF_USE_JSVALUE64 1 -#elif PLATFORM(AIX64) +#if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS) || OS(SOLARIS) || OS(HPUX))) || (CPU(IA64) && !CPU(IA64_32)) || CPU(ALPHA) || CPU(AIX64) || CPU(SPARC64) #define WTF_USE_JSVALUE64 1 -#elif PLATFORM(ARM) || PLATFORM(PPC64) +#elif CPU(ARM) || CPU(PPC64) #define WTF_USE_JSVALUE32 1 -#elif PLATFORM(WIN_OS) && COMPILER(MINGW) +#elif OS(WINDOWS) && COMPILER(MINGW) /* Using JSVALUE32_64 causes padding/alignement issues for JITStubArg on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #define WTF_USE_JSVALUE32 1 @@ -742,36 +880,38 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #if !defined(ENABLE_JIT) /* The JIT is tested & working on x86_64 Mac */ -#if PLATFORM(X86_64) && PLATFORM(MAC) +#if CPU(X86_64) && PLATFORM(MAC) #define ENABLE_JIT 1 /* The JIT is tested & working on x86 Mac */ -#elif PLATFORM(X86) && PLATFORM(MAC) +#elif CPU(X86) && PLATFORM(MAC) #define ENABLE_JIT 1 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 -#elif PLATFORM(ARM_THUMB2) && PLATFORM(IPHONE) - /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ - #define ENABLE_JIT 0 - #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 0 +#elif CPU(ARM_THUMB2) && PLATFORM(IPHONE) + #define ENABLE_JIT 1 /* The JIT is tested & working on x86 Windows */ -#elif PLATFORM(X86) && PLATFORM(WIN) +#elif CPU(X86) && PLATFORM(WIN) #define ENABLE_JIT 1 #endif #if PLATFORM(QT) -#if PLATFORM(X86) && PLATFORM(WIN_OS) && COMPILER(MINGW) && GCC_VERSION >= 40100 +#if CPU(X86_64) && OS(DARWIN) + #define ENABLE_JIT 1 +#elif CPU(X86) && OS(DARWIN) #define ENABLE_JIT 1 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 -#elif PLATFORM(X86) && PLATFORM(WIN_OS) && COMPILER(MSVC) +#elif CPU(X86) && OS(WINDOWS) && COMPILER(MINGW) && GCC_VERSION >= 40100 + #define ENABLE_JIT 1 + #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 +#elif CPU(X86) && OS(WINDOWS) && COMPILER(MSVC) #define ENABLE_JIT 1 #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1 -#elif PLATFORM(X86) && PLATFORM(LINUX) && GCC_VERSION >= 40100 +#elif CPU(X86) && OS(LINUX) && GCC_VERSION >= 40100 #define ENABLE_JIT 1 #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 1 -#elif PLATFORM(ARM_TRADITIONAL) && PLATFORM(LINUX) +#elif CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100 + #define ENABLE_JIT 1 +#elif CPU(ARM_TRADITIONAL) && OS(LINUX) #define ENABLE_JIT 1 - #if PLATFORM(ARM_THUMB2) - #define ENABLE_JIT_OPTIMIZE_NATIVE_CALL 0 - #endif #endif #endif /* PLATFORM(QT) */ @@ -792,9 +932,9 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #endif #endif -#if PLATFORM(X86) && COMPILER(MSVC) +#if CPU(X86) && COMPILER(MSVC) #define JSC_HOST_CALL __fastcall -#elif PLATFORM(X86) && COMPILER(GCC) +#elif CPU(X86) && COMPILER(GCC) #define JSC_HOST_CALL __attribute__ ((fastcall)) #else #define JSC_HOST_CALL @@ -814,20 +954,20 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #if !defined(ENABLE_YARR_JIT) /* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */ -#if (PLATFORM(X86) && PLATFORM(MAC)) \ - || (PLATFORM(X86_64) && PLATFORM(MAC)) \ - /* Under development, temporarily disabled until 16Mb link range limit in assembler is fixed. */ \ - || (PLATFORM(ARM_THUMB2) && PLATFORM(IPHONE) && 0) \ - || (PLATFORM(X86) && PLATFORM(WIN)) +#if (CPU(X86) && PLATFORM(MAC)) \ + || (CPU(X86_64) && PLATFORM(MAC)) \ + || (CPU(ARM_THUMB2) && PLATFORM(IPHONE)) \ + || (CPU(X86) && PLATFORM(WIN)) #define ENABLE_YARR 1 #define ENABLE_YARR_JIT 1 #endif #if PLATFORM(QT) -#if (PLATFORM(X86) && PLATFORM(WIN_OS) && COMPILER(MINGW) && GCC_VERSION >= 40100) \ - || (PLATFORM(X86) && PLATFORM(WIN_OS) && COMPILER(MSVC)) \ - || (PLATFORM(X86) && PLATFORM(LINUX) && GCC_VERSION >= 40100) \ - || (PLATFORM(ARM_TRADITIONAL) && PLATFORM(LINUX)) +#if (CPU(X86) && OS(WINDOWS) && COMPILER(MINGW) && GCC_VERSION >= 40100) \ + || (CPU(X86) && OS(WINDOWS) && COMPILER(MSVC)) \ + || (CPU(X86) && OS(LINUX) && GCC_VERSION >= 40100) \ + || (CPU(X86_64) && OS(LINUX) && GCC_VERSION >= 40100) \ + || (CPU(ARM_TRADITIONAL) && OS(LINUX)) #define ENABLE_YARR 1 #define ENABLE_YARR_JIT 1 #endif @@ -851,15 +991,15 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #define ENABLE_ASSEMBLER_WX_EXCLUSIVE 0 #endif -#if !defined(ENABLE_PAN_SCROLLING) && PLATFORM(WIN_OS) +#if !defined(ENABLE_PAN_SCROLLING) && OS(WINDOWS) #define ENABLE_PAN_SCROLLING 1 #endif -/* Use the QtXmlStreamReader implementation for XMLTokenizer */ +/* Use the QXmlStreamReader implementation for XMLTokenizer */ +/* Use the QXmlQuery implementation for XSLTProcessor */ #if PLATFORM(QT) -#if !ENABLE(XSLT) #define WTF_USE_QXMLSTREAM 1 -#endif +#define WTF_USE_QXMLQUERY 1 #endif #if !PLATFORM(QT) @@ -877,13 +1017,30 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #define WTF_USE_ACCELERATED_COMPOSITING 1 #endif +/* FIXME: Defining ENABLE_3D_RENDERING here isn't really right, but it's always used with + with WTF_USE_ACCELERATED_COMPOSITING, and it allows the feature to be turned on and + off in one place. */ +#if PLATFORM(WIN) +#include "QuartzCorePresent.h" +#if QUARTZCORE_PRESENT +#define WTF_USE_ACCELERATED_COMPOSITING 1 +#define ENABLE_3D_RENDERING 1 +#endif +#endif + #if COMPILER(GCC) #define WARN_UNUSED_RETURN __attribute__ ((warn_unused_result)) #else #define WARN_UNUSED_RETURN #endif +#if !ENABLE(NETSCAPE_PLUGIN_API) || (ENABLE(NETSCAPE_PLUGIN_API) && ((OS(UNIX) && (PLATFORM(QT) || PLATFORM(WX))) || PLATFORM(GTK))) +#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1 +#endif + /* Set up a define for a common error that is intended to cause a build error -- thus the space after Error. */ #define WTF_PLATFORM_CFNETWORK Error USE_macro_should_be_used_with_CFNETWORK +#define ENABLE_JSC_ZOMBIES 0 + #endif /* WTF_Platform_h */ diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/PtrAndFlags.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/PtrAndFlags.h index 5d0bd2a..1e1bee0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/PtrAndFlags.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/PtrAndFlags.h @@ -68,7 +68,7 @@ namespace WTF { PtrAndFlags(T* ptr) { PtrAndFlagsBase<T, FlagEnum>::m_ptrAndFlags = 0; - set(ptr); + PtrAndFlagsBase<T, FlagEnum>::set(ptr); } }; } // namespace WTF diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RandomNumber.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RandomNumber.cpp index 52fb130..74bb45c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RandomNumber.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RandomNumber.cpp @@ -34,7 +34,7 @@ #include <stdint.h> #include <stdlib.h> -#if PLATFORM(WINCE) +#if OS(WINCE) extern "C" { #include "wince/mt19937ar.c" } @@ -66,10 +66,10 @@ double randomNumber() uint32_t bits; rand_s(&bits); return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); -#elif PLATFORM(DARWIN) +#elif OS(DARWIN) uint32_t bits = arc4random(); return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); -#elif PLATFORM(UNIX) +#elif OS(UNIX) uint32_t part1 = random() & (RAND_MAX - 1); uint32_t part2 = random() & (RAND_MAX - 1); // random only provides 31 bits @@ -80,9 +80,9 @@ double randomNumber() // Mask off the low 53bits fullRandom &= (1LL << 53) - 1; return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); -#elif PLATFORM(WINCE) +#elif OS(WINCE) return genrand_res53(); -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) uint32_t part1 = rand() & (RAND_MAX - 1); uint32_t part2 = rand() & (RAND_MAX - 1); uint32_t part3 = rand() & (RAND_MAX - 1); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RandomNumberSeed.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RandomNumberSeed.h index a66433e..ae414c0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RandomNumberSeed.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RandomNumberSeed.h @@ -33,12 +33,12 @@ #include <sys/time.h> #endif -#if PLATFORM(UNIX) +#if OS(UNIX) #include <sys/types.h> #include <unistd.h> #endif -#if PLATFORM(WINCE) +#if OS(WINCE) extern "C" { void init_by_array(unsigned long init_key[],int key_length); } @@ -49,9 +49,9 @@ namespace WTF { inline void initializeRandomNumberGenerator() { -#if PLATFORM(DARWIN) +#if OS(DARWIN) // On Darwin we use arc4random which initialises itself. -#elif PLATFORM(WINCE) +#elif OS(WINCE) // initialize rand() srand(static_cast<unsigned>(time(0))); @@ -64,7 +64,7 @@ inline void initializeRandomNumberGenerator() init_by_array(initializationBuffer, 4); #elif COMPILER(MSVC) && defined(_CRT_RAND_S) // On Windows we use rand_s which initialises itself -#elif PLATFORM(UNIX) +#elif OS(UNIX) // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved timeval time; gettimeofday(&time, 0); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RefPtr.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RefPtr.h index 1a0b1fe..83c54bc 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RefPtr.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/RefPtr.h @@ -24,22 +24,27 @@ #include <algorithm> #include "AlwaysInline.h" #include "FastAllocBase.h" +#if COMPILER(WINSCW) +#include "PassRefPtr.h" +#endif namespace WTF { enum PlacementNewAdoptType { PlacementNewAdopt }; template <typename T> class PassRefPtr; + template <typename T> class NonNullPassRefPtr; enum HashTableDeletedValueType { HashTableDeletedValue }; template <typename T> class RefPtr : public FastAllocBase { public: RefPtr() : m_ptr(0) { } - RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } - RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { T* ptr = m_ptr; refIfNotNull(ptr); } + RefPtr(T* ptr) : m_ptr(ptr) { if (ptr) ptr->ref(); } + RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { if (T* ptr = m_ptr) ptr->ref(); } // see comment in PassRefPtr.h for why this takes const reference template <typename U> RefPtr(const PassRefPtr<U>&); + template <typename U> RefPtr(const NonNullPassRefPtr<U>&); // Special constructor for cases where we overwrite an object in place. RefPtr(PlacementNewAdoptType) { } @@ -48,13 +53,21 @@ namespace WTF { RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } - ~RefPtr() { T* ptr = m_ptr; derefIfNotNull(ptr); } +#if COMPILER(WINSCW) + ~RefPtr() { if (T* ptr = m_ptr) derefIfNotNull<T>(ptr); } +#else + ~RefPtr() { if (T* ptr = m_ptr) ptr->deref(); } +#endif - template <typename U> RefPtr(const RefPtr<U>& o) : m_ptr(static_cast<T*>(o.get())) { if (T* ptr = static_cast<T*>(m_ptr)) ptr->ref(); } + template <typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { if (T* ptr = m_ptr) ptr->ref(); } T* get() const { return m_ptr; } - void clear() { T* ptr = m_ptr; derefIfNotNull(ptr); m_ptr = 0; } +#if COMPILER(WINSCW) + void clear() { if (T* ptr = m_ptr) derefIfNotNull<T>(ptr); m_ptr = 0; } +#else + void clear() { if (T* ptr = m_ptr) ptr->deref(); m_ptr = 0; } +#endif PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; } T& operator*() const { return *m_ptr; } @@ -73,8 +86,10 @@ namespace WTF { RefPtr& operator=(const RefPtr&); RefPtr& operator=(T*); RefPtr& operator=(const PassRefPtr<T>&); + RefPtr& operator=(const NonNullPassRefPtr<T>&); template <typename U> RefPtr& operator=(const RefPtr<U>&); template <typename U> RefPtr& operator=(const PassRefPtr<U>&); + template <typename U> RefPtr& operator=(const NonNullPassRefPtr<U>&); void swap(RefPtr&); @@ -89,32 +104,43 @@ namespace WTF { { } + template <typename T> template <typename U> inline RefPtr<T>::RefPtr(const NonNullPassRefPtr<U>& o) + : m_ptr(o.releaseRef()) + { + } + template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o) { T* optr = o.get(); - refIfNotNull(optr); + if (optr) + optr->ref(); T* ptr = m_ptr; m_ptr = optr; - derefIfNotNull(ptr); + if (ptr) + ptr->deref(); return *this; } template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o) { T* optr = o.get(); - refIfNotNull(optr); + if (optr) + optr->ref(); T* ptr = m_ptr; m_ptr = optr; - derefIfNotNull(ptr); + if (ptr) + ptr->deref(); return *this; } template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr) { - refIfNotNull(optr); + if (optr) + optr->ref(); T* ptr = m_ptr; m_ptr = optr; - derefIfNotNull(ptr); + if (ptr) + ptr->deref(); return *this; } @@ -122,7 +148,17 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = o.releaseRef(); - derefIfNotNull(ptr); + if (ptr) + ptr->deref(); + return *this; + } + + template <typename T> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<T>& o) + { + T* ptr = m_ptr; + m_ptr = o.releaseRef(); + if (ptr) + ptr->deref(); return *this; } @@ -130,7 +166,17 @@ namespace WTF { { T* ptr = m_ptr; m_ptr = o.releaseRef(); - derefIfNotNull(ptr); + if (ptr) + ptr->deref(); + return *this; + } + + template <typename T> template <typename U> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<U>& o) + { + T* ptr = m_ptr; + m_ptr = o.releaseRef(); + if (ptr) + ptr->deref(); return *this; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StdLibExtras.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StdLibExtras.h index d21d1ff..9dfb969 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StdLibExtras.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StdLibExtras.h @@ -32,6 +32,7 @@ // Use these to declare and define a static local variable (static T;) so that // it is leaked so that its destructors are not called at exit. Using this // macro also allows workarounds a compiler bug present in Apple's version of GCC 4.0.1. +#ifndef DEFINE_STATIC_LOCAL #if COMPILER(GCC) && defined(__APPLE_CC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 1 #define DEFINE_STATIC_LOCAL(type, name, arguments) \ static type* name##Ptr = new type arguments; \ @@ -40,12 +41,17 @@ #define DEFINE_STATIC_LOCAL(type, name, arguments) \ static type& name = *new type arguments #endif +#endif // OBJECT_OFFSETOF: Like the C++ offsetof macro, but you can use it with classes. // The magic number 0x4000 is insignificant. We use it to avoid using NULL, since // NULL can cause compiler problems, especially in cases of multiple inheritance. #define OBJECT_OFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000) +// STRINGIZE: Can convert any value to quoted string, even expandable macros +#define STRINGIZE(exp) #exp +#define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp) + namespace WTF { /* @@ -63,6 +69,14 @@ namespace WTF { return u.to; } + // Returns a count of the number of bits set in 'bits'. + inline size_t bitCount(unsigned bits) + { + bits = bits - ((bits >> 1) & 0x55555555); + bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333); + return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; + } + } // namespace WTF #endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringExtras.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringExtras.cpp new file mode 100644 index 0000000..1b96417 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringExtras.cpp @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2009 Company 100, 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 COMPUTER, 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 COMPUTER, 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. + */ + +#include "config.h" + +#if COMPILER(RVCT) && __ARMCC_VERSION < 400000 + +#include "StringExtras.h" + +#include "ASCIICType.h" + +int strcasecmp(const char* s1, const char* s2) +{ + while (toASCIIUpper(*s1) == toASCIIUpper(*s2)) { + if (*s1 == '\0') + return 0; + s1++; + s2++; + } + + return toASCIIUpper(*s1) - toASCIIUpper(*s2); +} + +int strncasecmp(const char* s1, const char* s2, size_t len) +{ + while (len > 0 && toASCIIUpper(*s1) == toASCIIUpper(*s2)) { + if (*s1 == '\0') + return 0; + s1++; + s2++; + len--; + } + + if (!len) + return 0; + + return toASCIIUpper(*s1) - toASCIIUpper(*s2); +} + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringExtras.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringExtras.h index 559e3f2..b1ec09f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringExtras.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringExtras.h @@ -34,6 +34,7 @@ #endif #if COMPILER(MSVC) +// FIXME: why a COMPILER check instead of OS? also, these should be HAVE checks inline int snprintf(char* buffer, size_t count, const char* format, ...) { @@ -45,7 +46,7 @@ inline int snprintf(char* buffer, size_t count, const char* format, ...) return result; } -#if COMPILER(MSVC7) || PLATFORM(WINCE) +#if COMPILER(MSVC7) || OS(WINCE) inline int vsnprintf(char* buffer, size_t count, const char* format, va_list args) { @@ -54,7 +55,7 @@ inline int vsnprintf(char* buffer, size_t count, const char* format, va_list arg #endif -#if PLATFORM(WINCE) +#if OS(WINCE) inline int strnicmp(const char* string1, const char* string2, size_t count) { @@ -75,17 +76,18 @@ inline char* strdup(const char* strSource) inline int strncasecmp(const char* s1, const char* s2, size_t len) { - return strnicmp(s1, s2, len); + return _strnicmp(s1, s2, len); } inline int strcasecmp(const char* s1, const char* s2) { - return stricmp(s1, s2); + return _stricmp(s1, s2); } #endif -#if PLATFORM(WIN_OS) || PLATFORM(LINUX) +#if OS(WINDOWS) || OS(LINUX) || OS(SOLARIS) +// FIXME: should check HAVE_STRNSTR inline char* strnstr(const char* buffer, const char* target, size_t bufferLength) { @@ -101,4 +103,11 @@ inline char* strnstr(const char* buffer, const char* target, size_t bufferLength #endif +#if COMPILER(RVCT) && __ARMCC_VERSION < 400000 + +int strcasecmp(const char* s1, const char* s2); +int strncasecmp(const char* s1, const char* s2, size_t len); + +#endif + #endif // WTF_StringExtras_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringHashFunctions.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringHashFunctions.h new file mode 100644 index 0000000..07f117f --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/StringHashFunctions.h @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2005, 2006, 2008, 2010 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef WTF_StringHashFunctions_h +#define WTF_StringHashFunctions_h + +#include <wtf/unicode/Unicode.h> + +namespace WTF { + +// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's +static const unsigned stringHashingStartValue = 0x9e3779b9U; + +// stringHash methods based on Paul Hsieh's SuperFastHash. +// http://www.azillionmonkeys.com/qed/hash.html +// char* data is interpreted as latin-encoded (zero extended to 16 bits). + +inline unsigned stringHash(const UChar* data, unsigned length) +{ + unsigned hash = WTF::stringHashingStartValue; + unsigned rem = length & 1; + length >>= 1; + + // Main loop + for (; length > 0; length--) { + hash += data[0]; + unsigned tmp = (data[1] << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2; + hash += hash >> 11; + } + + // Handle end case + if (rem) { + hash += data[0]; + hash ^= hash << 11; + hash += hash >> 17; + } + + // Force "avalanching" of final 127 bits + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 2; + hash += hash >> 15; + hash ^= hash << 10; + + hash &= 0x7fffffff; + + // this avoids ever returning a hash code of 0, since that is used to + // signal "hash not computed yet", using a value that is likely to be + // effectively the same as 0 when the low bits are masked + if (hash == 0) + hash = 0x40000000; + + return hash; +} + +inline unsigned stringHash(const char* data, unsigned length) +{ + unsigned hash = WTF::stringHashingStartValue; + unsigned rem = length & 1; + length >>= 1; + + // Main loop + for (; length > 0; length--) { + hash += static_cast<unsigned char>(data[0]); + unsigned tmp = (static_cast<unsigned char>(data[1]) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2; + hash += hash >> 11; + } + + // Handle end case + if (rem) { + hash += static_cast<unsigned char>(data[0]); + hash ^= hash << 11; + hash += hash >> 17; + } + + // Force "avalanching" of final 127 bits + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 2; + hash += hash >> 15; + hash ^= hash << 10; + + hash &= 0x7fffffff; + + // this avoids ever returning a hash code of 0, since that is used to + // signal "hash not computed yet", using a value that is likely to be + // effectively the same as 0 when the low bits are masked + if (hash == 0) + hash = 0x40000000; + + return hash; +} + +inline unsigned stringHash(const char* data) +{ + unsigned hash = WTF::stringHashingStartValue; + + // Main loop + for (;;) { + unsigned char b0 = data[0]; + if (!b0) + break; + unsigned char b1 = data[1]; + if (!b1) { + hash += b0; + hash ^= hash << 11; + hash += hash >> 17; + break; + } + hash += b0; + unsigned tmp = (b1 << 11) ^ hash; + hash = (hash << 16) ^ tmp; + data += 2; + hash += hash >> 11; + } + + // Force "avalanching" of final 127 bits. + hash ^= hash << 3; + hash += hash >> 5; + hash ^= hash << 2; + hash += hash >> 15; + hash ^= hash << 10; + + hash &= 0x7fffffff; + + // This avoids ever returning a hash code of 0, since that is used to + // signal "hash not computed yet", using a value that is likely to be + // effectively the same as 0 when the low bits are masked. + if (hash == 0) + hash = 0x40000000; + + return hash; +} + +} // namespace WTF + +#endif // WTF_StringHashFunctions_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TCSpinLock.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TCSpinLock.h index 4cf30c2..8a73e13 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TCSpinLock.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TCSpinLock.h @@ -33,7 +33,7 @@ #ifndef TCMALLOC_INTERNAL_SPINLOCK_H__ #define TCMALLOC_INTERNAL_SPINLOCK_H__ -#if (PLATFORM(X86) || PLATFORM(PPC)) && (COMPILER(GCC) || COMPILER(MSVC)) +#if (CPU(X86) || CPU(X86_64) || CPU(PPC)) && (COMPILER(GCC) || COMPILER(MSVC)) #include <time.h> /* For nanosleep() */ @@ -47,7 +47,7 @@ #include <sys/types.h> #endif -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif @@ -62,7 +62,7 @@ struct TCMalloc_SpinLock { inline void Lock() { int r; #if COMPILER(GCC) -#if PLATFORM(X86) +#if CPU(X86) || CPU(X86_64) __asm__ __volatile__ ("xchgl %0, %1" : "=r"(r), "=m"(lockword_) @@ -92,7 +92,7 @@ struct TCMalloc_SpinLock { inline void Unlock() { #if COMPILER(GCC) -#if PLATFORM(X86) +#if CPU(X86) || CPU(X86_64) __asm__ __volatile__ ("movl $0, %0" : "=m"(lockword_) @@ -103,7 +103,7 @@ struct TCMalloc_SpinLock { ("isync\n\t" "eieio\n\t" "stw %1, %0" -#if PLATFORM(DARWIN) || PLATFORM(PPC) +#if OS(DARWIN) || CPU(PPC) : "=o" (lockword_) #else : "=m" (lockword_) @@ -138,7 +138,7 @@ static void TCMalloc_SlowLock(volatile unsigned int* lockword) { while (true) { int r; #if COMPILER(GCC) -#if PLATFORM(X86) +#if CPU(X86) || CPU(X86_64) __asm__ __volatile__ ("xchgl %0, %1" : "=r"(r), "=m"(*lockword) @@ -178,7 +178,7 @@ static void TCMalloc_SlowLock(volatile unsigned int* lockword) { // from taking 30 seconds to 16 seconds. // Sleep for a few milliseconds -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) Sleep(2); #else struct timespec tm; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TCSystemAlloc.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TCSystemAlloc.cpp index a43baa8..909f14e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TCSystemAlloc.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TCSystemAlloc.cpp @@ -47,7 +47,7 @@ #include <sys/types.h> #endif -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #include "windows.h" #else #include <errno.h> @@ -324,10 +324,10 @@ static void* TryDevMem(size_t size, size_t *actual_size, size_t alignment) { // Return the unused virtual memory to the system if (adjust > 0) { - munmap(reinterpret_cast<char*>(ptr), adjust); + munmap(reinterpret_cast<void*>(ptr), adjust); } if (adjust < extra) { - munmap(reinterpret_cast<char*>(ptr + adjust + size), extra - adjust); + munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust); } ptr += adjust; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp new file mode 100644 index 0000000..042d49e --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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. + */ + +#include "config.h" + +#if USE(PTHREADS) + +#include "ThreadIdentifierDataPthreads.h" + +#include "Threading.h" + +namespace WTF { + +pthread_key_t ThreadIdentifierData::m_key; + +void clearPthreadHandleForIdentifier(ThreadIdentifier); + +ThreadIdentifierData::~ThreadIdentifierData() +{ + clearPthreadHandleForIdentifier(m_identifier); +} + +ThreadIdentifier ThreadIdentifierData::identifier() +{ + initializeKeyOnce(); + ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(pthread_getspecific(m_key)); + + return threadIdentifierData ? threadIdentifierData->m_identifier : 0; +} + +void ThreadIdentifierData::initialize(ThreadIdentifier id) +{ + ASSERT(!identifier()); + + initializeKeyOnce(); + pthread_setspecific(m_key, new ThreadIdentifierData(id)); +} + +void ThreadIdentifierData::destruct(void* data) +{ + ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(data); + ASSERT(threadIdentifierData); + + if (threadIdentifierData->m_isDestroyedOnce) { + delete threadIdentifierData; + return; + } + + threadIdentifierData->m_isDestroyedOnce = true; + // Re-setting the value for key causes another destruct() call after all other thread-specific destructors were called. + pthread_setspecific(m_key, threadIdentifierData); +} + +void ThreadIdentifierData::initializeKeyOnceHelper() +{ + if (pthread_key_create(&m_key, destruct)) + CRASH(); +} + +void ThreadIdentifierData::initializeKeyOnce() +{ + static pthread_once_t onceControl = PTHREAD_ONCE_INIT; + if (pthread_once(&onceControl, initializeKeyOnceHelper)) + CRASH(); +} + +} // namespace WTF + +#endif // USE(PTHREADS) + diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h new file mode 100644 index 0000000..3af87a8 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 Google 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: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 THE COPYRIGHT + * OWNER 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 ThreadIdentifierDataPthreads_h +#define ThreadIdentifierDataPthreads_h + +#include <wtf/Noncopyable.h> +#include <wtf/Threading.h> + +namespace WTF { + +// Holds ThreadIdentifier in the thread-specific storage and employs pthreads-specific 2-pass destruction to reliably remove +// ThreadIdentifier from threadMap. It assumes regular ThreadSpecific types don't use multiple-pass destruction. +class ThreadIdentifierData : public Noncopyable { +public: + ~ThreadIdentifierData(); + + // Creates and puts an instance of ThreadIdentifierData into thread-specific storage. + static void initialize(ThreadIdentifier identifier); + + // Returns 0 if thread-specific storage was not initialized. + static ThreadIdentifier identifier(); + +private: + ThreadIdentifierData(ThreadIdentifier identifier) + : m_identifier(identifier) + , m_isDestroyedOnce(false) + { + } + + // This thread-specific destructor is called 2 times when thread terminates: + // - first, when all the other thread-specific destructors are called, it simply remembers it was 'destroyed once' + // and re-sets itself into the thread-specific slot to make Pthreads to call it again later. + // - second, after all thread-specific destructors were invoked, it gets called again - this time, we remove the + // ThreadIdentifier from the threadMap, completing the cleanup. + static void destruct(void* data); + + static void initializeKeyOnceHelper(); + static void initializeKeyOnce(); + + ThreadIdentifier m_identifier; + bool m_isDestroyedOnce; + static pthread_key_t m_key; +}; + +} // namespace WTF + +#endif // ThreadIdentifierDataPthreads_h + + diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadSpecific.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadSpecific.h index b6f5fd3..3abbc58 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadSpecific.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadSpecific.h @@ -47,13 +47,13 @@ #include <pthread.h> #elif PLATFORM(QT) #include <QThreadStorage> -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) #include <windows.h> #endif namespace WTF { -#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS) +#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS) // ThreadSpecificThreadExit should be called each time when a thread is detached. // This is done automatically for threads created with WTF::createThread. void ThreadSpecificThreadExit(); @@ -68,7 +68,7 @@ public: ~ThreadSpecific(); private: -#if !USE(PTHREADS) && !PLATFORM(QT) && PLATFORM(WIN_OS) +#if !USE(PTHREADS) && !PLATFORM(QT) && OS(WINDOWS) friend void ThreadSpecificThreadExit(); #endif @@ -76,7 +76,7 @@ private: void set(T*); void static destroy(void* ptr); -#if USE(PTHREADS) || PLATFORM(QT) || PLATFORM(WIN_OS) +#if USE(PTHREADS) || PLATFORM(QT) || OS(WINDOWS) struct Data : Noncopyable { Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} #if PLATFORM(QT) @@ -91,15 +91,44 @@ private: }; #endif +#if ENABLE(SINGLE_THREADED) + T* m_value; +#else #if USE(PTHREADS) pthread_key_t m_key; #elif PLATFORM(QT) QThreadStorage<Data*> m_key; -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) int m_index; #endif +#endif }; +#if ENABLE(SINGLE_THREADED) +template<typename T> +inline ThreadSpecific<T>::ThreadSpecific() + : m_value(0) +{ +} + +template<typename T> +inline ThreadSpecific<T>::~ThreadSpecific() +{ +} + +template<typename T> +inline T* ThreadSpecific<T>::get() +{ + return m_value; +} + +template<typename T> +inline void ThreadSpecific<T>::set(T* ptr) +{ + ASSERT(!get()); + m_value = ptr; +} +#else #if USE(PTHREADS) template<typename T> inline ThreadSpecific<T>::ThreadSpecific() @@ -157,7 +186,7 @@ inline void ThreadSpecific<T>::set(T* ptr) m_key.setLocalData(data); } -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) // The maximum number of TLS keys that can be created. For simplification, we assume that: // 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies. @@ -207,10 +236,12 @@ inline void ThreadSpecific<T>::set(T* ptr) #else #error ThreadSpecific is not implemented for this platform. #endif +#endif template<typename T> inline void ThreadSpecific<T>::destroy(void* ptr) { +#if !ENABLE(SINGLE_THREADED) Data* data = static_cast<Data*>(ptr); #if USE(PTHREADS) @@ -230,7 +261,7 @@ inline void ThreadSpecific<T>::destroy(void* ptr) pthread_setspecific(data->owner->m_key, 0); #elif PLATFORM(QT) // Do nothing here -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) TlsSetValue(tlsKeys()[data->owner->m_index], 0); #else #error ThreadSpecific is not implemented for this platform. @@ -239,6 +270,7 @@ inline void ThreadSpecific<T>::destroy(void* ptr) #if !PLATFORM(QT) delete data; #endif +#endif } template<typename T> diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.cpp index 56bf438..49de59e 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.cpp @@ -49,13 +49,14 @@ static void* threadEntryPoint(void* contextData) { NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData); - setThreadNameInternal(context->name); - - // Block until our creating thread has completed any extra setup work + // Block until our creating thread has completed any extra setup work, including + // establishing ThreadIdentifier. { MutexLocker locker(context->creationMutex); } + initializeCurrentThreadInternal(context->name); + // Grab the info that we need out of the context, then deallocate it. ThreadFunction entryPoint = context->entryPoint; void* data = context->data; @@ -75,7 +76,7 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* NewThreadContext* context = new NewThreadContext(entryPoint, data, name); - // Prevent the thread body from executing until we've established the thread identifier + // Prevent the thread body from executing until we've established the thread identifier. MutexLocker locker(context->creationMutex); return createThreadInternal(threadEntryPoint, context, name); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h index 5154545..1599562 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h @@ -61,7 +61,7 @@ #include "Platform.h" -#if PLATFORM(WINCE) +#if OS(WINCE) #include <windows.h> #endif @@ -69,10 +69,12 @@ #include <wtf/Locker.h> #include <wtf/Noncopyable.h> -#if PLATFORM(WIN_OS) && !PLATFORM(WINCE) +#if OS(WINDOWS) && !OS(WINCE) #include <windows.h> -#elif PLATFORM(DARWIN) +#elif OS(DARWIN) #include <libkern/OSAtomic.h> +#elif OS(ANDROID) +#include <cutils/atomic.h> #elif COMPILER(GCC) #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) #include <ext/atomicity.h> @@ -84,7 +86,7 @@ #if USE(PTHREADS) #include <pthread.h> #elif PLATFORM(GTK) -#include <wtf/GOwnPtr.h> +#include <wtf/gtk/GOwnPtr.h> typedef struct _GMutex GMutex; typedef struct _GCond GCond; #endif @@ -119,7 +121,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadN // Called in the thread during initialization. // Helpful for platforms where the thread name must be set from within the thread. -void setThreadNameInternal(const char* threadName); +void initializeCurrentThreadInternal(const char* threadName); ThreadIdentifier currentThread(); bool isMainThread(); @@ -128,7 +130,11 @@ void detachThread(ThreadIdentifier); #if USE(PTHREADS) typedef pthread_mutex_t PlatformMutex; +#if HAVE(PTHREAD_RWLOCK) typedef pthread_rwlock_t PlatformReadWriteLock; +#else +typedef void* PlatformReadWriteLock; +#endif typedef pthread_cond_t PlatformCondition; #elif PLATFORM(GTK) typedef GOwnPtr<GMutex> PlatformMutex; @@ -138,7 +144,7 @@ typedef GOwnPtr<GCond> PlatformCondition; typedef QT_PREPEND_NAMESPACE(QMutex)* PlatformMutex; typedef void* PlatformReadWriteLock; // FIXME: Implement. typedef QT_PREPEND_NAMESPACE(QWaitCondition)* PlatformCondition; -#elif PLATFORM(WIN_OS) +#elif OS(WINDOWS) struct PlatformMutex { CRITICAL_SECTION m_internalMutex; size_t m_recursionCount; @@ -211,10 +217,10 @@ private: PlatformCondition m_condition; }; -#if PLATFORM(WIN_OS) +#if OS(WINDOWS) #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 -#if COMPILER(MINGW) || COMPILER(MSVC7) || PLATFORM(WINCE) +#if COMPILER(MINGW) || COMPILER(MSVC7) || OS(WINCE) inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast<long*>(addend)); } inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); } #else @@ -222,13 +228,18 @@ inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(r inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); } #endif -#elif PLATFORM(DARWIN) +#elif OS(DARWIN) #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 inline int atomicIncrement(int volatile* addend) { return OSAtomicIncrement32Barrier(const_cast<int*>(addend)); } inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); } -#elif COMPILER(GCC) && !PLATFORM(SPARC64) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc +#elif OS(ANDROID) + +inline int atomicIncrement(int volatile* addend) { return android_atomic_inc(addend); } +inline int atomicDecrement(int volatile* addend) { return android_atomic_dec(addend); } + +#elif COMPILER(GCC) && !CPU(SPARC64) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingNone.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingNone.cpp index 46f23d2..2e8a259 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingNone.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingNone.cpp @@ -30,11 +30,13 @@ #include "config.h" #include "Threading.h" +#if ENABLE(SINGLE_THREADED) + namespace WTF { void initializeThreading() { } ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char*) { return ThreadIdentifier(); } -void setThreadNameInternal(const char*) { } +void initializeCurrentThreadInternal(const char*) { } int waitForThreadCompletion(ThreadIdentifier, void**) { return 0; } void detachThread(ThreadIdentifier) { } ThreadIdentifier currentThread() { return ThreadIdentifier(); } @@ -57,3 +59,5 @@ void lockAtomicallyInitializedStaticMutex() { } void unlockAtomicallyInitializedStaticMutex() { } } // namespace WebCore + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingPthreads.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingPthreads.cpp index e4fb419..2feb808 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingPthreads.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingPthreads.cpp @@ -37,6 +37,8 @@ #include "MainThread.h" #include "RandomNumberSeed.h" #include "StdLibExtras.h" +#include "ThreadIdentifierDataPthreads.h" +#include "ThreadSpecific.h" #include "UnusedParam.h" #include <errno.h> @@ -45,7 +47,7 @@ #include <sys/time.h> #endif -#if PLATFORM(ANDROID) +#if OS(ANDROID) #include "jni_utility.h" #endif @@ -55,10 +57,12 @@ typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap; static Mutex* atomicallyInitializedStaticMutex; -#if !PLATFORM(DARWIN) || PLATFORM(CHROMIUM) -static ThreadIdentifier mainThreadIdentifier; // The thread that was the first to call initializeThreading(), which must be the main thread. +#if !OS(DARWIN) || PLATFORM(CHROMIUM) || USE(WEB_THREAD) +static pthread_t mainThread; // The thread that was the first to call initializeThreading(), which must be the main thread. #endif +void clearPthreadHandleForIdentifier(ThreadIdentifier); + static Mutex& threadMapMutex() { DEFINE_STATIC_LOCAL(Mutex, mutex, ()); @@ -71,8 +75,8 @@ void initializeThreading() atomicallyInitializedStaticMutex = new Mutex; threadMapMutex(); initializeRandomNumberGenerator(); -#if !PLATFORM(DARWIN) || PLATFORM(CHROMIUM) - mainThreadIdentifier = currentThread(); +#if !OS(DARWIN) || PLATFORM(CHROMIUM) || USE(WEB_THREAD) + mainThread = pthread_self(); #endif initializeMainThread(); } @@ -108,7 +112,7 @@ static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle return 0; } -static ThreadIdentifier establishIdentifierForPthreadHandle(pthread_t& pthreadHandle) +static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle) { ASSERT(!identifierByPthreadHandle(pthreadHandle)); @@ -128,7 +132,7 @@ static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id) return threadMap().get(id); } -static void clearPthreadHandleForIdentifier(ThreadIdentifier id) +void clearPthreadHandleForIdentifier(ThreadIdentifier id) { MutexLocker locker(threadMapMutex()); @@ -137,7 +141,7 @@ static void clearPthreadHandleForIdentifier(ThreadIdentifier id) threadMap().remove(id); } -#if PLATFORM(ANDROID) +#if OS(ANDROID) // On the Android platform, threads must be registered with the VM before they run. struct ThreadData { ThreadFunction entryPoint; @@ -167,6 +171,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con if (pthread_create(&threadHandle, 0, runThreadWithRegistration, static_cast<void*>(threadData))) { LOG_ERROR("Failed to create pthread at entry point %p with data %p", entryPoint, data); + delete threadData; return 0; } return establishIdentifierForPthreadHandle(threadHandle); @@ -184,13 +189,17 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con } #endif -void setThreadNameInternal(const char* threadName) +void initializeCurrentThreadInternal(const char* threadName) { #if HAVE(PTHREAD_SETNAME_NP) pthread_setname_np(threadName); #else UNUSED_PARAM(threadName); #endif + + ThreadIdentifier id = identifierByPthreadHandle(pthread_self()); + ASSERT(id); + ThreadIdentifierData::initialize(id); } int waitForThreadCompletion(ThreadIdentifier threadID, void** result) @@ -198,12 +207,13 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) ASSERT(threadID); pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID); + if (!pthreadHandle) + return 0; int joinResult = pthread_join(pthreadHandle, result); if (joinResult == EDEADLK) LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID); - clearPthreadHandleForIdentifier(threadID); return joinResult; } @@ -212,26 +222,30 @@ void detachThread(ThreadIdentifier threadID) ASSERT(threadID); pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID); + if (!pthreadHandle) + return; pthread_detach(pthreadHandle); - - clearPthreadHandleForIdentifier(threadID); } ThreadIdentifier currentThread() { - pthread_t currentThread = pthread_self(); - if (ThreadIdentifier id = identifierByPthreadHandle(currentThread)) + ThreadIdentifier id = ThreadIdentifierData::identifier(); + if (id) return id; - return establishIdentifierForPthreadHandle(currentThread); + + // Not a WTF-created thread, ThreadIdentifier is not established yet. + id = establishIdentifierForPthreadHandle(pthread_self()); + ThreadIdentifierData::initialize(id); + return id; } bool isMainThread() { -#if PLATFORM(DARWIN) && !PLATFORM(CHROMIUM) +#if OS(DARWIN) && !PLATFORM(CHROMIUM) && !USE(WEB_THREAD) return pthread_main_np(); #else - return currentThread() == mainThreadIdentifier; + return pthread_equal(pthread_self(), mainThread); #endif } @@ -270,7 +284,7 @@ void Mutex::unlock() ASSERT_UNUSED(result, !result); } - +#if HAVE(PTHREAD_RWLOCK) ReadWriteLock::ReadWriteLock() { pthread_rwlock_init(&m_readWriteLock, NULL); @@ -324,6 +338,7 @@ void ReadWriteLock::unlock() int result = pthread_rwlock_unlock(&m_readWriteLock); ASSERT_UNUSED(result, !result); } +#endif // HAVE(PTHREAD_RWLOCK) ThreadCondition::ThreadCondition() { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingWin.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingWin.cpp index cccbda1..73c3f0c 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingWin.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/ThreadingWin.cpp @@ -87,10 +87,10 @@ #include "Threading.h" #include "MainThread.h" -#if !USE(PTHREADS) && PLATFORM(WIN_OS) +#if !USE(PTHREADS) && OS(WINDOWS) #include "ThreadSpecific.h" #endif -#if !PLATFORM(WINCE) +#if !OS(WINCE) #include <process.h> #endif #if HAVE(ERRNO_H) @@ -118,7 +118,7 @@ typedef struct tagTHREADNAME_INFO { } THREADNAME_INFO; #pragma pack(pop) -void setThreadNameInternal(const char* szThreadName) +void initializeCurrentThreadInternal(const char* szThreadName) { THREADNAME_INFO info; info.dwType = 0x1000; @@ -161,7 +161,7 @@ void initializeThreading() initializeRandomNumberGenerator(); initializeMainThread(); mainThreadIdentifier = currentThread(); - setThreadNameInternal("Main Thread"); + initializeCurrentThreadInternal("Main Thread"); } } @@ -205,7 +205,7 @@ static unsigned __stdcall wtfThreadEntryPoint(void* param) void* result = invocation.function(invocation.data); -#if !USE(PTHREADS) && PLATFORM(WIN_OS) +#if !USE(PTHREADS) && OS(WINDOWS) // Do the TLS cleanup. ThreadSpecificThreadExit(); #endif @@ -218,7 +218,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con unsigned threadIdentifier = 0; ThreadIdentifier threadID = 0; ThreadFunctionInvocation* invocation = new ThreadFunctionInvocation(entryPoint, data); -#if PLATFORM(WINCE) +#if OS(WINCE) // This is safe on WINCE, since CRT is in the core and innately multithreaded. // On desktop Windows, need to use _beginthreadex (not available on WinCE) if using any CRT functions HANDLE threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)wtfThreadEntryPoint, invocation, 0, (LPDWORD)&threadIdentifier); @@ -226,7 +226,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation, 0, &threadIdentifier)); #endif if (!threadHandle) { -#if PLATFORM(WINCE) +#if OS(WINCE) LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, ::GetLastError()); #elif defined(NO_ERRNO) LOG_ERROR("Failed to create thread at entry point %p with data %p.", entryPoint, data); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TypeTraits.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TypeTraits.cpp index 36fc6c6..9e51ad0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TypeTraits.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TypeTraits.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009, 2010 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -101,6 +101,20 @@ COMPILE_ASSERT((!IsSameType<int, int*>::value), WTF_IsSameType_int_int_pointer_f COMPILE_ASSERT((!IsSameType<bool, const bool>::value), WTF_IsSameType_const_change_false); COMPILE_ASSERT((!IsSameType<bool, volatile bool>::value), WTF_IsSameType_volatile_change_false); +template <typename T> +class TestBaseClass { +}; + +class TestDerivedClass : public TestBaseClass<int> { +}; + +COMPILE_ASSERT((IsSubclass<TestDerivedClass, TestBaseClass<int> >::value), WTF_Test_IsSubclass_Derived_From_Base); +COMPILE_ASSERT((!IsSubclass<TestBaseClass<int>, TestDerivedClass>::value), WTF_Test_IsSubclass_Base_From_Derived); +COMPILE_ASSERT((IsSubclassOfTemplate<TestDerivedClass, TestBaseClass>::value), WTF_Test_IsSubclassOfTemplate_Base_From_Derived); +COMPILE_ASSERT((IsSameType<RemoveTemplate<TestBaseClass<int>, TestBaseClass>::Type, int>::value), WTF_Test_RemoveTemplate); +COMPILE_ASSERT((IsSameType<RemoveTemplate<int, TestBaseClass>::Type, int>::value), WTF_Test_RemoveTemplate_WithoutTemplate); + + COMPILE_ASSERT((IsSameType<bool, RemoveConst<const bool>::Type>::value), WTF_test_RemoveConst_const_bool); COMPILE_ASSERT((!IsSameType<bool, RemoveConst<volatile bool>::Type>::value), WTF_test_RemoveConst_volatile_bool); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TypeTraits.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TypeTraits.h index c03e8a7..7ba487f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TypeTraits.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/TypeTraits.h @@ -1,6 +1,6 @@ /* * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2009, 2010 Google Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -104,6 +104,40 @@ namespace WTF { static const bool value = true; }; + template <typename T, typename U> class IsSubclass { + typedef char YesType; + struct NoType { + char padding[8]; + }; + + static YesType subclassCheck(U*); + static NoType subclassCheck(...); + static T* t; + public: + static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); + }; + + template <typename T, template<class V> class U> class IsSubclassOfTemplate { + typedef char YesType; + struct NoType { + char padding[8]; + }; + + template<typename W> static YesType subclassCheck(U<W>*); + static NoType subclassCheck(...); + static T* t; + public: + static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); + }; + + template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate { + typedef T Type; + }; + + template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> { + typedef T Type; + }; + template <typename T> struct RemoveConst { typedef T Type; }; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/VMTags.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/VMTags.h index 519f518..1ec79d9 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/VMTags.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/VMTags.h @@ -30,7 +30,7 @@ // On Mac OS X, the VM subsystem allows tagging memory requested from mmap and vm_map // in order to aid tools that inspect system memory use. -#if PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) +#if OS(DARWIN) && !defined(BUILDING_ON_TIGER) #include <mach/vm_statistics.h> @@ -44,12 +44,12 @@ #define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(65) #endif // defined(VM_MEMORY_JAVASCRIPT_CORE) && defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) && defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) -#else // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) +#else // OS(DARWIN) && !defined(BUILDING_ON_TIGER) #define VM_TAG_FOR_COLLECTOR_MEMORY -1 #define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1 #define VM_TAG_FOR_REGISTERFILE_MEMORY -1 -#endif // PLATFORM(DARWIN) && !defined(BUILDING_ON_TIGER) +#endif // OS(DARWIN) && !defined(BUILDING_ON_TIGER) #endif // VMTags_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Vector.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Vector.h index 7decc4a..8a4ffba 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Vector.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Vector.h @@ -76,8 +76,15 @@ namespace WTF { }; #endif + template <size_t size, size_t alignment> + void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b) + { + for (size_t i = 0; i < size; ++i) + std::swap(a.buffer[i], b.buffer[i]); + } + template <bool needsDestruction, typename T> - class VectorDestructor; + struct VectorDestructor; template<typename T> struct VectorDestructor<false, T> @@ -96,7 +103,7 @@ namespace WTF { }; template <bool needsInitialization, bool canInitializeWithMemset, typename T> - class VectorInitializer; + struct VectorInitializer; template<bool ignore, typename T> struct VectorInitializer<false, ignore, T> @@ -124,7 +131,7 @@ namespace WTF { }; template <bool canMoveWithMemcpy, typename T> - class VectorMover; + struct VectorMover; template<typename T> struct VectorMover<false, T> @@ -168,7 +175,7 @@ namespace WTF { }; template <bool canCopyWithMemcpy, typename T> - class VectorCopier; + struct VectorCopier; template<typename T> struct VectorCopier<false, T> @@ -193,7 +200,7 @@ namespace WTF { }; template <bool canFillWithMemset, typename T> - class VectorFiller; + struct VectorFiller; template<typename T> struct VectorFiller<false, T> @@ -218,7 +225,7 @@ namespace WTF { }; template<bool canCompareWithMemcmp, typename T> - class VectorComparer; + struct VectorComparer; template<typename T> struct VectorComparer<false, T> @@ -417,6 +424,27 @@ namespace WTF { Base::deallocateBuffer(bufferToDeallocate); } + void swap(VectorBuffer<T, inlineCapacity>& other) + { + if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) { + WTF::swap(m_inlineBuffer, other.m_inlineBuffer); + std::swap(m_capacity, other.m_capacity); + } else if (buffer() == inlineBuffer()) { + m_buffer = other.m_buffer; + other.m_buffer = other.inlineBuffer(); + WTF::swap(m_inlineBuffer, other.m_inlineBuffer); + std::swap(m_capacity, other.m_capacity); + } else if (other.buffer() == other.inlineBuffer()) { + other.m_buffer = m_buffer; + m_buffer = inlineBuffer(); + WTF::swap(m_inlineBuffer, other.m_inlineBuffer); + std::swap(m_capacity, other.m_capacity); + } else { + std::swap(m_buffer, other.m_buffer); + std::swap(m_capacity, other.m_capacity); + } + } + void restoreInlineBufferIfNeeded() { if (m_buffer) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/VectorTraits.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/VectorTraits.h index eb4c279..bf77878 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/VectorTraits.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/VectorTraits.h @@ -32,7 +32,7 @@ using std::pair; namespace WTF { template<bool isPod, typename T> - class VectorTraitsBase; + struct VectorTraitsBase; template<typename T> struct VectorTraitsBase<false, T> diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/android/AndroidThreading.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/android/AndroidThreading.h new file mode 100644 index 0000000..27f548c --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/android/AndroidThreading.h @@ -0,0 +1,39 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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 AndroidThreading_h +#define AndroidThreading_h + +namespace WTF { + +// An interface to the embedding layer, which provides threading support. +class AndroidThreading { +public: + static void scheduleDispatchFunctionsOnMainThread(); +}; + +} // namespace WTF + +#endif // AndroidThreading_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/android/MainThreadAndroid.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/android/MainThreadAndroid.cpp new file mode 100644 index 0000000..5e5f7b1 --- /dev/null +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/android/MainThreadAndroid.cpp @@ -0,0 +1,42 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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 THE COPYRIGHT HOLDERS ``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 THE COPYRIGHT OWNER 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. + */ + +#include "config.h" +#include "MainThread.h" + +#include "AndroidThreading.h" + +namespace WTF { + +void initializeMainThreadPlatform() +{ +} + +void scheduleDispatchFunctionsOnMainThread() +{ + AndroidThreading::scheduleDispatchFunctionsOnMainThread(); +} + +} // namespace WTF diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/dtoa.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/dtoa.cpp index d75c17a..6289d04 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/dtoa.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/dtoa.cpp @@ -140,7 +140,6 @@ #else #define NO_ERRNO #endif -#include <float.h> #include <math.h> #include <stdint.h> #include <stdlib.h> @@ -148,6 +147,7 @@ #include <wtf/AlwaysInline.h> #include <wtf/Assertions.h> #include <wtf/FastMalloc.h> +#include <wtf/MathExtras.h> #include <wtf/Vector.h> #include <wtf/Threading.h> @@ -159,9 +159,9 @@ #pragma warning(disable: 4554) #endif -#if PLATFORM(BIG_ENDIAN) +#if CPU(BIG_ENDIAN) #define IEEE_MC68k -#elif PLATFORM(MIDDLE_ENDIAN) +#elif CPU(MIDDLE_ENDIAN) #define IEEE_ARM #else #define IEEE_8087 @@ -262,7 +262,8 @@ typedef union { double d; uint32_t L[2]; } U; #define Pack_32 #endif -#if PLATFORM(PPC64) || PLATFORM(X86_64) +#if CPU(PPC64) || CPU(X86_64) +// FIXME: should we enable this on all 64-bit CPUs? // 64-bit emulation provided by the compiler is likely to be slower than dtoa own code on 32-bit hardware. #define USE_LONG_LONG #endif @@ -560,7 +561,7 @@ static void mult(BigInt& aRef, const BigInt& bRef) aRef = c; } -struct P5Node { +struct P5Node : Noncopyable { BigInt val; P5Node* next; }; @@ -1869,7 +1870,7 @@ static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S) * calculation. */ -void dtoa(char* result, double dd, int ndigits, int* decpt, int* sign, char** rve) +void dtoa(DtoaBuffer result, double dd, int ndigits, int* decpt, int* sign, char** rve) { /* Arguments ndigits, decpt, sign are similar to those @@ -1908,16 +1909,23 @@ void dtoa(char* result, double dd, int ndigits, int* decpt, int* sign, char** rv { /* Infinity or NaN */ *decpt = 9999; - if (!word1(&u) && !(word0(&u) & 0xfffff)) + if (!word1(&u) && !(word0(&u) & 0xfffff)) { strcpy(result, "Infinity"); - else + if (rve) + *rve = result + 8; + } else { strcpy(result, "NaN"); + if (rve) + *rve = result + 3; + } return; } if (!dval(&u)) { *decpt = 1; result[0] = '0'; result[1] = '\0'; + if (rve) + *rve = result + 1; return; } @@ -2376,4 +2384,83 @@ ret: *rve = s; } +static ALWAYS_INLINE void append(char*& next, const char* src, unsigned size) +{ + for (unsigned i = 0; i < size; ++i) + *next++ = *src++; +} + +void doubleToStringInJavaScriptFormat(double d, DtoaBuffer buffer, unsigned* resultLength) +{ + ASSERT(buffer); + + // avoid ever printing -NaN, in JS conceptually there is only one NaN value + if (isnan(d)) { + append(buffer, "NaN", 3); + if (resultLength) + *resultLength = 3; + return; + } + // -0 -> "0" + if (!d) { + buffer[0] = '0'; + if (resultLength) + *resultLength = 1; + return; + } + + int decimalPoint; + int sign; + + DtoaBuffer result; + char* resultEnd = 0; + WTF::dtoa(result, d, 0, &decimalPoint, &sign, &resultEnd); + int length = resultEnd - result; + + char* next = buffer; + if (sign) + *next++ = '-'; + + if (decimalPoint <= 0 && decimalPoint > -6) { + *next++ = '0'; + *next++ = '.'; + for (int j = decimalPoint; j < 0; j++) + *next++ = '0'; + append(next, result, length); + } else if (decimalPoint <= 21 && decimalPoint > 0) { + if (length <= decimalPoint) { + append(next, result, length); + for (int j = 0; j < decimalPoint - length; j++) + *next++ = '0'; + } else { + append(next, result, decimalPoint); + *next++ = '.'; + append(next, result + decimalPoint, length - decimalPoint); + } + } else if (result[0] < '0' || result[0] > '9') + append(next, result, length); + else { + *next++ = result[0]; + if (length > 1) { + *next++ = '.'; + append(next, result + 1, length - 1); + } + + *next++ = 'e'; + *next++ = (decimalPoint >= 0) ? '+' : '-'; + // decimalPoint can't be more than 3 digits decimal given the + // nature of float representation + int exponential = decimalPoint - 1; + if (exponential < 0) + exponential = -exponential; + if (exponential >= 100) + *next++ = static_cast<char>('0' + exponential / 100); + if (exponential >= 10) + *next++ = static_cast<char>('0' + (exponential % 100) / 10); + *next++ = static_cast<char>('0' + exponential % 10); + } + if (resultLength) + *resultLength = next - buffer; +} + } // namespace WTF diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/dtoa.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/dtoa.h index cbec7c7..6127f53 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/dtoa.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/dtoa.h @@ -30,8 +30,18 @@ namespace WTF { extern WTF::Mutex* s_dtoaP5Mutex; double strtod(const char* s00, char** se); - void dtoa(char* result, double d, int ndigits, int* decpt, int* sign, char** rve); + + typedef char DtoaBuffer[80]; + void dtoa(DtoaBuffer result, double d, int ndigits, int* decpt, int* sign, char** rve); + + // dtoa() for ECMA-262 'ToString Applied to the Number Type.' + // The *resultLength will have the length of the resultant string in bufer. + // The resultant string isn't terminated by 0. + void doubleToStringInJavaScriptFormat(double, DtoaBuffer, unsigned* resultLength); } // namespace WTF +using WTF::DtoaBuffer; +using WTF::doubleToStringInJavaScriptFormat; + #endif // WTF_dtoa_h diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/qt/ThreadingQt.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/qt/ThreadingQt.cpp index 5a84764..3e5aa59 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/qt/ThreadingQt.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/qt/ThreadingQt.cpp @@ -29,6 +29,8 @@ #include "config.h" #include "Threading.h" +#if !ENABLE(SINGLE_THREADED) + #include "CurrentTime.h" #include "HashMap.h" #include "MainThread.h" @@ -66,6 +68,21 @@ void ThreadPrivate::run() m_returnValue = m_entryPoint(m_data); } +class ThreadMonitor : public QObject { + Q_OBJECT +public: + static ThreadMonitor * instance() + { + static ThreadMonitor *instance = new ThreadMonitor(); + return instance; + } + +public Q_SLOTS: + void threadFinished() + { + sender()->deleteLater(); + } +}; static Mutex* atomicallyInitializedStaticMutex; @@ -157,6 +174,9 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con LOG_ERROR("Failed to create thread at entry point %p with data %p", entryPoint, data); return 0; } + + QObject::connect(thread, SIGNAL(finished()), ThreadMonitor::instance(), SLOT(threadFinished())); + thread->start(); QThread* threadRef = static_cast<QThread*>(thread); @@ -164,7 +184,7 @@ ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, con return establishIdentifierForThread(threadRef); } -void setThreadNameInternal(const char*) +void initializeCurrentThreadInternal(const char*) { } @@ -183,8 +203,10 @@ int waitForThreadCompletion(ThreadIdentifier threadID, void** result) return !res; } -void detachThread(ThreadIdentifier) +void detachThread(ThreadIdentifier threadID) { + ASSERT(threadID); + clearThreadForIdentifier(threadID); } ThreadIdentifier currentThread() @@ -269,3 +291,7 @@ void ThreadCondition::broadcast() } } // namespace WebCore + +#include "ThreadingQt.moc" + +#endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/UTF8.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/UTF8.cpp index 9e713fe..21d5856 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/UTF8.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/UTF8.cpp @@ -23,6 +23,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include "config.h" #include "UTF8.h" namespace WTF { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/Unicode.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/Unicode.h index 7016a03..d59439d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/Unicode.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/Unicode.h @@ -26,11 +26,7 @@ #include <wtf/Assertions.h> #if USE(QT4_UNICODE) -#if COMPILER(WINSCW) || COMPILER(RVCT) -#include "wtf/unicode/qt4/UnicodeQt4.h" -#else #include "qt4/UnicodeQt4.h" -#endif #elif USE(ICU_UNICODE) #include <wtf/unicode/icu/UnicodeIcu.h> #elif USE(GLIB_UNICODE) diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp index a779b36..e20c376 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp @@ -19,6 +19,7 @@ * */ +#include "config.h" #include "UnicodeGLib.h" namespace WTF { diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h index c03d3ec..d72e707 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h @@ -26,7 +26,7 @@ #define UnicodeGLib_h #include "UnicodeMacrosFromICU.h" -#include <wtf/GOwnPtr.h> +#include <wtf/gtk/GOwnPtr.h> #include <glib.h> #include <pango/pango.h> @@ -152,6 +152,11 @@ inline bool isArabicChar(UChar32 c) return c >= 0x0600 && c <= 0x06FF; } +inline bool isAlphanumeric(UChar32 c) +{ + return g_unichar_isalnum(c); +} + inline bool isFormatChar(UChar32 c) { return g_unichar_type(c) == G_UNICODE_FORMAT; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp index 6376bb3..a1753a4 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp @@ -36,7 +36,7 @@ #include <unicode/ucol.h> #include <string.h> -#if PLATFORM(DARWIN) +#if OS(DARWIN) #include "RetainPtr.h" #include <CoreFoundation/CoreFoundation.h> #endif @@ -59,9 +59,9 @@ Collator::Collator(const char* locale) std::auto_ptr<Collator> Collator::userDefault() { -#if PLATFORM(DARWIN) && PLATFORM(CF) +#if OS(DARWIN) && PLATFORM(CF) // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work. -#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !PLATFORM(IPHONE) +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !OS(IPHONE_OS) RetainPtr<CFLocaleRef> currentLocale(AdoptCF, CFLocaleCopyCurrent()); CFStringRef collationOrder = (CFStringRef)CFLocaleGetValue(currentLocale.get(), kCFLocaleCollatorIdentifier); #else diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h index 35c6fbf..a2a5c0a 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h @@ -164,6 +164,11 @@ inline bool isArabicChar(UChar32 c) return ublock_getCode(c) == UBLOCK_ARABIC; } +inline bool isAlphanumeric(UChar32 c) +{ + return u_isalnum(c); +} + inline bool isSeparatorSpace(UChar32 c) { return u_charType(c) == U_SPACE_SEPARATOR; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h index e01f825..1c7a692f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h @@ -30,7 +30,6 @@ #include <stdint.h> -#if QT_VERSION >= 0x040300 QT_BEGIN_NAMESPACE namespace QUnicodeTables { struct Properties { @@ -55,7 +54,6 @@ namespace QUnicodeTables { Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2); } QT_END_NAMESPACE -#endif // ugly hack to make UChar compatible with JSChar in API/JSStringRef.h #if defined(Q_OS_WIN) || COMPILER(WINSCW) @@ -188,8 +186,6 @@ enum CharCategory { }; -#if QT_VERSION >= 0x040300 - // FIXME: handle surrogates correctly in all methods inline UChar32 toLower(UChar32 ch) @@ -408,138 +404,6 @@ inline CharCategory category(UChar32 c) return (CharCategory) U_MASK(QChar::category(c)); } -#else - -inline UChar32 toLower(UChar32 ch) -{ - if (ch > 0xffff) - return ch; - return QChar((unsigned short)ch).toLower().unicode(); -} - -inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - *error = false; - if (resultLength < srcLength) { - *error = true; - return srcLength; - } - for (int i = 0; i < srcLength; ++i) - result[i] = QChar(src[i]).toLower().unicode(); - return srcLength; -} - -inline UChar32 toUpper(UChar32 ch) -{ - if (ch > 0xffff) - return ch; - return QChar((unsigned short)ch).toUpper().unicode(); -} - -inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - *error = false; - if (resultLength < srcLength) { - *error = true; - return srcLength; - } - for (int i = 0; i < srcLength; ++i) - result[i] = QChar(src[i]).toUpper().unicode(); - return srcLength; -} - -inline int toTitleCase(UChar32 c) -{ - if (c > 0xffff) - return c; - return QChar((unsigned short)c).toUpper().unicode(); -} - -inline UChar32 foldCase(UChar32 c) -{ - if (c > 0xffff) - return c; - return QChar((unsigned short)c).toLower().unicode(); -} - -inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - return toLower(result, resultLength, src, srcLength, error); -} - -inline bool isPrintableChar(UChar32 c) -{ - return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPrint(); -} - -inline bool isArabicChar(UChar32 c) -{ - return c >= 0x0600 && c <= 0x06FF; -} - -inline bool isSeparatorSpace(UChar32 c) -{ - return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Separator_Space; -} - -inline bool isPunct(UChar32 c) -{ - return (c & 0xffff0000) == 0 && QChar((unsigned short)c).isPunct(); -} - -inline bool isLower(UChar32 c) -{ - return (c & 0xffff0000) == 0 && QChar((unsigned short)c).category() == QChar::Letter_Lowercase; -} - -inline UChar32 mirroredChar(UChar32 c) -{ - if (c > 0xffff) - return c; - return QChar(c).mirroredChar().unicode(); -} - -inline uint8_t combiningClass(UChar32 c) -{ - if (c > 0xffff) - return 0; - return QChar((unsigned short)c).combiningClass(); -} - -inline DecompositionType decompositionType(UChar32 c) -{ - if (c > 0xffff) - return DecompositionNone; - return (DecompositionType)QChar(c).decompositionTag(); -} - -inline int umemcasecmp(const UChar* a, const UChar* b, int len) -{ - for (int i = 0; i < len; ++i) { - QChar c1 = QChar(a[i]).toLower(); - QChar c2 = QChar(b[i]).toLower(); - if (c1 != c2) - return c1.unicode() - c2.unicode(); - } - return 0; -} - -inline Direction direction(UChar32 c) -{ - if (c > 0xffff) - return LeftToRight; - return (Direction)QChar(c).direction(); -} - -inline CharCategory category(UChar32 c) -{ - if (c > 0xffff) - return NoCategory; - return (CharCategory) U_MASK(QChar(c).category()); -} - -#endif - } } #endif // WTF_UNICODE_QT4_H diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/wince/UnicodeWince.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/wince/UnicodeWince.cpp index 966f2a1..2df44f8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/wince/UnicodeWince.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/unicode/wince/UnicodeWince.cpp @@ -19,6 +19,7 @@ * Boston, MA 02110-1301, USA. */ +#include "config.h" #include "UnicodeWince.h" #include <wchar.h> diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/wince/FastMallocWince.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/wince/FastMallocWince.h index 93d9f75..37174f0 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/wince/FastMallocWince.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/wince/FastMallocWince.h @@ -1,5 +1,4 @@ /* - * This file is part of the KDE libraries * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved * diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/wince/MemoryManager.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/wince/MemoryManager.cpp index b65b368..81d4f80 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/wince/MemoryManager.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/wince/MemoryManager.cpp @@ -139,25 +139,25 @@ void* fastZeroedMalloc(size_t n) return p; } -void* tryFastMalloc(size_t n) +TryMallocReturnValue tryFastMalloc(size_t n) { MemoryAllocationCanFail canFail; return fastMalloc(n); } -void* tryFastZeroedMalloc(size_t n) +TryMallocReturnValue tryFastZeroedMalloc(size_t n) { MemoryAllocationCanFail canFail; return fastZeroedMalloc(n); } -void* tryFastCalloc(size_t n_elements, size_t element_size) +TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size) { MemoryAllocationCanFail canFail; return fastCalloc(n_elements, element_size); } -void* tryFastRealloc(void* p, size_t n) +TryMallocReturnValue tryFastRealloc(void* p, size_t n) { MemoryAllocationCanFail canFail; return fastRealloc(p, n); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexCompiler.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexCompiler.cpp index c7b3c81..9cd3d12 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexCompiler.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexCompiler.cpp @@ -708,7 +708,7 @@ const char* compileRegex(const UString& patternString, RegexPattern& pattern) unsigned numSubpatterns = pattern.m_numSubpatterns; constructor.reset(); -#ifndef NDEBUG +#if !ASSERT_DISABLED const char* error = #endif parse(constructor, patternString, numSubpatterns); diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexInterpreter.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexInterpreter.cpp index aafea3c..d088086 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexInterpreter.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexInterpreter.cpp @@ -1490,7 +1490,7 @@ public: closeBodyAlternative(); } - void alterantiveBodyDisjunction() + void alternativeBodyDisjunction() { int newAlternativeIndex = m_bodyDisjunction->terms.size(); m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex; @@ -1499,7 +1499,7 @@ public: m_currentAlternativeIndex = newAlternativeIndex; } - void alterantiveDisjunction() + void alternativeDisjunction() { int newAlternativeIndex = m_bodyDisjunction->terms.size(); m_bodyDisjunction->terms[m_currentAlternativeIndex].alternative.next = newAlternativeIndex - m_currentAlternativeIndex; @@ -1515,9 +1515,9 @@ public: if (alt) { if (disjunction == m_pattern.m_body) - alterantiveBodyDisjunction(); + alternativeBodyDisjunction(); else - alterantiveDisjunction(); + alternativeDisjunction(); } PatternAlternative* alternative = disjunction->m_alternatives[alt]; diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexJIT.cpp b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexJIT.cpp index d777424..fcb8d86 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexJIT.cpp +++ b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexJIT.cpp @@ -44,7 +44,7 @@ namespace JSC { namespace Yarr { class RegexGenerator : private MacroAssembler { friend void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline); -#if PLATFORM(ARM) +#if CPU(ARM) static const RegisterID input = ARMRegisters::r0; static const RegisterID index = ARMRegisters::r1; static const RegisterID length = ARMRegisters::r2; @@ -54,7 +54,7 @@ class RegexGenerator : private MacroAssembler { static const RegisterID regT1 = ARMRegisters::r6; static const RegisterID returnRegister = ARMRegisters::r0; -#elif PLATFORM(X86) +#elif CPU(X86) static const RegisterID input = X86Registers::eax; static const RegisterID index = X86Registers::edx; static const RegisterID length = X86Registers::ecx; @@ -64,7 +64,7 @@ class RegexGenerator : private MacroAssembler { static const RegisterID regT1 = X86Registers::esi; static const RegisterID returnRegister = X86Registers::eax; -#elif PLATFORM(X86_64) +#elif CPU(X86_64) static const RegisterID input = X86Registers::edi; static const RegisterID index = X86Registers::esi; static const RegisterID length = X86Registers::edx; @@ -1264,7 +1264,7 @@ class RegexGenerator : private MacroAssembler { // complex here in compilation, and in the common case we should end up coallescing the checks. // // FIXME: a nice improvement here may be to stop trying to match sooner, based on the least - // of the minimum-alterantive-lengths. E.g. if I have two alternatives of length 200 and 150, + // of the minimum-alternative-lengths. E.g. if I have two alternatives of length 200 and 150, // and a string of length 100, we'll end up looping index from 0 to 100, checking whether there // is sufficient input to run either alternative (constantly failing). If there had been only // one alternative, or if the shorter alternative had come first, we would have terminated @@ -1288,11 +1288,11 @@ class RegexGenerator : private MacroAssembler { void generateEnter() { -#if PLATFORM(X86_64) +#if CPU(X86_64) push(X86Registers::ebp); move(stackPointerRegister, X86Registers::ebp); push(X86Registers::ebx); -#elif PLATFORM(X86) +#elif CPU(X86) push(X86Registers::ebp); move(stackPointerRegister, X86Registers::ebp); // TODO: do we need spill registers to fill the output pointer if there are no sub captures? @@ -1308,10 +1308,7 @@ class RegexGenerator : private MacroAssembler { #else loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output); #endif -#elif PLATFORM(ARM) -#if PLATFORM(ARM_TRADITIONAL) - push(ARMRegisters::lr); -#endif +#elif CPU(ARM) push(ARMRegisters::r4); push(ARMRegisters::r5); push(ARMRegisters::r6); @@ -1321,15 +1318,15 @@ class RegexGenerator : private MacroAssembler { void generateReturn() { -#if PLATFORM(X86_64) +#if CPU(X86_64) pop(X86Registers::ebx); pop(X86Registers::ebp); -#elif PLATFORM(X86) +#elif CPU(X86) pop(X86Registers::esi); pop(X86Registers::edi); pop(X86Registers::ebx); pop(X86Registers::ebp); -#elif PLATFORM(ARM) +#elif CPU(ARM) pop(ARMRegisters::r6); pop(ARMRegisters::r5); pop(ARMRegisters::r4); @@ -1400,14 +1397,6 @@ void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const } } -int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize) -{ - if (JSRegExp* fallback = jitObject.getFallback()) - return (jsRegExpExecute(fallback, input, length, start, output, outputArraySize) < 0) ? -1 : output[0]; - - return jitObject.execute(input, start, length, output); -} - }} #endif diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexJIT.h b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexJIT.h index 5b0df9d..5ead00f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexJIT.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexJIT.h @@ -37,7 +37,7 @@ #include <pcre.h> struct JSRegExp; // temporary, remove when fallback is removed. -#if PLATFORM(X86) && !COMPILER(MSVC) +#if CPU(X86) && !COMPILER(MSVC) #define YARR_CALL __attribute__ ((regparm (3))) #else #define YARR_CALL @@ -73,7 +73,7 @@ public: int execute(const UChar* input, unsigned start, unsigned length, int* output) { - return reinterpret_cast<RegexJITCode>(m_ref.m_code.executableAddress())(input, start, length, output); + return ((RegexJITCode)(m_ref.m_code.executableAddress()))(input, start, length, output); } private: @@ -82,7 +82,14 @@ private: }; void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase = false, bool multiline = false); -int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize); + +inline int executeRegex(RegexCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output, int outputArraySize) +{ + if (JSRegExp* fallback = jitObject.getFallback()) + return (jsRegExpExecute(fallback, input, length, start, output, outputArraySize) < 0) ? -1 : output[0]; + + return jitObject.execute(input, start, length, output); +} } } // namespace JSC::Yarr diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexPattern.h b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexPattern.h index a451131..dd7512d 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexPattern.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/yarr/RegexPattern.h @@ -137,7 +137,7 @@ struct PatternTerm { PatternTerm(unsigned spatternId) : type(TypeBackReference) - , invertOrCapture(invertOrCapture) + , invertOrCapture(false) { subpatternId = spatternId; quantityType = QuantifierFixedCount; diff --git a/src/3rdparty/javascriptcore/VERSION b/src/3rdparty/javascriptcore/VERSION index d75862d..6351105 100644 --- a/src/3rdparty/javascriptcore/VERSION +++ b/src/3rdparty/javascriptcore/VERSION @@ -4,8 +4,8 @@ This is a snapshot of JavaScriptCore from The commit imported was from the - jsc-for-qtscript-4.6-staging-06102009 branch/tag + javascriptcore-snapshot-23022010 branch/tag and has the sha1 checksum - 32d226eb14d44f80e9ec96d4ca2c595181eeeca3 + 8a21225144f7c1e10ffcb9aa7a545164d9495bf2 diff --git a/src/3rdparty/javascriptcore/WebKit.pri b/src/3rdparty/javascriptcore/WebKit.pri index 16f89bf..0dd0799 100644 --- a/src/3rdparty/javascriptcore/WebKit.pri +++ b/src/3rdparty/javascriptcore/WebKit.pri @@ -1,5 +1,16 @@ # Include file to make it easy to include WebKit into Qt projects +# Detect that we are building as a standalone package by the presence of +# either the generated files directory or as part of the Qt package through +# QTDIR_build +CONFIG(QTDIR_build): CONFIG += standalone_package +else:exists($$PWD/WebCore/generated): CONFIG += standalone_package + +CONFIG(standalone_package) { + OUTPUT_DIR=$$PWD +} + +CONFIG += depend_includepath isEmpty(OUTPUT_DIR) { CONFIG(debug, debug|release) { @@ -17,19 +28,28 @@ building-libs { QT += webkit } else { QMAKE_LIBDIR = $$OUTPUT_DIR/lib $$QMAKE_LIBDIR + QTWEBKITLIBNAME = QtWebKit mac:!static:contains(QT_CONFIG, qt_framework):!CONFIG(webkit_no_framework) { - LIBS += -framework QtWebKit + LIBS += -framework $$QTWEBKITLIBNAME QMAKE_FRAMEWORKPATH = $$OUTPUT_DIR/lib $$QMAKE_FRAMEWORKPATH } else { win32-*|wince* { - LIBS += -lQtWebKit$${QT_MAJOR_VERSION} + CONFIG(debug, debug|release):build_pass: QTWEBKITLIBNAME = $${QTWEBKITLIBNAME}d + QTWEBKITLIBNAME = $${QTWEBKITLIBNAME}$${QT_MAJOR_VERSION} + win32-g++: LIBS += -l$$QTWEBKITLIBNAME + else: LIBS += $${QTWEBKITLIBNAME}.lib } else { LIBS += -lQtWebKit + symbian { + TARGET.EPOCSTACKSIZE = 0x14000 // 80 kB + TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 // Min 128kB, Max 32MB + } } } } DEPENDPATH += $$PWD/WebKit/qt/Api } +greaterThan(QT_MINOR_VERSION, 5):DEFINES += WTF_USE_ACCELERATED_COMPOSITING !mac:!unix|symbian { DEFINES += USE_SYSTEM_MALLOC @@ -43,15 +63,13 @@ BASE_DIR = $$PWD INCLUDEPATH += $$PWD/WebKit/qt/Api CONFIG -= warn_on -*-g++*:QMAKE_CXXFLAGS += -Wreturn-type -fno-strict-aliasing -#QMAKE_CXXFLAGS += -Wall -Wno-undef -Wno-unused-parameter +*-g++*:QMAKE_CXXFLAGS += -Wall -Wreturn-type -fno-strict-aliasing -Wcast-align -Wchar-subscripts -Wformat-security -Wreturn-type -Wno-unused-parameter -Wno-sign-compare -Wno-switch -Wno-switch-enum -Wundef -Wmissing-noreturn -Winit-self # Enable GNU compiler extensions to the ARM compiler for all Qt ports using RVCT symbian|*-armcc { RVCT_COMMON_CFLAGS = --gnu --diag_suppress 68,111,177,368,830,1293 RVCT_COMMON_CXXFLAGS = $$RVCT_COMMON_CFLAGS --no_parse_templates - DEFINES *= QT_NO_UITOOLS -} +} *-armcc { QMAKE_CFLAGS += $$RVCT_COMMON_CFLAGS @@ -62,75 +80,11 @@ symbian { QMAKE_CXXFLAGS.ARMCC += $$RVCT_COMMON_CXXFLAGS } +symbian|maemo5: DEFINES *= QT_NO_UITOOLS + contains(DEFINES, QT_NO_UITOOLS): CONFIG -= uitools # Disable a few warnings on Windows. The warnings are also # disabled in WebKitLibraries/win/tools/vsprops/common.vsprops -win32-msvc*: QMAKE_CXXFLAGS += -wd4291 -wd4344 -wd4503 -wd4800 -wd4819 -wd4996 - -# -# For builds inside Qt we interpret the output rule and the input of each extra compiler manually -# and add the resulting sources to the SOURCES variable, because the build inside Qt contains already -# all the generated files. We do not need to generate any extra compiler rules in that case. -# -# In addition this function adds a new target called 'generated_files' that allows manually calling -# all the extra compilers to generate all the necessary files for the build using 'make generated_files' -# -defineTest(addExtraCompiler) { - CONFIG(QTDIR_build) { - outputRule = $$eval($${1}.output) - outVariable = $$eval($${1}.variable_out) - !isEqual(outVariable,GENERATED_SOURCES):return(true) - - input = $$eval($${1}.input) - input = $$eval($$input) - - for(file,input) { - base = $$basename(file) - base ~= s/\..+// - newfile=$$replace(outputRule,\\$\\{QMAKE_FILE_BASE\\},$$base) - SOURCES += $$newfile - } - - export(SOURCES) - } else { - QMAKE_EXTRA_COMPILERS += $$1 - generated_files.depends += compiler_$${1}_make_all - export(QMAKE_EXTRA_COMPILERS) - export(generated_files.depends) - } - return(true) -} - -defineTest(addExtraCompilerWithHeader) { - addExtraCompiler($$1) - - eval(headerFile = $${2}) - isEmpty(headerFile) { - eval($${1}_header.output = $$eval($${1}.output)) - eval($${1}_header.output ~= s/\.cpp/.h/) - eval($${1}_header.output ~= s/\.c/.h/) - } else { - eval($${1}_header.output = $$headerFile) - } - - eval($${1}_header.input = $$eval($${1}.input)) - eval($${1}_header.commands = @echo -n '') - eval($${1}_header.depends = compiler_$${1}_make_all) - eval($${1}_header.variable_out = GENERATED_FILES) - - export($${1}_header.output) - export($${1}_header.input) - export($${1}_header.commands) - export($${1}_header.depends) - export($${1}_header.variable_out) - - !CONFIG(QTDIR_build): QMAKE_EXTRA_COMPILERS += $${1}_header - - export(QMAKE_EXTRA_COMPILERS) - export(generated_files.depends) - export(SOURCES) - - return(true) -} +win32-msvc*: QMAKE_CXXFLAGS += -wd4291 -wd4344 -wd4396 -wd4503 -wd4800 -wd4819 -wd4996 diff --git a/src/corelib/arch/qatomic_arm.h b/src/corelib/arch/qatomic_arm.h index 9d7e9c6..9df02a2 100644 --- a/src/corelib/arch/qatomic_arm.h +++ b/src/corelib/arch/qatomic_arm.h @@ -108,8 +108,8 @@ Q_INLINE_TEMPLATE bool QBasicAtomicPointer<T>::isFetchAndAddWaitFree() // kernel places a restartable cmpxchg implementation at a fixed address extern "C" typedef int (qt_atomic_eabi_cmpxchg_int_t)(int oldval, int newval, volatile int *ptr); extern "C" typedef int (qt_atomic_eabi_cmpxchg_ptr_t)(void *oldval, void *newval, volatile void *ptr); -#define qt_atomic_eabi_cmpxchg_int (*(qt_atomic_eabi_cmpxchg_int_t *)0xffff0fc0) -#define qt_atomic_eabi_cmpxchg_ptr (*(qt_atomic_eabi_cmpxchg_ptr_t *)0xffff0fc0) +#define qt_atomic_eabi_cmpxchg_int (*reinterpret_cast<qt_atomic_eabi_cmpxchg_int_t *>(0xffff0fc0)) +#define qt_atomic_eabi_cmpxchg_ptr (*reinterpret_cast<qt_atomic_eabi_cmpxchg_ptr_t *>(0xffff0fc0)) #else diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp index 4034218..72b0128 100644 --- a/src/corelib/codecs/qtextcodec.cpp +++ b/src/corelib/codecs/qtextcodec.cpp @@ -399,9 +399,35 @@ QString QWindowsLocalCodec::convertToUnicodeCharByChar(const char *chars, int le return s; } -QByteArray QWindowsLocalCodec::convertFromUnicode(const QChar *uc, int len, ConverterState *) const +QByteArray QWindowsLocalCodec::convertFromUnicode(const QChar *ch, int uclen, ConverterState *) const { - return qt_winQString2MB(uc, len); + if (!ch) + return QByteArray(); + if (uclen == 0) + return QByteArray(""); + BOOL used_def; + QByteArray mb(4096, 0); + int len; + while (!(len=WideCharToMultiByte(CP_ACP, 0, (const wchar_t*)ch, uclen, + mb.data(), mb.size()-1, 0, &used_def))) + { + int r = GetLastError(); + if (r == ERROR_INSUFFICIENT_BUFFER) { + mb.resize(1+WideCharToMultiByte(CP_ACP, 0, + (const wchar_t*)ch, uclen, + 0, 0, 0, &used_def)); + // and try again... + } else { +#ifndef QT_NO_DEBUG + // Fail. + qWarning("WideCharToMultiByte: Cannot convert multibyte text (error %d): %s (UTF-8)", + r, QString(ch, uclen).toLocal8Bit().data()); +#endif + break; + } + } + mb.resize(len); + return mb; } diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp index 625098e..37591c5 100644 --- a/src/corelib/io/qfileinfo.cpp +++ b/src/corelib/io/qfileinfo.cpp @@ -41,7 +41,6 @@ #include "qplatformdefs.h" #include "qfileinfo.h" -#include "qfsfileengine_p.h" #include "qglobal.h" #include "qdir.h" #include "qfileinfo_p.h" @@ -75,50 +74,6 @@ void QFileInfoPrivate::initFileEngine(const QString &file) data->fileName = file; } -bool QFileInfoPrivate::hasAccess(Access access) const -{ - if (!(getFileFlags(QAbstractFileEngine::PermsMask - | QAbstractFileEngine::LocalDiskFlag) & QAbstractFileEngine::LocalDiskFlag)) { - switch (access) { - case ReadAccess: - return getFileFlags(QAbstractFileEngine::ReadUserPerm); - case WriteAccess: - return getFileFlags(QAbstractFileEngine::WriteUserPerm); - case ExecuteAccess: - return getFileFlags(QAbstractFileEngine::ExeUserPerm); - default: - return false; - } - } - - int mode = 0; - switch (access) { - case ReadAccess: - mode = R_OK; - break; - case WriteAccess: - mode = W_OK; - break; - case ExecuteAccess: - mode = X_OK; - break; - }; -#ifdef Q_OS_UNIX - return QT_ACCESS(QFile::encodeName(data->fileName).data(), mode) == 0; -#endif -#ifdef Q_OS_WIN - if ((access == ReadAccess && !getFileFlags(QAbstractFileEngine::ReadUserPerm)) - || (access == WriteAccess && !getFileFlags(QAbstractFileEngine::WriteUserPerm))) { - return false; - } - if (access == ExecuteAccess) - return getFileFlags(QAbstractFileEngine::ExeUserPerm); - - return ::_waccess((wchar_t*)QFSFileEnginePrivate::longFileName(data->fileName).utf16(), mode) == 0; -#endif - return false; -} - void QFileInfoPrivate::detach() { qAtomicDetach(data); @@ -893,7 +848,7 @@ bool QFileInfo::isReadable() const Q_D(const QFileInfo); if (!d->data->fileEngine) return false; - return d->hasAccess(QFileInfoPrivate::ReadAccess); + return d->getFileFlags(QAbstractFileEngine::ReadUserPerm); } /*! @@ -906,7 +861,7 @@ bool QFileInfo::isWritable() const Q_D(const QFileInfo); if (!d->data->fileEngine) return false; - return d->hasAccess(QFileInfoPrivate::WriteAccess); + return d->getFileFlags(QAbstractFileEngine::WriteUserPerm); } /*! @@ -919,7 +874,7 @@ bool QFileInfo::isExecutable() const Q_D(const QFileInfo); if (!d->data->fileEngine) return false; - return d->hasAccess(QFileInfoPrivate::ExecuteAccess); + return d->getFileFlags(QAbstractFileEngine::ExeUserPerm); } /*! diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h index d97a0cf..306ffe1 100644 --- a/src/corelib/io/qfileinfo_p.h +++ b/src/corelib/io/qfileinfo_p.h @@ -68,13 +68,6 @@ public: void initFileEngine(const QString &); - enum Access { - ReadAccess, - WriteAccess, - ExecuteAccess - }; - bool hasAccess(Access access) const; - uint getFileFlags(QAbstractFileEngine::FileFlags) const; QDateTime &getFileTime(QAbstractFileEngine::FileTime) const; QString getFileName(QAbstractFileEngine::FileName) const; diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 070edb4..5e14804 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -1033,6 +1033,10 @@ bool QFSFileEngine::supportsExtension(Extension extension) const to store temporary files). */ +/*! \fn QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFileEngine::FileFlags type) const + \internal +*/ + QT_END_NAMESPACE #endif // QT_NO_FSFILEENGINE diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 0f63eb8..d07c3a0 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -156,9 +156,7 @@ protected: void init(); -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) - QAbstractFileEngine::FileFlags getPermissions() const; -#endif + QAbstractFileEngine::FileFlags getPermissions(QAbstractFileEngine::FileFlags type) const; }; QT_END_NAMESPACE diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 1331f54..6df00d6 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -736,6 +736,46 @@ static bool _q_isMacHidden(const QString &path) } #endif +QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFileEngine::FileFlags type) const +{ + QAbstractFileEngine::FileFlags ret = 0; + + if (st.st_mode & S_IRUSR) + ret |= QAbstractFileEngine::ReadOwnerPerm; + if (st.st_mode & S_IWUSR) + ret |= QAbstractFileEngine::WriteOwnerPerm; + if (st.st_mode & S_IXUSR) + ret |= QAbstractFileEngine::ExeOwnerPerm; + if (st.st_mode & S_IRGRP) + ret |= QAbstractFileEngine::ReadGroupPerm; + if (st.st_mode & S_IWGRP) + ret |= QAbstractFileEngine::WriteGroupPerm; + if (st.st_mode & S_IXGRP) + ret |= QAbstractFileEngine::ExeGroupPerm; + if (st.st_mode & S_IROTH) + ret |= QAbstractFileEngine::ReadOtherPerm; + if (st.st_mode & S_IWOTH) + ret |= QAbstractFileEngine::WriteOtherPerm; + if (st.st_mode & S_IXOTH) + ret |= QAbstractFileEngine::ExeOtherPerm; + + // calculate user permissions + if (type & QAbstractFileEngine::ReadUserPerm) { + if (QT_ACCESS(nativeFilePath.constData(), R_OK) == 0) + ret |= QAbstractFileEngine::ReadUserPerm; + } + if (type & QAbstractFileEngine::WriteUserPerm) { + if (QT_ACCESS(nativeFilePath.constData(), W_OK) == 0) + ret |= QAbstractFileEngine::WriteUserPerm; + } + if (type & QAbstractFileEngine::ExeUserPerm) { + if (QT_ACCESS(nativeFilePath.constData(), X_OK) == 0) + ret |= QAbstractFileEngine::ExeUserPerm; + } + + return ret; +} + /*! \reimp */ @@ -755,32 +795,8 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const if (!exists && !d->isSymlink()) return ret; - if (exists && (type & PermsMask)) { - if (d->st.st_mode & S_IRUSR) - ret |= ReadOwnerPerm; - if (d->st.st_mode & S_IWUSR) - ret |= WriteOwnerPerm; - if (d->st.st_mode & S_IXUSR) - ret |= ExeOwnerPerm; - if (d->st.st_mode & S_IRUSR) - ret |= ReadUserPerm; - if (d->st.st_mode & S_IWUSR) - ret |= WriteUserPerm; - if (d->st.st_mode & S_IXUSR) - ret |= ExeUserPerm; - if (d->st.st_mode & S_IRGRP) - ret |= ReadGroupPerm; - if (d->st.st_mode & S_IWGRP) - ret |= WriteGroupPerm; - if (d->st.st_mode & S_IXGRP) - ret |= ExeGroupPerm; - if (d->st.st_mode & S_IROTH) - ret |= ReadOtherPerm; - if (d->st.st_mode & S_IWOTH) - ret |= WriteOtherPerm; - if (d->st.st_mode & S_IXOTH) - ret |= ExeOtherPerm; - } + if (exists && (type & PermsMask)) + ret |= d->getPermissions(type); if (type & TypesMask) { #if !defined(QWS) && defined(Q_OS_MAC) bool foundAlias = false; diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index d8b1c03..8d34486 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -1405,10 +1405,7 @@ bool QFSFileEngine::link(const QString &newName) #endif // Q_OS_WINCE } -/*! - \internal -*/ -QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const +QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions(QAbstractFileEngine::FileFlags type) const { QAbstractFileEngine::FileFlags ret = 0; @@ -1429,7 +1426,7 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const if(res == ERROR_SUCCESS) { ACCESS_MASK access_mask; TRUSTEE_W trustee; - { //user + if (type & 0x0700) { // user if(ptrGetEffectiveRightsFromAclW(pDacl, ¤tUserTrusteeW, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; if(access_mask & ReadMask) @@ -1439,7 +1436,7 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const if(access_mask & ExecMask) ret |= QAbstractFileEngine::ExeUserPerm; } - { //owner + if (type & 0x7000) { // owner ptrBuildTrusteeWithSidW(&trustee, pOwner); if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; @@ -1450,7 +1447,7 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const if(access_mask & ExecMask) ret |= QAbstractFileEngine::ExeOwnerPerm; } - { //group + if (type & 0x0070) { // group ptrBuildTrusteeWithSidW(&trustee, pGroup); if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; @@ -1461,7 +1458,7 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const if(access_mask & ExecMask) ret |= QAbstractFileEngine::ExeGroupPerm; } - { //other (world) + if (type & 0x0007) { // other (world) if(ptrGetEffectiveRightsFromAclW(pDacl, &worldTrusteeW, &access_mask) != ERROR_SUCCESS) access_mask = (ACCESS_MASK)-1; // ### if(access_mask & ReadMask) @@ -1476,29 +1473,35 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const } } else #endif - { + { //### what to do with permissions if we don't use NTFS // for now just add all permissions and what about exe missions ?? // also qt_ntfs_permission_lookup is now not set by default ... should it ? - ret |= QAbstractFileEngine::ReadOtherPerm | QAbstractFileEngine::ReadGroupPerm - | QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadUserPerm - | QAbstractFileEngine::WriteUserPerm | QAbstractFileEngine::WriteOwnerPerm - | QAbstractFileEngine::WriteGroupPerm | QAbstractFileEngine::WriteOtherPerm; - - if (doStat()) { - if (ret & (QAbstractFileEngine::WriteOwnerPerm | QAbstractFileEngine::WriteUserPerm | - QAbstractFileEngine::WriteGroupPerm | QAbstractFileEngine::WriteOtherPerm)) { - if (fileAttrib & FILE_ATTRIBUTE_READONLY) - ret &= ~(QAbstractFileEngine::WriteOwnerPerm | QAbstractFileEngine::WriteUserPerm | - QAbstractFileEngine::WriteGroupPerm | QAbstractFileEngine::WriteOtherPerm); - } + ret |= QAbstractFileEngine::ReadOwnerPerm | QAbstractFileEngine::ReadGroupPerm + | QAbstractFileEngine::ReadOtherPerm; - QString fname = filePath.endsWith(QLatin1String(".lnk")) ? readLink(filePath) : filePath; - QString ext = fname.right(4).toLower(); - if (ext == QLatin1String(".exe") || ext == QLatin1String(".com") || ext == QLatin1String(".bat") || - ext == QLatin1String(".pif") || ext == QLatin1String(".cmd") || (fileAttrib & FILE_ATTRIBUTE_DIRECTORY)) - ret |= QAbstractFileEngine::ExeOwnerPerm | QAbstractFileEngine::ExeGroupPerm | - QAbstractFileEngine::ExeOtherPerm | QAbstractFileEngine::ExeUserPerm; + if (!(fileAttrib & FILE_ATTRIBUTE_READONLY)) { + ret |= QAbstractFileEngine::WriteOwnerPerm | QAbstractFileEngine::WriteGroupPerm + | QAbstractFileEngine::WriteOtherPerm; + } + + QString fname = filePath.endsWith(QLatin1String(".lnk")) ? readLink(filePath) : filePath; + QString ext = fname.right(4).toLower(); + if ((fileAttrib & FILE_ATTRIBUTE_DIRECTORY) || + ext == QLatin1String(".exe") || ext == QLatin1String(".com") || ext == QLatin1String(".bat") || + ext == QLatin1String(".pif") || ext == QLatin1String(".cmd")) { + ret |= QAbstractFileEngine::ExeOwnerPerm | QAbstractFileEngine::ExeGroupPerm + | QAbstractFileEngine::ExeOtherPerm | QAbstractFileEngine::ExeUserPerm; + } + + // calculate user permissions + if (type & QAbstractFileEngine::ReadUserPerm) { + if (::_waccess((wchar_t*)longFileName(fname).utf16(), R_OK) == 0) + ret |= QAbstractFileEngine::ReadUserPerm; + } + if (type & QAbstractFileEngine::WriteUserPerm) { + if (::_waccess((wchar_t*)longFileName(fname).utf16(), W_OK) == 0) + ret |= QAbstractFileEngine::WriteUserPerm; } } return ret; @@ -1555,13 +1558,10 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil } if (type & PermsMask) { - ret |= d->getPermissions(); - // ### Workaround pascals ### above. Since we always set all properties to true - // we need to disable read and exec access if the file does not exists - if (d->doStat()) + if (d->doStat()) { ret |= ExistsFlag; - else - ret &= 0x2222; + ret |= d->getPermissions(type); + } } if (type & TypesMask) { if (d->filePath.endsWith(QLatin1String(".lnk"))) { diff --git a/src/corelib/tools/qbytedata_p.h b/src/corelib/tools/qbytedata_p.h index 9aad6a9..c48bb33 100644 --- a/src/corelib/tools/qbytedata_p.h +++ b/src/corelib/tools/qbytedata_p.h @@ -206,6 +206,13 @@ public: { return buffers[i]; } + + inline bool canReadLine() const { + for (int i = 0; i < buffers.length(); i++) + if (buffers.at(i).contains('\n')) + return true; + return false; + } }; QT_END_NAMESPACE diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index c6dd106..67f63f3 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -98,25 +98,6 @@ struct Q_CORE_EXPORT QListData { inline void **end() const { return d->array + d->end; } }; -////////////////////////////////////////////////////////////////////////////////// -// -// QtPodForSize and QtPodForType are internal and may change or go away any time. -// We mean it. -// -////////////////////////////////////////////////////////////////////////////////// -template <int N> struct QtPodForSize { - // This base type is rather obviously broken and cannot be made - // working due to alignment constraints. - // This doesn't matter as far as QList is concerned, as we are - // using this type only for QTypeInfo<T>::isLarge == false. - typedef struct { } Type; -}; -template <> struct QtPodForSize<1> { typedef quint8 Type; }; -template <> struct QtPodForSize<2> { typedef quint16 Type; }; -template <> struct QtPodForSize<4> { typedef quint32 Type; }; -template <> struct QtPodForSize<8> { typedef quint64 Type; }; -template <class T> struct QtPodForType : QtPodForSize<sizeof(T)> { }; - template <typename T> class QList { @@ -377,7 +358,15 @@ Q_INLINE_TEMPLATE void QList<T>::node_construct(Node *n, const T &t) { if (QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic) n->v = new T(t); else if (QTypeInfo<T>::isComplex) new (n) T(t); +#if (defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__IBMCPP__)) && !defined(__OPTIMIZE__) + // This violates pointer aliasing rules, but it is known to be safe (and silent) + // in unoptimized GCC builds (-fno-strict-aliasing). The other compilers which + // set the same define are assumed to be safe. else *reinterpret_cast<T*>(n) = t; +#else + // This is always safe, but penaltizes unoptimized builds a lot. + else ::memcpy(n, &t, sizeof(T)); +#endif } template <typename T> @@ -521,16 +510,15 @@ Q_OUTOFLINE_TEMPLATE void QList<T>::append(const T &t) QT_RETHROW; } } else { - typedef typename QtPodForType<T>::Type PodNode; - PodNode cpy = *reinterpret_cast<const PodNode *>(&t); - Node *n = reinterpret_cast<Node *>(p.append()); + Node *n, copy; + node_construct(©, t); // t might be a reference to an object in the array QT_TRY { - void *ptr = &cpy; - node_construct(n, *reinterpret_cast<T *>(ptr)); + n = reinterpret_cast<Node *>(p.append());; } QT_CATCH(...) { - --d->end; + node_destruct(©); QT_RETHROW; } + *n = copy; } } } @@ -556,16 +544,15 @@ inline void QList<T>::prepend(const T &t) QT_RETHROW; } } else { - typedef typename QtPodForType<T>::Type PodNode; - PodNode cpy = *reinterpret_cast<const PodNode *>(&t); - Node *n = reinterpret_cast<Node *>(p.prepend()); + Node *n, copy; + node_construct(©, t); // t might be a reference to an object in the array QT_TRY { - void *ptr = &cpy; - node_construct(n, *reinterpret_cast<T *>(ptr)); + n = reinterpret_cast<Node *>(p.prepend());; } QT_CATCH(...) { - ++d->begin; + node_destruct(©); QT_RETHROW; } + *n = copy; } } } @@ -591,16 +578,15 @@ inline void QList<T>::insert(int i, const T &t) QT_RETHROW; } } else { - typedef typename QtPodForType<T>::Type PodNode; - PodNode cpy = *reinterpret_cast<const PodNode *>(&t); - Node *n = reinterpret_cast<Node *>(p.insert(i)); + Node *n, copy; + node_construct(©, t); // t might be a reference to an object in the array QT_TRY { - void *ptr = &cpy; - node_construct(n, *reinterpret_cast<T *>(ptr)); + n = reinterpret_cast<Node *>(p.insert(i));; } QT_CATCH(...) { - p.remove(i); + node_destruct(©); QT_RETHROW; } + *n = copy; } } } @@ -636,12 +622,10 @@ inline void QList<T>::move(int from, int to) template<typename T> Q_OUTOFLINE_TEMPLATE QList<T> QList<T>::mid(int pos, int alength) const { - if (alength < 0) + if (alength < 0 || pos + alength > size()) alength = size() - pos; if (pos == 0 && alength == size()) return *this; - if (pos + alength > size()) - alength = size() - pos; QList<T> cpy; cpy.reserve(alength); cpy.d->end = alength; diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 84bc154..1966a79 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -3147,7 +3147,7 @@ QString QLocale::toString(double i, char f, int prec) const On Windows and Mac, this locale will use the decimal/grouping characters and date/time formats specified in the system configuration panel. - \sa QTextCodec::locale() c() + \sa c() */ QLocale QLocale::system() diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index b54315c..464e77b 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -3827,100 +3827,6 @@ const char *QString::latin1_helper() const #endif -QT_END_NAMESPACE - -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) -#include "qt_windows.h" - -QT_BEGIN_NAMESPACE - -QByteArray qt_winQString2MB(const QString& s, int uclen) -{ - if (uclen < 0) - uclen = s.length(); - if (s.isNull()) - return QByteArray(); - if (uclen == 0) - return QByteArray(""); - return qt_winQString2MB(s.constData(), uclen); -} - -QByteArray qt_winQString2MB(const QChar *ch, int uclen) -{ - if (!ch) - return QByteArray(); - if (uclen == 0) - return QByteArray(""); - BOOL used_def; - QByteArray mb(4096, 0); - int len; - while (!(len=WideCharToMultiByte(CP_ACP, 0, (const wchar_t*)ch, uclen, - mb.data(), mb.size()-1, 0, &used_def))) - { - int r = GetLastError(); - if (r == ERROR_INSUFFICIENT_BUFFER) { - mb.resize(1+WideCharToMultiByte(CP_ACP, 0, - (const wchar_t*)ch, uclen, - 0, 0, 0, &used_def)); - // and try again... - } else { -#ifndef QT_NO_DEBUG - // Fail. - qWarning("WideCharToMultiByte: Cannot convert multibyte text (error %d): %s (UTF-8)", - r, QString(ch, uclen).toLocal8Bit().data()); -#endif - break; - } - } - mb.resize(len); - return mb; -} - -QString qt_winMB2QString(const char *mb, int mblen) -{ - if (!mb || !mblen) - return QString(); - const int wclen_auto = 4096; - wchar_t wc_auto[wclen_auto]; - int wclen = wclen_auto; - wchar_t *wc = wc_auto; - int len; - while (!(len=MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, - mb, mblen, wc, wclen))) - { - int r = GetLastError(); - if (r == ERROR_INSUFFICIENT_BUFFER) { - if (wc != wc_auto) { - qWarning("MultiByteToWideChar: Size changed"); - break; - } else { - wclen = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, - mb, mblen, 0, 0); - wc = new wchar_t[wclen]; - // and try again... - } - } else { - // Fail. - qWarning("MultiByteToWideChar: Cannot convert multibyte text"); - break; - } - } - if (len <= 0) - return QString(); - if (wc[len-1] == 0) // len - 1: we don't want terminator - --len; - QString s((QChar*)wc, len); - if (wc != wc_auto) - delete [] wc; - return s; -} - -QT_END_NAMESPACE - -#endif // Q_OS_WIN32 - -QT_BEGIN_NAMESPACE - /*! Returns a QString initialized with the first \a size characters of the 8-bit string \a str. @@ -4815,6 +4721,12 @@ int QString::localeAwareCompare(const QString &other) const return localeAwareCompare_helper(constData(), length(), other.constData(), other.length()); } +#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) +QT_END_NAMESPACE +#include "qt_windows.h" +QT_BEGIN_NAMESPACE +#endif + /*! \internal \since 4.5 diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index a59c0bd..ea12c2f 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -1096,12 +1096,6 @@ Q_DECLARE_TYPEINFO(QString, Q_MOVABLE_TYPE); Q_DECLARE_SHARED(QString) Q_DECLARE_OPERATORS_FOR_FLAGS(QString::SectionFlags) -#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE) -extern Q_CORE_EXPORT QByteArray qt_winQString2MB(const QString& s, int len=-1); -extern Q_CORE_EXPORT QByteArray qt_winQString2MB(const QChar *ch, int len); -extern Q_CORE_EXPORT QString qt_winMB2QString(const char* mb, int len=-1); -#endif - class Q_CORE_EXPORT QStringRef { const QString *m_string; diff --git a/src/declarative/qml/qdeclarativeextensionplugin.cpp b/src/declarative/qml/qdeclarativeextensionplugin.cpp index 7617977..5b7f1e8 100644 --- a/src/declarative/qml/qdeclarativeextensionplugin.cpp +++ b/src/declarative/qml/qdeclarativeextensionplugin.cpp @@ -80,6 +80,9 @@ QDeclarativeExtensionPlugin::QDeclarativeExtensionPlugin(QObject *parent) { } +/*! + Destructor. + */ QDeclarativeExtensionPlugin::~QDeclarativeExtensionPlugin() { } diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp index 855d623..2d5f096 100644 --- a/src/declarative/qml/qdeclarativesqldatabase.cpp +++ b/src/declarative/qml/qdeclarativesqldatabase.cpp @@ -217,9 +217,15 @@ static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEn if (context->argumentCount() > 1) { QScriptValue values = context->argument(1); if (values.isObject()) { - for (QScriptValueIterator it(values); it.hasNext();) { - it.next(); - query.bindValue(it.name(),it.value().toVariant()); + if (values.isArray()) { + int size = values.property(QLatin1String("length")).toInt32(); + for (int i = 0; i < size; ++i) + query.bindValue(i, values.property(i).toVariant()); + } else { + for (QScriptValueIterator it(values); it.hasNext();) { + it.next(); + query.bindValue(it.name(),it.value().toVariant()); + } } } else { query.bindValue(0,values.toVariant()); diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp index 20449d7..81c548b 100644 --- a/src/declarative/util/qdeclarativeanimation.cpp +++ b/src/declarative/util/qdeclarativeanimation.cpp @@ -2131,10 +2131,10 @@ void QDeclarativePropertyAnimation::setProperties(const QString &prop) } /*! - \qmlproperty string PropertyAnimation::property \qmlproperty string PropertyAnimation::properties - \qmlproperty Object PropertyAnimation::target \qmlproperty list<Object> PropertyAnimation::targets + \qmlproperty string PropertyAnimation::property + \qmlproperty Object PropertyAnimation::target These properties are used as a set to determine which properties should be animated. The singular and plural forms are functionally identical, e.g. diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp index e3f26d7..b968ca5 100644 --- a/src/declarative/util/qdeclarativelistmodel.cpp +++ b/src/declarative/util/qdeclarativelistmodel.cpp @@ -284,12 +284,11 @@ void ModelNode::setObjectValue(const QScriptValue& valuemap) { } void ModelNode::setListValue(const QScriptValue& valuelist) { - QScriptValueIterator it(valuelist); + int size = valuelist.property(QString::fromLatin1("length")).toInt32(); values.clear(); - while (it.hasNext()) { - it.next(); + for (int i = 0; i < size; ++i) { ModelNode *value = new ModelNode; - QScriptValue v = it.value(); + QScriptValue v = valuelist.property(i); if (v.isArray()) { value->isArray = true; value->setListValue(v); diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index 089e04a..ef2b223 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -228,7 +228,8 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook \value ReadOnly Indicates that the model is readonly. - \value HideNameFilterDetails Indicates if the is hidden or not. + \value HideNameFilterDetails Indicates if the file name filter details are + hidden or not. \value DontUseSheet In previous versions of Qt, the static functions would create a sheet by default if the static function diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp index 3120938..afeed8e 100644 --- a/src/gui/dialogs/qfiledialog_win.cpp +++ b/src/gui/dialogs/qfiledialog_win.cpp @@ -583,6 +583,63 @@ static QStringList qt_win_CID_get_open_file_names(const QFileDialogArgs &args, return result; } +QString qt_win_CID_get_existing_directory(const QFileDialogArgs &args) +{ + QString result; + QDialog modal_widget; + modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); + modal_widget.setParent(args.parent, Qt::Window); + QApplicationPrivate::enterModal(&modal_widget); + + IFileOpenDialog *pfd = 0; + HRESULT hr = CoCreateInstance(QT_CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, + QT_IID_IFileOpenDialog, reinterpret_cast<void**>(&pfd)); + + if (SUCCEEDED(hr)) { + qt_win_set_IFileDialogOptions(pfd, args.selection, + args.directory, args.caption, + QStringList(), QFileDialog::ExistingFiles, + args.options); + + // Set the FOS_PICKFOLDERS flag + DWORD newOptions; + hr = pfd->GetOptions(&newOptions); + newOptions |= FOS_PICKFOLDERS; + if (SUCCEEDED(hr) && SUCCEEDED((hr = pfd->SetOptions(newOptions)))) { + QWidget *parentWindow = args.parent; + if (parentWindow) + parentWindow = parentWindow->window(); + else + parentWindow = QApplication::activeWindow(); + + // Show the file dialog. + hr = pfd->Show(parentWindow ? parentWindow->winId() : 0); + if (SUCCEEDED(hr)) { + // Retrieve the result + IShellItem *psi = 0; + hr = pfd->GetResult(&psi); + if (SUCCEEDED(hr)) { + // Retrieve the file name from shell item. + wchar_t *pszPath; + hr = psi->GetDisplayName(SIGDN_FILESYSPATH, &pszPath); + if (SUCCEEDED(hr)) { + result = QString::fromWCharArray(pszPath); + CoTaskMemFree(pszPath); + } + psi->Release(); // Free the current item. + } + } + } + } + QApplicationPrivate::leaveModal(&modal_widget); + + qt_win_eatMouseMove(); + + if (pfd) + pfd->Release(); + return result; +} + #endif QStringList qt_win_get_open_file_names(const QFileDialogArgs &args, @@ -701,6 +758,11 @@ static int __stdcall winGetExistDirCallbackProc(HWND hwnd, QString qt_win_get_existing_directory(const QFileDialogArgs &args) { +#ifndef Q_WS_WINCE + if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based) + return qt_win_CID_get_existing_directory(args); +#endif + QString currentDir = QDir::currentPath(); QString result; QWidget *parent = args.parent; diff --git a/src/gui/dialogs/qfileinfogatherer.cpp b/src/gui/dialogs/qfileinfogatherer.cpp index c75cdfd..3b08bf6 100644 --- a/src/gui/dialogs/qfileinfogatherer.cpp +++ b/src/gui/dialogs/qfileinfogatherer.cpp @@ -216,41 +216,10 @@ void QFileInfoGatherer::run() } } -/* - QFileInfo::permissions is different depending upon your platform. - - "normalize this" so they can mean the same to us. -*/ -QFile::Permissions QFileInfoGatherer::translatePermissions(const QFileInfo &fileInfo) const { - QFile::Permissions permissions = fileInfo.permissions(); -#ifdef Q_OS_WIN - return permissions; -#else - QFile::Permissions p = permissions; - p &= ~(QFile::ReadUser|QFile::WriteUser|QFile::ExeUser); - if ( permissions & QFile::ReadOther - || (fileInfo.ownerId() == userId && permissions & QFile::ReadOwner) - || (fileInfo.groupId() == groupId && permissions & QFile::ReadGroup)) - p |= QFile::ReadUser; - - if ( permissions & QFile::WriteOther - || (fileInfo.ownerId() == userId && permissions & QFile::WriteOwner) - || (fileInfo.groupId() == groupId && permissions & QFile::WriteGroup)) - p |= QFile::WriteUser; - - if ( permissions & QFile::ExeOther - || (fileInfo.ownerId() == userId && permissions & QFile::ExeOwner) - || (fileInfo.groupId() == groupId && permissions & QFile::ExeGroup)) - p |= QFile::ExeUser; - return p; -#endif -} - QExtendedInformation QFileInfoGatherer::getInfo(const QFileInfo &fileInfo) const { QExtendedInformation info(fileInfo); info.icon = m_iconProvider->icon(fileInfo); - info.setPermissions(translatePermissions(fileInfo)); info.displayType = m_iconProvider->type(fileInfo); #ifndef QT_NO_FILESYSTEMWATCHER // ### Not ready to listen all modifications diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h index b8b58a2..eff6b3c 100644 --- a/src/gui/dialogs/qfileinfogatherer_p.h +++ b/src/gui/dialogs/qfileinfogatherer_p.h @@ -88,11 +88,7 @@ public: return fe.caseSensitive(); } QFile::Permissions permissions() const { - return mPermissions; - } - - void setPermissions (QFile::Permissions permissions) { - mPermissions = permissions; + return mFileInfo.permissions(); } Type type() const { @@ -140,7 +136,6 @@ public: private : QFileInfo mFileInfo; - QFile::Permissions mPermissions; }; class QFileIconProvider; @@ -181,7 +176,6 @@ protected: private: void fetch(const QFileInfo &info, QTime &base, bool &firstTime, QList<QPair<QString, QFileInfo> > &updatedFiles, const QString &path); QString translateDriveName(const QFileInfo &drive) const; - QFile::Permissions translatePermissions(const QFileInfo &fileInfo) const; QMutex mutex; QWaitCondition condition; diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm index c7d0e48..28072fc 100644 --- a/src/gui/kernel/qapplication_mac.mm +++ b/src/gui/kernel/qapplication_mac.mm @@ -1759,14 +1759,19 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event // (actually two events; one for horizontal and one for vertical). // As a results of this, and to make sure we dont't receive duplicate events, // we try to detect when this happend by checking the 'compatibilityEvent'. + // Since delta is delivered as pixels rather than degrees, we need to + // convert from pixels to degrees in a sensible manner. + // It looks like 1/4 degrees per pixel behaves most native. + // (NB: Qt expects the unit for delta to be 8 per degree): + const int pixelsToDegrees = 2; SInt32 mdelt = 0; GetEventParameter(event, kEventParamMouseWheelSmoothHorizontalDelta, typeSInt32, 0, sizeof(mdelt), 0, &mdelt); - wheel_deltaX = mdelt; + wheel_deltaX = mdelt * pixelsToDegrees; mdelt = 0; GetEventParameter(event, kEventParamMouseWheelSmoothVerticalDelta, typeSInt32, 0, sizeof(mdelt), 0, &mdelt); - wheel_deltaY = mdelt; + wheel_deltaY = mdelt * pixelsToDegrees; GetEventParameter(event, kEventParamEventRef, typeEventRef, 0, sizeof(compatibilityEvent), 0, &compatibilityEvent); } else if (ekind == kEventMouseWheelMoved) { diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 20a7ff2..985f825 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -709,6 +709,10 @@ static int qt_x_errhandler(Display *dpy, XErrorEvent *err) extensionName = "XInputExtension"; else if (err->request_code == X11->mitshm_major) extensionName = "MIT-SHM"; +#ifndef QT_NO_XKB + else if(err->request_code == X11->xkb_major) + extensionName = "XKEYBOARD"; +#endif char minor_str[256]; if (extensionName) { @@ -1635,6 +1639,11 @@ void qt_init(QApplicationPrivate *priv, int, X11->xinput_eventbase = 0; X11->xinput_errorbase = 0; + X11->use_xkb = false; + X11->xkb_major = 0; + X11->xkb_eventbase = 0; + X11->xkb_errorbase = 0; + // MIT-SHM X11->use_mitshm = false; X11->use_mitshm_pixmaps = false; @@ -2108,6 +2117,33 @@ void qt_init(QApplicationPrivate *priv, int, } #endif // QT_NO_XINPUT +#ifndef QT_NO_XKB + int xkblibMajor = XkbMajorVersion; + int xkblibMinor = XkbMinorVersion; + X11->use_xkb = XkbQueryExtension(X11->display, + &X11->xkb_major, + &X11->xkb_eventbase, + &X11->xkb_errorbase, + &xkblibMajor, + &xkblibMinor); + if (X11->use_xkb) { + // If XKB is detected, set the GrabsUseXKBState option so input method + // compositions continue to work (ie. deadkeys) + unsigned int state = XkbPCF_GrabsUseXKBStateMask; + (void) XkbSetPerClientControls(X11->display, state, &state); + + // select for group change events + XkbSelectEventDetails(X11->display, + XkbUseCoreKbd, + XkbStateNotify, + XkbAllStateComponentsMask, + XkbGroupStateMask); + + // current group state is queried when creating the keymapper, no need to do it here + } +#endif + + #if !defined(QT_NO_FONTCONFIG) int dpi = 0; getXDefault("Xft", FC_DPI, &dpi); @@ -2186,15 +2222,6 @@ void qt_init(QApplicationPrivate *priv, int, // initialize key mapper QKeyMapper::changeKeyboard(); -#ifndef QT_NO_XKB - if (qt_keymapper_private()->useXKB) { - // If XKB is detected, set the GrabsUseXKBState option so input method - // compositions continue to work (ie. deadkeys) - unsigned int state = XkbPCF_GrabsUseXKBStateMask; - (void) XkbSetPerClientControls(X11->display, state, &state); - } -#endif // QT_NO_XKB - // Misc. initialization #if 0 //disabled for now.. QSegfaultHandler::initialize(priv->argv, priv->argc); @@ -3229,6 +3256,24 @@ int QApplication::x11ProcessEvent(XEvent* event) QKeyMapper::changeKeyboard(); return 0; } +#ifndef QT_NO_XKB + else if (X11->use_xkb && event->type == X11->xkb_eventbase) { + XkbAnyEvent *xkbevent = (XkbAnyEvent *) event; + switch (xkbevent->xkb_type) { + case XkbStateNotify: + { + XkbStateNotifyEvent *xkbstateevent = (XkbStateNotifyEvent *) xkbevent; + if ((xkbstateevent->changed & XkbGroupStateMask) != 0) { + qt_keymapper_private()->xkb_currentGroup = xkbstateevent->group; + QKeyMapper::changeKeyboard(); + } + break; + } + default: + break; + } + } +#endif if (!widget) { // don't know this windows QWidget* popup = QApplication::activePopupWidget(); diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm index f7cb21f..4f71681 100644 --- a/src/gui/kernel/qcocoaview_mac.mm +++ b/src/gui/kernel/qcocoaview_mac.mm @@ -480,7 +480,7 @@ static int qCocoaViewCount = 0; return; if (QApplicationPrivate::graphicsSystem() != 0) { - if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore()) { + if (qwidgetprivate->maybeBackingStore()) { // Drawing is handled on the window level // See qcocoasharedwindowmethods_mac_p.h if (!qwidget->testAttribute(Qt::WA_PaintOnScreen)) @@ -819,11 +819,12 @@ static int qCocoaViewCount = 0; // The mouse device containts pixel scroll wheel support (Mighty Mouse, Trackpad). // Since deviceDelta is delivered as pixels rather than degrees, we need to // convert from pixels to degrees in a sensible manner. - // It looks like four degrees per pixel behaves most native. - // Qt expects the unit for delta to be 1/8 of a degree: - deltaX = [theEvent deviceDeltaX]; - deltaY = [theEvent deviceDeltaY]; - deltaZ = [theEvent deviceDeltaZ]; + // It looks like 1/4 degrees per pixel behaves most native. + // (NB: Qt expects the unit for delta to be 8 per degree): + const int pixelsToDegrees = 2; // 8 * 1/4 + deltaX = [theEvent deviceDeltaX] * pixelsToDegrees; + deltaY = [theEvent deviceDeltaY] * pixelsToDegrees; + deltaZ = [theEvent deviceDeltaZ] * pixelsToDegrees; } else { // carbonEventKind == kEventMouseWheelMoved // Remove acceleration, and use either -120 or 120 as delta: diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp index c88a9a7..9dcca17 100644 --- a/src/gui/kernel/qgesturerecognizer.cpp +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -161,6 +161,8 @@ QGestureRecognizer::~QGestureRecognizer() Reimplement this function to create a custom QGesture-derived gesture object if necessary. + + The application takes ownership of the created gesture object. */ QGesture *QGestureRecognizer::create(QObject *target) { diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp index a31480d..f259654 100644 --- a/src/gui/kernel/qkeymapper_mac.cpp +++ b/src/gui/kernel/qkeymapper_mac.cpp @@ -323,6 +323,32 @@ static qt_mac_enum_mapper qt_mac_keyvkey_symbols[] = { //real scan codes { 0, QT_MAC_MAP_ENUM(0) } }; +static qt_mac_enum_mapper qt_mac_private_unicode[] = { + { 0xF700, QT_MAC_MAP_ENUM(Qt::Key_Up) }, //NSUpArrowFunctionKey + { 0xF701, QT_MAC_MAP_ENUM(Qt::Key_Down) }, //NSDownArrowFunctionKey + { 0xF702, QT_MAC_MAP_ENUM(Qt::Key_Left) }, //NSLeftArrowFunctionKey + { 0xF703, QT_MAC_MAP_ENUM(Qt::Key_Right) }, //NSRightArrowFunctionKey + { 0xF727, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertFunctionKey + { 0xF728, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteFunctionKey + { 0xF729, QT_MAC_MAP_ENUM(Qt::Key_Home) }, //NSHomeFunctionKey + { 0xF72B, QT_MAC_MAP_ENUM(Qt::Key_End) }, //NSEndFunctionKey + { 0xF72C, QT_MAC_MAP_ENUM(Qt::Key_PageUp) }, //NSPageUpFunctionKey + { 0xF72D, QT_MAC_MAP_ENUM(Qt::Key_PageDown) }, //NSPageDownFunctionKey + { 0xF72F, QT_MAC_MAP_ENUM(Qt::Key_ScrollLock) }, //NSScrollLockFunctionKey + { 0xF730, QT_MAC_MAP_ENUM(Qt::Key_Pause) }, //NSPauseFunctionKey + { 0xF731, QT_MAC_MAP_ENUM(Qt::Key_SysReq) }, //NSSysReqFunctionKey + { 0xF735, QT_MAC_MAP_ENUM(Qt::Key_Menu) }, //NSMenuFunctionKey + { 0xF738, QT_MAC_MAP_ENUM(Qt::Key_Print) }, //NSPrintFunctionKey + { 0xF73A, QT_MAC_MAP_ENUM(Qt::Key_Clear) }, //NSClearDisplayFunctionKey + { 0xF73D, QT_MAC_MAP_ENUM(Qt::Key_Insert) }, //NSInsertCharFunctionKey + { 0xF73E, QT_MAC_MAP_ENUM(Qt::Key_Delete) }, //NSDeleteCharFunctionKey + { 0xF741, QT_MAC_MAP_ENUM(Qt::Key_Select) }, //NSSelectFunctionKey + { 0xF742, QT_MAC_MAP_ENUM(Qt::Key_Execute) }, //NSExecuteFunctionKey + { 0xF746, QT_MAC_MAP_ENUM(Qt::Key_Help) }, //NSHelpFunctionKey + { 0xF747, QT_MAC_MAP_ENUM(Qt::Key_Mode_switch) }, //NSModeSwitchFunctionKey + { 0, QT_MAC_MAP_ENUM(0) } +}; + static int qt_mac_get_key(int modif, const QChar &key, int virtualKey) { #ifdef DEBUG_KEY_BINDINGS @@ -379,6 +405,19 @@ static int qt_mac_get_key(int modif, const QChar &key, int virtualKey) } } + // check if they belong to key codes in private unicode range + if (key >= 0xf700 && key <= 0xf747) { + if (key >= 0xf704 && key <= 0xf726) { + return Qt::Key_F1 + (key.unicode() - 0xf704) ; + } + for (int i = 0; qt_mac_private_unicode[i].qt_code; i++) { + if (qt_mac_private_unicode[i].mac_code == key) { + return qt_mac_private_unicode[i].qt_code; + } + } + + } + //oh well #ifdef DEBUG_KEY_BINDINGS qDebug("Unknown case.. %s:%d %d[%d] %d", __FILE__, __LINE__, key.unicode(), key.toLatin1(), virtualKey); @@ -847,7 +886,11 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e } void -QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *) +QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void * +#if defined(QT_MAC_USE_COCOA) + unicodeKey // unicode character from NSEvent (modifiers applied) +#endif + ) { UInt32 macVirtualKey = 0; GetEventParameter(event, kEventParamKeyCode, typeUInt32, 0, sizeof(macVirtualKey), 0, &macVirtualKey); @@ -875,6 +918,15 @@ QKeyMapperPrivate::updateKeyMap(EventHandlerCallRef, EventRef event, void *) qtkey = unicode.unicode(); keyLayout[macVirtualKey]->qtKey[i] = qtkey; } +#ifndef Q_WS_MAC32 + else { + const QChar unicode(*((UniChar *)unicodeKey)); + int qtkey = qt_mac_get_key(keyModifier, unicode, macVirtualKey); + if (qtkey == Qt::Key_unknown) + qtkey = unicode.unicode(); + keyLayout[macVirtualKey]->qtKey[i] = qtkey; + } +#endif #ifdef Q_WS_MAC32 } else { const UInt32 keyModifier = (qt_mac_get_mac_modifiers(ModsTbl[i])); diff --git a/src/gui/kernel/qkeymapper_p.h b/src/gui/kernel/qkeymapper_p.h index 3e42d6e..38f141e 100644 --- a/src/gui/kernel/qkeymapper_p.h +++ b/src/gui/kernel/qkeymapper_p.h @@ -183,7 +183,7 @@ public: const XEvent *, bool grab); - bool useXKB; + int xkb_currentGroup; QXCoreDesc coreDesc; #elif defined(Q_WS_MAC) diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp index d6d1042..428ac3e 100644 --- a/src/gui/kernel/qkeymapper_x11.cpp +++ b/src/gui/kernel/qkeymapper_x11.cpp @@ -248,22 +248,17 @@ qt_XTranslateKey(register QXCoreDesc *dpy, QKeyMapperPrivate::QKeyMapperPrivate() - : keyboardInputDirection(Qt::LeftToRight), useXKB(false) + : keyboardInputDirection(Qt::LeftToRight), xkb_currentGroup(0) { memset(&coreDesc, 0, sizeof(coreDesc)); #ifndef QT_NO_XKB - int opcode = -1; - int xkbEventBase = -1; - int xkbErrorBase = -1; - int xkblibMajor = XkbMajorVersion; - int xkblibMinor = XkbMinorVersion; - if (XkbQueryExtension(X11->display, &opcode, &xkbEventBase, &xkbErrorBase, &xkblibMajor, &xkblibMinor)) - useXKB = true; -#endif - -#if 0 - qDebug() << "useXKB =" << useXKB; + if (X11->use_xkb) { + // get the current group + XkbStateRec xkbState; + if (XkbGetState(X11->display, XkbUseCoreKbd, &xkbState) == Success) + xkb_currentGroup = xkbState.group; + } #endif } @@ -276,7 +271,7 @@ QKeyMapperPrivate::~QKeyMapperPrivate() QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *event) { #ifndef QT_NO_XKB - if (useXKB) + if (X11->use_xkb) return possibleKeysXKB(event); #endif return possibleKeysCore(event); @@ -486,7 +481,7 @@ enum { void QKeyMapperPrivate::clearMappings() { #ifndef QT_NO_XKB - if (useXKB) { + if (X11->use_xkb) { // try to determine the layout name and input direction by reading the _XKB_RULES_NAMES property off // the root window QByteArray layoutName; @@ -515,8 +510,13 @@ void QKeyMapperPrivate::clearMappings() p += qstrlen(p) + 1; } while (p < end); - layoutName = QByteArray::fromRawData(names[2], qstrlen(names[2])); - variantName = QByteArray::fromRawData(names[3], qstrlen(names[3])); + // the layout names and variants are saved in the _XKB_RULES_NAMES property as a comma separated list + QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(','); + if (uint(xkb_currentGroup) < uint(layoutNames.count())) + layoutName = layoutNames.at(xkb_currentGroup); + QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(','); + if (uint(xkb_currentGroup) < uint(variantNames.count())) + variantName = variantNames.at(xkb_currentGroup); } // ### ??? @@ -574,7 +574,7 @@ void QKeyMapperPrivate::clearMappings() // look at the modifier mapping, and get the correct masks for alt, meta, super, hyper, and mode_switch #ifndef QT_NO_XKB - if (useXKB) { + if (X11->use_xkb) { XkbDescPtr xkbDesc = XkbGetMap(X11->display, XkbAllClientInfoMask, XkbUseCoreKbd); for (int i = xkbDesc->min_key_code; i < xkbDesc->max_key_code; ++i) { const uint mask = xkbDesc->map->modmap ? xkbDesc->map->modmap[i] : 0; diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 99bf971..7f92a2c 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -696,6 +696,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = { {QKeySequence::Redo, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Z, QApplicationPrivate::KB_Mac}, //different priority from above {QKeySequence::PreviousChild, 1, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11}, {QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Backtab, QApplicationPrivate::KB_Mac },//different priority from above + {QKeySequence::Paste, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Insert, QApplicationPrivate::KB_X11}, {QKeySequence::SelectStartOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Home, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::SelectEndOfDocument, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_End, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, {QKeySequence::SelectPreviousWord, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_Left, QApplicationPrivate::KB_Win | QApplicationPrivate::KB_X11 | QApplicationPrivate::KB_S60}, diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm index 3fbd978..24fe5f7 100644 --- a/src/gui/kernel/qt_cocoa_helpers_mac.mm +++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm @@ -684,7 +684,9 @@ bool qt_dispatchKeyEvent(void * /*NSEvent * */ keyEvent, QWidget *widgetToGetEve EventRef key_event = static_cast<EventRef>(const_cast<void *>([event eventRef])); Q_ASSERT(key_event); if ([event type] == NSKeyDown) { - qt_keymapper_private()->updateKeyMap(0, key_event, 0); + NSString *characters = [event characters]; + unichar value = [characters characterAtIndex:0]; + qt_keymapper_private()->updateKeyMap(0, key_event, (void *)&value); } // Redirect keys to alien widgets. diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h index 8af4df5..e1b2625 100644 --- a/src/gui/kernel/qt_x11_p.h +++ b/src/gui/kernel/qt_x11_p.h @@ -439,6 +439,12 @@ struct QX11Data int xinput_eventbase; int xinput_errorbase; + // for XKEYBOARD support + bool use_xkb; + int xkb_major; + int xkb_eventbase; + int xkb_errorbase; + QList<QWidget *> deferred_map; struct ScrollInProgress { long id; diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm index a0e4050..b3a6aec 100644 --- a/src/gui/kernel/qwidget_mac.mm +++ b/src/gui/kernel/qwidget_mac.mm @@ -3294,7 +3294,7 @@ void QWidgetPrivate::update_sys(const QRect &r) #ifndef QT_MAC_USE_COCOA HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); #else - [qt_mac_nativeview_for(q) setNeedsDisplay:YES]; + qt_mac_set_needs_display(q, QRegion()); #endif return; } @@ -3332,21 +3332,24 @@ void QWidgetPrivate::update_sys(const QRegion &rgn) HIViewSetNeedsDisplay(qt_mac_nativeview_for(q), true); // do a complete repaint on overflow. } #else - // Cocoa doesn't do regions, it seems more efficient to just update the bounding rect instead of a potential number of message passes for each rect. - const QRect & boundingRect = rgn.boundingRect(); - // Alien support: get the first native ancestor widget (will be q itself in the non-alien case), // map the coordinates from q space to NSView space and invalidate the rect. QWidget *nativeParent = q->internalWinId() ? q : q->nativeParentWidget(); if (nativeParent == 0) - return; - const QRect nativeBoundingRect = QRect( - QPoint(q->mapTo(nativeParent, boundingRect.topLeft())), - QSize(boundingRect.size())); + return; + + QVector<QRect> rects = rgn.rects(); + for (int i = 0; i < rects.count(); ++i) { + const QRect &rect = rects.at(i); - [qt_mac_nativeview_for(nativeParent) setNeedsDisplayInRect:NSMakeRect(nativeBoundingRect.x(), - nativeBoundingRect.y(), nativeBoundingRect.width(), - nativeBoundingRect.height())]; + const QRect nativeBoundingRect = QRect( + QPoint(q->mapTo(nativeParent, rect.topLeft())), + QSize(rect.size())); + + [qt_mac_nativeview_for(nativeParent) setNeedsDisplayInRect:NSMakeRect(nativeBoundingRect.x(), + nativeBoundingRect.y(), nativeBoundingRect.width(), + nativeBoundingRect.height())]; + } #endif } @@ -4027,7 +4030,7 @@ static void qt_mac_update_widget_posisiton(QWidget *q, QRect oldRect, QRect newR #else Q_UNUSED(oldRect); NSRect bounds = NSMakeRect(newRect.x(), newRect.y(), - newRect.width(), newRect.height()); + newRect.width(), newRect.height()); [qt_mac_nativeview_for(q) setFrame:bounds]; #endif } @@ -4830,7 +4833,7 @@ void QWidgetPrivate::finishCocoaMaskSetup() [window setOpaque:(extra->imageMask == 0)]; [window invalidateShadow]; } - [qt_mac_nativeview_for(q) setNeedsDisplay:YES]; + qt_mac_set_needs_display(q, QRegion()); } #endif diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 581b538..e5b3ac0 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -4734,7 +4734,7 @@ static void blend_untransformed_argb8565(int count, const QSpan *spans, static void blend_untransformed_rgb565(int count, const QSpan *spans, void *userData) { -#if defined(QT_QWS_DEPTH_16) +#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) @@ -5577,7 +5577,7 @@ static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, v static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans, void *userData) { -#if defined(QT_QWS_DEPTH_16) +#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format == QImage::Format_RGB16) @@ -6164,7 +6164,7 @@ static void blend_transformed_argb8565(int count, const QSpan *spans, static void blend_transformed_rgb565(int count, const QSpan *spans, void *userData) { -#if defined(QT_QWS_DEPTH_16) +#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) @@ -6577,7 +6577,7 @@ static void blend_transformed_tiled_argb8565(int count, const QSpan *spans, static void blend_transformed_tiled_rgb565(int count, const QSpan *spans, void *userData) { -#if defined(QT_QWS_DEPTH_16) +#if !defined(Q_WS_QWS) || defined(QT_QWS_DEPTH_16) QSpanData *data = reinterpret_cast<QSpanData *>(userData); if (data->texture.format == QImage::Format_ARGB8565_Premultiplied) diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index f345cd1..6864fe1 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -848,9 +848,9 @@ void QTextControl::copy() QApplication::clipboard()->setMimeData(data); } -void QTextControl::paste() +void QTextControl::paste(QClipboard::Mode mode) { - const QMimeData *md = QApplication::clipboard()->mimeData(); + const QMimeData *md = QApplication::clipboard()->mimeData(mode); if (md) insertFromMimeData(md); } @@ -1230,7 +1230,12 @@ void QTextControlPrivate::keyPressEvent(QKeyEvent *e) q->cut(); } else if (e == QKeySequence::Paste) { - q->paste(); + QClipboard::Mode mode = QClipboard::Clipboard; +#ifdef Q_WS_X11 + if (e->modifiers() == (Qt::CTRL | Qt::SHIFT) && e->key() == Qt::Key_Insert) + mode = QClipboard::Selection; +#endif + q->paste(mode); } #endif else if (e == QKeySequence::Delete) { diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h index 40507f4..8399d50 100644 --- a/src/gui/text/qtextcontrol_p.h +++ b/src/gui/text/qtextcontrol_p.h @@ -62,6 +62,7 @@ #include <QtCore/qrect.h> #include <QtGui/qabstracttextdocumentlayout.h> #include <QtGui/qtextdocumentfragment.h> +#include <QtGui/qclipboard.h> #ifdef QT3_SUPPORT #include <QtGui/qtextobject.h> @@ -191,7 +192,7 @@ public Q_SLOTS: #ifndef QT_NO_CLIPBOARD void cut(); void copy(); - void paste(); + void paste(QClipboard::Mode mode = QClipboard::Clipboard); #endif void undo(); diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp index d30c996..6f099a9 100644 --- a/src/gui/text/qzip.cpp +++ b/src/gui/text/qzip.cpp @@ -280,6 +280,21 @@ static QFile::Permissions modeToPermissions(quint32 mode) return ret; } +static QDateTime readMSDosDate(const uchar *src) +{ + uint dosDate = readUInt(src); + quint64 uDate; + uDate = (quint64)(dosDate >> 16); + uint tm_mday = (uDate & 0x1f); + uint tm_mon = ((uDate & 0x1E0) >> 5); + uint tm_year = (((uDate & 0x0FE00) >> 9) + 1980); + uint tm_hour = ((dosDate & 0xF800) >> 11); + uint tm_min = ((dosDate & 0x7E0) >> 5); + uint tm_sec = ((dosDate & 0x1f) << 1); + + return QDateTime(QDate(tm_year, tm_mon, tm_mday), QTime(tm_hour, tm_min, tm_sec)); +} + struct LocalFileHeader { uchar signature[4]; // 0x04034b50 @@ -343,7 +358,7 @@ struct FileHeader }; QZipReader::FileInfo::FileInfo() - : isDir(false), isFile(true), isSymLink(false), crc32(0), size(0) + : isDir(false), isFile(false), isSymLink(false), crc32(0), size(0) { } @@ -365,9 +380,15 @@ QZipReader::FileInfo& QZipReader::FileInfo::operator=(const FileInfo &other) permissions = other.permissions; crc32 = other.crc32; size = other.size; + lastModified = other.lastModified; return *this; } +bool QZipReader::FileInfo::isValid() const +{ + return isDir || isFile || isSymLink; +} + class QZipPrivate { public: @@ -403,6 +424,7 @@ void QZipPrivate::fillFileInfo(int index, QZipReader::FileInfo &fileInfo) const fileInfo.permissions = modeToPermissions(mode); fileInfo.crc32 = readUInt(header.h.crc_32); fileInfo.size = readUInt(header.h.uncompressed_size); + fileInfo.lastModified = readMSDosDate(header.h.last_mod_file); } class QZipReaderPrivate : public QZipPrivate @@ -750,6 +772,14 @@ QZipReader::~QZipReader() } /*! + Returns device used for reading zip archive. +*/ +QIODevice* QZipReader::device() const +{ + return d->device; +} + +/*! Returns true if the user can read the file; otherwise returns false. */ bool QZipReader::isReadable() const @@ -796,6 +826,7 @@ int QZipReader::count() const /*! Returns a FileInfo of an entry in the zipfile. The \a index is the index into the directoy listing of the zipfile. + Returns an invalid FileInfo if \a index is out of boundaries. \sa fileInfoList() */ @@ -803,7 +834,8 @@ QZipReader::FileInfo QZipReader::entryInfoAt(int index) const { d->scanFiles(); QZipReader::FileInfo fi; - d->fillFileInfo(index, fi); + if (index >= 0 && index < d->fileHeaders.count()) + d->fillFileInfo(index, fi); return fi; } @@ -1022,6 +1054,14 @@ QZipWriter::~QZipWriter() } /*! + Returns device used for writing zip archive. +*/ +QIODevice* QZipWriter::device() const +{ + return d->device; +} + +/*! Returns true if the user can write to the archive; otherwise returns false. */ bool QZipWriter::isWritable() const diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h index 9b73373..6466a7b 100644 --- a/src/gui/text/qzipreader_p.h +++ b/src/gui/text/qzipreader_p.h @@ -55,6 +55,7 @@ // We mean it. // +#include <QtCore/qdatetime.h> #include <QtCore/qfile.h> #include <QtCore/qstring.h> @@ -70,6 +71,8 @@ public: explicit QZipReader(QIODevice *device); ~QZipReader(); + QIODevice* device() const; + bool isReadable() const; bool exists() const; @@ -79,6 +82,7 @@ public: FileInfo(const FileInfo &other); ~FileInfo(); FileInfo &operator=(const FileInfo &other); + bool isValid() const; QString filePath; uint isDir : 1; uint isFile : 1; @@ -86,6 +90,7 @@ public: QFile::Permissions permissions; uint crc32; qint64 size; + QDateTime lastModified; void *d; }; diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h index 9322f4a..a50c172 100644 --- a/src/gui/text/qzipwriter_p.h +++ b/src/gui/text/qzipwriter_p.h @@ -69,6 +69,8 @@ public: explicit QZipWriter(QIODevice *device); ~QZipWriter(); + QIODevice* device() const; + bool isWritable() const; bool exists() const; diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp index 2888490..522d472 100644 --- a/src/gui/widgets/qabstractslider.cpp +++ b/src/gui/widgets/qabstractslider.cpp @@ -712,7 +712,15 @@ bool QAbstractSliderPrivate::scrollByDelta(Qt::Orientation orientation, Qt::Keyb offset_accumulated = 0; offset_accumulated += stepsToScrollF; +#ifndef Q_WS_MAC + // Dont't scroll more than one page in any case: stepsToScroll = qBound(-pageStep, int(offset_accumulated), pageStep); +#else + // Native UI-elements on Mac can scroll hundreds of lines at a time as + // a result of acceleration. So keep the same behaviour in Qt, and + // dont restrict stepsToScroll to certain maximum (pageStep): + stepsToScroll = int(offset_accumulated); +#endif offset_accumulated -= int(offset_accumulated); if (stepsToScroll == 0) return false; diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 9ec0feb..8e715a9 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -136,9 +136,9 @@ void QLineControl::copy(QClipboard::Mode mode) const \sa insert() */ -void QLineControl::paste() +void QLineControl::paste(QClipboard::Mode clipboardMode) { - QString clip = QApplication::clipboard()->text(QClipboard::Clipboard); + QString clip = QApplication::clipboard()->text(clipboardMode); if (!clip.isEmpty() || hasSelectedText()) { separate(); //make it a separate undo/redo command insert(clip); @@ -1576,8 +1576,14 @@ void QLineControl::processKeyEvent(QKeyEvent* event) copy(); } else if (event == QKeySequence::Paste) { - if (!isReadOnly()) - paste(); + if (!isReadOnly()) { + QClipboard::Mode mode = QClipboard::Clipboard; +#ifdef Q_WS_X11 + if (event->modifiers() == (Qt::CTRL | Qt::SHIFT) && event->key() == Qt::Key_Insert) + mode = QClipboard::Selection; +#endif + paste(mode); + } } else if (event == QKeySequence::Cut) { if (!isReadOnly()) { diff --git a/src/gui/widgets/qlinecontrol_p.h b/src/gui/widgets/qlinecontrol_p.h index 3f1bc2c..dd82581 100644 --- a/src/gui/widgets/qlinecontrol_p.h +++ b/src/gui/widgets/qlinecontrol_p.h @@ -128,7 +128,7 @@ public: #ifndef QT_NO_CLIPBOARD void copy(QClipboard::Mode mode = QClipboard::Clipboard) const; - void paste(); + void paste(QClipboard::Mode mode = QClipboard::Clipboard); #endif int cursor() const; diff --git a/src/imports/qimportbase.pri b/src/imports/qimportbase.pri index 5433059..ea12356 100644 --- a/src/imports/qimportbase.pri +++ b/src/imports/qimportbase.pri @@ -22,7 +22,7 @@ QMAKE_EXTRA_COMPILERS += copy2build TARGET = $$qtLibraryTarget($$TARGET) contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols -include(../../qt_targets.pri) +include(../qt_targets.pri) wince*:LIBS += $$QMAKE_LIBS_GUI diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 7bb1399..1940dd1 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -880,17 +880,18 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera return new QDisabledNetworkReply(this, req, op); } +#ifdef QT_QNAM_DEFAULT_NETWORK_SESSION if (!d->networkSession && (d->initializeSession || !d->networkConfiguration.isEmpty())) { QNetworkConfigurationManager manager; if (d->networkConfiguration.isEmpty()) d->createSession(manager.defaultConfiguration()); else d->createSession(manager.configurationFromIdentifier(d->networkConfiguration)); + } +#endif - d->initializeSession = false; - } else if (d->networkSession) { + if (d->networkSession) d->networkSession->setSessionProperty(QLatin1String("AutoCloseSessionTimeout"), -1); - } QNetworkRequest request = req; if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() && @@ -1207,6 +1208,10 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co { Q_Q(QNetworkAccessManager); +#ifdef QT_QNAM_DEFAULT_NETWORK_SESSION + initializeSession = false; +#endif + if (networkSession) delete networkSession; @@ -1229,24 +1234,29 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co void QNetworkAccessManagerPrivate::_q_networkSessionClosed() { - networkConfiguration = networkSession->configuration().identifier(); + if (networkSession) { + networkConfiguration = networkSession->configuration().identifier(); - delete networkSession; - networkSession = 0; + networkSession->deleteLater(); + networkSession = 0; + } } void QNetworkAccessManagerPrivate::_q_networkSessionNewConfigurationActivated() { Q_Q(QNetworkAccessManager); - networkSession->accept(); + if (networkSession) { + networkSession->accept(); - emit q->networkSessionOnline(); + emit q->networkSessionOnline(); + } } void QNetworkAccessManagerPrivate::_q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &, bool) { - networkSession->migrate(); + if (networkSession) + networkSession->migrate(); } QT_END_NAMESPACE diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index 0140268..4a2a840 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -77,7 +77,9 @@ public: #endif networkSession(0), networkAccessEnabled(true), +#ifdef QT_QNAM_DEFAULT_NETWORK_SESSION initializeSession(true), +#endif cookieJarCreated(false) { } ~QNetworkAccessManagerPrivate(); @@ -124,7 +126,9 @@ public: QNetworkSession *networkSession; QString networkConfiguration; bool networkAccessEnabled; +#ifdef QT_QNAM_DEFAULT_NETWORK_SESSION bool initializeSession; +#endif bool cookieJarCreated; diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index b201380..8505a41 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -67,6 +67,8 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate() void QNetworkReplyImplPrivate::_q_startOperation() { + Q_Q(QNetworkReplyImpl); + // ensure this function is only being called once if (state == Working) { qDebug("QNetworkReplyImpl::_q_startOperation was called more than once"); @@ -93,6 +95,9 @@ void QNetworkReplyImplPrivate::_q_startOperation() QNetworkSession *session = manager->d_func()->networkSession; if (session) { + QObject::connect(session, SIGNAL(error(QNetworkSession::SessionError)), + q, SLOT(_q_networkSessionFailed())); + if (!session->isOpen()) session->open(); } else { @@ -247,6 +252,17 @@ void QNetworkReplyImplPrivate::_q_networkSessionOnline() } } +void QNetworkReplyImplPrivate::_q_networkSessionFailed() +{ + // Abort waiting replies. + if (state == WaitingForSession) { + state = Working; + error(QNetworkReplyImpl::UnknownNetworkError, + QCoreApplication::translate("QNetworkReply", "Network session error.")); + finished(); + } +} + void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *data) { @@ -707,6 +723,13 @@ void QNetworkReplyImpl::close() d->finished(); } +bool QNetworkReplyImpl::canReadLine () const +{ + Q_D(const QNetworkReplyImpl); + return QNetworkReply::canReadLine() || d->readBuffer.canReadLine(); +} + + /*! Returns the number of bytes available for reading with QIODevice::read(). The number of bytes available may grow until diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index b4fbd1e..6045ef4 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -77,10 +77,11 @@ public: ~QNetworkReplyImpl(); virtual void abort(); - // reimplemented from QNetworkReply + // reimplemented from QNetworkReply / QIODevice virtual void close(); virtual qint64 bytesAvailable() const; virtual void setReadBufferSize(qint64 size); + virtual bool canReadLine () const; virtual qint64 readData(char *data, qint64 maxlen); virtual bool event(QEvent *); @@ -99,6 +100,7 @@ public: Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData()) Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished()) Q_PRIVATE_SLOT(d_func(), void _q_networkSessionOnline()) + Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed()) }; class QNetworkReplyImplPrivate: public QNetworkReplyPrivate @@ -132,6 +134,7 @@ public: void _q_bufferOutgoingData(); void _q_bufferOutgoingDataFinished(); void _q_networkSessionOnline(); + void _q_networkSessionFailed(); void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData); diff --git a/src/network/bearer/qbearerengine_p.h b/src/network/bearer/qbearerengine_p.h index 028c174..fd4bf87 100644 --- a/src/network/bearer/qbearerengine_p.h +++ b/src/network/bearer/qbearerengine_p.h @@ -73,7 +73,7 @@ class Q_NETWORK_EXPORT QBearerEngine : public QObject { Q_OBJECT - friend class QNetworkConfigurationManager; + friend class QNetworkConfigurationManagerPrivate; public: QBearerEngine(QObject *parent = 0); @@ -81,8 +81,6 @@ public: virtual bool hasIdentifier(const QString &id) = 0; - virtual void requestUpdate() = 0; - virtual QNetworkConfigurationManager::Capabilities capabilities() const = 0; virtual QNetworkSessionPrivate *createSessionBackend() = 0; diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp index b631cf1..e7595a4 100644 --- a/src/network/bearer/qnetworkconfigmanager.cpp +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -212,114 +212,7 @@ QNetworkConfigurationManager::~QNetworkConfigurationManager() */ QNetworkConfiguration QNetworkConfigurationManager::defaultConfiguration() const { - QNetworkConfigurationManagerPrivate *conPriv = connManager(); - - foreach (QBearerEngine *engine, conPriv->engines()) { - QNetworkConfigurationPrivatePointer ptr = engine->defaultConfiguration(); - - if (ptr) { - QNetworkConfiguration config; - config.d = ptr; - return config; - } - } - - // Engines don't have a default configuration. - - // Return first active snap - QNetworkConfigurationPrivatePointer defaultConfiguration; - - foreach (QBearerEngine *engine, conPriv->engines()) { - QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it; - QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end; - - QMutexLocker locker(&engine->mutex); - - for (it = engine->snapConfigurations.begin(), end = engine->snapConfigurations.end(); - it != end; ++it) { - if ((it.value()->state & QNetworkConfiguration::Active) == - QNetworkConfiguration::Active) { - QNetworkConfiguration config; - config.d = it.value(); - return config; - } else if (!defaultConfiguration) { - if ((it.value()->state & QNetworkConfiguration::Discovered) == - QNetworkConfiguration::Discovered) { - defaultConfiguration = it.value(); - } - } - } - } - - // No Active SNAPs return first Discovered SNAP. - if (defaultConfiguration) { - QNetworkConfiguration config; - config.d = defaultConfiguration; - return config; - } - - /* - No Active or Discovered SNAPs, find the perferred access point. - The following priority order is used: - - 1. Active Ethernet - 2. Active WLAN - 3. Active Other - 4. Discovered Ethernet - 5. Discovered WLAN - 6. Discovered Other - */ - - defaultConfiguration.reset(); - - foreach (QBearerEngine *engine, conPriv->engines()) { - QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it; - QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end; - - QMutexLocker locker(&engine->mutex); - - for (it = engine->accessPointConfigurations.begin(), - end = engine->accessPointConfigurations.end(); it != end; ++it) { - - if ((it.value()->state & QNetworkConfiguration::Discovered) == - QNetworkConfiguration::Discovered) { - if (!defaultConfiguration) { - defaultConfiguration = it.value(); - } else { - if (defaultConfiguration->state == it.value()->state) { - if (defaultConfiguration->bearerName() == QLatin1String("Ethernet")) { - // do nothing - } else if (defaultConfiguration->bearerName() == QLatin1String("WLAN")) { - // ethernet beats wlan - if (it.value()->bearerName() == QLatin1String("Ethernet")) - defaultConfiguration = it.value(); - } else { - // ethernet and wlan beats other - if (it.value()->bearerName() == QLatin1String("Ethernet") || - it.value()->bearerName() == QLatin1String("WLAN")) { - defaultConfiguration = it.value(); - } - } - } else { - // active beats discovered - if ((defaultConfiguration->state & QNetworkConfiguration::Active) != - QNetworkConfiguration::Active) { - defaultConfiguration = it.value(); - } - } - } - } - } - } - - // No Active InternetAccessPoint return first Discovered InternetAccessPoint. - if (defaultConfiguration) { - QNetworkConfiguration config; - config.d = defaultConfiguration; - return config; - } - - return QNetworkConfiguration(); + return connManager()->defaultConfiguration(); } /*! @@ -349,37 +242,7 @@ QNetworkConfiguration QNetworkConfigurationManager::defaultConfiguration() const */ QList<QNetworkConfiguration> QNetworkConfigurationManager::allConfigurations(QNetworkConfiguration::StateFlags filter) const { - QList<QNetworkConfiguration> result; - QNetworkConfigurationManagerPrivate* conPriv = connManager(); - - foreach (QBearerEngine *engine, conPriv->engines()) { - QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it; - QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end; - - QMutexLocker locker(&engine->mutex); - - //find all InternetAccessPoints - for (it = engine->accessPointConfigurations.begin(), - end = engine->accessPointConfigurations.end(); it != end; ++it) { - if ((it.value()->state & filter) == filter) { - QNetworkConfiguration pt; - pt.d = it.value(); - result << pt; - } - } - - //find all service networks - for (it = engine->snapConfigurations.begin(), - end = engine->snapConfigurations.end(); it != end; ++it) { - if ((it.value()->state & filter) == filter) { - QNetworkConfiguration pt; - pt.d = it.value(); - result << pt; - } - } - } - - return result; + return connManager()->allConfigurations(filter); } /*! @@ -388,28 +251,9 @@ QList<QNetworkConfiguration> QNetworkConfigurationManager::allConfigurations(QNe \sa QNetworkConfiguration::identifier() */ -QNetworkConfiguration QNetworkConfigurationManager::configurationFromIdentifier(const QString& identifier) const +QNetworkConfiguration QNetworkConfigurationManager::configurationFromIdentifier(const QString &identifier) const { - QNetworkConfigurationManagerPrivate* conPriv = connManager(); - - QNetworkConfiguration item; - - foreach (QBearerEngine *engine, conPriv->engines()) { - QMutexLocker locker(&engine->mutex); - - if (engine->accessPointConfigurations.contains(identifier)) - item.d = engine->accessPointConfigurations.value(identifier); - else if (engine->snapConfigurations.contains(identifier)) - item.d = engine->snapConfigurations.value(identifier); - else if (engine->userChoiceConfigurations.contains(identifier)) - item.d = engine->userChoiceConfigurations.value(identifier); - else - continue; - - return item; - } - - return item; + return connManager()->configurationFromIdentifier(identifier); } /*! @@ -424,10 +268,7 @@ QNetworkConfiguration QNetworkConfigurationManager::configurationFromIdentifier( */ bool QNetworkConfigurationManager::isOnline() const { - QNetworkConfigurationManagerPrivate* conPriv = connManager(); - Q_UNUSED(conPriv); - QList<QNetworkConfiguration> activeConfigs = allConfigurations(QNetworkConfiguration::Active); - return activeConfigs.count() > 0; + return connManager()->isOnline(); } /*! diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index 9740424..c665fa2 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -47,6 +47,7 @@ #include <QtCore/qdebug.h> #include <QtCore/qtimer.h> #include <QtCore/qstringlist.h> +#include <QtCore/qthread.h> #include <QtCore/private/qcoreapplication_p.h> QT_BEGIN_NAMESPACE @@ -57,11 +58,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate() : capFlags(0), mutex(QMutex::Recursive), pollTimer(0), forcedPolling(0), firstUpdate(true) { - updateConfigurations(); + qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration"); moveToThread(QCoreApplicationPrivate::mainThread()); - foreach (QBearerEngine *engine, sessionEngines) - engine->moveToThread(QCoreApplicationPrivate::mainThread()); + updateConfigurations(); } QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate() @@ -71,6 +71,200 @@ QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate() qDeleteAll(sessionEngines); } +QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration() +{ + QMutexLocker locker(&mutex); + + foreach (QBearerEngine *engine, sessionEngines) { + QNetworkConfigurationPrivatePointer ptr = engine->defaultConfiguration(); + + if (ptr) { + QNetworkConfiguration config; + config.d = ptr; + return config; + } + } + + // Engines don't have a default configuration. + + // Return first active snap + QNetworkConfigurationPrivatePointer defaultConfiguration; + + foreach (QBearerEngine *engine, sessionEngines) { + QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it; + QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end; + + QMutexLocker locker(&engine->mutex); + + for (it = engine->snapConfigurations.begin(), end = engine->snapConfigurations.end(); + it != end; ++it) { + QNetworkConfigurationPrivatePointer ptr = it.value(); + + QMutexLocker configLocker(&ptr->mutex); + + if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + QNetworkConfiguration config; + config.d = ptr; + return config; + } else if (!defaultConfiguration) { + if ((ptr->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + defaultConfiguration = ptr; + } + } + } + } + + // No Active SNAPs return first Discovered SNAP. + if (defaultConfiguration) { + QNetworkConfiguration config; + config.d = defaultConfiguration; + return config; + } + + /* + No Active or Discovered SNAPs, find the perferred access point. + The following priority order is used: + + 1. Active Ethernet + 2. Active WLAN + 3. Active Other + 4. Discovered Ethernet + 5. Discovered WLAN + 6. Discovered Other + */ + + defaultConfiguration.reset(); + + foreach (QBearerEngine *engine, sessionEngines) { + QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it; + QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end; + + QMutexLocker locker(&engine->mutex); + + for (it = engine->accessPointConfigurations.begin(), + end = engine->accessPointConfigurations.end(); it != end; ++it) { + QNetworkConfigurationPrivatePointer ptr = it.value(); + + const QString bearerName = ptr->bearerName(); + QMutexLocker configLocker(&ptr->mutex); + + if ((ptr->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + if (!defaultConfiguration) { + defaultConfiguration = ptr; + } else { + if (defaultConfiguration->state == ptr->state) { + if (defaultConfiguration->bearerName() == QLatin1String("Ethernet")) { + // do nothing + } else if (defaultConfiguration->bearerName() == QLatin1String("WLAN")) { + // ethernet beats wlan + if (bearerName == QLatin1String("Ethernet")) + defaultConfiguration = ptr; + } else { + // ethernet and wlan beats other + if (bearerName == QLatin1String("Ethernet") || + bearerName == QLatin1String("WLAN")) { + defaultConfiguration = ptr; + } + } + } else { + // active beats discovered + if ((defaultConfiguration->state & QNetworkConfiguration::Active) != + QNetworkConfiguration::Active) { + defaultConfiguration = ptr; + } + } + } + } + } + } + + // No Active InternetAccessPoint return first Discovered InternetAccessPoint. + if (defaultConfiguration) { + QNetworkConfiguration config; + config.d = defaultConfiguration; + return config; + } + + return QNetworkConfiguration(); +} + +QList<QNetworkConfiguration> QNetworkConfigurationManagerPrivate::allConfigurations(QNetworkConfiguration::StateFlags filter) +{ + QList<QNetworkConfiguration> result; + + QMutexLocker locker(&mutex); + + foreach (QBearerEngine *engine, sessionEngines) { + QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it; + QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end; + + QMutexLocker locker(&engine->mutex); + + //find all InternetAccessPoints + for (it = engine->accessPointConfigurations.begin(), + end = engine->accessPointConfigurations.end(); it != end; ++it) { + QNetworkConfigurationPrivatePointer ptr = it.value(); + + QMutexLocker configLocker(&ptr->mutex); + + if ((ptr->state & filter) == filter) { + QNetworkConfiguration pt; + pt.d = ptr; + result << pt; + } + } + + //find all service networks + for (it = engine->snapConfigurations.begin(), + end = engine->snapConfigurations.end(); it != end; ++it) { + QNetworkConfigurationPrivatePointer ptr = it.value(); + + QMutexLocker configLocker(&ptr->mutex); + + if ((ptr->state & filter) == filter) { + QNetworkConfiguration pt; + pt.d = ptr; + result << pt; + } + } + } + + return result; +} + +QNetworkConfiguration QNetworkConfigurationManagerPrivate::configurationFromIdentifier(const QString &identifier) +{ + QNetworkConfiguration item; + + QMutexLocker locker(&mutex); + + foreach (QBearerEngine *engine, sessionEngines) { + QMutexLocker locker(&engine->mutex); + + if (engine->accessPointConfigurations.contains(identifier)) + item.d = engine->accessPointConfigurations.value(identifier); + else if (engine->snapConfigurations.contains(identifier)) + item.d = engine->snapConfigurations.value(identifier); + else if (engine->userChoiceConfigurations.contains(identifier)) + item.d = engine->userChoiceConfigurations.value(identifier); + else + continue; + + return item; + } + + return item; +} + +bool QNetworkConfigurationManagerPrivate::isOnline() +{ + QMutexLocker locker(&mutex); + + return !onlineConfigurations.isEmpty(); +} + void QNetworkConfigurationManagerPrivate::configurationAdded(QNetworkConfigurationPrivatePointer ptr) { QMutexLocker locker(&mutex); @@ -81,10 +275,14 @@ void QNetworkConfigurationManagerPrivate::configurationAdded(QNetworkConfigurati emit configurationAdded(item); } + ptr->mutex.lock(); if (ptr->state == QNetworkConfiguration::Active) { + ptr->mutex.unlock(); onlineConfigurations.insert(ptr->id); if (!firstUpdate && onlineConfigurations.count() == 1) emit onlineStateChanged(true); + } else { + ptr->mutex.unlock(); } } @@ -92,7 +290,9 @@ void QNetworkConfigurationManagerPrivate::configurationRemoved(QNetworkConfigura { QMutexLocker locker(&mutex); + ptr->mutex.lock(); ptr->isValid = false; + ptr->mutex.unlock(); if (!firstUpdate) { QNetworkConfiguration item; @@ -117,10 +317,12 @@ void QNetworkConfigurationManagerPrivate::configurationChanged(QNetworkConfigura bool previous = !onlineConfigurations.isEmpty(); + ptr->mutex.lock(); if (ptr->state == QNetworkConfiguration::Active) onlineConfigurations.insert(ptr->id); else onlineConfigurations.remove(ptr->id); + ptr->mutex.unlock(); bool online = !onlineConfigurations.isEmpty(); @@ -154,6 +356,8 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() else sessionEngines.append(engine); + engine->moveToThread(QCoreApplicationPrivate::mainThread()); + connect(engine, SIGNAL(updateCompleted()), this, SLOT(updateConfigurations())); connect(engine, SIGNAL(configurationAdded(QNetworkConfigurationPrivatePointer)), @@ -165,7 +369,7 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() capFlags |= engine->capabilities(); - engine->requestUpdate(); + QMetaObject::invokeMethod(engine, "requestUpdate"); } } @@ -211,7 +415,7 @@ void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate() for (int i = 0; i < sessionEngines.count(); ++i) { updatingEngines.insert(i); - sessionEngines.at(i)->requestUpdate(); + QMetaObject::invokeMethod(sessionEngines.at(i), "requestUpdate"); } } @@ -266,7 +470,7 @@ void QNetworkConfigurationManagerPrivate::pollEngines() if ((forcedPolling && sessionEngines.at(i)->requiresPolling()) || sessionEngines.at(i)->configurationsInUse()) { pollingEngines.insert(i); - sessionEngines.at(i)->requestUpdate(); + QMetaObject::invokeMethod(sessionEngines.at(i), "requestUpdate"); } } } @@ -278,7 +482,7 @@ void QNetworkConfigurationManagerPrivate::enablePolling() ++forcedPolling; if (forcedPolling == 1) - startPolling(); + QMetaObject::invokeMethod(this, "startPolling"); } void QNetworkConfigurationManagerPrivate::disablePolling() diff --git a/src/network/bearer/qnetworkconfigmanager_p.h b/src/network/bearer/qnetworkconfigmanager_p.h index ac8518c..8ec8152 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.h +++ b/src/network/bearer/qnetworkconfigmanager_p.h @@ -66,11 +66,16 @@ class QTimer; class Q_NETWORK_EXPORT QNetworkConfigurationManagerPrivate : public QObject { Q_OBJECT + public: QNetworkConfigurationManagerPrivate(); virtual ~QNetworkConfigurationManagerPrivate(); QNetworkConfiguration defaultConfiguration(); + QList<QNetworkConfiguration> allConfigurations(QNetworkConfiguration::StateFlags filter); + QNetworkConfiguration configurationFromIdentifier(const QString &identifier); + + bool isOnline(); QNetworkConfigurationManager::Capabilities capFlags; @@ -78,7 +83,7 @@ public: QList<QBearerEngine *> engines(); - void startPolling(); + Q_INVOKABLE void startPolling(); void enablePolling(); void disablePolling(); diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp index c4ba406..82669e0 100644 --- a/src/network/bearer/qnetworkconfiguration.cpp +++ b/src/network/bearer/qnetworkconfiguration.cpp @@ -246,7 +246,11 @@ bool QNetworkConfiguration::operator==(const QNetworkConfiguration& other) const */ QString QNetworkConfiguration::name() const { - return d ? d->name : QString(); + if (!d) + return QString(); + + QMutexLocker locker(&d->mutex); + return d->name; } /*! @@ -255,7 +259,11 @@ QString QNetworkConfiguration::name() const */ QString QNetworkConfiguration::identifier() const { - return d ? d->id : QString(); + if (!d) + return QString(); + + QMutexLocker locker(&d->mutex); + return d->id; } /*! @@ -268,7 +276,11 @@ QString QNetworkConfiguration::identifier() const */ QNetworkConfiguration::Type QNetworkConfiguration::type() const { - return d ? d->type : QNetworkConfiguration::Invalid; + if (!d) + return QNetworkConfiguration::Invalid; + + QMutexLocker locker(&d->mutex); + return d->type; } /*! @@ -283,7 +295,11 @@ QNetworkConfiguration::Type QNetworkConfiguration::type() const */ bool QNetworkConfiguration::isValid() const { - return d ? d->isValid : false; + if (!d) + return false; + + QMutexLocker locker(&d->mutex); + return d->isValid; } /*! @@ -291,7 +307,11 @@ bool QNetworkConfiguration::isValid() const */ QNetworkConfiguration::StateFlags QNetworkConfiguration::state() const { - return d ? d->state : QNetworkConfiguration::Undefined; + if (!d) + return QNetworkConfiguration::Undefined; + + QMutexLocker locker(&d->mutex); + return d->state; } /*! @@ -303,7 +323,11 @@ QNetworkConfiguration::StateFlags QNetworkConfiguration::state() const */ QNetworkConfiguration::Purpose QNetworkConfiguration::purpose() const { - return d ? d->purpose : QNetworkConfiguration::UnknownPurpose; + if (!d) + return QNetworkConfiguration::UnknownPurpose; + + QMutexLocker locker(&d->mutex); + return d->purpose; } /*! @@ -311,7 +335,11 @@ QNetworkConfiguration::Purpose QNetworkConfiguration::purpose() const */ bool QNetworkConfiguration::isRoamingAvailable() const { - return d ? d->roamingSupported : false; + if (!d) + return false; + + QMutexLocker locker(&d->mutex); + return d->roamingSupported; } /*! @@ -322,15 +350,25 @@ bool QNetworkConfiguration::isRoamingAvailable() const QList<QNetworkConfiguration> QNetworkConfiguration::children() const { QList<QNetworkConfiguration> results; - if (type() != QNetworkConfiguration::ServiceNetwork || !isValid() ) + + if (type() != QNetworkConfiguration::ServiceNetwork || !isValid()) return results; + QMutexLocker locker(&d->mutex); + QMutableListIterator<QNetworkConfigurationPrivatePointer> iter(d->serviceNetworkMembers); - while(iter.hasNext()) { + while (iter.hasNext()) { QNetworkConfigurationPrivatePointer p = iter.next(); + //if we have an invalid member get rid of it -> was deleted earlier on - if (!p->isValid) - iter.remove(); + { + QMutexLocker childLocker(&p->mutex); + + if (!p->isValid) { + iter.remove(); + continue; + } + } QNetworkConfiguration item; item.d = p; diff --git a/src/network/bearer/qnetworkconfiguration_p.h b/src/network/bearer/qnetworkconfiguration_p.h index 6b40946..6908277 100644 --- a/src/network/bearer/qnetworkconfiguration_p.h +++ b/src/network/bearer/qnetworkconfiguration_p.h @@ -54,7 +54,9 @@ // #include "qnetworkconfiguration.h" + #include <QtCore/qshareddata.h> +#include <QtCore/qmutex.h> #include <QtNetwork/QNetworkInterface> QT_BEGIN_NAMESPACE @@ -64,8 +66,9 @@ class QNetworkConfigurationPrivate : public QSharedData { public: QNetworkConfigurationPrivate () - : isValid(false), type(QNetworkConfiguration::Invalid), - roamingSupported(false), purpose(QNetworkConfiguration::UnknownPurpose), internet(false) + : mutex(QMutex::Recursive), type(QNetworkConfiguration::Invalid), + purpose(QNetworkConfiguration::UnknownPurpose), + isValid(false), roamingSupported(false) { } @@ -77,26 +80,27 @@ public: virtual QString bearerName() const { + QMutexLocker locker(&mutex); + return bearer; } - QString bearer; + mutable QMutex mutex; + QString bearer; QString name; - - bool isValid; QString id; + QNetworkConfiguration::StateFlags state; QNetworkConfiguration::Type type; - bool roamingSupported; QNetworkConfiguration::Purpose purpose; - bool internet; - QList<QNetworkConfigurationPrivatePointer> serviceNetworkMembers; -private: + bool isValid; + bool roamingSupported; +private: // disallow detaching QNetworkConfigurationPrivate &operator=(const QNetworkConfigurationPrivate &other); QNetworkConfigurationPrivate(const QNetworkConfigurationPrivate &other); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index ce2aee1..4010710 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -153,6 +153,7 @@ static unsigned long id_function() QSslSocketBackendPrivate::QSslSocketBackendPrivate() : ssl(0), ctx(0), + pkey(0), readBio(0), writeBio(0), session(0) @@ -311,11 +312,14 @@ init_context: } // Load private key - EVP_PKEY *pkey = q_EVP_PKEY_new(); + pkey = q_EVP_PKEY_new(); + // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free. + // this lead to a memory leak. Now we use the *_set1_* functions which do not + // take ownership of the RSA/DSA key instance because the QSslKey already has ownership. if (configuration.privateKey.algorithm() == QSsl::Rsa) - q_EVP_PKEY_assign_RSA(pkey, (RSA *)configuration.privateKey.handle()); + q_EVP_PKEY_set1_RSA(pkey, (RSA *)configuration.privateKey.handle()); else - q_EVP_PKEY_assign_DSA(pkey, (DSA *)configuration.privateKey.handle()); + q_EVP_PKEY_set1_DSA(pkey, (DSA *)configuration.privateKey.handle()); if (!q_SSL_CTX_use_PrivateKey(ctx, pkey)) { q->setErrorString(QSslSocket::tr("Error loading private key, %1").arg(SSL_ERRORSTR())); emit q->error(QAbstractSocket::UnknownSocketError); @@ -922,6 +926,11 @@ void QSslSocketBackendPrivate::disconnected() q_SSL_CTX_free(ctx); ctx = 0; } + if (pkey) { + q_EVP_PKEY_free(pkey); + pkey = 0; + } + } QSslCipher QSslSocketBackendPrivate::sessionCipher() const diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index 836f064..3c08757 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -97,6 +97,7 @@ public: bool initSslContext(); SSL *ssl; SSL_CTX *ctx; + EVP_PKEY *pkey; BIO *readBio; BIO *writeBio; SSL_SESSION *session; diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 94cc9d2..d2eb6f1 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -119,6 +119,8 @@ DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return) +DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return) +DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return) DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG) DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return 0, return) DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return 0, return) @@ -510,6 +512,8 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(ERR_get_error, 749, libs.second ) RESOLVEFUNC(EVP_des_ede3_cbc, 919, libs.second ) RESOLVEFUNC(EVP_PKEY_assign, 859, libs.second ) + RESOLVEFUNC(EVP_PKEY_set1_RSA, 880, libs.second ) + RESOLVEFUNC(EVP_PKEY_set1_DSA, 879, libs.second ) RESOLVEFUNC(EVP_PKEY_free, 867, libs.second ) RESOLVEFUNC(EVP_PKEY_get1_DSA, 869, libs.second ) RESOLVEFUNC(EVP_PKEY_get1_RSA, 870, libs.second ) @@ -632,6 +636,8 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(ERR_get_error) RESOLVEFUNC(EVP_des_ede3_cbc) RESOLVEFUNC(EVP_PKEY_assign) + RESOLVEFUNC(EVP_PKEY_set1_RSA) + RESOLVEFUNC(EVP_PKEY_set1_DSA) RESOLVEFUNC(EVP_PKEY_free) RESOLVEFUNC(EVP_PKEY_get1_DSA) RESOLVEFUNC(EVP_PKEY_get1_RSA) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index c93d547..ef61dbf 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -227,6 +227,8 @@ char *q_ERR_error_string(unsigned long a, char *b); unsigned long q_ERR_get_error(); const EVP_CIPHER *q_EVP_des_ede3_cbc(); int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c); +int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b); +int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b); void q_EVP_PKEY_free(EVP_PKEY *a); RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a); DSA *q_EVP_PKEY_get1_DSA(EVP_PKEY *a); diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro index a67c8f6..00be80e 100644 --- a/src/plugins/bearer/bearer.pro +++ b/src/plugins/bearer/bearer.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs -!maemo:contains(QT_CONFIG, dbus):contains(QT_CONFIG, networkmanager) { +!maemo6:contains(QT_CONFIG, dbus) { SUBDIRS += networkmanager generic } #win32:SUBDIRS += nla diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.h b/src/plugins/bearer/corewlan/qcorewlanengine.h index cbaa9d6..76574a8 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.h +++ b/src/plugins/bearer/corewlan/qcorewlanengine.h @@ -68,7 +68,7 @@ public: void connectToId(const QString &id); void disconnectFromId(const QString &id); - void requestUpdate(); + Q_INVOKABLE void requestUpdate(); QNetworkSession::State sessionStateForId(const QString &id); @@ -90,14 +90,21 @@ private: QMap<QString, QString> configurationInterface; QStringList scanForSsids(const QString &interfaceName); - bool isKnownSsid(const QString &interfaceName, const QString &ssid); + bool isKnownSsid(const QString &ssid); QList<QNetworkConfigurationPrivate *> foundConfigurations; SCDynamicStoreRef storeSession; CFRunLoopSourceRef runloopSource; - void startNetworkChangeLoop(); + bool hasWifi; + +protected: + QMap<QString, QMap<QString,QString> > userProfiles; + void startNetworkChangeLoop(); + void getUserConfigurations(); + QString getNetworkNameFromSsid(const QString &ssid); + QString getSsidFromNetworkName(const QString &name); }; QT_END_NAMESPACE diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index cb278d9..60c6fbd 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.mm +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -50,13 +50,11 @@ #include <QtCore/qstringlist.h> #include <QtCore/qdebug.h> - -#if defined(MAC_SDK_10_6) //not much functionality without this +#include <QDir> #include <CoreWLAN/CoreWLAN.h> #include <CoreWLAN/CWInterface.h> #include <CoreWLAN/CWNetwork.h> #include <CoreWLAN/CWNetwork.h> -#endif #include <Foundation/NSEnumerator.h> #include <Foundation/NSKeyValueObserving.h> @@ -69,16 +67,14 @@ QMap <QString, QString> networkInterfaces; -#ifdef MAC_SDK_10_6 @interface QNSListener : NSObject { NSNotificationCenter *center; CWInterface *currentInterface; QCoreWlanEngine *engine; - NSAutoreleasePool *autoreleasepool; NSLock *locker; } -- (void)notificationHandler:(NSNotification *)notification; +- (void)notificationHandler;//:(NSNotification *)notification; - (void)remove; - (void)setEngine:(QCoreWlanEngine *)coreEngine; - (void)dealloc; @@ -91,7 +87,7 @@ QMap <QString, QString> networkInterfaces; - (id) init { [locker lock]; - autoreleasepool = [[NSAutoreleasePool alloc] init]; + QMacCocoaAutoReleasePool pool; center = [NSNotificationCenter defaultCenter]; currentInterface = [CWInterface interface]; // [center addObserver:self selector:@selector(notificationHandler:) name:kCWLinkDidChangeNotification object:nil]; @@ -102,7 +98,6 @@ QMap <QString, QString> networkInterfaces; -(void)dealloc { - [autoreleasepool release]; [super dealloc]; } @@ -121,7 +116,7 @@ QMap <QString, QString> networkInterfaces; [locker unlock]; } -- (void)notificationHandler:(NSNotification *)notification +- (void)notificationHandler//:(NSNotification *)notification { engine->requestUpdate(); } @@ -129,14 +124,12 @@ QMap <QString, QString> networkInterfaces; QNSListener *listener = 0; -#endif - QT_BEGIN_NAMESPACE static QString qGetInterfaceType(const QString &interfaceString) { - return networkInterfaces.value(interfaceString, QLatin1String("Unknown")); + return networkInterfaces.value(interfaceString, QLatin1String("WLAN")); } void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info) @@ -157,22 +150,23 @@ QCoreWlanEngine::QCoreWlanEngine(QObject *parent) { startNetworkChangeLoop(); -#if defined(MAC_SDK_10_6) - if(!listener) { + QMacCocoaAutoReleasePool pool; + if([[CWInterface supportedInterfaces] count] > 0 && !listener) { listener = [[QNSListener alloc] init]; listener.engine = this; + hasWifi = true; + } else { + hasWifi = false; } -#endif + requestUpdate(); } QCoreWlanEngine::~QCoreWlanEngine() { while (!foundConfigurations.isEmpty()) delete foundConfigurations.takeFirst(); -#if defined(MAC_SDK_10_6) [listener remove]; [listener release]; -#endif } QString QCoreWlanEngine::getInterfaceFromId(const QString &id) @@ -192,73 +186,88 @@ bool QCoreWlanEngine::hasIdentifier(const QString &id) void QCoreWlanEngine::connectToId(const QString &id) { QMutexLocker locker(&mutex); - - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + QMacCocoaAutoReleasePool pool; QString interfaceString = getInterfaceFromId(id); if(networkInterfaces.value(interfaceString) == "WLAN") { -#if defined(MAC_SDK_10_6) CWInterface *wifiInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceString)]; - CWConfiguration *userConfig = [ wifiInterface configuration]; - NSSet *remNets = [userConfig rememberedNetworks]; //CWWirelessProfile - - NSEnumerator *enumerator = [remNets objectEnumerator]; - CWWirelessProfile *wProfile; - NSUInteger index=0; - NSDictionary *parametersDict; - NSArray* apArray; - - CW8021XProfile *user8021XProfile; - NSError *err; - NSMutableDictionary *params; + if([wifiInterface power]) { + NSError *err = nil; + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; + + NSString *wantedSsid = 0; + bool okToProceed = true; + if(getNetworkNameFromSsid(id) != id) { + NSArray *array = [CW8021XProfile allUser8021XProfiles]; + for (NSUInteger i=0; i<[array count]; ++i) { + const QString idCheck = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([[array objectAtIndex:i] userDefinedName]))); + const QString idCheck2 = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([[array objectAtIndex:i] ssid]))); + + if(id == idCheck + || id == idCheck2) { + QString thisName = getSsidFromNetworkName(id); + if(thisName.isEmpty()) { + wantedSsid = qt_mac_QStringToNSString(id); + } else { + wantedSsid = qt_mac_QStringToNSString(thisName); + } + okToProceed = false; + [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile]; + break; + } + } + } - while ((wProfile = [enumerator nextObject])) { //CWWirelessProfile + if(okToProceed) { + NSUInteger index = 0; - if(id == QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([wProfile ssid])))) { - user8021XProfile = nil; - user8021XProfile = [ wProfile user8021XProfile]; + CWConfiguration *userConfig = [ wifiInterface configuration]; + NSSet *remNets = [userConfig rememberedNetworks]; + NSEnumerator *enumerator = [remNets objectEnumerator]; + CWWirelessProfile *wProfile; - err = nil; - params = [NSMutableDictionary dictionaryWithCapacity:0]; + while ((wProfile = [enumerator nextObject])) { + const QString idCheck = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([wProfile ssid]))); - if(user8021XProfile) { - [params setValue: user8021XProfile forKey:kCWAssocKey8021XProfile]; - } else { - [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; + if(id == idCheck) { + wantedSsid = [wProfile ssid]; + [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; + break; + } + index++; } + } - parametersDict = nil; - apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; - - if(!err) { - - for(uint row=0; row < [apArray count]; row++ ) { - CWNetwork *apNetwork = [apArray objectAtIndex:row]; - if([[apNetwork ssid] compare:[wProfile ssid]] == NSOrderedSame) { + NSDictionary *parametersDict = nil; + NSArray *apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; - bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; + if(!err) { + for(uint row=0; row < [apArray count]; row++ ) { + CWNetwork *apNetwork = [apArray objectAtIndex:row]; + if([[apNetwork ssid] compare:wantedSsid] == NSOrderedSame) { + bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; - if(!result) { - emit connectionError(id, ConnectError); - } else { - [autoreleasepool release]; - return; - } + if(!result) { + emit connectionError(id, ConnectError); + } else { + return; } } } + } else { + qDebug() <<"ERROR"<< qt_mac_NSStringToQString([err localizedDescription ]); } - index++; - } + emit connectionError(id, InterfaceLookupError); + } else { + // not wifi + } + locker.unlock(); emit connectionError(id, InterfaceLookupError); -#endif - } else { - // not wifi + locker.relock(); } emit connectionError(id, OperationNotSupported); - [autoreleasepool release]; } void QCoreWlanEngine::disconnectFromId(const QString &id) @@ -268,25 +277,27 @@ void QCoreWlanEngine::disconnectFromId(const QString &id) QString interfaceString = getInterfaceFromId(id); if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now #if defined(MAC_SDK_10_6) - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + QMacCocoaAutoReleasePool pool; CWInterface *wifiInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceString)]; [wifiInterface disassociate]; if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { + locker.unlock(); emit connectionError(id, DisconnectionError); + locker.relock(); } - [autoreleasepool release]; return; #endif } else { } + + locker.unlock(); emit connectionError(id, OperationNotSupported); } void QCoreWlanEngine::requestUpdate() { - QMutexLocker locker(&mutex); - + getUserConfigurations(); doRequestUpdate(); } @@ -340,6 +351,8 @@ void QCoreWlanEngine::doRequestUpdate() bool changed = false; + ptr->mutex.lock(); + if (!ptr->isValid) { ptr->isValid = true; changed = true; @@ -360,8 +373,13 @@ void QCoreWlanEngine::doRequestUpdate() changed = true; } - if (changed) + ptr->mutex.unlock(); + + if (changed) { + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } } } @@ -369,9 +387,13 @@ void QCoreWlanEngine::doRequestUpdate() QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(previous.takeFirst()); configurationInterface.remove(ptr->id); + + locker.unlock(); emit configurationRemoved(ptr); + locker.relock(); } + locker.unlock(); emit updateCompleted(); } @@ -381,16 +403,20 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) QStringList found; -#if defined(MAC_SDK_10_6) - QMacCocoaAutoReleasePool pool; + if(!hasWifi) { + return found; + } + QMacCocoaAutoReleasePool pool; CWInterface *currentInterface = [CWInterface interfaceWithName:qt_mac_QStringToNSString(interfaceName)]; + QStringList addedConfigs; + if([currentInterface power]) { NSError *err = nil; NSDictionary *parametersDict = nil; NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; - CWNetwork *apNetwork; + if (!err) { for(uint row=0; row < [apArray count]; row++ ) { @@ -402,15 +428,18 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) found.append(id); QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; - - if ([currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { - if (networkSsid == qt_mac_NSStringToQString([currentInterface ssid])) + bool known = isKnownSsid(networkSsid); + if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + if( networkSsid == qt_mac_NSStringToQString( [currentInterface ssid])) { state = QNetworkConfiguration::Active; - } else { - if (isKnownSsid(interfaceName, networkSsid)) + } + } + if(state == QNetworkConfiguration::Undefined) { + if(known) { state = QNetworkConfiguration::Discovered; - else - state = QNetworkConfiguration::Defined; + } else { + state = QNetworkConfiguration::Undefined; + } } if (accessPointConfigurations.contains(id)) { @@ -418,6 +447,8 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) bool changed = false; + ptr->mutex.lock(); + if (!ptr->isValid) { ptr->isValid = true; changed = true; @@ -438,11 +469,18 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) changed = true; } - if (changed) + ptr->mutex.unlock(); + + if (changed) { + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } + addedConfigs << networkSsid; } else { QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + found.append(id); ptr->name = networkSsid; ptr->isValid = true; ptr->id = id; @@ -450,17 +488,60 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) ptr->type = QNetworkConfiguration::InternetAccessPoint; ptr->bearer = QLatin1String("WLAN"); - accessPointConfigurations.insert(id, ptr); - configurationInterface.insert(id, interfaceName); + accessPointConfigurations.insert(ptr->id, ptr); + configurationInterface.insert(ptr->id, interfaceName); + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); + addedConfigs << networkSsid; } } } } -#else - Q_UNUSED(interfaceName); -#endif + + // add known configurations that are not around. + QMapIterator<QString, QMap<QString,QString> > i(userProfiles); + while (i.hasNext()) { + i.next(); + QString networkName = i.key(); + if(!addedConfigs.contains(networkName)) { + QString interfaceName; + QMapIterator<QString, QString> ij(i.value()); + while (ij.hasNext()) { + ij.next(); + interfaceName = ij.value(); + } + QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName)); + found.append(id); + + ptr->name = networkName; + ptr->isValid = true; + ptr->id = id; + ptr->bearer = QLatin1String("WLAN"); + ptr->type = QNetworkConfiguration::InternetAccessPoint; + QString ssid = getSsidFromNetworkName(networkName); + + if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + if( ssid == qt_mac_NSStringToQString([currentInterface ssid])) { + ptr->state = QNetworkConfiguration::Active; + } + } + + if(!ptr->state) { + if( addedConfigs.contains(ssid)) { + ptr->state = QNetworkConfiguration::Discovered; + } + } + + if(!ptr->state) { + ptr->state = QNetworkConfiguration::Defined; + } + accessPointConfigurations.insert(ptr->id, ptr); + configurationInterface.insert(ptr->id, interfaceName); + } + } return found; } @@ -468,32 +549,27 @@ bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) { QMutexLocker locker(&mutex); -#if defined(MAC_SDK_10_6) - CWInterface *defaultInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(wifiDeviceName)]; - if([defaultInterface power]) - return true; -#else - Q_UNUSED(wifiDeviceName); -#endif + if(hasWifi) { + QMacCocoaAutoReleasePool pool; + CWInterface *defaultInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(wifiDeviceName)]; + if([defaultInterface power]) + return true; + } return false; } -bool QCoreWlanEngine::isKnownSsid(const QString &interfaceName, const QString &ssid) +bool QCoreWlanEngine::isKnownSsid(const QString &ssid) { QMutexLocker locker(&mutex); -#if defined(MAC_SDK_10_6) - CWInterface *wifiInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceName)]; - CWConfiguration *userConfig = [wifiInterface configuration]; - NSSet *remNets = [userConfig rememberedNetworks]; - for (CWWirelessProfile *wProfile in remNets) { - if(ssid == qt_mac_NSStringToQString([wProfile ssid])) + QMapIterator<QString, QMap<QString,QString> > i(userProfiles); + while (i.hasNext()) { + i.next(); + QMap<QString,QString> map = i.value(); + if(map.keys().contains(ssid)) { return true; + } } -#else - Q_UNUSED(interfaceName); - Q_UNUSED(ssid); -#endif return false; } @@ -508,7 +584,6 @@ bool QCoreWlanEngine::getWifiInterfaces() for(uint row=0; row < [wifiInterfaces count]; row++ ) { networkInterfaces.insert( qt_mac_NSStringToQString([wifiInterfaces objectAtIndex:row]),"WLAN"); } - return true; } @@ -612,4 +687,109 @@ bool QCoreWlanEngine::requiresPolling() const return true; } +QString QCoreWlanEngine::getSsidFromNetworkName(const QString &name) +{ + QMapIterator<QString, QMap<QString,QString> > i(userProfiles); + while (i.hasNext()) { + i.next(); + + QMap<QString,QString> map = i.value(); + QMapIterator<QString, QString> ij(i.value()); + while (ij.hasNext()) { + ij.next(); + const QString idCheck = QString::number(qHash(QLatin1String("corewlan:") +i.key())); + if(name == i.key() || name == idCheck) { + return ij.key(); + } + } + } + return QString(); +} + +QString QCoreWlanEngine::getNetworkNameFromSsid(const QString &ssid) +{ + QMapIterator<QString, QMap<QString,QString> > i(userProfiles); + while (i.hasNext()) { + i.next(); + QMap<QString,QString> map = i.value(); + QMapIterator<QString, QString> ij(i.value()); + while (ij.hasNext()) { + ij.next(); + if(ij.key() == ssid) { + return i.key(); + } + + } + return map.key(ssid); + } + return QString(); +} + + +void QCoreWlanEngine::getUserConfigurations() +{ + QMacCocoaAutoReleasePool pool; + userProfiles.clear(); + + NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; + for(uint row=0; row < [wifiInterfaces count]; row++ ) { + + CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]]; + +// add user configured system networks + SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil); + CFDictionaryRef airportPlist = (const __CFDictionary*)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", [wifiInterface name]]); + CFRelease(dynRef); + + NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"]; + + NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"]; + for(NSString *ssidkey in thisSsidarray) { + QString thisSsid = qt_mac_NSStringToQString(ssidkey); + if(!userProfiles.contains(thisSsid)) { + QMap <QString,QString> map; + map.insert(thisSsid, qt_mac_NSStringToQString([wifiInterface name])); + userProfiles.insert(thisSsid, map); + } + } + CFRelease(airportPlist); + + // 802.1X user profiles + QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist"; + NSDictionary* eapDict = [[NSMutableDictionary alloc] initWithContentsOfFile:qt_mac_QStringToNSString(userProfilePath)]; + NSString *profileStr= @"Profiles"; + NSString *nameStr = @"UserDefinedName"; + NSString *networkSsidStr = @"Wireless Network"; + for (id profileKey in eapDict) { + if ([profileStr isEqualToString:profileKey]) { + NSDictionary *itemDict = [eapDict objectForKey:profileKey]; + for (id itemKey in itemDict) { + + NSInteger dictSize = [itemKey count]; + id objects[dictSize]; + id keys[dictSize]; + + [itemKey getObjects:objects andKeys:keys]; + QString networkName; + QString ssid; + for(int i = 0; i < dictSize; i++) { + if([nameStr isEqualToString:keys[i]]) { + networkName = qt_mac_NSStringToQString(objects[i]); + } + if([networkSsidStr isEqualToString:keys[i]]) { + ssid = qt_mac_NSStringToQString(objects[i]); + } + if(!userProfiles.contains(networkName) + && !ssid.isEmpty()) { + QMap<QString,QString> map; + map.insert(ssid, qt_mac_NSStringToQString([wifiInterface name])); + userProfiles.insert(networkName, map); + } + } + } + } + } + } +} + QT_END_NAMESPACE diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp index a9e78b2..dfc74f2 100644 --- a/src/plugins/bearer/generic/qgenericengine.cpp +++ b/src/plugins/bearer/generic/qgenericengine.cpp @@ -50,6 +50,7 @@ #include <QtCore/qstringlist.h> #include <QtCore/qdebug.h> +#include <QtCore/private/qcoreapplication_p.h> #ifdef Q_OS_WIN #include "../platformdefs_win.h" @@ -174,8 +175,6 @@ void QGenericEngine::disconnectFromId(const QString &id) void QGenericEngine::requestUpdate() { - QMutexLocker locker(&mutex); - doRequestUpdate(); } @@ -231,6 +230,8 @@ void QGenericEngine::doRequestUpdate() bool changed = false; + ptr->mutex.lock(); + if (!ptr->isValid) { ptr->isValid = true; changed = true; @@ -251,8 +252,13 @@ void QGenericEngine::doRequestUpdate() changed = true; } - if (changed) + ptr->mutex.unlock(); + + if (changed) { + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } } else { QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); @@ -266,7 +272,9 @@ void QGenericEngine::doRequestUpdate() accessPointConfigurations.insert(id, ptr); configurationInterface.insert(id, interface.name()); + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); } } @@ -275,9 +283,13 @@ void QGenericEngine::doRequestUpdate() accessPointConfigurations.take(previous.takeFirst()); configurationInterface.remove(ptr->id); + + locker.unlock(); emit configurationRemoved(ptr); + locker.relock(); } + locker.unlock(); emit updateCompleted(); } @@ -290,6 +302,8 @@ QNetworkSession::State QGenericEngine::sessionStateForId(const QString &id) if (!ptr) return QNetworkSession::Invalid; + QMutexLocker configLocker(&ptr->mutex); + if (!ptr->isValid) { return QNetworkSession::Invalid; } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { diff --git a/src/plugins/bearer/generic/qgenericengine.h b/src/plugins/bearer/generic/qgenericengine.h index a1b9167..616a3fd 100644 --- a/src/plugins/bearer/generic/qgenericengine.h +++ b/src/plugins/bearer/generic/qgenericengine.h @@ -68,7 +68,7 @@ public: void connectToId(const QString &id); void disconnectFromId(const QString &id); - void requestUpdate(); + Q_INVOKABLE void requestUpdate(); QNetworkSession::State sessionStateForId(const QString &id); diff --git a/src/plugins/bearer/icd/qicdengine.cpp b/src/plugins/bearer/icd/qicdengine.cpp index 5e506ef..5e9dc0a 100644 --- a/src/plugins/bearer/icd/qicdengine.cpp +++ b/src/plugins/bearer/icd/qicdengine.cpp @@ -180,7 +180,10 @@ void QIcdEngine::doRequestUpdate() ptr->roamingSupported = false; userChoiceConfigurations.insert(ptr->id, ptr); + + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); } /* We return currently configured IAPs in the first run and do the WLAN @@ -241,7 +244,10 @@ void QIcdEngine::doRequestUpdate() QNetworkConfigurationPrivatePointer ptr(cpPriv); accessPointConfigurations.insert(iap_id, ptr); + + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); #ifdef BEARER_MANAGEMENT_DEBUG qDebug("IAP: %s, name: %s, ssid: %s, added to known list", @@ -299,6 +305,8 @@ void QIcdEngine::doRequestUpdate() bool changed = false; + ptr->mutex.lock(); + if (!ptr->isValid) { ptr->isValid = true; changed = true; @@ -319,8 +327,13 @@ void QIcdEngine::doRequestUpdate() iapid.toAscii().data(), scanned_ssid.data()); #endif - if (changed) + ptr->mutex.unlock(); + + if (changed) { + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } if (!ap.scan.network_type.startsWith("WLAN")) continue; // not a wlan AP @@ -354,7 +367,10 @@ void QIcdEngine::doRequestUpdate() QNetworkConfigurationPrivatePointer ptr(cpPriv); accessPointConfigurations.insert(ptr->id, ptr); + + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); } } } @@ -363,11 +379,15 @@ void QIcdEngine::doRequestUpdate() QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(previous.takeFirst()); + locker.unlock(); emit configurationRemoved(ptr); + locker.relock(); } - if (sender()) + if (sender()) { + locker.unlock(); emit updateCompleted(); + } } void QIcdEngine::deleteConfiguration(const QString &iap_id) @@ -384,6 +404,7 @@ void QIcdEngine::deleteConfiguration(const QString &iap_id) qDebug() << "IAP" << iap_id << "was removed from storage."; #endif + locker.unlock(); emit configurationRemoved(ptr); } else { #ifdef BEARER_MANAGEMENT_DEBUG diff --git a/src/plugins/bearer/icd/qicdengine.h b/src/plugins/bearer/icd/qicdengine.h index 6ebe40d..50cda62 100644 --- a/src/plugins/bearer/icd/qicdengine.h +++ b/src/plugins/bearer/icd/qicdengine.h @@ -86,7 +86,7 @@ public: bool hasIdentifier(const QString &id); - void requestUpdate(); + Q_INVOKABLE void requestUpdate(); QNetworkConfigurationManager::Capabilities capabilities() const; diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp index bb81408..a2ae65c 100644 --- a/src/plugins/bearer/icd/qnetworksession_impl.cpp +++ b/src/plugins/bearer/icd/qnetworksession_impl.cpp @@ -312,19 +312,42 @@ void QNetworkSessionPrivateImpl::updateState(QNetworkSession::State newState) state = newState; if (state == QNetworkSession::Disconnected) { - isOpen = false; + isOpen = false; currentNetworkInterface.clear(); - if (publicConfig.type() == QNetworkConfiguration::UserChoice) - privateConfiguration(activeConfig)->state = QNetworkConfiguration::Defined; - privateConfiguration(publicConfig)->state = QNetworkConfiguration::Defined; + if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + IcdNetworkConfigurationPrivate *icdConfig = + toIcdConfig(privateConfiguration(activeConfig)); + + icdConfig->mutex.lock(); + icdConfig->state = QNetworkConfiguration::Defined; + icdConfig->mutex.unlock(); + } + + IcdNetworkConfigurationPrivate *icdConfig = + toIcdConfig(privateConfiguration(publicConfig)); + + icdConfig->mutex.lock(); + icdConfig->state = QNetworkConfiguration::Defined; + icdConfig->mutex.unlock(); } else if (state == QNetworkSession::Connected) { - isOpen = true; + isOpen = true; if (publicConfig.type() == QNetworkConfiguration::UserChoice) { - privateConfiguration(activeConfig)->state = QNetworkConfiguration::Active; - privateConfiguration(activeConfig)->type = QNetworkConfiguration::InternetAccessPoint; + IcdNetworkConfigurationPrivate *icdConfig = + toIcdConfig(privateConfiguration(activeConfig)); + + icdConfig->mutex.lock(); + icdConfig->state = QNetworkConfiguration::Active; + icdConfig->type = QNetworkConfiguration::InternetAccessPoint; + icdConfig->mutex.unlock(); } - privateConfiguration(publicConfig)->state = QNetworkConfiguration::Active; + + IcdNetworkConfigurationPrivate *icdConfig = + toIcdConfig(privateConfiguration(publicConfig)); + + icdConfig->mutex.lock(); + icdConfig->state = QNetworkConfiguration::Active; + icdConfig->mutex.unlock(); } emit stateChanged(newState); @@ -334,13 +357,22 @@ void QNetworkSessionPrivateImpl::updateState(QNetworkSession::State newState) void QNetworkSessionPrivateImpl::updateIdentifier(QString &newId) { if (publicConfig.type() == QNetworkConfiguration::UserChoice) { - toIcdConfig(privateConfiguration(activeConfig))->network_attrs |= ICD_NW_ATTR_IAPNAME; - privateConfiguration(activeConfig)->id = newId; + IcdNetworkConfigurationPrivate *icdConfig = + toIcdConfig(privateConfiguration(activeConfig)); + + icdConfig->mutex.lock(); + icdConfig->network_attrs |= ICD_NW_ATTR_IAPNAME; + icdConfig->id = newId; + icdConfig->mutex.unlock(); } else { - toIcdConfig(privateConfiguration(publicConfig))->network_attrs |= ICD_NW_ATTR_IAPNAME; - if (privateConfiguration(publicConfig)->id != newId) { - privateConfiguration(publicConfig)->id = newId; - } + IcdNetworkConfigurationPrivate *icdConfig = + toIcdConfig(privateConfiguration(publicConfig)); + + icdConfig->mutex.lock(); + icdConfig->network_attrs |= ICD_NW_ATTR_IAPNAME; + if (icdConfig->id != newId) + icdConfig->id = newId; + icdConfig->mutex.unlock(); } } @@ -368,10 +400,15 @@ quint64 QNetworkSessionPrivateImpl::getStatistics(bool sent) const } } else { /* We probably will never get to this branch */ - if (res.params.network_id == toIcdConfig(privateConfiguration(activeConfig))->network_id) { - counter_tx = res.bytes_sent; - counter_rx = res.bytes_received; + IcdNetworkConfigurationPrivate *icdConfig = + toIcdConfig(privateConfiguration(activeConfig)); + + icdConfig->mutex.lock(); + if (res.params.network_id == icdConfig->network_id) { + counter_tx = res.bytes_sent; + counter_rx = res.bytes_received; } + icdConfig->mutex.unlock(); } } @@ -413,20 +450,25 @@ QNetworkConfiguration& QNetworkSessionPrivateImpl::copyConfig(QNetworkConfigurat cpPriv = toIcdConfig(privateConfiguration(toConfig)); } - cpPriv->name = privateConfiguration(fromConfig)->name; - cpPriv->isValid = privateConfiguration(fromConfig)->isValid; + IcdNetworkConfigurationPrivate *fromPriv = toIcdConfig(privateConfiguration(fromConfig)); + + QMutexLocker toLocker(&cpPriv->mutex); + QMutexLocker fromLocker(&fromPriv->mutex); + + cpPriv->name = fromPriv->name; + cpPriv->isValid = fromPriv->isValid; // Note that we do not copy id field here as the publicConfig does // not contain a valid IAP id. - cpPriv->state = privateConfiguration(fromConfig)->state; - cpPriv->type = privateConfiguration(fromConfig)->type; - cpPriv->roamingSupported = privateConfiguration(fromConfig)->roamingSupported; - cpPriv->purpose = privateConfiguration(fromConfig)->purpose; - cpPriv->network_id = toIcdConfig(privateConfiguration(fromConfig))->network_id; - cpPriv->iap_type = toIcdConfig(privateConfiguration(fromConfig))->iap_type; - cpPriv->network_attrs = toIcdConfig(privateConfiguration(fromConfig))->network_attrs; - cpPriv->service_type = toIcdConfig(privateConfiguration(fromConfig))->service_type; - cpPriv->service_id = toIcdConfig(privateConfiguration(fromConfig))->service_id; - cpPriv->service_attrs = toIcdConfig(privateConfiguration(fromConfig))->service_attrs; + cpPriv->state = fromPriv->state; + cpPriv->type = fromPriv->type; + cpPriv->roamingSupported = fromPriv->roamingSupported; + cpPriv->purpose = fromPriv->purpose; + cpPriv->network_id = fromPriv->network_id; + cpPriv->iap_type = fromPriv->iap_type; + cpPriv->network_attrs = fromPriv->network_attrs; + cpPriv->service_type = fromPriv->service_type; + cpPriv->service_id = fromPriv->service_id; + cpPriv->service_attrs = fromPriv->service_attrs; return toConfig; } @@ -511,18 +553,30 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() * then do not update current state etc. */ if (publicConfig.type() == QNetworkConfiguration::UserChoice || - privateConfiguration(publicConfig)->id == state_results.first().params.network_id) { + publicConfig.identifier() == state_results.first().params.network_id) { switch (state_results.first().state) { case ICD_STATE_DISCONNECTED: state = QNetworkSession::Disconnected; - if (privateConfiguration(activeConfig)) - privateConfiguration(activeConfig)->isValid = true; + { + QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig); + if (ptr) { + ptr->mutex.lock(); + ptr->isValid = true; + ptr->mutex.unlock(); + } + } break; case ICD_STATE_CONNECTING: state = QNetworkSession::Connecting; - if (privateConfiguration(activeConfig)) - privateConfiguration(activeConfig)->isValid = true; + { + QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig); + if (ptr) { + ptr->mutex.lock(); + ptr->isValid = true; + ptr->mutex.unlock(); + } + } break; case ICD_STATE_CONNECTED: { @@ -540,6 +594,8 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig); + QMutexLocker configLocker(&ptr->mutex); + state = QNetworkSession::Connected; toIcdConfig(ptr)->network_id = state_results.first().params.network_id; ptr->id = toIcdConfig(ptr)->network_id; @@ -553,26 +609,35 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() ptr->isValid = true; currentNetworkInterface = get_network_interface(); - Maemo::IAPConf iap_name(privateConfiguration(activeConfig)->id); + Maemo::IAPConf iap_name(ptr->id); QString name_value = iap_name.value("name").toString(); if (!name_value.isEmpty()) - privateConfiguration(activeConfig)->name = name_value; + ptr->name = name_value; else - privateConfiguration(activeConfig)->name = privateConfiguration(activeConfig)->id; + ptr->name = ptr->id; // Add the new active configuration to manager or update the old config - if (!engine->hasIdentifier(privateConfiguration(activeConfig)->id)) - engine->addSessionConfiguration(privateConfiguration(activeConfig)); - else - engine->changedSessionConfiguration(privateConfiguration(activeConfig)); - } + if (!engine->hasIdentifier(ptr->id)) { + configLocker.unlock(); + engine->addSessionConfiguration(ptr); + } else { + configLocker.unlock(); + engine->changedSessionConfiguration(ptr); + } + } break; case ICD_STATE_DISCONNECTING: state = QNetworkSession::Closing; - if (privateConfiguration(activeConfig)) - privateConfiguration(activeConfig)->isValid = true; + { + QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig); + if (ptr) { + ptr->mutex.lock(); + ptr->isValid = true; + ptr->mutex.unlock(); + } + } break; default: break; @@ -634,12 +699,16 @@ void QNetworkSessionPrivateImpl::updateStateFromServiceNetwork() void QNetworkSessionPrivateImpl::clearConfiguration(QNetworkConfiguration &config) { - toIcdConfig(privateConfiguration(config))->network_id.clear(); - toIcdConfig(privateConfiguration(config))->iap_type.clear(); - toIcdConfig(privateConfiguration(config))->network_attrs = 0; - toIcdConfig(privateConfiguration(config))->service_type.clear(); - toIcdConfig(privateConfiguration(config))->service_id.clear(); - toIcdConfig(privateConfiguration(config))->service_attrs = 0; + IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config)); + + QMutexLocker locker(&icdConfig->mutex); + + icdConfig->network_id.clear(); + icdConfig->iap_type.clear(); + icdConfig->network_attrs = 0; + icdConfig->service_type.clear(); + icdConfig->service_id.clear(); + icdConfig->service_attrs = 0; } @@ -649,8 +718,8 @@ void QNetworkSessionPrivateImpl::updateStateFromActiveConfig() bool newActive = false; - if (!privateConfiguration(activeConfig)) - return; + if (!activeConfig.isValid()) + return; if (!activeConfig.isValid()) { state = QNetworkSession::Invalid; @@ -837,16 +906,21 @@ void QNetworkSessionPrivateImpl::do_open() QList<Maemo::ConnectParams> params; Maemo::ConnectParams param; - param.connect.service_type = toIcdConfig(privateConfiguration(config))->service_type; - param.connect.service_attrs = toIcdConfig(privateConfiguration(config))->service_attrs; - param.connect.service_id = toIcdConfig(privateConfiguration(config))->service_id; - param.connect.network_type = toIcdConfig(privateConfiguration(config))->iap_type; - param.connect.network_attrs = toIcdConfig(privateConfiguration(config))->network_attrs; - if (toIcdConfig(privateConfiguration(config))->network_attrs & ICD_NW_ATTR_IAPNAME) + + IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config)); + + icdConfig->mutex.lock(); + param.connect.service_type = icdConfig->service_type; + param.connect.service_attrs = icdConfig->service_attrs; + param.connect.service_id = icdConfig->service_id; + param.connect.network_type = icdConfig->iap_type; + param.connect.network_attrs = icdConfig->network_attrs; + if (icdConfig->network_attrs & ICD_NW_ATTR_IAPNAME) param.connect.network_id = QByteArray(iap.toLatin1()); else - param.connect.network_id = toIcdConfig(privateConfiguration(config))->network_id; + param.connect.network_id = icdConfig->network_id; params.append(param); + icdConfig->mutex.unlock(); #ifdef BEARER_MANAGEMENT_DEBUG qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s", @@ -887,26 +961,30 @@ void QNetworkSessionPrivateImpl::do_open() return; } + IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config)); /* Did we connect to non saved IAP? */ - if (!(toIcdConfig(privateConfiguration(config))->network_attrs & ICD_NW_ATTR_IAPNAME)) { + icdConfig->mutex.lock(); + if (!(icdConfig->network_attrs & ICD_NW_ATTR_IAPNAME)) { /* Because the connection succeeded, the IAP is now known. */ - toIcdConfig(privateConfiguration(config))->network_attrs |= ICD_NW_ATTR_IAPNAME; - privateConfiguration(config)->id = connected_iap; + icdConfig->network_attrs |= ICD_NW_ATTR_IAPNAME; + icdConfig->id = connected_iap; } /* User might have changed the IAP name when a new IAP was saved */ - Maemo::IAPConf iap_name(privateConfiguration(config)->id); + Maemo::IAPConf iap_name(icdConfig->id); QString name = iap_name.value("name").toString(); if (!name.isEmpty()) - privateConfiguration(config)->name = name; + icdConfig->name = name; + + icdConfig->iap_type = connect_result.connect.network_type; - toIcdConfig(privateConfiguration(config))->iap_type = connect_result.connect.network_type; + icdConfig->isValid = true; + icdConfig->state = QNetworkConfiguration::Active; + icdConfig->type = QNetworkConfiguration::InternetAccessPoint; - privateConfiguration(config)->isValid = true; - privateConfiguration(config)->state = QNetworkConfiguration::Active; - privateConfiguration(config)->type = QNetworkConfiguration::InternetAccessPoint; + icdConfig->mutex.unlock(); startTime = QDateTime::currentDateTime(); updateState(QNetworkSession::Connected); @@ -995,8 +1073,11 @@ void QNetworkSessionPrivateImpl::stop() * configurationChanged is emitted (below). */ - privateConfiguration(activeConfig)->state = QNetworkConfiguration::Discovered; - engine->changedSessionConfiguration(privateConfiguration(activeConfig)); + QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig); + ptr->mutex.lock(); + ptr->state = QNetworkConfiguration::Discovered; + ptr->mutex.unlock(); + engine->changedSessionConfiguration(ptr); opened = false; isOpen = false; diff --git a/src/plugins/bearer/nativewifi/qnativewifiengine.cpp b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp index b6522ad..6c74159 100644 --- a/src/plugins/bearer/nativewifi/qnativewifiengine.cpp +++ b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp @@ -185,6 +185,8 @@ void QNativeWifiEngine::scanComplete() bool changed = false; + ptr->mutex.lock(); + if (!ptr->isValid) { ptr->isValid = true; changed = true; @@ -200,8 +202,13 @@ void QNativeWifiEngine::scanComplete() changed = true; } - if (changed) + ptr->mutex.unlock(); + + if (changed) { + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } } else { QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); @@ -214,7 +221,9 @@ void QNativeWifiEngine::scanComplete() accessPointConfigurations.insert(id, ptr); + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); } } @@ -227,9 +236,12 @@ void QNativeWifiEngine::scanComplete() QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(previous.takeFirst()); + locker.unlock(); emit configurationRemoved(ptr); + locker.relock(); } + locker.unlock(); emit updateCompleted(); } @@ -358,6 +370,7 @@ void QNativeWifiEngine::connectToId(const QString &id) #ifdef BEARER_MANAGEMENT_DEBUG qDebug("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); #endif + locker.unlock(); emit connectionError(id, InterfaceLookupError); return; } @@ -405,7 +418,9 @@ void QNativeWifiEngine::connectToId(const QString &id) #ifdef BEARER_MANAGEMENT_DEBUG qDebug("%s: WlanConnect failed with error %ld\n", __FUNCTION__, result); #endif + locker.unlock(); emit connectionError(id, ConnectError); + locker.relock(); break; } @@ -415,8 +430,10 @@ void QNativeWifiEngine::connectToId(const QString &id) local_WlanFreeMemory(interfaceList); - if (profile.isEmpty()) + if (profile.isEmpty()) { + locker.unlock(); emit connectionError(id, InterfaceLookupError); + } } void QNativeWifiEngine::disconnectFromId(const QString &id) @@ -426,6 +443,7 @@ void QNativeWifiEngine::disconnectFromId(const QString &id) QString interface = getInterfaceFromId(id); if (interface.isEmpty()) { + locker.unlock(); emit connectionError(id, InterfaceLookupError); return; } @@ -446,6 +464,7 @@ void QNativeWifiEngine::disconnectFromId(const QString &id) #ifdef BEARER_MANAGEMENT_DEBUG qDebug("%s: WlanDisconnect failed with error %ld\n", __FUNCTION__, result); #endif + locker.unlock(); emit connectionError(id, DisconnectionError); return; } diff --git a/src/plugins/bearer/nativewifi/qnativewifiengine.h b/src/plugins/bearer/nativewifi/qnativewifiengine.h index 56489b6..2005b2b 100644 --- a/src/plugins/bearer/nativewifi/qnativewifiengine.h +++ b/src/plugins/bearer/nativewifi/qnativewifiengine.h @@ -78,7 +78,7 @@ public: void connectToId(const QString &id); void disconnectFromId(const QString &id); - void requestUpdate(); + Q_INVOKABLE void requestUpdate(); QNetworkSession::State sessionStateForId(const QString &id); diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp index 0fa8f3c..d7e315a 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp @@ -297,10 +297,17 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (ptr) { + ptr->mutex.lock(); if (activeConnection->state() == 2 && ptr->state != QNetworkConfiguration::Active) { ptr->state = QNetworkConfiguration::Active; + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } else { + ptr->mutex.unlock(); } } } @@ -313,9 +320,16 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(identifiers.takeFirst()); + ptr->mutex.lock(); if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { ptr->state = QNetworkConfiguration::Discovered; + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } else { + ptr->mutex.unlock(); } } } @@ -339,10 +353,17 @@ void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QString &pat QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (ptr) { + ptr->mutex.lock(); if (activeConnection->state() == 2 && ptr->state != QNetworkConfiguration::Active) { ptr->state = QNetworkConfiguration::Active; + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } else { + ptr->mutex.unlock(); } } } @@ -424,6 +445,8 @@ void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path, QNetworkConfigurationPrivatePointer ptr(cpPriv); accessPointConfigurations.insert(ptr->id, ptr); + + locker.unlock(); emit configurationAdded(ptr); } @@ -444,7 +467,8 @@ void QNetworkManagerEngine::removeConnection(const QString &path) connection->connectionInterface()->path())); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(id); - ptr->isValid = false; + + locker.unlock(); emit configurationRemoved(ptr); } @@ -476,11 +500,16 @@ void QNetworkManagerEngine::updateConnection(const QNmSettingsMap &settings) QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id); + ptr->mutex.lock(); + ptr->isValid = cpPriv->isValid; ptr->name = cpPriv->name; ptr->id = cpPriv->id; ptr->state = cpPriv->state; + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); delete cpPriv; } @@ -500,10 +529,17 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher) QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); if (ptr) { + ptr->mutex.lock(); if (activeConnection.state() == 2 && ptr->state != QNetworkConfiguration::Active) { ptr->state = QNetworkConfiguration::Active; + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } else { + ptr->mutex.unlock(); } } } @@ -543,7 +579,11 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjec QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(connectionId); + ptr->mutex.lock(); ptr->state = QNetworkConfiguration::Discovered; + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); return; } @@ -562,6 +602,8 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjec ptr->bearer = QLatin1String("WLAN"); accessPointConfigurations.insert(ptr->id, ptr); + + locker.unlock(); emit configurationAdded(ptr); } @@ -592,7 +634,11 @@ void QNetworkManagerEngine::removeAccessPoint(const QString &path, QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(connectionId); + ptr->mutex.lock(); ptr->state = QNetworkConfiguration::Defined; + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); return; } @@ -601,8 +647,11 @@ void QNetworkManagerEngine::removeAccessPoint(const QString &path, QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(QString::number(qHash(objectPath.path()))); - if (ptr) + if (ptr) { + locker.unlock(); emit configurationRemoved(ptr); + locker.relock(); + } } delete accessPoint; @@ -633,7 +682,11 @@ void QNetworkManagerEngine::updateAccessPoint(const QMap<QString, QVariant> &map QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(connectionId); + ptr->mutex.lock(); ptr->state = QNetworkConfiguration::Discovered; + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); return; } @@ -687,7 +740,10 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri QString::number(qHash(accessPoints.at(i)->connectionInterface()->path())); QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(accessPointId); + + locker.unlock(); emit configurationRemoved(ptr); + locker.relock(); } break; } diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h index ca1f857..05a1429 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h @@ -80,7 +80,7 @@ public: void connectToId(const QString &id); void disconnectFromId(const QString &id); - void requestUpdate(); + Q_INVOKABLE void requestUpdate(); QNetworkSession::State sessionStateForId(const QString &id); diff --git a/src/plugins/bearer/nla/qnlaengine.cpp b/src/plugins/bearer/nla/qnlaengine.cpp index 334eb14..9ab9924 100644 --- a/src/plugins/bearer/nla/qnlaengine.cpp +++ b/src/plugins/bearer/nla/qnlaengine.cpp @@ -522,6 +522,8 @@ void QNlaEngine::networksChanged() bool changed = false; + ptr->mutex.lock(); + if (ptr->isValid != cpPriv->isValid) { ptr->isValid = cpPriv->isValid; changed = true; @@ -537,8 +539,13 @@ void QNlaEngine::networksChanged() changed = true; } - if (changed) + ptr->mutex.unlock(); + + if (changed) { + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + } delete cpPriv; } else { @@ -546,7 +553,9 @@ void QNlaEngine::networksChanged() accessPointConfigurations.insert(ptr->id, ptr); + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); } } @@ -554,9 +563,12 @@ void QNlaEngine::networksChanged() QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(previous.takeFirst()); + locker.unlock(); emit configurationRemoved(ptr); + locker.relock(); } + locker.unlock(); emit updateCompleted(); } diff --git a/src/plugins/bearer/nla/qnlaengine.h b/src/plugins/bearer/nla/qnlaengine.h index 14c5201..1d49464 100644 --- a/src/plugins/bearer/nla/qnlaengine.h +++ b/src/plugins/bearer/nla/qnlaengine.h @@ -90,7 +90,7 @@ public: void connectToId(const QString &id); void disconnectFromId(const QString &id); - void requestUpdate(); + Q_INVOKABLE void requestUpdate(); QNetworkSession::State sessionStateForId(const QString &id); diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index bec562d..0737942 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -100,7 +100,7 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl() void QNetworkSessionPrivateImpl::syncStateWithInterface() { - if (!privateConfiguration(publicConfig)) + if (!publicConfig.isValid()) return; // Start monitoring changes in IAP states @@ -143,9 +143,8 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() // There were no open connections to used IAP or SNAP if (iError == QNetworkSession::InvalidConfigurationError) { newState(QNetworkSession::Invalid); - } - else if ((privateConfiguration(publicConfig)->state & QNetworkConfiguration::Discovered) == - QNetworkConfiguration::Discovered) { + } else if ((publicConfig.state() & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { newState(QNetworkSession::Disconnected); } else { newState(QNetworkSession::NotAvailable); @@ -293,10 +292,15 @@ void QNetworkSessionPrivateImpl::open() for (TUint i=1; i<=count; i++) { // Note: GetConnectionInfo expects 1-based index. if (iConnection.GetConnectionInfo(i, connInfo) == KErrNone) { - if (connInfo().iIapId == toSymbianConfig(privateConfiguration(publicConfig))->numericId) { + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(publicConfig)); + + QMutexLocker configLocker(&symbianConfig->mutex); + + if (connInfo().iIapId == symbianConfig->numericId) { if (iConnection.Attach(connInfo, RConnection::EAttachTypeNormal) == KErrNone) { activeConfig = publicConfig; - activeInterface = interface(toSymbianConfig(privateConfiguration(activeConfig))->numericId); + activeInterface = interface(symbianConfig->numericId); connected = ETrue; startTime = QDateTime::currentDateTime(); if (iDynamicSetdefaultif) { @@ -320,7 +324,12 @@ void QNetworkSessionPrivateImpl::open() if (!connected) { TCommDbConnPref pref; pref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); - pref.SetIapId(toSymbianConfig(privateConfiguration(publicConfig))->numericId); + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(publicConfig)); + + symbianConfig->mutex.lock(); + pref.SetIapId(symbianConfig->numericId); + symbianConfig->mutex.unlock(); iConnection.Start(pref, iStatus); if (!IsActive()) { SetActive(); @@ -328,7 +337,12 @@ void QNetworkSessionPrivateImpl::open() newState(QNetworkSession::Connecting); } } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { - TConnSnapPref snapPref(toSymbianConfig(privateConfiguration(publicConfig))->numericId); + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(publicConfig)); + + symbianConfig->mutex.lock(); + TConnSnapPref snapPref(symbianConfig->numericId); + symbianConfig->mutex.unlock(); iConnection.Start(snapPref, iStatus); if (!IsActive()) { SetActive(); @@ -387,7 +401,13 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals) return; } - TUint activeIap = toSymbianConfig(privateConfiguration(activeConfig))->numericId; + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(activeConfig)); + + symbianConfig->mutex.lock(); + TUint activeIap = symbianConfig->numericId; + symbianConfig->mutex.unlock(); + isOpen = false; activeConfig = QNetworkConfiguration(); serviceConfig = QNetworkConfiguration(); @@ -501,7 +521,13 @@ void QNetworkSessionPrivateImpl::PreferredCarrierAvailable(TAccessPointInfo aOld iALRUpgradingConnection = aIsUpgrade; QList<QNetworkConfiguration> configs = publicConfig.children(); for (int i=0; i < configs.count(); i++) { - if (toSymbianConfig(privateConfiguration(configs[i]))->numericId == aNewAPInfo.AccessPoint()) { + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(configs[i])); + + QMutexLocker configLocker(&symbianConfig->mutex); + + if (symbianConfig->numericId == aNewAPInfo.AccessPoint()) { + configLocker.unlock(); emit preferredConfigurationChanged(configs[i], aIsSeamless); } } @@ -625,13 +651,24 @@ quint64 QNetworkSessionPrivateImpl::transferredData(TUint dataType) const if (config.type() == QNetworkConfiguration::ServiceNetwork) { QList<QNetworkConfiguration> configs = config.children(); for (int i=0; i < configs.count(); i++) { - if (toSymbianConfig(privateConfiguration(configs[i]))->numericId == apId) { + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(configs[i])); + + QMutexLocker configLocker(&symbianConfig->mutex); + + if (symbianConfig->numericId == apId) { configFound = true; break; } } - } else if (toSymbianConfig(privateConfiguration(config))->numericId == apId) { - configFound = true; + } else { + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(config)); + + symbianConfig->mutex.lock(); + if (symbianConfig->numericId == apId) + configFound = true; + symbianConfig->mutex.unlock(); } if (configFound) { TUint tData; @@ -668,9 +705,12 @@ QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 ia // Try to search IAP from the used SNAP using IAP Id QList<QNetworkConfiguration> children = publicConfig.children(); for (int i=0; i < children.count(); i++) { - if (toSymbianConfig(privateConfiguration(children[i]))->numericId == iapId) { + SymbianNetworkConfigurationPrivate *childConfig = + toSymbianConfig(privateConfiguration(children[i])); + + QMutexLocker childLocker(&childConfig->mutex); + if (childConfig->numericId == iapId) return children[i]; - } } // Given IAP Id was not found from the used SNAP @@ -682,10 +722,21 @@ QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 ia // <=> Note: It's possible that in this case reported IAP is // clone of the one of the IAPs of the used SNAP // => If mappingName matches, clone has been found - QNetworkConfiguration pt = QNetworkConfigurationManager().configurationFromIdentifier(QString::number(qHash(iapId))); - if (privateConfiguration(pt)) { + QNetworkConfiguration pt = QNetworkConfigurationManager() + .configurationFromIdentifier(QString::number(qHash(iapId))); + + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(pt)); + if (symbianConfig) { + QMutexLocker configLocker(&symbianConfig->mutex); + for (int i=0; i < children.count(); i++) { - if (toSymbianConfig(privateConfiguration(children[i]))->mappingName == toSymbianConfig(privateConfiguration(pt))->mappingName) { + SymbianNetworkConfigurationPrivate *childConfig = + toSymbianConfig(privateConfiguration(children[i])); + + QMutexLocker childLocker(&childConfig->mutex); + + if (childConfig->mappingName == symbianConfig->mappingName) { return children[i]; } } @@ -776,13 +827,21 @@ void QNetworkSessionPrivateImpl::RunL() iMobility = CActiveCommsMobilityApiExt::NewL(iConnection, *this); } #endif + isOpen = true; activeConfig = newActiveConfig; - activeInterface = interface(toSymbianConfig(privateConfiguration(activeConfig))->numericId); + + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(activeConfig)); + + symbianConfig->mutex.lock(); + activeInterface = interface(symbianConfig->numericId); if (publicConfig.type() == QNetworkConfiguration::UserChoice) { - serviceConfig = QNetworkConfigurationManager().configurationFromIdentifier(toSymbianConfig(privateConfiguration(activeConfig))->serviceNetworkPtr->id); + serviceConfig = QNetworkConfigurationManager() + .configurationFromIdentifier(symbianConfig->serviceNetworkPtr->id); } - + symbianConfig->mutex.unlock(); + startTime = QDateTime::currentDateTime(); newState(QNetworkSession::Connected); @@ -830,7 +889,14 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint if (isOpen && publicConfig.type() == QNetworkConfiguration::ServiceNetwork && newState == QNetworkSession::Connected) { activeConfig = activeConfiguration(accessPointId); - activeInterface = interface(toSymbianConfig(privateConfiguration(activeConfig))->numericId); + + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(activeConfig)); + + symbianConfig->mutex.lock(); + activeInterface = interface(symbianConfig->numericId); + symbianConfig->mutex.unlock(); + #ifdef SNAP_FUNCTIONALITY_AVAILABLE if (iDynamicSetdefaultif) { // Use name of the IAP to set default IAP @@ -880,13 +946,25 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint retVal = true; } else { if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { - if (toSymbianConfig(privateConfiguration(publicConfig))->numericId == accessPointId) { + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(publicConfig)); + + QMutexLocker configLocker(&symbianConfig->mutex); + if (symbianConfig->numericId == accessPointId) { + configLocker.unlock(); + state = newState; emit stateChanged(state); retVal = true; } } else if (publicConfig.type() == QNetworkConfiguration::UserChoice && isOpen) { - if (toSymbianConfig(privateConfiguration(activeConfig))->numericId == accessPointId) { + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(activeConfig)); + + QMutexLocker configLocker(&symbianConfig->mutex); + if (symbianConfig->numericId == accessPointId) { + configLocker.unlock(); + state = newState; emit stateChanged(state); retVal = true; @@ -894,11 +972,17 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { QList<QNetworkConfiguration> subConfigurations = publicConfig.children(); for (int i = 0; i < subConfigurations.count(); i++) { - if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->numericId == accessPointId) { + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(subConfigurations[i])); + + QMutexLocker configLocker(&symbianConfig->mutex); + + if (symbianConfig->numericId == accessPointId) { if (newState == QNetworkSession::Connected) { // Make sure that when AccessPoint is reported to be Connected // also state of the related configuration changes to Active. - privateConfiguration(subConfigurations[i])->state = QNetworkConfiguration::Active; + symbianConfig->state = QNetworkConfiguration::Active; + configLocker.unlock(); state = newState; emit stateChanged(state); @@ -907,11 +991,14 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint if (newState == QNetworkSession::Disconnected) { // Make sure that when AccessPoint is reported to be disconnected // also state of the related configuration changes from Active to Defined. - privateConfiguration(subConfigurations[i])->state = QNetworkConfiguration::Defined; + symbianConfig->state = QNetworkConfiguration::Defined; } QNetworkConfiguration config = bestConfigFromSNAP(publicConfig); if ((config.state() == QNetworkConfiguration::Defined) || (config.state() == QNetworkConfiguration::Discovered)) { + + configLocker.unlock(); + state = newState; emit stateChanged(state); retVal = true; @@ -1033,15 +1120,24 @@ void QNetworkSessionPrivateImpl::EventL(const CConnMonEventBase& aEvent) if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { QList<QNetworkConfiguration> subConfigurations = publicConfig.children(); for (int i = 0; i < subConfigurations.count(); i++ ) { - if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId == connectionId) { - apId = toSymbianConfig(privateConfiguration(subConfigurations[i]))->numericId; + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(subConfigurations[i])); + + QMutexLocker configLocker(&symbianConfig->mutex); + + if (symbianConfig->connectionId == connectionId) { + apId = symbianConfig->numericId; break; } } } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { - if (toSymbianConfig(privateConfiguration(publicConfig))->connectionId == connectionId) { - apId = toSymbianConfig(privateConfiguration(publicConfig))->numericId; - } + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(publicConfig)); + + symbianConfig->mutex.lock(); + if (symbianConfig->connectionId == connectionId) + apId = symbianConfig->numericId; + symbianConfig->mutex.unlock(); } if (apId > 0) { @@ -1064,15 +1160,24 @@ void QNetworkSessionPrivateImpl::EventL(const CConnMonEventBase& aEvent) if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { QList<QNetworkConfiguration> subConfigurations = publicConfig.children(); for (int i = 0; i < subConfigurations.count(); i++ ) { - if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->numericId == apId) { - toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId = connectionId; + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(subConfigurations[i])); + + QMutexLocker configLocker(&symbianConfig->mutex); + + if (symbianConfig->numericId == apId) { + symbianConfig->connectionId = connectionId; break; } } } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { - if (toSymbianConfig(privateConfiguration(publicConfig))->numericId == apId) { - toSymbianConfig(privateConfiguration(publicConfig))->connectionId = connectionId; - } + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(publicConfig)); + + symbianConfig->mutex.lock(); + if (symbianConfig->numericId == apId) + symbianConfig->connectionId = connectionId; + symbianConfig->mutex.unlock(); } } } @@ -1087,15 +1192,24 @@ void QNetworkSessionPrivateImpl::EventL(const CConnMonEventBase& aEvent) if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { QList<QNetworkConfiguration> subConfigurations = publicConfig.children(); for (int i = 0; i < subConfigurations.count(); i++ ) { - if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId == connectionId) { - toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId = 0; + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(subConfigurations[i])); + + QMutexLocker configLocker(&symbianConfig->mutex); + + if (symbianConfig->connectionId == connectionId) { + symbianConfig->connectionId = 0; break; } } } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { - if (toSymbianConfig(privateConfiguration(publicConfig))->connectionId == connectionId) { - toSymbianConfig(privateConfiguration(publicConfig))->connectionId = 0; - } + SymbianNetworkConfigurationPrivate *symbianConfig = + toSymbianConfig(privateConfiguration(publicConfig)); + + symbianConfig->mutex.lock(); + if (symbianConfig->connectionId == connectionId) + symbianConfig->connectionId = 0; + symbianConfig->mutex.unlock(); } } break; diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp index 88a563c..980892a 100644 --- a/src/plugins/bearer/symbian/symbianengine.cpp +++ b/src/plugins/bearer/symbian/symbianengine.cpp @@ -75,6 +75,8 @@ SymbianNetworkConfigurationPrivate::~SymbianNetworkConfigurationPrivate() QString SymbianNetworkConfigurationPrivate::bearerName() const { + QMutexLocker locker(&mutex); + switch (bearer) { case BearerEthernet: return QLatin1String("Ethernet"); @@ -250,7 +252,10 @@ void SymbianEngine::updateConfigurationsL() if (error == KErrNone) { QNetworkConfigurationPrivatePointer ptr(cpPriv); accessPointConfigurations.insert(ptr->id, ptr); + + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); } } CleanupStack::PopAndDestroy(&connectionMethod); @@ -288,7 +293,10 @@ void SymbianEngine::updateConfigurationsL() QNetworkConfigurationPrivatePointer ptr(cpPriv); snapConfigurations.insert(ident, ptr); + + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); CleanupStack::Pop(cpPriv); } @@ -309,7 +317,11 @@ void SymbianEngine::updateConfigurationsL() QNetworkConfigurationPrivatePointer ptr(cpPriv); toSymbianConfig(ptr)->serviceNetworkPtr = privSNAP; accessPointConfigurations.insert(ptr->id, ptr); + + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); + privSNAP->serviceNetworkMembers.append(ptr); } } else { @@ -358,7 +370,9 @@ void SymbianEngine::updateConfigurationsL() QNetworkConfigurationPrivatePointer ptr(cpPriv); accessPointConfigurations.insert(ident, ptr); + locker.unlock(); emit configurationAdded(ptr); + locker.relock(); } else { delete cpPriv; } @@ -372,7 +386,10 @@ void SymbianEngine::updateConfigurationsL() foreach (const QString &oldIface, knownConfigs) { //remove non existing IAP QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldIface); + + locker.unlock(); emit configurationRemoved(ptr); + locker.relock(); // Remove non existing IAP from SNAPs foreach (const QString &iface, snapConfigurations.keys()) { @@ -391,7 +408,10 @@ void SymbianEngine::updateConfigurationsL() foreach (const QString &oldIface, knownSnapConfigs) { //remove non existing SNAPs QNetworkConfigurationPrivatePointer ptr = snapConfigurations.take(oldIface); + + locker.unlock(); emit configurationRemoved(ptr); + locker.relock(); } } @@ -596,7 +616,7 @@ QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfigurationL() } #endif - if (!ptr->isValid) { + if (!ptr || !ptr->isValid) { QString iface = QString::number(qHash(KUserChoiceIAPId)); ptr = userChoiceConfigurations.value(iface); } @@ -651,7 +671,9 @@ void SymbianEngine::updateActiveAccessPoints() if (iOnline != online) { iOnline = online; + locker.unlock(); emit this->onlineStateChanged(iOnline); + locker.relock(); } } @@ -704,7 +726,9 @@ void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapIn if (!iFirstUpdate) { startCommsDatabaseNotifications(); + locker.unlock(); emit updateCompleted(); + locker.relock(); } } @@ -746,10 +770,18 @@ bool SymbianEngine::changeConfigurationStateTo(QNetworkConfigurationPrivatePoint { QMutexLocker locker(&mutex); + ptr->mutex.lock(); if (newState != ptr->state) { ptr->state = newState; + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + return true; + } else { + ptr->mutex.unlock(); } return false; } @@ -763,10 +795,18 @@ bool SymbianEngine::changeConfigurationStateAtMinTo(QNetworkConfigurationPrivate { QMutexLocker locker(&mutex); + ptr->mutex.lock(); if ((newState | ptr->state) != ptr->state) { ptr->state = (ptr->state | newState); + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + return true; + } else { + ptr->mutex.unlock(); } return false; } @@ -781,10 +821,18 @@ bool SymbianEngine::changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivate { QMutexLocker locker(&mutex); + ptr->mutex.lock(); if ((newState & ptr->state) != ptr->state) { ptr->state = (newState & ptr->state); + ptr->mutex.unlock(); + + locker.unlock(); emit configurationChanged(ptr); + locker.relock(); + return true; + } else { + ptr->mutex.unlock(); } return false; } @@ -893,7 +941,10 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent) if (!iOnline) { iOnline = true; + + locker.unlock(); emit this->onlineStateChanged(iOnline); + locker.relock(); } } } @@ -923,7 +974,10 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent) } if (iOnline != online) { iOnline = online; + + locker.unlock(); emit this->onlineStateChanged(iOnline); + locker.relock(); } } break; diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h index ee6d070..e6af908 100644 --- a/src/plugins/bearer/symbian/symbianengine.h +++ b/src/plugins/bearer/symbian/symbianengine.h @@ -109,7 +109,7 @@ public: bool hasIdentifier(const QString &id); - void requestUpdate(); + Q_INVOKABLE void requestUpdate(); QNetworkConfigurationManager::Capabilities capabilities() const; diff --git a/src/script/api/qscriptcontextinfo.cpp b/src/script/api/qscriptcontextinfo.cpp index cc5fcc1..ebb1770 100644 --- a/src/script/api/qscriptcontextinfo.cpp +++ b/src/script/api/qscriptcontextinfo.cpp @@ -181,7 +181,7 @@ QScriptContextInfoPrivate::QScriptContextInfoPrivate(const QScriptContext *conte // Get the others informations: JSC::JSObject *callee = frame->callee(); if (callee && callee->inherits(&JSC::InternalFunction::info)) - functionName = JSC::asInternalFunction(callee)->name(&frame->globalData()); + functionName = JSC::asInternalFunction(callee)->name(frame); if (callee && callee->inherits(&JSC::JSFunction::info)) { functionType = QScriptContextInfo::ScriptFunction; JSC::FunctionExecutable *body = JSC::asFunction(callee)->jsExecutable(); diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 024b4d0..294c3a0 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -898,6 +898,8 @@ QScriptEnginePrivate::QScriptEnginePrivate() QScriptEnginePrivate::~QScriptEnginePrivate() { + JSC::setCurrentIdentifierTable(globalData->identifierTable); + //disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events QHash<intptr_t,QScript::UStringSourceProviderWithFeedback*>::const_iterator it; for (it = loadedScripts.constBegin(); it != loadedScripts.constEnd(); ++it) @@ -988,8 +990,7 @@ JSC::JSValue QScriptEnginePrivate::objectFromVariantMap(JSC::ExecState *exec, co QVariantMap QScriptEnginePrivate::variantMapFromObject(JSC::ExecState *exec, JSC::JSValue obj) { JSC::PropertyNameArray propertyNames(exec); - propertyNames.setShouldCache(false); - JSC::asObject(obj)->getOwnPropertyNames(exec, propertyNames, /*includeNonEnumerable=*/true); + JSC::asObject(obj)->getOwnPropertyNames(exec, propertyNames, JSC::IncludeDontEnumProperties); QVariantMap vmap; JSC::PropertyNameArray::const_iterator it = propertyNames.begin(); for( ; it != propertyNames.end(); ++it) @@ -1187,7 +1188,8 @@ bool QScriptEnginePrivate::isCollecting() const void QScriptEnginePrivate::collectGarbage() { JSC::JSLock lock(false); - globalData->heap.collect(); + QScript::APIShim shim(this); + globalData->heap.collectAllGarbage(); } QScript::TimeoutCheckerProxy *QScriptEnginePrivate::timeoutChecker() const @@ -1218,7 +1220,7 @@ JSC::JSValue QScriptEnginePrivate::evaluateHelper(JSC::ExecState *exec, intptr_t debugger->evaluateStart(sourceId); q->clearExceptions(); - JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject()); + JSC::DynamicGlobalObjectScope dynamicGlobalObjectScope(exec, exec->scopeChain()->globalObject); if (compile) { JSC::JSObject* error = executable->compile(exec, exec->scopeChain()); @@ -1670,15 +1672,15 @@ void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue object // deleting getter/setter if ((flags & QScriptValue::PropertyGetter) && (flags & QScriptValue::PropertySetter)) { // deleting both: just delete the property - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); + thisObject->deleteProperty(exec, id); } else if (flags & QScriptValue::PropertyGetter) { // preserve setter, if there is one - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); + thisObject->deleteProperty(exec, id); if (setter && setter.isObject()) thisObject->defineSetter(exec, id, JSC::asObject(setter)); } else { // flags & QScriptValue::PropertySetter // preserve getter, if there is one - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); + thisObject->deleteProperty(exec, id); if (getter && getter.isObject()) thisObject->defineGetter(exec, id, JSC::asObject(getter)); } @@ -1708,10 +1710,10 @@ void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue object } if (!value) { // ### check if it's a getter/setter property - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); + thisObject->deleteProperty(exec, id); } else if (flags != QScriptValue::KeepExistingFlags) { if (thisObject->hasOwnProperty(exec, id)) - thisObject->deleteProperty(exec, id, /*checkDontDelete=*/false); // ### hmmm - can't we just update the attributes? + thisObject->deleteProperty(exec, id); // ### hmmm - can't we just update the attributes? unsigned attribs = 0; if (flags & QScriptValue::ReadOnly) attribs |= JSC::ReadOnly; @@ -1732,7 +1734,7 @@ void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue object JSC::JSValue value, const QScriptValue::PropertyFlags &flags) { if (!value) { - JSC::asObject(objectValue)->deleteProperty(exec, index, /*checkDontDelete=*/false); + JSC::asObject(objectValue)->deleteProperty(exec, index); } else { if ((flags & QScriptValue::PropertyGetter) || (flags & QScriptValue::PropertySetter)) { // fall back to string-based setProperty(), since there is no @@ -1766,7 +1768,7 @@ QScriptValue::PropertyFlags QScriptEnginePrivate::propertyFlags(JSC::ExecState * JSC::PropertyDescriptor descriptor; if (object->getOwnPropertyDescriptor(exec, id, descriptor)) attribs = descriptor.attributes(); - else if (!object->getPropertyAttributes(exec, id, attribs)) { + else { if ((mode & QScriptValue::ResolvePrototype) && object->prototype() && object->prototype().isObject()) { JSC::JSValue proto = object->prototype(); return propertyFlags(exec, proto, id, mode); @@ -1793,6 +1795,15 @@ QScriptValue::PropertyFlags QScriptEnginePrivate::propertyFlags(JSC::ExecState * return result; } +QScriptString QScriptEnginePrivate::toStringHandle(const JSC::Identifier &name) +{ + QScriptString result; + QScriptStringPrivate *p = new QScriptStringPrivate(this, name, QScriptStringPrivate::HeapAllocated); + QScriptStringPrivate::init(result, p); + registerScriptString(p); + return result; +} + #ifdef QT_NO_QOBJECT QScriptEngine::QScriptEngine() @@ -2466,15 +2477,16 @@ QScriptSyntaxCheckResult QScriptEnginePrivate::checkSyntax(const QString &progra QScriptValue QScriptEngine::evaluate(const QString &program, const QString &fileName, int lineNumber) { Q_D(QScriptEngine); + QScript::APIShim shim(d); WTF::PassRefPtr<QScript::UStringSourceProviderWithFeedback> provider = QScript::UStringSourceProviderWithFeedback::create(program, fileName, lineNumber, d); intptr_t sourceId = provider->asID(); JSC::SourceCode source(provider, lineNumber); //after construction of SourceCode provider variable will be null. JSC::ExecState* exec = d->currentFrame; - JSC::EvalExecutable executable(exec, source); + WTF::RefPtr<JSC::EvalExecutable> executable = JSC::EvalExecutable::create(exec, source); bool compile = true; - return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, &executable, compile)); + return d->scriptValueFromJSCValue(d->evaluateHelper(exec, sourceId, executable.get(), compile)); } /*! @@ -2491,6 +2503,7 @@ QScriptValue QScriptEngine::evaluate(const QScriptProgram &program) if (!program_d) return QScriptValue(); + QScript::APIShim shim(d); JSC::ExecState* exec = d->currentFrame; JSC::EvalExecutable *executable = program_d->executable(exec, d); bool compile = !program_d->isCompiled; @@ -2603,7 +2616,7 @@ JSC::CallFrame *QScriptEnginePrivate::pushContext(JSC::CallFrame *exec, JSC::JSV newCallFrame->init(0, /*vPC=*/0, exec->scopeChain(), exec, flags | ShouldRestoreCallFrame, argc, callee); } else { JSC::JSObject *jscObject = originalGlobalObject(); - JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), jscObject); + JSC::ScopeChainNode *scn = new JSC::ScopeChainNode(0, jscObject, &exec->globalData(), exec->lexicalGlobalObject(), jscObject); newCallFrame->init(0, /*vPC=*/0, scn, exec, flags | ShouldRestoreCallFrame, argc, callee); } } else { @@ -2935,7 +2948,7 @@ JSC::JSValue QScriptEnginePrivate::create(JSC::ExecState *exec, int type, const } } if (result && result.isObject() && info && info->prototype - && JSC::JSValue::strictEqual(JSC::asObject(result)->prototype(), eng->originalGlobalObject()->objectPrototype())) { + && JSC::JSValue::strictEqual(exec, JSC::asObject(result)->prototype(), eng->originalGlobalObject()->objectPrototype())) { JSC::asObject(result)->setPrototype(info->prototype); } return result; @@ -4050,11 +4063,8 @@ QScriptEngineAgent *QScriptEngine::agent() const QScriptString QScriptEngine::toStringHandle(const QString &str) { Q_D(QScriptEngine); - QScriptString result; - QScriptStringPrivate *p = new QScriptStringPrivate(d, JSC::Identifier(d->currentFrame, str), QScriptStringPrivate::HeapAllocated); - QScriptStringPrivate::init(result, p); - d->registerScriptString(p); - return result; + QScript::APIShim shim(d); + return d->toStringHandle(JSC::Identifier(d->currentFrame, str)); } /*! diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h index 5166d89..47e5d8a 100644 --- a/src/script/api/qscriptengine_p.h +++ b/src/script/api/qscriptengine_p.h @@ -279,6 +279,7 @@ public: inline void registerScriptString(QScriptStringPrivate *value); inline void unregisterScriptString(QScriptStringPrivate *value); void detachAllRegisteredScriptStrings(); + QScriptString toStringHandle(const JSC::Identifier &name); static inline JSC::JSValue newArray(JSC::ExecState *, uint length); static inline JSC::JSValue newDate(JSC::ExecState *, qsreal value); @@ -383,6 +384,23 @@ public: namespace QScript { +class APIShim +{ +public: + APIShim(QScriptEnginePrivate *engine) + : m_engine(engine), m_oldTable(JSC::setCurrentIdentifierTable(engine->globalData->identifierTable)) + { + } + ~APIShim() + { + JSC::setCurrentIdentifierTable(m_oldTable); + } + +private: + QScriptEnginePrivate *m_engine; + JSC::IdentifierTable *m_oldTable; +}; + /*Helper class. Main purpose is to give debugger feedback about unloading and loading scripts. It keeps pointer to JSGlobalObject assuming that it is always the same - there is no way to update this data. Class is internal and used as an implementation detail in and only in QScriptEngine::evaluate.*/ @@ -685,17 +703,17 @@ inline void QScriptEnginePrivate::setProperty(JSC::ExecState *exec, JSC::JSValue setProperty(exec, objectValue, JSC::Identifier(exec, name), value, flags); } -inline JSC::JSValue QScriptValuePrivate::property(const JSC::Identifier &id, int resolveMode) const +inline JSC::JSValue QScriptValuePrivate::property(const JSC::Identifier &id, const QScriptValue::ResolveFlags &resolveMode) const { return QScriptEnginePrivate::property(engine->currentFrame, jscValue, id, resolveMode); } -inline JSC::JSValue QScriptValuePrivate::property(quint32 index, int resolveMode) const +inline JSC::JSValue QScriptValuePrivate::property(quint32 index, const QScriptValue::ResolveFlags &resolveMode) const { return QScriptEnginePrivate::property(engine->currentFrame, jscValue, index, resolveMode); } -inline JSC::JSValue QScriptValuePrivate::property(const JSC::UString &name, int resolveMode) const +inline JSC::JSValue QScriptValuePrivate::property(const JSC::UString &name, const QScriptValue::ResolveFlags &resolveMode) const { JSC::ExecState *exec = engine->currentFrame; return QScriptEnginePrivate::property(exec, jscValue, JSC::Identifier(exec, name), resolveMode); @@ -779,6 +797,7 @@ inline void QScriptEnginePrivate::unregisterScriptString(QScriptStringPrivate *v registeredScriptStrings = value->next; value->prev = 0; value->next = 0; + JSC::setCurrentIdentifierTable(globalData->identifierTable); } inline QScriptContext *QScriptEnginePrivate::contextForFrame(JSC::ExecState *frame) diff --git a/src/script/api/qscriptengineagent.cpp b/src/script/api/qscriptengineagent.cpp index 3bd97eb..28905e8 100644 --- a/src/script/api/qscriptengineagent.cpp +++ b/src/script/api/qscriptengineagent.cpp @@ -151,14 +151,15 @@ void QScriptEngineAgentPrivate::exceptionCatch(const JSC::DebuggerCallFrame& fra engine->clearCurrentException(); } -void QScriptEngineAgentPrivate::atStatement(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno, int column) +void QScriptEngineAgentPrivate::atStatement(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno/*, int column*/) { QScript::UStringSourceProviderWithFeedback *source = engine->loadedScripts.value(sourceID); if (!source) { // QTBUG-6108: We don't have the source for this script, so ignore. return; } - column = source->columnNumberFromOffset(column); +// column = source->columnNumberFromOffset(column); + int column = 1; JSC::CallFrame *oldFrame = engine->currentFrame; int oldAgentLineNumber = engine->agentLineNumber; engine->currentFrame = frame.callFrame(); @@ -182,7 +183,7 @@ void QScriptEngineAgentPrivate::evaluateStop(const JSC::JSValue& returnValue, in } void QScriptEngineAgentPrivate::didReachBreakpoint(const JSC::DebuggerCallFrame& frame, - intptr_t sourceID, int lineno, int column) + intptr_t sourceID, int lineno/*, int column*/) { if (q_ptr->supportsExtension(QScriptEngineAgent::DebuggerInvocationRequest)) { QScript::UStringSourceProviderWithFeedback *source = engine->loadedScripts.value(sourceID); @@ -190,7 +191,8 @@ void QScriptEngineAgentPrivate::didReachBreakpoint(const JSC::DebuggerCallFrame& // QTBUG-6108: We don't have the source for this script, so ignore. return; } - column = source->columnNumberFromOffset(column); +// column = source->columnNumberFromOffset(column); + int column = 1; JSC::CallFrame *oldFrame = engine->currentFrame; int oldAgentLineNumber = engine->agentLineNumber; engine->currentFrame = frame.callFrame(); diff --git a/src/script/api/qscriptengineagent_p.h b/src/script/api/qscriptengineagent_p.h index 8354143..fd10e68 100644 --- a/src/script/api/qscriptengineagent_p.h +++ b/src/script/api/qscriptengineagent_p.h @@ -75,17 +75,18 @@ public: }; //exceptions - virtual void exception(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno) + virtual void exception(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno, bool hasHandler) { Q_UNUSED(frame); Q_UNUSED(sourceID); Q_UNUSED(lineno); + Q_UNUSED(hasHandler); }; virtual void exceptionThrow(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, bool hasHandler); virtual void exceptionCatch(const JSC::DebuggerCallFrame& frame, intptr_t sourceID); //statements - virtual void atStatement(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno, int column); + virtual void atStatement(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno/*, int column*/); virtual void callEvent(const JSC::DebuggerCallFrame&, intptr_t sourceID, int lineno) { Q_UNUSED(lineno); @@ -107,7 +108,7 @@ public: }; virtual void functionExit(const JSC::JSValue& returnValue, intptr_t sourceID); //others - virtual void didReachBreakpoint(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno, int column); + virtual void didReachBreakpoint(const JSC::DebuggerCallFrame& frame, intptr_t sourceID, int lineno/*, int column*/); virtual void evaluateStart(intptr_t sourceID) { diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index 414a45c..a3af2d4 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -898,18 +898,21 @@ bool QScriptValue::strictlyEquals(const QScriptValue &other) const if (d->type == QScriptValuePrivate::JavaScriptCore) { QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine; if (eng_p) - return JSC::JSValue::strictEqual(d->jscValue, eng_p->scriptValueToJSCValue(other)); + return JSC::JSValue::strictEqual(eng_p->currentFrame, d->jscValue, eng_p->scriptValueToJSCValue(other)); } else if (other.d_ptr->type == QScriptValuePrivate::JavaScriptCore) { QScriptEnginePrivate *eng_p = other.d_ptr->engine ? other.d_ptr->engine : d->engine; if (eng_p) - return JSC::JSValue::strictEqual(eng_p->scriptValueToJSCValue(*this), other.d_ptr->jscValue); + return JSC::JSValue::strictEqual(eng_p->currentFrame, eng_p->scriptValueToJSCValue(*this), other.d_ptr->jscValue); } return false; } switch (d->type) { - case QScriptValuePrivate::JavaScriptCore: - return JSC::JSValue::strictEqual(d->jscValue, other.d_ptr->jscValue); + case QScriptValuePrivate::JavaScriptCore: { + QScriptEnginePrivate *eng_p = d->engine ? d->engine : other.d_ptr->engine; + JSC::ExecState *exec = eng_p ? eng_p->currentFrame : 0; + return JSC::JSValue::strictEqual(exec, d->jscValue, other.d_ptr->jscValue); + } case QScriptValuePrivate::Number: return (d->numberValue == other.d_ptr->numberValue); case QScriptValuePrivate::String: @@ -1301,6 +1304,7 @@ void QScriptValue::setProperty(const QString &name, const QScriptValue &value, Q_D(QScriptValue); if (!d || !d->isObject()) return; + QScript::APIShim shim(d->engine); QScriptEnginePrivate *valueEngine = QScriptValuePrivate::getEngine(value); if (valueEngine && (valueEngine != d->engine)) { qWarning("QScriptValue::setProperty(%s) failed: " @@ -1333,6 +1337,7 @@ QScriptValue QScriptValue::property(const QString &name, Q_D(const QScriptValue); if (!d || !d->isObject()) return QScriptValue(); + QScript::APIShim shim(d->engine); return d->engine->scriptValueFromJSCValue(d->property(name, mode)); } @@ -1450,6 +1455,7 @@ QScriptValue::PropertyFlags QScriptValue::propertyFlags(const QString &name, Q_D(const QScriptValue); if (!d || !d->isObject()) return 0; + QScript::APIShim shim(d->engine); JSC::ExecState *exec = d->engine->currentFrame; return d->propertyFlags(JSC::Identifier(exec, name), mode); diff --git a/src/script/api/qscriptvalue_p.h b/src/script/api/qscriptvalue_p.h index 089b923..853c6c8 100644 --- a/src/script/api/qscriptvalue_p.h +++ b/src/script/api/qscriptvalue_p.h @@ -86,17 +86,18 @@ public: return q.d_ptr->engine; } - inline JSC::JSValue property(const JSC::Identifier &id, int resolveMode) const; - inline JSC::JSValue property(quint32 index, int resolveMode) const; - inline JSC::JSValue property(const JSC::UString &, int resolveMode) const; + inline JSC::JSValue property(const JSC::Identifier &id, + const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const; + inline JSC::JSValue property(quint32 index, const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const; + inline JSC::JSValue property(const JSC::UString &, const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const; inline void setProperty(const JSC::UString &name, const JSC::JSValue &value, - const QScriptValue::PropertyFlags &flags); + const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags); inline void setProperty(const JSC::Identifier &id, const JSC::JSValue &value, - const QScriptValue::PropertyFlags &flags); + const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags); inline void setProperty(quint32 index, const JSC::JSValue &value, - const QScriptValue::PropertyFlags &flags); + const QScriptValue::PropertyFlags &flags = QScriptValue::KeepExistingFlags); inline QScriptValue::PropertyFlags propertyFlags( - const JSC::Identifier &id, const QScriptValue::ResolveFlags &mode) const; + const JSC::Identifier &id, const QScriptValue::ResolveFlags &mode = QScriptValue::ResolvePrototype) const; void detachFromEngine(); diff --git a/src/script/api/qscriptvalueiterator.cpp b/src/script/api/qscriptvalueiterator.cpp index 24d9754..5c1e6f2 100644 --- a/src/script/api/qscriptvalueiterator.cpp +++ b/src/script/api/qscriptvalueiterator.cpp @@ -84,28 +84,38 @@ public: QScriptValueIteratorPrivate() : initialized(false) {} + + QScriptValuePrivate *object() const + { + return QScriptValuePrivate::get(objectValue); + } + + QScriptEnginePrivate *engine() const + { + return QScriptEnginePrivate::get(objectValue.engine()); + } + void ensureInitialized() { if (initialized) return; - QScriptEnginePrivate *eng_p = QScriptEnginePrivate::get(object.engine()); + QScriptEnginePrivate *eng_p = engine(); JSC::ExecState *exec = eng_p->globalExec(); JSC::PropertyNameArray propertyNamesArray(exec); - propertyNamesArray.setShouldCache(false); - JSC::asObject(QScriptValuePrivate::get(object)->jscValue)->getOwnPropertyNames(exec, propertyNamesArray, /*includeNonEnumerable=*/true); + JSC::asObject(object()->jscValue)->getOwnPropertyNames(exec, propertyNamesArray, JSC::IncludeDontEnumProperties); JSC::PropertyNameArray::const_iterator propertyNamesIt = propertyNamesArray.begin(); for(; propertyNamesIt != propertyNamesArray.end(); ++propertyNamesIt) { - propertyNames.append(propertyNamesIt->ustring()); + propertyNames.append(*propertyNamesIt); } it = propertyNames.begin(); initialized = true; } - QScriptValue object; - QLinkedList<JSC::UString> propertyNames; - QLinkedList<JSC::UString>::iterator it; - QLinkedList<JSC::UString>::iterator current; + QScriptValue objectValue; + QLinkedList<JSC::Identifier> propertyNames; + QLinkedList<JSC::Identifier>::iterator it; + QLinkedList<JSC::Identifier>::iterator current; bool initialized; }; @@ -119,7 +129,7 @@ QScriptValueIterator::QScriptValueIterator(const QScriptValue &object) { if (object.isObject()) { d_ptr.reset(new QScriptValueIteratorPrivate()); - d_ptr->object = object; + d_ptr->objectValue = object; } } @@ -240,9 +250,9 @@ void QScriptValueIterator::toBack() QString QScriptValueIterator::name() const { Q_D(const QScriptValueIterator); - if (!d || !d->initialized) + if (!d || !d->initialized || !d->engine()) return QString(); - return *d->current; + return d->current->ustring(); } /*! @@ -254,9 +264,9 @@ QString QScriptValueIterator::name() const QScriptString QScriptValueIterator::scriptName() const { Q_D(const QScriptValueIterator); - if (!d || !d->initialized) + if (!d || !d->initialized || !d->engine()) return QScriptString(); - return d->object.engine()->toStringHandle(name()); + return d->engine()->toStringHandle(*d->current); } /*! @@ -268,9 +278,10 @@ QScriptString QScriptValueIterator::scriptName() const QScriptValue QScriptValueIterator::value() const { Q_D(const QScriptValueIterator); - if (!d || !d->initialized) + if (!d || !d->initialized || !d->engine()) return QScriptValue(); - return d->object.property(name()); + JSC::JSValue jsValue = d->object()->property(*d->current); + return d->engine()->scriptValueFromJSCValue(jsValue); } /*! @@ -282,9 +293,10 @@ QScriptValue QScriptValueIterator::value() const void QScriptValueIterator::setValue(const QScriptValue &value) { Q_D(QScriptValueIterator); - if (!d || !d->initialized) + if (!d || !d->initialized || !d->engine()) return; - d->object.setProperty(name(), value); + JSC::JSValue jsValue = d->engine()->scriptValueToJSCValue(value); + d->object()->setProperty(*d->current, jsValue); } /*! @@ -296,9 +308,9 @@ void QScriptValueIterator::setValue(const QScriptValue &value) QScriptValue::PropertyFlags QScriptValueIterator::flags() const { Q_D(const QScriptValueIterator); - if (!d || !d->initialized) + if (!d || !d->initialized || !d->engine()) return 0; - return d->object.propertyFlags(name()); + return d->object()->propertyFlags(*d->current); } /*! @@ -310,9 +322,9 @@ QScriptValue::PropertyFlags QScriptValueIterator::flags() const void QScriptValueIterator::remove() { Q_D(QScriptValueIterator); - if (!d || !d->initialized) + if (!d || !d->initialized || !d->engine()) return; - d->object.setProperty(name(), QScriptValue()); + d->object()->setProperty(*d->current, JSC::JSValue()); d->propertyNames.erase(d->current); } @@ -326,7 +338,7 @@ QScriptValueIterator& QScriptValueIterator::operator=(QScriptValue &object) d_ptr.reset(); if (object.isObject()) { d_ptr.reset(new QScriptValueIteratorPrivate()); - d_ptr->object = object; + d_ptr->objectValue = object; } return *this; } diff --git a/src/script/bridge/qscriptactivationobject.cpp b/src/script/bridge/qscriptactivationobject.cpp index 7189f2e..6a8ae56 100644 --- a/src/script/bridge/qscriptactivationobject.cpp +++ b/src/script/bridge/qscriptactivationobject.cpp @@ -63,20 +63,20 @@ bool QScriptActivationObject::getOwnPropertySlot(JSC::ExecState* exec, const JSC return JSC::JSVariableObject::getOwnPropertySlot(exec, propertyName, slot); } -bool QScriptActivationObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, unsigned& attributes) const +bool QScriptActivationObject::getOwnPropertyDescriptor(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::PropertyDescriptor& descriptor) { if (d_ptr()->delegate != 0) - return d_ptr()->delegate->getPropertyAttributes(exec, propertyName, attributes); - return JSC::JSVariableObject::getPropertyAttributes(exec, propertyName, attributes); + return d_ptr()->delegate->getOwnPropertyDescriptor(exec, propertyName, descriptor); + return JSC::JSVariableObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); } -void QScriptActivationObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, bool includeNonEnumerable) +void QScriptActivationObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, JSC::EnumerationMode mode) { if (d_ptr()->delegate != 0) { - d_ptr()->delegate->getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + d_ptr()->delegate->getOwnPropertyNames(exec, propertyNames, mode); return; } - return JSC::JSVariableObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + return JSC::JSVariableObject::getOwnPropertyNames(exec, propertyNames, mode); } void QScriptActivationObject::putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes) @@ -111,11 +111,11 @@ void QScriptActivationObject::put(JSC::ExecState* exec, unsigned propertyName, J JSC::JSVariableObject::put(exec, propertyName, value); } -bool QScriptActivationObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName, bool checkDontDelete) +bool QScriptActivationObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName) { if (d_ptr()->delegate != 0) - return d_ptr()->delegate->deleteProperty(exec, propertyName, checkDontDelete); - return JSC::JSVariableObject::deleteProperty(exec, propertyName, checkDontDelete); + return d_ptr()->delegate->deleteProperty(exec, propertyName); + return JSC::JSVariableObject::deleteProperty(exec, propertyName); } void QScriptActivationObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction) diff --git a/src/script/bridge/qscriptactivationobject_p.h b/src/script/bridge/qscriptactivationobject_p.h index 7648a26..72ea11f 100644 --- a/src/script/bridge/qscriptactivationobject_p.h +++ b/src/script/bridge/qscriptactivationobject_p.h @@ -51,14 +51,14 @@ public: virtual bool isDynamicScope() const { return true; } virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); - virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, unsigned&) const; - virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, bool includeNonEnumerable = false); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&); + virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void putWithAttributes(JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, unsigned attributes); virtual void put(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot&); virtual void put(JSC::ExecState*, unsigned propertyName, JSC::JSValue value); - virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName, bool checkDontDelete = true); + virtual bool deleteProperty(JSC::ExecState*, const JSC::Identifier& propertyName); virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction); virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction); diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp index ce0a08e..a7b5f48 100644 --- a/src/script/bridge/qscriptclassobject.cpp +++ b/src/script/bridge/qscriptclassobject.cpp @@ -84,6 +84,47 @@ bool ClassObjectDelegate::getOwnPropertySlot(QScriptObject* object, return false; } +bool ClassObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, + JSC::ExecState *exec, + const JSC::Identifier &propertyName, + JSC::PropertyDescriptor &descriptor) +{ + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + QScript::SaveFrameHelper saveFrame(engine, exec); + // for compatibility with the old back-end, normal JS properties + // are queried first. + if (QScriptObjectDelegate::getOwnPropertyDescriptor(object, exec, propertyName, descriptor)) + return true; + + QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); + QScriptString scriptName; + QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); + QScriptStringPrivate::init(scriptName, &scriptName_d); + uint id = 0; + QScriptClass::QueryFlags qflags = m_scriptClass->queryProperty( + scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id); + if (qflags & QScriptClass::HandlesReadAccess) { + QScriptValue::PropertyFlags pflags = m_scriptClass->propertyFlags(scriptObject, scriptName, id); + unsigned attribs = 0; + if (pflags & QScriptValue::ReadOnly) + attribs |= JSC::ReadOnly; + if (pflags & QScriptValue::SkipInEnumeration) + attribs |= JSC::DontEnum; + if (pflags & QScriptValue::Undeletable) + attribs |= JSC::DontDelete; + if (pflags & QScriptValue::PropertyGetter) + attribs |= JSC::Getter; + if (pflags & QScriptValue::PropertySetter) + attribs |= JSC::Setter; + attribs |= pflags & QScriptValue::UserRange; + // Rather than calling the getter, we could return an access descriptor here. + QScriptValue value = m_scriptClass->property(scriptObject, scriptName, id); + descriptor.setDescriptor(engine->scriptValueToJSCValue(value), attribs); + return true; + } + return false; +} + void ClassObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, const JSC::Identifier &propertyName, JSC::JSValue value, JSC::PutPropertySlot &slot) @@ -105,8 +146,7 @@ void ClassObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, } bool ClassObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec, - const JSC::Identifier &propertyName, - bool checkDontDelete) + const JSC::Identifier &propertyName) { // ### avoid duplication of put() QScriptEnginePrivate *engine = scriptEngineFromExec(exec); @@ -124,44 +164,12 @@ bool ClassObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState * m_scriptClass->setProperty(scriptObject, scriptName, id, QScriptValue()); return true; } - return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete); -} - -bool ClassObjectDelegate::getPropertyAttributes(const QScriptObject* object, JSC::ExecState *exec, - const JSC::Identifier &propertyName, - unsigned &attribs) const -{ - QScriptEnginePrivate *engine = scriptEngineFromExec(exec); - QScript::SaveFrameHelper saveFrame(engine, exec); - QScriptValue scriptObject = engine->scriptValueFromJSCValue(object); - QScriptString scriptName; - QScriptStringPrivate scriptName_d(engine, propertyName, QScriptStringPrivate::StackAllocated); - QScriptStringPrivate::init(scriptName, &scriptName_d); - uint id = 0; - QScriptClass::QueryFlags flags = m_scriptClass->queryProperty( - scriptObject, scriptName, QScriptClass::HandlesReadAccess, &id); - if (flags & QScriptClass::HandlesReadAccess) { - QScriptValue::PropertyFlags flags = m_scriptClass->propertyFlags(scriptObject, scriptName, id); - attribs = 0; - if (flags & QScriptValue::ReadOnly) - attribs |= JSC::ReadOnly; - if (flags & QScriptValue::SkipInEnumeration) - attribs |= JSC::DontEnum; - if (flags & QScriptValue::Undeletable) - attribs |= JSC::DontDelete; - if (flags & QScriptValue::PropertyGetter) - attribs |= JSC::Getter; - if (flags & QScriptValue::PropertySetter) - attribs |= JSC::Setter; - attribs |= flags & QScriptValue::UserRange; - return true; - } - return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs); + return QScriptObjectDelegate::deleteProperty(object, exec, propertyName); } void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScript::SaveFrameHelper saveFrame(engine, exec); @@ -175,7 +183,7 @@ void ClassObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecSt } delete it; } - QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable); + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode); } JSC::CallType ClassObjectDelegate::getCallData(QScriptObject*, JSC::CallData &callData) diff --git a/src/script/bridge/qscriptclassobject_p.h b/src/script/bridge/qscriptclassobject_p.h index 89142ab..83fa61b 100644 --- a/src/script/bridge/qscriptclassobject_p.h +++ b/src/script/bridge/qscriptclassobject_p.h @@ -60,18 +60,17 @@ public: virtual bool getOwnPropertySlot(QScriptObject*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(QScriptObject*, JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor&); virtual void put(QScriptObject*, JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(QScriptObject*, JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, - const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*, diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp index 1d11ede..a753f59 100644 --- a/src/script/bridge/qscriptdeclarativeclass.cpp +++ b/src/script/bridge/qscriptdeclarativeclass.cpp @@ -141,19 +141,22 @@ QScriptValue QScriptDeclarativeClass::Value::toScriptValue(QScriptEngine *engine } QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier() -: identifier(0) + : identifier(0), engine(0) { new (&d) JSC::Identifier(); } QScriptDeclarativeClass::PersistentIdentifier::~PersistentIdentifier() { + if (engine) + JSC::setCurrentIdentifierTable(engine->globalData->identifierTable); ((JSC::Identifier &)d).JSC::Identifier::~Identifier(); } QScriptDeclarativeClass::PersistentIdentifier::PersistentIdentifier(const PersistentIdentifier &other) { identifier = other.identifier; + engine = other.engine; new (&d) JSC::Identifier((JSC::Identifier &)(other.d)); } @@ -161,6 +164,7 @@ QScriptDeclarativeClass::PersistentIdentifier & QScriptDeclarativeClass::PersistentIdentifier::operator=(const PersistentIdentifier &other) { identifier = other.identifier; + engine = other.engine; ((JSC::Identifier &)d) = (JSC::Identifier &)(other.d); return *this; } @@ -419,7 +423,7 @@ QScriptDeclarativeClass::createPersistentIdentifier(const QString &str) static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; - PersistentIdentifier rv(true); + PersistentIdentifier rv(p); new (&rv.d) JSC::Identifier(exec, (UChar *)str.constData(), str.size()); rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep(); return rv; @@ -432,7 +436,7 @@ QScriptDeclarativeClass::createPersistentIdentifier(const Identifier &id) static_cast<QScriptEnginePrivate *>(QObjectPrivate::get(d_ptr->engine)); JSC::ExecState* exec = p->currentFrame; - PersistentIdentifier rv(true); + PersistentIdentifier rv(p); new (&rv.d) JSC::Identifier(exec, (JSC::UString::Rep *)id); rv.identifier = (void *)((JSC::Identifier &)rv.d).ustring().rep(); return rv; diff --git a/src/script/bridge/qscriptdeclarativeclass_p.h b/src/script/bridge/qscriptdeclarativeclass_p.h index a0fd6d5..a187391 100644 --- a/src/script/bridge/qscriptdeclarativeclass_p.h +++ b/src/script/bridge/qscriptdeclarativeclass_p.h @@ -104,7 +104,8 @@ public: private: friend class QScriptDeclarativeClass; - PersistentIdentifier(bool) : identifier(0), d(0) {} + PersistentIdentifier(QScriptEnginePrivate *e) : identifier(0), engine(e), d(0) {} + QScriptEnginePrivate *engine; void *d; }; diff --git a/src/script/bridge/qscriptdeclarativeobject.cpp b/src/script/bridge/qscriptdeclarativeobject.cpp index c6ab6a7..a45bfbb 100644 --- a/src/script/bridge/qscriptdeclarativeobject.cpp +++ b/src/script/bridge/qscriptdeclarativeobject.cpp @@ -66,7 +66,6 @@ bool DeclarativeObjectDelegate::getOwnPropertySlot(QScriptObject* object, const JSC::Identifier &propertyName, JSC::PropertySlot &slot) { - QScriptEnginePrivate *engine = scriptEngineFromExec(exec); QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); QScriptDeclarativeClassPrivate *p = QScriptDeclarativeClassPrivate::get(m_class); @@ -106,43 +105,14 @@ void DeclarativeObjectDelegate::put(QScriptObject* object, JSC::ExecState *exec, } bool DeclarativeObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState *exec, - const JSC::Identifier &propertyName, - bool checkDontDelete) -{ - return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete); -} - -bool DeclarativeObjectDelegate::getPropertyAttributes(const QScriptObject* object, - JSC::ExecState *exec, - const JSC::Identifier &propertyName, - unsigned &attribs) const + const JSC::Identifier &propertyName) { - QScriptDeclarativeClass::Identifier identifier = (void *)propertyName.ustring().rep(); - - QScriptClass::QueryFlags flags = - m_class->queryProperty(m_object, identifier, QScriptClass::HandlesReadAccess); - if (flags & QScriptClass::HandlesReadAccess) { - QScriptValue::PropertyFlags flags = m_class->propertyFlags(m_object, identifier); - attribs = 0; - if (flags & QScriptValue::ReadOnly) - attribs |= JSC::ReadOnly; - if (flags & QScriptValue::SkipInEnumeration) - attribs |= JSC::DontEnum; - if (flags & QScriptValue::Undeletable) - attribs |= JSC::DontDelete; - if (flags & QScriptValue::PropertyGetter) - attribs |= JSC::Getter; - if (flags & QScriptValue::PropertySetter) - attribs |= JSC::Setter; - attribs |= flags & QScriptValue::UserRange; - return true; - } - return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attribs); + return QScriptObjectDelegate::deleteProperty(object, exec, propertyName); } void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { QStringList properties = m_class->propertyNames(m_object); for (int ii = 0; ii < properties.count(); ++ii) { @@ -150,7 +120,7 @@ void DeclarativeObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC:: propertyNames.add(JSC::Identifier(exec, name)); } - QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable); + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode); } JSC::CallType DeclarativeObjectDelegate::getCallData(QScriptObject *object, JSC::CallData &callData) diff --git a/src/script/bridge/qscriptdeclarativeobject_p.h b/src/script/bridge/qscriptdeclarativeobject_p.h index ec8a43e..5024a71 100644 --- a/src/script/bridge/qscriptdeclarativeobject_p.h +++ b/src/script/bridge/qscriptdeclarativeobject_p.h @@ -81,14 +81,10 @@ public: const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(QScriptObject*, JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, - const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); static JSC::JSValue JSC_HOST_CALL call(JSC::ExecState*, JSC::JSObject*, diff --git a/src/script/bridge/qscriptglobalobject.cpp b/src/script/bridge/qscriptglobalobject.cpp index e7ea0df..4c002b7 100644 --- a/src/script/bridge/qscriptglobalobject.cpp +++ b/src/script/bridge/qscriptglobalobject.cpp @@ -72,6 +72,23 @@ bool GlobalObject::getOwnPropertySlot(JSC::ExecState* exec, return JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot); } +bool GlobalObject::getOwnPropertyDescriptor(JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor& descriptor) +{ + // Must match the logic of getOwnPropertySlot(). + QScriptEnginePrivate *engine = scriptEngineFromExec(exec); + if (propertyName == exec->propertyNames().arguments && engine->currentFrame->argumentCount() > 0) { + // ### Can we get rid of this special handling of the arguments property? + JSC::JSValue args = engine->scriptValueToJSCValue(engine->contextForFrame(engine->currentFrame)->argumentsObject()); + descriptor.setValue(args); + return true; + } + if (customGlobalObject) + return customGlobalObject->getOwnPropertyDescriptor(exec, propertyName, descriptor); + return JSC::JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + void GlobalObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot& slot) { @@ -90,29 +107,20 @@ void GlobalObject::putWithAttributes(JSC::ExecState* exec, const JSC::Identifier JSC::JSGlobalObject::putWithAttributes(exec, propertyName, value, attributes); } -bool GlobalObject::deleteProperty(JSC::ExecState* exec, - const JSC::Identifier& propertyName, bool checkDontDelete) -{ - if (customGlobalObject) - return customGlobalObject->deleteProperty(exec, propertyName, checkDontDelete); - return JSC::JSGlobalObject::deleteProperty(exec, propertyName, checkDontDelete); -} - -bool GlobalObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, - unsigned& attributes) const +bool GlobalObject::deleteProperty(JSC::ExecState* exec, const JSC::Identifier& propertyName) { if (customGlobalObject) - return customGlobalObject->getPropertyAttributes(exec, propertyName, attributes); - return JSC::JSGlobalObject::getPropertyAttributes(exec, propertyName, attributes); + return customGlobalObject->deleteProperty(exec, propertyName); + return JSC::JSGlobalObject::deleteProperty(exec, propertyName); } void GlobalObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { if (customGlobalObject) - customGlobalObject->getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + customGlobalObject->getOwnPropertyNames(exec, propertyNames, mode); else - JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, mode); } void GlobalObject::defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes) diff --git a/src/script/bridge/qscriptglobalobject_p.h b/src/script/bridge/qscriptglobalobject_p.h index b210f78..c0a419f 100644 --- a/src/script/bridge/qscriptglobalobject_p.h +++ b/src/script/bridge/qscriptglobalobject_p.h @@ -54,17 +54,17 @@ public: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor&); virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual void putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, unsigned attributes); virtual bool deleteProperty(JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void defineGetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes = 0); virtual void defineSetter(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes = 0); virtual JSC::JSValue lookupGetter(JSC::ExecState*, const JSC::Identifier& propertyName); @@ -94,19 +94,20 @@ public: const JSC::Identifier& propertyName, JSC::PropertySlot& slot) { return originalGlobalObject->JSC::JSGlobalObject::getOwnPropertySlot(exec, propertyName, slot); } + virtual bool getOwnPropertyDescriptor(JSC::ExecState* exec, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor& descriptor) + { return originalGlobalObject->JSC::JSGlobalObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); } virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot& slot) { originalGlobalObject->JSC::JSGlobalObject::put(exec, propertyName, value, slot); } virtual void putWithAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, unsigned attributes) { originalGlobalObject->JSC::JSGlobalObject::putWithAttributes(exec, propertyName, value, attributes); } virtual bool deleteProperty(JSC::ExecState* exec, - const JSC::Identifier& propertyName, bool checkDontDelete = true) - { return originalGlobalObject->JSC::JSGlobalObject::deleteProperty(exec, propertyName, checkDontDelete); } - virtual bool getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, - unsigned& attributes) const - { return originalGlobalObject->JSC::JSGlobalObject::getPropertyAttributes(exec, propertyName, attributes); } - virtual void getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, bool includeNonEnumerable = false) - { originalGlobalObject->JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); } + const JSC::Identifier& propertyName) + { return originalGlobalObject->JSC::JSGlobalObject::deleteProperty(exec, propertyName); } + virtual void getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties) + { originalGlobalObject->JSC::JSGlobalObject::getOwnPropertyNames(exec, propertyNames, mode); } virtual void defineGetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* getterFunction, unsigned attributes) { originalGlobalObject->JSC::JSGlobalObject::defineGetter(exec, propertyName, getterFunction, attributes); } virtual void defineSetter(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSObject* setterFunction, unsigned attributes) diff --git a/src/script/bridge/qscriptobject.cpp b/src/script/bridge/qscriptobject.cpp index 3db109e..9b6910e 100644 --- a/src/script/bridge/qscriptobject.cpp +++ b/src/script/bridge/qscriptobject.cpp @@ -81,30 +81,21 @@ void QScriptObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyNam } bool QScriptObject::deleteProperty(JSC::ExecState* exec, - const JSC::Identifier& propertyName, - bool checkDontDelete) + const JSC::Identifier& propertyName) { if (!d || !d->delegate) - return JSC::JSObject::deleteProperty(exec, propertyName, checkDontDelete); - return d->delegate->deleteProperty(this, exec, propertyName, checkDontDelete); -} - -bool QScriptObject::getPropertyAttributes(JSC::ExecState* exec, const JSC::Identifier& propertyName, - unsigned& attributes) const -{ - if (!d || !d->delegate) - return JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); - return d->delegate->getPropertyAttributes(this, exec, propertyName, attributes); + return JSC::JSObject::deleteProperty(exec, propertyName); + return d->delegate->deleteProperty(this, exec, propertyName); } void QScriptObject::getOwnPropertyNames(JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { if (!d || !d->delegate) { - JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode); return; } - d->delegate->getOwnPropertyNames(this, exec, propertyNames, includeNonEnumerable); + d->delegate->getOwnPropertyNames(this, exec, propertyNames, mode); } bool QScriptObject::compareToObject(JSC::ExecState* exec, JSC::JSObject *other) @@ -189,25 +180,16 @@ void QScriptObjectDelegate::put(QScriptObject* object, JSC::ExecState* exec, } bool QScriptObjectDelegate::deleteProperty(QScriptObject* object, JSC::ExecState* exec, - const JSC::Identifier& propertyName, - bool checkDontDelete) -{ - return object->JSC::JSObject::deleteProperty(exec, propertyName, checkDontDelete); -} - -bool QScriptObjectDelegate::getPropertyAttributes(const QScriptObject* object, - JSC::ExecState* exec, - const JSC::Identifier& propertyName, - unsigned& attributes) const + const JSC::Identifier& propertyName) { - return object->JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); + return object->JSC::JSObject::deleteProperty(exec, propertyName); } void QScriptObjectDelegate::getOwnPropertyNames(QScriptObject* object, JSC::ExecState* exec, JSC::PropertyNameArray& propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { - object->JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + object->JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode); } void QScriptObjectDelegate::markChildren(QScriptObject* object, JSC::MarkStack& markStack) diff --git a/src/script/bridge/qscriptobject_p.h b/src/script/bridge/qscriptobject_p.h index 4d15bee..f6de418 100644 --- a/src/script/bridge/qscriptobject_p.h +++ b/src/script/bridge/qscriptobject_p.h @@ -67,12 +67,9 @@ public: virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void markChildren(JSC::MarkStack& markStack); virtual JSC::CallType getCallData(JSC::CallData&); virtual JSC::ConstructType getConstructData(JSC::ConstructData&); @@ -84,7 +81,7 @@ public: static WTF::PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, JSC::ImplementsHasInstance | JSC::OverridesHasInstance)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); } inline JSC::JSValue data() const; @@ -94,6 +91,8 @@ public: inline void setDelegate(QScriptObjectDelegate *delegate); protected: + static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesHasInstance | JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSObject::StructureFlags; + Data *d; }; @@ -128,12 +127,9 @@ public: virtual void put(QScriptObject*, JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(QScriptObject*, JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, - const JSC::Identifier&, unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void markChildren(QScriptObject*, JSC::MarkStack& markStack); virtual JSC::CallType getCallData(QScriptObject*, JSC::CallData&); virtual JSC::ConstructType getConstructData(QScriptObject*, JSC::ConstructData&); diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index 6c401f8..765e074 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -537,40 +537,43 @@ static JSC::JSValue callQtMethod(JSC::ExecState *exec, QMetaMethod::MethodType c continue; } + QList<QByteArray> parameterTypeNames = method.parameterTypes(); + QVector<QScriptMetaType> types; + types.resize(1 + parameterTypeNames.size()); + QScriptMetaType *typesData = types.data(); // resolve return type QByteArray returnTypeName = method.typeName(); int rtype = QMetaType::type(returnTypeName); if ((rtype == 0) && !returnTypeName.isEmpty()) { int enumIndex = indexOfMetaEnum(meta, returnTypeName); if (enumIndex != -1) - types.append(QScriptMetaType::metaEnum(enumIndex, returnTypeName)); + typesData[0] = QScriptMetaType::metaEnum(enumIndex, returnTypeName); else - types.append(QScriptMetaType::unresolved(returnTypeName)); + typesData[0] = QScriptMetaType::unresolved(returnTypeName); } else { if (callType == QMetaMethod::Constructor) - types.append(QScriptMetaType::metaType(QMetaType::QObjectStar, "QObject*")); + typesData[0] = QScriptMetaType::metaType(QMetaType::QObjectStar, "QObject*"); else if (rtype == QMetaType::QVariant) - types.append(QScriptMetaType::variant()); + typesData[0] = QScriptMetaType::variant(); else - types.append(QScriptMetaType::metaType(rtype, returnTypeName)); + typesData[0] = QScriptMetaType::metaType(rtype, returnTypeName); } // resolve argument types - QList<QByteArray> parameterTypeNames = method.parameterTypes(); for (int i = 0; i < parameterTypeNames.count(); ++i) { QByteArray argTypeName = parameterTypeNames.at(i); int atype = QMetaType::type(argTypeName); if (atype == 0) { int enumIndex = indexOfMetaEnum(meta, argTypeName); if (enumIndex != -1) - types.append(QScriptMetaType::metaEnum(enumIndex, argTypeName)); + typesData[1 + i] = QScriptMetaType::metaEnum(enumIndex, argTypeName); else - types.append(QScriptMetaType::unresolved(argTypeName)); + typesData[1 + i] = QScriptMetaType::unresolved(argTypeName); } else if (atype == QMetaType::QVariant) { - types.append(QScriptMetaType::variant()); + typesData[1 + i] = QScriptMetaType::variant(); } else { - types.append(QScriptMetaType::metaType(atype, argTypeName)); + typesData[1 + i] = QScriptMetaType::metaType(atype, argTypeName); } } @@ -1298,7 +1301,7 @@ bool QObjectDelegate::getOwnPropertyDescriptor(QScriptObject *object, JSC::ExecS const JSC::Identifier &propertyName, JSC::PropertyDescriptor &descriptor) { - //Note: this has to be kept in sync with getOwnPropertySlot abd getPropertyAttributes + //Note: this has to be kept in sync with getOwnPropertySlot #ifndef QT_NO_PROPERTIES QByteArray name = convertToLatin1(propertyName.ustring()); QObject *qobject = data->value; @@ -1528,8 +1531,7 @@ void QObjectDelegate::put(QScriptObject *object, JSC::ExecState* exec, } bool QObjectDelegate::deleteProperty(QScriptObject *object, JSC::ExecState *exec, - const JSC::Identifier& propertyName, - bool checkDontDelete) + const JSC::Identifier& propertyName) { #ifndef QT_NO_PROPERTIES QByteArray name = convertToLatin1(propertyName.ustring()); @@ -1569,86 +1571,7 @@ bool QObjectDelegate::deleteProperty(QScriptObject *object, JSC::ExecState *exec return true; } - return QScriptObjectDelegate::deleteProperty(object, exec, propertyName, checkDontDelete); -#else //QT_NO_PROPERTIES - return false; -#endif //QT_NO_PROPERTIES -} - -bool QObjectDelegate::getPropertyAttributes(const QScriptObject *object, - JSC::ExecState *exec, - const JSC::Identifier &propertyName, - unsigned &attributes) const -{ -#ifndef QT_NO_PROPERTIES - //Note: this has to be kept in sync with getOwnPropertyDescriptor and getOwnPropertySlot - QByteArray name = convertToLatin1(propertyName.ustring()); - QObject *qobject = data->value; - if (!qobject) - return false; - - const QScriptEngine::QObjectWrapOptions &opt = data->options; - const QMetaObject *meta = qobject->metaObject(); - int index = -1; - if (name.contains('(')) { - QByteArray normalized = QMetaObject::normalizedSignature(name); - if (-1 != (index = meta->indexOfMethod(normalized))) { - QMetaMethod method = meta->method(index); - if (hasMethodAccess(method, index, opt)) { - if (!(opt & QScriptEngine::ExcludeSuperClassMethods) - || (index >= meta->methodOffset())) { - attributes = QObjectMemberAttribute; - if (opt & QScriptEngine::SkipMethodsInEnumeration) - attributes |= JSC::DontEnum; - return true; - } - } - } - } - - index = meta->indexOfProperty(name); - if (index != -1) { - QMetaProperty prop = meta->property(index); - if (prop.isScriptable()) { - if (!(opt & QScriptEngine::ExcludeSuperClassProperties) - || (index >= meta->propertyOffset())) { - attributes = flagsForMetaProperty(prop); - return true; - } - } - } - - index = qobject->dynamicPropertyNames().indexOf(name); - if (index != -1) { - attributes = QObjectMemberAttribute; - return true; - } - - const int offset = (opt & QScriptEngine::ExcludeSuperClassMethods) - ? meta->methodOffset() : 0; - for (index = meta->methodCount() - 1; index >= offset; --index) { - QMetaMethod method = meta->method(index); - if (hasMethodAccess(method, index, opt) - && methodNameEquals(method, name.constData(), name.length())) { - attributes = QObjectMemberAttribute; - if (opt & QScriptEngine::SkipMethodsInEnumeration) - attributes |= JSC::DontEnum; - return true; - } - } - - if (!(opt & QScriptEngine::ExcludeChildObjects)) { - QList<QObject*> children = qobject->children(); - for (index = 0; index < children.count(); ++index) { - QObject *child = children.at(index); - if (child->objectName() == (QString)(propertyName.ustring())) { - attributes = JSC::ReadOnly | JSC::DontDelete | JSC::DontEnum; - return true; - } - } - } - - return QScriptObjectDelegate::getPropertyAttributes(object, exec, propertyName, attributes); + return QScriptObjectDelegate::deleteProperty(object, exec, propertyName); #else //QT_NO_PROPERTIES return false; #endif //QT_NO_PROPERTIES @@ -1656,7 +1579,7 @@ bool QObjectDelegate::getPropertyAttributes(const QScriptObject *object, void QObjectDelegate::getOwnPropertyNames(QScriptObject *object, JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { #ifndef QT_NO_PROPERTIES QObject *qobject = data->value; @@ -1701,7 +1624,7 @@ void QObjectDelegate::getOwnPropertyNames(QScriptObject *object, JSC::ExecState } } - QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, includeNonEnumerable); + QScriptObjectDelegate::getOwnPropertyNames(object, exec, propertyNames, mode); #endif //QT_NO_PROPERTIES } @@ -1884,6 +1807,39 @@ bool QMetaObjectWrapperObject::getOwnPropertySlot( return JSC::JSObject::getOwnPropertySlot(exec, propertyName, slot); } +bool QMetaObjectWrapperObject::getOwnPropertyDescriptor( + JSC::ExecState* exec, const JSC::Identifier& propertyName, + JSC::PropertyDescriptor& descriptor) +{ + const QMetaObject *meta = data->value; + if (!meta) + return false; + + if (propertyName == exec->propertyNames().prototype) { + descriptor.setDescriptor(data->ctor + ? data->ctor.get(exec, propertyName) + : data->prototype, + JSC::DontDelete | JSC::DontEnum); + return true; + } + + QByteArray name = QString(propertyName.ustring()).toLatin1(); + + for (int i = 0; i < meta->enumeratorCount(); ++i) { + QMetaEnum e = meta->enumerator(i); + for (int j = 0; j < e.keyCount(); ++j) { + const char *key = e.key(j); + if (!qstrcmp(key, name.constData())) { + descriptor.setDescriptor(JSC::JSValue(exec, e.value(j)), + JSC::ReadOnly | JSC::DontDelete); + return true; + } + } + } + + return JSC::JSObject::getOwnPropertyDescriptor(exec, propertyName, descriptor); +} + void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue value, JSC::PutPropertySlot &slot) { @@ -1909,8 +1865,7 @@ void QMetaObjectWrapperObject::put(JSC::ExecState* exec, const JSC::Identifier& } bool QMetaObjectWrapperObject::deleteProperty( - JSC::ExecState *exec, const JSC::Identifier& propertyName, - bool checkDontDelete) + JSC::ExecState *exec, const JSC::Identifier& propertyName) { if (propertyName == exec->propertyNames().prototype) return false; @@ -1925,36 +1880,12 @@ bool QMetaObjectWrapperObject::deleteProperty( } } } - return JSC::JSObject::deleteProperty(exec, propertyName, checkDontDelete); -} - -bool QMetaObjectWrapperObject::getPropertyAttributes(JSC::ExecState *exec, - const JSC::Identifier &propertyName, - unsigned &attributes) const -{ - if (propertyName == exec->propertyNames().prototype) { - attributes = JSC::DontDelete; - return true; - } - const QMetaObject *meta = data->value; - if (meta) { - QByteArray name = convertToLatin1(propertyName.ustring()); - for (int i = 0; i < meta->enumeratorCount(); ++i) { - QMetaEnum e = meta->enumerator(i); - for (int j = 0; j < e.keyCount(); ++j) { - if (!qstrcmp(e.key(j), name.constData())) { - attributes = JSC::ReadOnly | JSC::DontDelete; - return true; - } - } - } - } - return JSC::JSObject::getPropertyAttributes(exec, propertyName, attributes); + return JSC::JSObject::deleteProperty(exec, propertyName); } void QMetaObjectWrapperObject::getOwnPropertyNames(JSC::ExecState *exec, JSC::PropertyNameArray &propertyNames, - bool includeNonEnumerable) + JSC::EnumerationMode mode) { const QMetaObject *meta = data->value; if (!meta) @@ -1964,7 +1895,7 @@ void QMetaObjectWrapperObject::getOwnPropertyNames(JSC::ExecState *exec, for (int j = 0; j < e.keyCount(); ++j) propertyNames.add(JSC::Identifier(exec, e.key(j))); } - JSC::JSObject::getOwnPropertyNames(exec, propertyNames, includeNonEnumerable); + JSC::JSObject::getOwnPropertyNames(exec, propertyNames, mode); } void QMetaObjectWrapperObject::markChildren(JSC::MarkStack& markStack) diff --git a/src/script/bridge/qscriptqobject_p.h b/src/script/bridge/qscriptqobject_p.h index 8b05d6b..b82bcb7 100644 --- a/src/script/bridge/qscriptqobject_p.h +++ b/src/script/bridge/qscriptqobject_p.h @@ -86,14 +86,10 @@ public: const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(QScriptObject*, JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(const QScriptObject*, JSC::ExecState*, - const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(QScriptObject*, JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void markChildren(QScriptObject*, JSC::MarkStack& markStack); virtual bool compareToObject(QScriptObject*, JSC::ExecState*, JSC::JSObject*); @@ -275,15 +271,15 @@ public: virtual bool getOwnPropertySlot(JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); + virtual bool getOwnPropertyDescriptor(JSC::ExecState*, + const JSC::Identifier& propertyName, + JSC::PropertyDescriptor&); virtual void put(JSC::ExecState* exec, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); virtual bool deleteProperty(JSC::ExecState*, - const JSC::Identifier& propertyName, - bool checkDontDelete = true); - virtual bool getPropertyAttributes(JSC::ExecState*, const JSC::Identifier&, - unsigned&) const; + const JSC::Identifier& propertyName); virtual void getOwnPropertyNames(JSC::ExecState*, JSC::PropertyNameArray&, - bool includeNonEnumerable = false); + JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties); virtual void markChildren(JSC::MarkStack& markStack); virtual JSC::CallType getCallData(JSC::CallData&); @@ -303,10 +299,12 @@ public: static WTF::PassRefPtr<JSC::Structure> createStructure(JSC::JSValue prototype) { - return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType)); + return JSC::Structure::create(prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags)); } protected: + static const unsigned StructureFlags = JSC::OverridesGetOwnPropertySlot | JSC::OverridesMarkChildren | JSC::OverridesGetPropertyNames | JSObject::StructureFlags; + Data *data; }; diff --git a/src/script/bridge/qscriptvariant.cpp b/src/script/bridge/qscriptvariant.cpp index b4f0365..b2dd3b0 100644 --- a/src/script/bridge/qscriptvariant.cpp +++ b/src/script/bridge/qscriptvariant.cpp @@ -119,11 +119,8 @@ static JSC::JSValue JSC_HOST_CALL variantProtoFuncToString(JSC::ExecState *exec, JSC::JSValue value = variantProtoFuncValueOf(exec, callee, thisValue, args); if (value.isObject()) { result = v.toString(); - if (result.isEmpty() && !v.canConvert(QVariant::String)) { - result = "QVariant("; - result += v.typeName(); - result += ")"; - } + if (result.isEmpty() && !v.canConvert(QVariant::String)) + result = QString::fromLatin1("QVariant(%0)").arg(QString::fromLatin1(v.typeName())); } else { result = value.toString(exec); } diff --git a/src/script/script.pro b/src/script/script.pro index 771047a..df5dbf3 100644 --- a/src/script/script.pro +++ b/src/script/script.pro @@ -39,6 +39,11 @@ wince* { LIBS += -lmmtimer } +mac { + DEFINES += ENABLE_JSC_MULTIPLE_THREADS=0 + LIBS_PRIVATE += -framework AppKit +} + include($$WEBKITDIR/JavaScriptCore/JavaScriptCore.pri) INCLUDEPATH += $$WEBKITDIR/JavaScriptCore @@ -68,7 +73,7 @@ solaris-g++:isEqual(QT_ARCH,sparc) { } # Avoid JSC C API functions being exported. -DEFINES += JS_EXPORT="" JS_EXPORTDATA="" +DEFINES += JS_NO_EXPORT JS_EXPORTDATA="" INCLUDEPATH += $$PWD |