diff options
author | Steve Block <steveblock@google.com> | 2010-04-27 16:31:00 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2010-05-11 14:42:12 +0100 |
commit | dcc8cf2e65d1aa555cce12431a16547e66b469ee (patch) | |
tree | 92a8d65cd5383bca9749f5327fb5e440563926e6 /JavaScriptCore | |
parent | ccac38a6b48843126402088a309597e682f40fe6 (diff) | |
download | external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.zip external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.gz external_webkit-dcc8cf2e65d1aa555cce12431a16547e66b469ee.tar.bz2 |
Merge webkit.org at r58033 : Initial merge by git
Change-Id: If006c38561af287c50cd578d251629b51e4d8cd1
Diffstat (limited to 'JavaScriptCore')
269 files changed, 17805 insertions, 5657 deletions
diff --git a/JavaScriptCore/API/APICast.h b/JavaScriptCore/API/APICast.h index 4284c44..ba00d02 100644 --- a/JavaScriptCore/API/APICast.h +++ b/JavaScriptCore/API/APICast.h @@ -29,7 +29,6 @@ #include "JSAPIValueWrapper.h" #include "JSGlobalObject.h" #include "JSValue.h" -#include <wtf/Platform.h> #include <wtf/UnusedParam.h> namespace JSC { diff --git a/JavaScriptCore/API/APIShims.h b/JavaScriptCore/API/APIShims.h index 9a6cacb..3d42ca2 100644 --- a/JavaScriptCore/API/APIShims.h +++ b/JavaScriptCore/API/APIShims.h @@ -28,6 +28,7 @@ #include "CallFrame.h" #include "JSLock.h" +#include <wtf/WTFThreadData.h> namespace JSC { @@ -35,7 +36,7 @@ class APIEntryShimWithoutLock { protected: APIEntryShimWithoutLock(JSGlobalData* globalData, bool registerThread) : m_globalData(globalData) - , m_entryIdentifierTable(setCurrentIdentifierTable(globalData->identifierTable)) + , m_entryIdentifierTable(wtfThreadData().setCurrentIdentifierTable(globalData->identifierTable)) { if (registerThread) globalData->heap.registerThread(); @@ -45,7 +46,7 @@ protected: ~APIEntryShimWithoutLock() { m_globalData->timeoutChecker.stop(); - setCurrentIdentifierTable(m_entryIdentifierTable); + wtfThreadData().setCurrentIdentifierTable(m_entryIdentifierTable); } private: @@ -79,12 +80,12 @@ public: : m_dropAllLocks(exec) , m_globalData(&exec->globalData()) { - resetCurrentIdentifierTable(); + wtfThreadData().resetCurrentIdentifierTable(); } ~APICallbackShim() { - setCurrentIdentifierTable(m_globalData->identifierTable); + wtfThreadData().setCurrentIdentifierTable(m_globalData->identifierTable); } private: diff --git a/JavaScriptCore/API/JSCallbackFunction.cpp b/JavaScriptCore/API/JSCallbackFunction.cpp index 0e434d9..63c8add 100644 --- a/JavaScriptCore/API/JSCallbackFunction.cpp +++ b/JavaScriptCore/API/JSCallbackFunction.cpp @@ -24,7 +24,6 @@ */ #include "config.h" -#include <wtf/Platform.h> #include "JSCallbackFunction.h" #include "APIShims.h" diff --git a/JavaScriptCore/API/JSCallbackObject.h b/JavaScriptCore/API/JSCallbackObject.h index adb5b60..1cf7a02 100644 --- a/JavaScriptCore/API/JSCallbackObject.h +++ b/JavaScriptCore/API/JSCallbackObject.h @@ -33,6 +33,84 @@ namespace JSC { +struct JSCallbackObjectData { + JSCallbackObjectData(void* privateData, JSClassRef jsClass) + : privateData(privateData) + , jsClass(jsClass) + { + JSClassRetain(jsClass); + } + + ~JSCallbackObjectData() + { + JSClassRelease(jsClass); + } + + JSValue getPrivateProperty(const Identifier& propertyName) const + { + if (!m_privateProperties) + return JSValue(); + return m_privateProperties->getPrivateProperty(propertyName); + } + + void setPrivateProperty(const Identifier& propertyName, JSValue value) + { + if (!m_privateProperties) + m_privateProperties.set(new JSPrivatePropertyMap); + m_privateProperties->setPrivateProperty(propertyName, value); + } + + void deletePrivateProperty(const Identifier& propertyName) + { + if (!m_privateProperties) + return; + m_privateProperties->deletePrivateProperty(propertyName); + } + + void markChildren(MarkStack& markStack) + { + if (!m_privateProperties) + return; + m_privateProperties->markChildren(markStack); + } + + void* privateData; + JSClassRef jsClass; + struct JSPrivatePropertyMap { + JSValue getPrivateProperty(const Identifier& propertyName) const + { + PrivatePropertyMap::const_iterator location = m_propertyMap.find(propertyName.ustring().rep()); + if (location == m_propertyMap.end()) + return JSValue(); + return location->second; + } + + void setPrivateProperty(const Identifier& propertyName, JSValue value) + { + m_propertyMap.set(propertyName.ustring().rep(), value); + } + + void deletePrivateProperty(const Identifier& propertyName) + { + m_propertyMap.remove(propertyName.ustring().rep()); + } + + void markChildren(MarkStack& markStack) + { + for (PrivatePropertyMap::iterator ptr = m_propertyMap.begin(); ptr != m_propertyMap.end(); ++ptr) { + if (ptr->second) + markStack.append(ptr->second); + } + } + + private: + typedef HashMap<RefPtr<UString::Rep>, JSValue, IdentifierRepHash> PrivatePropertyMap; + PrivatePropertyMap m_propertyMap; + }; + OwnPtr<JSPrivatePropertyMap> m_privateProperties; +}; + + template <class Base> class JSCallbackObject : public Base { public: @@ -52,6 +130,21 @@ public: { return Structure::create(proto, TypeInfo(ObjectType, StructureFlags), Base::AnonymousSlotCount); } + + JSValue getPrivateProperty(const Identifier& propertyName) const + { + return m_callbackObjectData->getPrivateProperty(propertyName); + } + + void setPrivateProperty(const Identifier& propertyName, JSValue value) + { + m_callbackObjectData->setPrivateProperty(propertyName, value); + } + + void deletePrivateProperty(const Identifier& propertyName) + { + m_callbackObjectData->deletePrivateProperty(propertyName); + } protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | OverridesHasInstance | OverridesMarkChildren | OverridesGetPropertyNames | Base::StructureFlags; @@ -79,6 +172,12 @@ private: virtual CallType getCallData(CallData&); virtual const ClassInfo* classInfo() const { return &info; } + virtual void markChildren(MarkStack& markStack) + { + Base::markChildren(markStack); + m_callbackObjectData->markChildren(markStack); + } + void init(ExecState*); static JSCallbackObject* asCallbackObject(JSValue); @@ -86,27 +185,10 @@ private: static JSValue JSC_HOST_CALL call(ExecState*, JSObject* functionObject, JSValue thisValue, const ArgList&); static JSObject* construct(ExecState*, JSObject* constructor, const ArgList&); - static JSValue staticValueGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue staticFunctionGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue callbackGetter(ExecState*, const Identifier&, const PropertySlot&); - - struct JSCallbackObjectData { - JSCallbackObjectData(void* privateData, JSClassRef jsClass) - : privateData(privateData) - , jsClass(jsClass) - { - JSClassRetain(jsClass); - } - - ~JSCallbackObjectData() - { - JSClassRelease(jsClass); - } - - void* privateData; - JSClassRef jsClass; - }; - + static JSValue staticValueGetter(ExecState*, JSValue, const Identifier&); + static JSValue staticFunctionGetter(ExecState*, JSValue, const Identifier&); + static JSValue callbackGetter(ExecState*, JSValue, const Identifier&); + OwnPtr<JSCallbackObjectData> m_callbackObjectData; }; diff --git a/JavaScriptCore/API/JSCallbackObjectFunctions.h b/JavaScriptCore/API/JSCallbackObjectFunctions.h index 4b28a99..6c83eb4 100644 --- a/JavaScriptCore/API/JSCallbackObjectFunctions.h +++ b/JavaScriptCore/API/JSCallbackObjectFunctions.h @@ -516,9 +516,9 @@ bool JSCallbackObject<Base>::inherits(JSClassRef c) const } template <class Base> -JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSCallbackObject* thisObj = asCallbackObject(slot.slotBase()); + JSCallbackObject* thisObj = asCallbackObject(slotBase); JSObjectRef thisRef = toRef(thisObj); RefPtr<OpaqueJSString> propertyNameRef; @@ -547,9 +547,9 @@ JSValue JSCallbackObject<Base>::staticValueGetter(ExecState* exec, const Identif } template <class Base> -JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSCallbackObject* thisObj = asCallbackObject(slot.slotBase()); + JSCallbackObject* thisObj = asCallbackObject(slotBase); // Check for cached or override property. PropertySlot slot2(thisObj); @@ -572,9 +572,9 @@ JSValue JSCallbackObject<Base>::staticFunctionGetter(ExecState* exec, const Iden } template <class Base> -JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, const Identifier& propertyName, const PropertySlot& slot) +JSValue JSCallbackObject<Base>::callbackGetter(ExecState* exec, JSValue slotBase, const Identifier& propertyName) { - JSCallbackObject* thisObj = asCallbackObject(slot.slotBase()); + JSCallbackObject* thisObj = asCallbackObject(slotBase); JSObjectRef thisRef = toRef(thisObj); RefPtr<OpaqueJSString> propertyNameRef; diff --git a/JavaScriptCore/API/JSClassRef.cpp b/JavaScriptCore/API/JSClassRef.cpp index 717488f..3e65b75 100644 --- a/JavaScriptCore/API/JSClassRef.cpp +++ b/JavaScriptCore/API/JSClassRef.cpp @@ -33,6 +33,7 @@ #include <runtime/JSGlobalObject.h> #include <runtime/ObjectPrototype.h> #include <runtime/Identifier.h> +#include <wtf/text/StringHash.h> #include <wtf/unicode/UTF8.h> using namespace std; @@ -111,7 +112,8 @@ OpaqueJSClass::OpaqueJSClass(const JSClassDefinition* definition, OpaqueJSClass* OpaqueJSClass::~OpaqueJSClass() { - ASSERT(!m_className.rep()->isIdentifier()); + // The empty string is shared across threads & is an identifier, in all other cases we should have done a deep copy in className(), below. + ASSERT(!m_className.size() || !m_className.rep()->isIdentifier()); if (m_staticValues) { OpaqueJSClassStaticValuesTable::const_iterator end = m_staticValues->end(); @@ -171,7 +173,7 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass) 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->length()), entry); + staticValues->add(UString::Rep::create(it->first->characters(), it->first->length()), entry); } } else staticValues = 0; @@ -183,7 +185,7 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(OpaqueJSClass* jsClass) 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->length()), entry); + staticFunctions->add(UString::Rep::create(it->first->characters(), it->first->length()), entry); } } else diff --git a/JavaScriptCore/API/JSContextRef.cpp b/JavaScriptCore/API/JSContextRef.cpp index 2c76338..06f9274 100644 --- a/JavaScriptCore/API/JSContextRef.cpp +++ b/JavaScriptCore/API/JSContextRef.cpp @@ -33,7 +33,7 @@ #include "JSClassRef.h" #include "JSGlobalObject.h" #include "JSObject.h" -#include <wtf/Platform.h> +#include <wtf/text/StringHash.h> #if OS(DARWIN) #include <mach-o/dyld.h> @@ -46,7 +46,7 @@ using namespace JSC; JSContextGroupRef JSContextGroupCreate() { initializeThreading(); - return toRef(JSGlobalData::createNonDefault().releaseRef()); + return toRef(JSGlobalData::createNonDefault(ThreadStackTypeSmall).releaseRef()); } JSContextGroupRef JSContextGroupRetain(JSContextGroupRef group) @@ -84,7 +84,7 @@ 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::createNonDefault(ThreadStackTypeSmall); APIEntryShim entryShim(globalData.get(), false); @@ -123,19 +123,32 @@ void JSGlobalContextRelease(JSGlobalContextRef ctx) JSLock lock(exec); JSGlobalData& globalData = exec->globalData(); - IdentifierTable* savedIdentifierTable = setCurrentIdentifierTable(globalData.identifierTable); - - gcUnprotect(exec->dynamicGlobalObject()); - - 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. + JSGlobalObject* dgo = exec->dynamicGlobalObject(); + IdentifierTable* savedIdentifierTable = wtfThreadData().setCurrentIdentifierTable(globalData.identifierTable); + + // One reference is held by JSGlobalObject, another added by JSGlobalContextRetain(). + bool releasingContextGroup = globalData.refCount() == 2; + bool releasingGlobalObject = Heap::heap(dgo)->unprotect(dgo); + // If this is the last reference to a global data, it should also + // be the only remaining reference to the global object too! + ASSERT(!releasingContextGroup || releasingGlobalObject); + + // An API 'JSGlobalContextRef' retains two things - a global object and a + // global data (or context group, in API terminology). + // * If this is the last reference to any contexts in the given context group, + // call destroy on the heap (the global data is being freed). + // * If this was the last reference to the global object, then unprotecting + // it may release a lot of GC memory - run the garbage collector now. + // * If there are more references remaining the the global object, then do nothing + // (specifically that is more protects, which we assume come from other JSGlobalContextRefs). + if (releasingContextGroup) globalData.heap.destroy(); - } else + else if (releasingGlobalObject) globalData.heap.collectAllGarbage(); globalData.deref(); - setCurrentIdentifierTable(savedIdentifierTable); + wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable); } JSObjectRef JSContextGetGlobalObject(JSContextRef ctx) diff --git a/JavaScriptCore/API/JSObjectRef.cpp b/JavaScriptCore/API/JSObjectRef.cpp index faaa4eb..8fdbdab 100644 --- a/JavaScriptCore/API/JSObjectRef.cpp +++ b/JavaScriptCore/API/JSObjectRef.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "JSObjectRef.h" +#include "JSObjectRefPrivate.h" #include "APICast.h" #include "CodeBlock.h" @@ -48,7 +49,6 @@ #include "ObjectPrototype.h" #include "PropertyNameArray.h" #include "RegExpConstructor.h" -#include <wtf/Platform.h> using namespace JSC; @@ -364,6 +364,55 @@ bool JSObjectSetPrivate(JSObjectRef object, void* data) return false; } +JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* jsObject = toJS(object); + JSValue result; + Identifier name(propertyName->identifier(&exec->globalData())); + if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) + result = static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name); + else if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) + result = static_cast<JSCallbackObject<JSObject>*>(jsObject)->getPrivateProperty(name); + return toRef(exec, result); +} + +bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* jsObject = toJS(object); + JSValue jsValue = toJS(exec, value); + Identifier name(propertyName->identifier(&exec->globalData())); + if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) { + static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(name, jsValue); + return true; + } + if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) { + static_cast<JSCallbackObject<JSObject>*>(jsObject)->setPrivateProperty(name, jsValue); + return true; + } + return false; +} + +bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* jsObject = toJS(object); + Identifier name(propertyName->identifier(&exec->globalData())); + if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) { + static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name); + return true; + } + if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) { + static_cast<JSCallbackObject<JSObject>*>(jsObject)->deletePrivateProperty(name); + return true; + } + return false; +} + bool JSObjectIsFunction(JSContextRef, JSObjectRef object) { CallData callData; diff --git a/JavaScriptCore/API/JSObjectRefPrivate.h b/JavaScriptCore/API/JSObjectRefPrivate.h new file mode 100644 index 0000000..32e80ab --- /dev/null +++ b/JavaScriptCore/API/JSObjectRefPrivate.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 JSObjectRefPrivate_h +#define JSObjectRefPrivate_h + +#include <JavaScriptCore/JSObjectRef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + @function + @abstract Sets a private property on an object. This private property cannot be accessed from within JavaScript. + @param ctx The execution context to use. + @param object The JSObject whose private property you want to set. + @param propertyName A JSString containing the property's name. + @param value A JSValue to use as the property's value. This may be NULL. + @result true if object can store private data, otherwise false. + @discussion This API allows you to store JS values directly an object in a way that will be ensure that they are kept alive without exposing them to JavaScript code and without introducing the reference cycles that may occur when using JSValueProtect. + + The default object class does not allocate storage for private data. Only objects created with a non-NULL JSClass can store private properties. + */ +JS_EXPORT bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value); + +/*! + @function + @abstract Gets a private property from an object. + @param ctx The execution context to use. + @param object The JSObject whose private property you want to get. + @param propertyName A JSString containing the property's name. + @result The property's value if object has the property, otherwise NULL. + */ +JS_EXPORT JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + +/*! + @function + @abstract Deletes a private property from an object. + @param ctx The execution context to use. + @param object The JSObject whose private property you want to delete. + @param propertyName A JSString containing the property's name. + @result true if object can store private data, otherwise false. + @discussion The default object class does not allocate storage for private data. Only objects created with a non-NULL JSClass can store private data. + */ +JS_EXPORT bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName); + +#ifdef __cplusplus +} +#endif + +#endif // JSObjectRefPrivate_h diff --git a/JavaScriptCore/API/JSValueRef.cpp b/JavaScriptCore/API/JSValueRef.cpp index a12cc34..f5dcccc 100644 --- a/JavaScriptCore/API/JSValueRef.cpp +++ b/JavaScriptCore/API/JSValueRef.cpp @@ -26,19 +26,21 @@ #include "config.h" #include "JSValueRef.h" -#include <wtf/Platform.h> #include "APICast.h" #include "APIShims.h" #include "JSCallbackObject.h" #include <runtime/JSGlobalObject.h> +#include <runtime/JSONObject.h> #include <runtime/JSString.h> +#include <runtime/LiteralParser.h> #include <runtime/Operations.h> #include <runtime/Protect.h> #include <runtime/UString.h> #include <runtime/JSValue.h> #include <wtf/Assertions.h> +#include <wtf/text/StringHash.h> #include <algorithm> // for std::min @@ -222,6 +224,31 @@ JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string) return toRef(exec, jsString(exec, string->ustring())); } +JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + LiteralParser parser(exec, string->ustring(), LiteralParser::StrictJSON); + return toRef(exec, parser.tryLiteralParse()); +} + +JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef apiValue, unsigned indent, JSValueRef* exception) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSValue value = toJS(exec, apiValue); + UString result = JSONStringify(exec, value, indent); + if (exception) + *exception = 0; + if (exec->hadException()) { + if (exception) + *exception = toRef(exec, exec->exception()); + exec->clearException(); + return 0; + } + return OpaqueJSString::create(result).releaseRef(); +} + bool JSValueToBoolean(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); diff --git a/JavaScriptCore/API/JSValueRef.h b/JavaScriptCore/API/JSValueRef.h index 7a7bf93..4186db8 100644 --- a/JavaScriptCore/API/JSValueRef.h +++ b/JavaScriptCore/API/JSValueRef.h @@ -27,6 +27,7 @@ #define JSValueRef_h #include <JavaScriptCore/JSBase.h> +#include <JavaScriptCore/WebKitAvailability.h> #ifndef __cplusplus #include <stdbool.h> @@ -208,6 +209,28 @@ JS_EXPORT JSValueRef JSValueMakeNumber(JSContextRef ctx, double number); */ JS_EXPORT JSValueRef JSValueMakeString(JSContextRef ctx, JSStringRef string); +/* Converting to and from JSON formatted strings */ + +/*! + @function + @abstract Creates a JavaScript value from a JSON formatted string. + @param ctx The execution context to use. + @param string The JSString containing the JSON string to be parsed. + @result A JSValue containing the parsed value, or NULL if the input is invalid. + */ +JS_EXPORT JSValueRef JSValueMakeFromJSONString(JSContextRef ctx, JSStringRef string) AVAILABLE_AFTER_WEBKIT_VERSION_4_0; + +/*! + @function + @abstract Creates a JavaScript string containing the JSON serialized representation of a JS value. + @param ctx The execution context to use. + @param value The value to serialize. + @param indent The number of spaces to indent when nesting. If 0, the resulting JSON will not contains newlines. The size of the indent is clamped to 10 spaces. + @param exception A pointer to a JSValueRef in which to store an exception, if any. Pass NULL if you do not care to store an exception. + @result A JSString with the result of serialization, or NULL if an exception is thrown. + */ +JS_EXPORT JSStringRef JSValueCreateJSONString(JSContextRef ctx, JSValueRef value, unsigned indent, JSValueRef* exception) AVAILABLE_AFTER_WEBKIT_VERSION_4_0; + /* Converting to primitive values */ /*! diff --git a/JavaScriptCore/API/JSWeakObjectMapRefInternal.h b/JavaScriptCore/API/JSWeakObjectMapRefInternal.h new file mode 100644 index 0000000..64e1f4d --- /dev/null +++ b/JavaScriptCore/API/JSWeakObjectMapRefInternal.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 JSWeakObjectMapRefInternal_h +#define JSWeakObjectMapRefInternal_h + +#include "WeakGCMap.h" +#include <wtf/RefCounted.h> + +namespace JSC { + +class JSObject; + +} + +typedef void (*JSWeakMapDestroyedCallback)(struct OpaqueJSWeakObjectMap*, void*); + +typedef JSC::WeakGCMap<void*, JSC::JSObject*> WeakMapType; + +struct OpaqueJSWeakObjectMap : public RefCounted<OpaqueJSWeakObjectMap> { +public: + static PassRefPtr<OpaqueJSWeakObjectMap> create(void* data, JSWeakMapDestroyedCallback callback) + { + return adoptRef(new OpaqueJSWeakObjectMap(data, callback)); + } + + WeakMapType& map() { return m_map; } + + ~OpaqueJSWeakObjectMap() + { + m_callback(this, m_data); + } + +private: + OpaqueJSWeakObjectMap(void* data, JSWeakMapDestroyedCallback callback) + : m_data(data) + , m_callback(callback) + { + } + WeakMapType m_map; + void* m_data; + JSWeakMapDestroyedCallback m_callback; +}; + + +#endif // JSWeakObjectMapInternal_h diff --git a/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp new file mode 100644 index 0000000..e377ea0 --- /dev/null +++ b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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. + */ + +#include "config.h" +#include "JSWeakObjectMapRefPrivate.h" + +#include "APICast.h" +#include "APIShims.h" +#include "JSCallbackObject.h" +#include "JSValue.h" +#include "JSWeakObjectMapRefInternal.h" +#include <wtf/HashMap.h> +#include <wtf/RefCounted.h> + +using namespace WTF; +using namespace JSC; + +#ifdef __cplusplus +extern "C" { +#endif + +JSWeakObjectMapRef JSWeakObjectMapCreate(JSContextRef context, void* privateData, JSWeakMapDestroyedCallback callback) +{ + ExecState* exec = toJS(context); + APIEntryShim entryShim(exec); + RefPtr<OpaqueJSWeakObjectMap> map = OpaqueJSWeakObjectMap::create(privateData, callback); + exec->lexicalGlobalObject()->registerWeakMap(map.get()); + return map.get(); +} + +void JSWeakObjectMapSet(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* obj = toJS(object); + if (!obj) + return; + ASSERT(obj->inherits(&JSCallbackObject<JSGlobalObject>::info) || obj->inherits(&JSCallbackObject<JSObject>::info)); + map->map().set(key, obj); +} + +JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* key) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + return toRef(static_cast<JSObject*>(map->map().get(key))); +} + +bool JSWeakObjectMapClear(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object) +{ + ExecState* exec = toJS(ctx); + APIEntryShim entryShim(exec); + JSObject* obj = toJS(object); + if (map->map().uncheckedRemove(key, obj)) + return true; + return false; +} + +#ifdef __cplusplus +} +#endif diff --git a/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h new file mode 100644 index 0000000..d36111c --- /dev/null +++ b/JavaScriptCore/API/JSWeakObjectMapRefPrivate.h @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 JSWeakObjectMapRefPrivate_h +#define JSWeakObjectMapRefPrivate_h + +#include <JavaScriptCore/JSContextRef.h> +#include <JavaScriptCore/JSValueRef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! @typedef JSWeakObjectMapRef A weak map for storing JSObjectRefs */ +typedef struct OpaqueJSWeakObjectMap* JSWeakObjectMapRef; + +/*! + @typedef JSWeakMapDestroyedCallback + @abstract The callback invoked when a JSWeakObjectMapRef is being destroyed. + @param map The map that is being destroyed. + @param data The private data (if any) that was associated with the map instance. + */ +typedef void (*JSWeakMapDestroyedCallback)(JSWeakObjectMapRef map, void* data); + +/*! + @function + @abstract Creates a weak value map that can be used to reference user defined objects without preventing them from being collected. + @param ctx The execution context to use. + @param data A void* to set as the map's private data. Pass NULL to specify no private data. + @param destructor A function to call when the weak map is destroyed. + @result A JSWeakObjectMapRef bound to the given context, data and destructor. + @discussion The JSWeakObjectMapRef can be used as a storage mechanism to hold custom JS objects without forcing those objects to + remain live as JSValueProtect would. Any objects that are intended to be stored in a weak map must be user defined objects that + remove themselves from the map in their finalizer. + */ +JS_EXPORT JSWeakObjectMapRef JSWeakObjectMapCreate(JSContextRef ctx, void* data, JSWeakMapDestroyedCallback destructor); + +/*! + @function + @abstract Associates a JSObjectRef with the given key in a JSWeakObjectMap. + @param ctx The execution context to use. + @param map The map to operate on. + @param key The key to associate a weak reference with. + @param object The user defined object to associate with the key. + */ +JS_EXPORT void JSWeakObjectMapSet(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef); + +/*! + @function + @abstract Retrieves the JSObjectRef associated with a key. + @param ctx The execution context to use. + @param map The map to query. + @param key The key to search for. + @result Either the live object associated with the provided key, or NULL. + */ +JS_EXPORT JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* key); + +/*! + @function + @abstract Clears the association between a key and an object in a JSWeakObjectMapRef + @param ctx The execution context to use. + @param map The map to clear the key association from. + @param key The key to use. + @param object The old object value. + @result Returns true if the key/object association was present in map, and has been removed. + */ +JS_EXPORT bool JSWeakObjectMapClear(JSContextRef ctx, JSWeakObjectMapRef map, void* key, JSObjectRef object); + +#ifdef __cplusplus +} +#endif + +#endif // JSWeakObjectMapPrivate_h diff --git a/JavaScriptCore/API/WebKitAvailability.h b/JavaScriptCore/API/WebKitAvailability.h index 8402528..0e4f091 100644 --- a/JavaScriptCore/API/WebKitAvailability.h +++ b/JavaScriptCore/API/WebKitAvailability.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -42,7 +42,7 @@ #define WEBKIT_VERSION_LATEST 0x9999 #ifdef __APPLE__ -#import <AvailabilityMacros.h> +#include <AvailabilityMacros.h> #else /* * For non-Mac platforms, require the newest version. @@ -86,6 +86,9 @@ #elif !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 /* WebKit 3.0 is the version that shipped on Mac OS X 10.5. */ #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_3_0 + #elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + /* WebKit 4.0 is the version that shipped on Mac OS X 10.6. */ + #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_4_0 #else #define WEBKIT_VERSION_MIN_REQUIRED WEBKIT_VERSION_LATEST #endif @@ -645,9 +648,9 @@ * * Used on declarations introduced in WebKit 4.0 */ -#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_4_0 #define AVAILABLE_IN_WEBKIT_VERSION_4_0 UNAVAILABLE_ATTRIBUTE -#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_LATEST +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_4_0 #define AVAILABLE_IN_WEBKIT_VERSION_4_0 WEAK_IMPORT_ATTRIBUTE #else #define AVAILABLE_IN_WEBKIT_VERSION_4_0 @@ -659,7 +662,7 @@ * Used on declarations introduced in WebKit 4.0, * and deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED DEPRECATED_ATTRIBUTE #else #define AVAILABLE_IN_WEBKIT_VERSION_4_0_BUT_DEPRECATED AVAILABLE_IN_WEBKIT_VERSION_4_0 @@ -671,7 +674,7 @@ * Used on declarations introduced in WebKit 1.0, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER @@ -683,7 +686,7 @@ * Used on declarations introduced in WebKit 1.1, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER @@ -695,7 +698,7 @@ * Used on declarations introduced in WebKit 1.2, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER @@ -707,7 +710,7 @@ * Used on declarations introduced in WebKit 1.3, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER @@ -719,7 +722,7 @@ * Used on declarations introduced in WebKit 2.0, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER @@ -731,7 +734,7 @@ * Used on declarations introduced in WebKit 3.0, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER @@ -743,7 +746,7 @@ * Used on declarations introduced in WebKit 3.1, * but later deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_IN_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER @@ -754,11 +757,148 @@ * * Used on types deprecated in WebKit 4.0 */ -#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_4_0 #define DEPRECATED_IN_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE #else #define DEPRECATED_IN_WEBKIT_VERSION_4_0 #endif + + + + +/* + * AVAILABLE_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced after WebKit 4.0 + */ +#if WEBKIT_VERSION_MAX_ALLOWED < WEBKIT_VERSION_LATEST + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0 UNAVAILABLE_ATTRIBUTE +#elif WEBKIT_VERSION_MIN_REQUIRED < WEBKIT_VERSION_LATEST + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0 WEAK_IMPORT_ATTRIBUTE +#else + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0 +#endif + +/* + * AVAILABLE_AFTER_WEBKIT_VERSION_4_0_BUT_DEPRECATED + * + * Used on declarations introduced after WebKit 4.0, + * and deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0_BUT_DEPRECATED DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_AFTER_WEBKIT_VERSION_4_0_BUT_DEPRECATED AVAILABLE_AFTER_WEBKIT_VERSION_4_0 +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.0, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.1, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.2, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_2_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 1.3, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_1_3_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 2.0, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_2_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 3.0, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_0_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 3.1, + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_3_1_AND_LATER +#endif + +/* + * AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on declarations introduced in WebKit 4.0 + * but later deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER_BUT_DEPRECATED_AFTER_WEBKIT_VERSION_4_0 AVAILABLE_WEBKIT_VERSION_4_0_AND_LATER +#endif + +/* + * DEPRECATED_AFTER_WEBKIT_VERSION_4_0 + * + * Used on types deprecated after WebKit 4.0 + */ +#if WEBKIT_VERSION_MIN_REQUIRED >= WEBKIT_VERSION_LATEST + #define DEPRECATED_AFTER_WEBKIT_VERSION_4_0 DEPRECATED_ATTRIBUTE +#else + #define DEPRECATED_AFTER_WEBKIT_VERSION_4_0 +#endif + + #endif /* __WebKitAvailability__ */ diff --git a/JavaScriptCore/API/tests/testapi.c b/JavaScriptCore/API/tests/testapi.c index ebc0cfb..28b4ec8 100644 --- a/JavaScriptCore/API/tests/testapi.c +++ b/JavaScriptCore/API/tests/testapi.c @@ -26,6 +26,7 @@ #include "JavaScriptCore.h" #include "JSBasePrivate.h" #include "JSContextRefPrivate.h" +#include "JSObjectRefPrivate.h" #include <math.h> #define ASSERT_DISABLED 0 #include <wtf/Assertions.h> @@ -754,6 +755,8 @@ static void testInitializeFinalize() static JSValueRef jsNumberValue = NULL; +static JSObjectRef aHeapRef = NULL; + static void makeGlobalNumberValue(JSContextRef context) { JSValueRef v = JSValueMakeNumber(context, 420); JSValueProtect(context, v); @@ -870,8 +873,107 @@ int main(int argc, char* argv[]) JSObjectSetProperty(context, globalObject, EmptyObjectIString, EmptyObject, kJSPropertyAttributeNone, NULL); JSStringRelease(EmptyObjectIString); + JSStringRef lengthStr = JSStringCreateWithUTF8CString("length"); + aHeapRef = JSObjectMakeArray(context, 0, 0, 0); + JSObjectSetProperty(context, aHeapRef, lengthStr, JSValueMakeNumber(context, 10), 0, 0); + JSStringRef privatePropertyName = JSStringCreateWithUTF8CString("privateProperty"); + if (!JSObjectSetPrivateProperty(context, myObject, privatePropertyName, aHeapRef)) { + printf("FAIL: Could not set private property.\n"); + failed = 1; + } else { + printf("PASS: Set private property.\n"); + } + if (JSObjectSetPrivateProperty(context, aHeapRef, privatePropertyName, aHeapRef)) { + printf("FAIL: JSObjectSetPrivateProperty should fail on non-API objects.\n"); + failed = 1; + } else { + printf("PASS: Did not allow JSObjectSetPrivateProperty on a non-API object.\n"); + } + if (JSObjectGetPrivateProperty(context, myObject, privatePropertyName) != aHeapRef) { + printf("FAIL: Could not retrieve private property.\n"); + failed = 1; + } else + printf("PASS: Retrieved private property.\n"); + if (JSObjectGetPrivateProperty(context, aHeapRef, privatePropertyName)) { + printf("FAIL: JSObjectGetPrivateProperty should return NULL when called on a non-API object.\n"); + failed = 1; + } else + printf("PASS: JSObjectGetPrivateProperty return NULL.\n"); + + if (JSObjectGetProperty(context, myObject, privatePropertyName, 0) == aHeapRef) { + printf("FAIL: Accessed private property through ordinary property lookup.\n"); + failed = 1; + } else + printf("PASS: Cannot access private property through ordinary property lookup.\n"); + + JSGarbageCollect(context); + + for (int i = 0; i < 10000; i++) + JSObjectMake(context, 0, 0); + + if (JSValueToNumber(context, JSObjectGetProperty(context, aHeapRef, lengthStr, 0), 0) != 10) { + printf("FAIL: Private property has been collected.\n"); + failed = 1; + } else + printf("PASS: Private property does not appear to have been collected.\n"); + JSStringRelease(lengthStr); + + JSStringRef validJSON = JSStringCreateWithUTF8CString("{\"aProperty\":true}"); + JSValueRef jsonObject = JSValueMakeFromJSONString(context, validJSON); + JSStringRelease(validJSON); + if (!JSValueIsObject(context, jsonObject)) { + printf("FAIL: Did not parse valid JSON correctly\n"); + failed = 1; + } else + printf("PASS: Parsed valid JSON string.\n"); + JSStringRef propertyName = JSStringCreateWithUTF8CString("aProperty"); + assertEqualsAsBoolean(JSObjectGetProperty(context, JSValueToObject(context, jsonObject, 0), propertyName, 0), true); + JSStringRelease(propertyName); + JSStringRef invalidJSON = JSStringCreateWithUTF8CString("fail!"); + if (JSValueMakeFromJSONString(context, invalidJSON)) { + printf("FAIL: Should return null for invalid JSON data\n"); + failed = 1; + } else + printf("PASS: Correctly returned null for invalid JSON data.\n"); JSValueRef exception; + JSStringRef str = JSValueCreateJSONString(context, jsonObject, 0, 0); + if (!JSStringIsEqualToUTF8CString(str, "{\"aProperty\":true}")) { + printf("FAIL: Did not correctly serialise with indent of 0.\n"); + failed = 1; + } else + printf("PASS: Correctly serialised with indent of 0.\n"); + JSStringRelease(str); + str = JSValueCreateJSONString(context, jsonObject, 4, 0); + if (!JSStringIsEqualToUTF8CString(str, "{\n \"aProperty\": true\n}")) { + printf("FAIL: Did not correctly serialise with indent of 4.\n"); + failed = 1; + } else + printf("PASS: Correctly serialised with indent of 4.\n"); + JSStringRelease(str); + JSStringRef src = JSStringCreateWithUTF8CString("({get a(){ throw '';}})"); + JSValueRef unstringifiableObj = JSEvaluateScript(context, src, NULL, NULL, 1, NULL); + + str = JSValueCreateJSONString(context, unstringifiableObj, 4, 0); + if (str) { + printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n"); + JSStringRelease(str); + failed = 1; + } else + printf("PASS: returned null when attempting to serialize unserializable value.\n"); + + str = JSValueCreateJSONString(context, unstringifiableObj, 4, &exception); + if (str) { + printf("FAIL: Didn't return null when attempting to serialize unserializable value.\n"); + JSStringRelease(str); + failed = 1; + } else + printf("PASS: returned null when attempting to serialize unserializable value.\n"); + if (!exception) { + printf("FAIL: Did not set exception on serialisation error\n"); + failed = 1; + } else + printf("PASS: set exception on serialisation error\n"); // Conversions that throw exceptions exception = NULL; ASSERT(NULL == JSValueToObject(context, jsNull, &exception)); diff --git a/JavaScriptCore/Android.mk b/JavaScriptCore/Android.mk index b03cd97..2c2a2d0 100644 --- a/JavaScriptCore/Android.mk +++ b/JavaScriptCore/Android.mk @@ -153,13 +153,6 @@ LOCAL_SRC_FILES := \ runtime/UString.cpp \ runtime/UStringImpl.cpp \ \ - wrec/CharacterClass.cpp \ - wrec/CharacterClassConstructor.cpp \ - wrec/WREC.cpp \ - wrec/WRECFunctors.cpp \ - wrec/WRECGenerator.cpp \ - wrec/WRECParser.cpp \ - \ wtf/Assertions.cpp \ wtf/ByteArray.cpp \ wtf/CurrentTime.cpp \ @@ -173,12 +166,18 @@ LOCAL_SRC_FILES := \ wtf/ThreadIdentifierDataPthreads.cpp \ wtf/Threading.cpp \ wtf/ThreadingPthreads.cpp \ + wtf/WTFThreadData.cpp \ \ wtf/TypeTraits.cpp \ wtf/dtoa.cpp \ \ wtf/android/MainThreadAndroid.cpp \ \ + wtf/text/AtomicString.cpp \ + wtf/text/CString.cpp \ + wtf/text/StringImpl.cpp \ + wtf/text/WTFString.cpp \ + \ wtf/unicode/CollatorDefault.cpp \ wtf/unicode/UTF8.cpp \ \ diff --git a/JavaScriptCore/Android.v8.wtf.mk b/JavaScriptCore/Android.v8.wtf.mk index 69128d6..9249e47 100644 --- a/JavaScriptCore/Android.v8.wtf.mk +++ b/JavaScriptCore/Android.v8.wtf.mk @@ -45,12 +45,18 @@ LOCAL_SRC_FILES := \ wtf/ThreadIdentifierDataPthreads.cpp \ wtf/Threading.cpp \ wtf/ThreadingPthreads.cpp \ - \ - wtf/android/MainThreadAndroid.cpp \ + wtf/WTFThreadData.cpp \ \ wtf/TypeTraits.cpp \ wtf/dtoa.cpp \ \ + wtf/android/MainThreadAndroid.cpp \ + \ + wtf/text/AtomicString.cpp \ + wtf/text/CString.cpp \ + wtf/text/StringImpl.cpp \ + wtf/text/WTFString.cpp \ + \ wtf/unicode/CollatorDefault.cpp \ wtf/unicode/UTF8.cpp \ \ diff --git a/JavaScriptCore/ChangeLog b/JavaScriptCore/ChangeLog index 3d1a925..11f02e3 100644 --- a/JavaScriptCore/ChangeLog +++ b/JavaScriptCore/ChangeLog @@ -1,3 +1,3664 @@ +2010-04-21 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Oliver Hunt. + + Make SmallStrings store an array of RefPtr<StringImpl>, + instead of a direct array of StringImpls. This allows + us to remove a friend (and a layering violation) from + WTF::StringImpl, and makes it so that all StringImpls + are individually heap allocated. + + * runtime/SmallStrings.cpp: + (JSC::SmallStringsStorage::rep): + (JSC::SmallStringsStorage::SmallStringsStorage): + * wtf/text/StringImpl.h: + +2010-04-21 Sam Weinig <sam@webkit.org> + + Reviewed by Geoffrey Garen. + + Fix for https://bugs.webkit.org/show_bug.cgi?id=37937 + Wean JavaScriptCore off calls to isMainThread() + + - Replace use of isMainThread() for interpreter reentry checks + with a stored value on the JSGlobalData. + - Replace use of isMainThread() for useMainThread only check in the + collector with a stored exclusive thread. + + * API/JSContextRef.cpp: + (JSContextGroupCreate): + Always default to a small stack type for uses of the JSC API. It is + unlikely that the interpreter reentry required on the web will be as + important for other uses of JavaScriptCore. + + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + Update exports. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + (JSC::Interpreter::prepareForRepeatCall): + Use new stored JSGlobalData::maxReentryDepth instead of isMainThread(). + + * interpreter/Interpreter.h: + Rename MaxMainThreadReentryDepth to MaxLargeThreadReentryDepth and + MaxSecondaryThreadReentryDepth to MaxSmallThreadReentryDepth. + + * jsc.cpp: + (main): Use the a large stack for jsc since it is always using the + main thread. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + (JSC::arrayProtoFuncToLocaleString): + (JSC::arrayProtoFuncJoin): + Use new stored JSGlobalData::maxReentryDepth instead of isMainThread(). + + * runtime/Collector.cpp: + (JSC::Heap::registerThread): + Use the concept of making JSC run on an exclusiveThread instead of + forcing a mainThreadOnly assertion. + + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + (JSC::JSGlobalData::createNonDefault): + (JSC::JSGlobalData::create): + (JSC::JSGlobalData::createLeaked): + (JSC::JSGlobalData::sharedInstance): + * runtime/JSGlobalData.h: + Add ThreadStackType argument to JSGlobalData constructors and set + maxReentryDepth based on it. + +2010-04-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix pt. 3). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-04-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix pt. 2). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-04-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (Qt build fix). + + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * wtf/qt/StringQt.cpp: Copied from WebCore/platform/text/qt/StringQt.cpp. + +2010-04-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix). + + * API/JSValueRef.cpp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * runtime/Identifier.cpp: + (JSC::IdentifierTable::~IdentifierTable): + (JSC::IdentifierTable::add): + * runtime/Identifier.h: + * wtf/WTFThreadData.h: + (JSC::IdentifierTable::remove): + (JSC::IdentifierTable::literalTable): + * wtf/text/StringImpl.cpp: + (WebCore::StringImpl::~StringImpl): + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt, Darin Adler. + + Bug 37906 - Remove JSC::UStringImpl; unify with StringImpl. + + JSC::UStringImpl and WebCore::StringImpl (soon to be renamed to + WTF::StringImpl) are almost identical. Remove duplication of code by unifying + the two, move missing features from UStringImpl into StringImpl & delete the + class UStringImpl. + + * API/JSClassRef.cpp: + * API/JSContextRef.cpp: + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.pro: + * JavaScriptCore.xcodeproj/project.pbxproj: + * bytecode/EvalCodeCache.h: + * bytecode/JumpTable.cpp: + * profiler/ProfileNode.cpp: + * runtime/Identifier.cpp: + (JSC::Identifier::add): + * runtime/Identifier.h: + (JSC::Identifier::equal): + * runtime/UString.cpp: + * runtime/UString.h: + (WTF::): + * runtime/UStringImpl.cpp: Removed. + * runtime/UStringImpl.h: + * wtf/text/StringHash.h: + (WebCore::StringHash::equal): + (WebCore::CaseFoldingHash::equal): + * wtf/text/StringImpl.cpp: + (WebCore::StringImpl::~StringImpl): + (WebCore::StringImpl::empty): + (WebCore::StringImpl::sharedBuffer): + (WebCore::equal): + * wtf/text/StringImpl.h: + (WebCore::StringImpl::StringImpl): + (WebCore::StringImpl::create): + (WebCore::StringImpl::tryCreateUninitialized): + (WebCore::StringImpl::cost): + (WebCore::StringImpl::isIdentifier): + (WebCore::StringImpl::setIsIdentifier): + (WebCore::StringImpl::computeHash): + (WebCore::StringImpl::copyChars): + (WebCore::StringImpl::): + +2010-04-21 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Darin Adler. + + Added missing #include "Lookup.h" in LUT source files. + https://bugs.webkit.org/show_bug.cgi?id=37903 + + * runtime/ArrayPrototype.cpp: + * runtime/DatePrototype.cpp: + * runtime/JSONObject.cpp: + * runtime/MathObject.cpp: + * runtime/NumberConstructor.cpp: + * runtime/RegExpConstructor.cpp: + * runtime/RegExpObject.cpp: + * runtime/StringPrototype.cpp: + +2010-04-21 Gustavo Sverzut Barbieri <barbieri@profusion.mobi> + + Reviewed by Nikolas Zimmermann. + + Add missing EFL JavaScriptCore file. + http://webkit.org/b/37854 + + * wtf/efl: Added. + * wtf/efl/MainThreadEfl.cpp: Added. + (WTF::initializeMainThreadPlatform): + (WTF::timeoutFired): + (WTF::scheduleDispatchFunctionsOnMainThread): + +2010-04-20 Xan Lopez <xlopez@igalia.com> + + Another attempt to fix the build. + + * GNUmakefile.am: + +2010-04-20 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + [ES5] RegExp literals are constants that should be persistent across multiple function calls. + https://bugs.webkit.org/show_bug.cgi?id=37908 + + Dump the separate RegExp constant pool, and just use the standard JS constant pool + in codeblock. This allows us to drop op_new_regexp and all associated code as well. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::shrinkToFit): + * bytecode/CodeBlock.h: + * bytecode/Opcode.h: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::emitLoad): + * bytecompiler/BytecodeGenerator.h: + * bytecompiler/NodesCodegen.cpp: + (JSC::RegExpNode::emitBytecode): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JIT.h: + * jit/JITOpcodes.cpp: + * jit/JITStubs.cpp: + * jit/JITStubs.h: + (JSC::): + +2010-04-20 Oliver Hunt <oliver@apple.com> + + Fix license on create_regex_tables + + * create_regex_tables: + +2010-04-20 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Fix gtk + + * GNUmakefile.am: + * make-generated-sources.sh: + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 37895 - Share common code from UStringImplBase with StringImpl + + The implementation of StringImpl & UStringImpl is very similar. Restructure + StringImpl to match UStringImpl, moving the flags and length into a base class, + so that this can be shared between both string types to increase code reuse. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/RopeImpl.h: + (JSC::RopeImpl::RopeImpl): + * runtime/UStringImpl.h: + (JSC::UStringImpl::UStringImpl): + * wtf/text/StringImpl.h: + (WebCore::StringImpl::StringImpl): + (WebCore::StringImpl::characters): + * wtf/text/StringImplBase.h: Copied from JavaScriptCore/runtime/UStringImpl.h. + (WTF::StringImplBase::length): + (WTF::StringImplBase::operator new): + (WTF::StringImplBase::StringImplBase): + +2010-04-20 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Autogenerate yarr character tables + https://bugs.webkit.org/show_bug.cgi?id=37877 + + Use a python script to automatically generate character tables + for the builtin YARR character classes. This allows us to generate + actual tables as well, by using these tables we can both increase + performance of the check (for complex builtins) and reduce the actual + code size. + + 4-8% win on string-unpack-code, but lots of noise on other tests so + i'm only confident saying its a 1% win overall. + + * DerivedSources.make: + * JavaScriptCore.xcodeproj/project.pbxproj: + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::ExtendedAddress::ExtendedAddress): + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::branchTest8): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::branchTest8): + * assembler/MacroAssemblerX86_64.h: + (JSC::MacroAssemblerX86_64::branchTest8): + * assembler/X86Assembler.h: + (JSC::X86Assembler::cmpb_im): + (JSC::X86Assembler::testb_im): + * bytecode/SamplingTool.cpp: + (JSC::SamplingTool::dump): + * create_regex_tables: Added. + * yarr/RegexCompiler.cpp: + (JSC::Yarr::CharacterClassConstructor::charClass): + * yarr/RegexJIT.cpp: + (JSC::Yarr::RegexGenerator::matchCharacterClass): + (JSC::Yarr::RegexGenerator::generatePatternCharacterGreedy): + (JSC::Yarr::RegexGenerator::generatePatternCharacterNonGreedy): + (JSC::Yarr::RegexGenerator::generateCharacterClassGreedy): + * yarr/RegexPattern.h: + (JSC::Yarr::CharacterClassTable::create): + (JSC::Yarr::CharacterClassTable::CharacterClassTable): + (JSC::Yarr::CharacterClass::CharacterClass): + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (speculative windows fix - missed a bit!). + + * wtf/text/AtomicString.h: + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (speculative windows fix). + + * wtf/text/AtomicString.h: + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix). + + Add missing .def file entries. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Bug 37869 - Move URopeImpl to its own .h/.cpp + + Currently Ropes are implemented by the class URopeImpl, which is defined in + UStringImpl.h, and then typedefed to the name JSString::Rope. Remove the + typedef, and rename all uses of URopeImpl and JSString::Rope to just RopeImpl. + + Move RopeImpl to its own header, and remove all remaining references to ropes + from UStringImpl (rename UStringOrRopeImpl to UStringImplBase, rename or move + the isRope & deref methods from UStringOrRopeImpl). + + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + * runtime/JSString.h: + (JSC::): + (JSC::RopeBuilder::JSString): + (JSC::RopeBuilder::~JSString): + (JSC::RopeBuilder::appendStringInConstruct): + (JSC::RopeBuilder::JSStringFinalizerStruct::): + * runtime/RopeImpl.cpp: Copied from JavaScriptCore/runtime/UStringImpl.cpp. + (JSC::RopeImpl::derefFibersNonRecursive): + (JSC::RopeImpl::destructNonRecursive): + * runtime/RopeImpl.h: Copied from JavaScriptCore/runtime/UStringImpl.h. + (JSC::RopeImpl::tryCreateUninitialized): + (JSC::RopeImpl::isRope): + (JSC::RopeImpl::deref): + (JSC::RopeImpl::RopeImpl): + * runtime/UStringImpl.cpp: + * runtime/UStringImpl.h: + (JSC::UStringImplBase::isInvalid): + (JSC::UStringImplBase::ref): + (JSC::UStringImplBase::UStringImplBase): + (JSC::UStringImplBase::): + (JSC::UStringImpl::UStringImpl): + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Bug 37828 - Move WebCore's String classes to WTF + + Move these classes up to WTF so they are available to all clients of WTF (in + particular JSC). + + As a first patch, making the most minimal change possible, since this patch + could easily grow rather large since we'll have to change every class forward + declaration ( e.g. every "namespace WebCore { class String; }" much change to + "namespace WTF { class String; }"). + + Moving the files, but leaving the classes logically in the WebCore namespace - + which is technically a layering violation - I'll come back and fix this up in a + subsequent patch. + + * Android.mk: + * Android.v8.wtf.mk: + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * config.h: + * wtf/StaticConstructors.h: Copied from WebCore/platform/StaticConstructors.h. + * wtf/text/AtomicString.cpp: Copied from WebCore/platform/text/AtomicString.cpp. + * wtf/text/AtomicString.h: Copied from WebCore/platform/text/AtomicString.h. + * wtf/text/AtomicStringImpl.h: Copied from WebCore/platform/text/AtomicStringImpl.h. + * wtf/text/StringBuffer.h: Copied from WebCore/platform/text/StringBuffer.h. + * wtf/text/StringHash.h: Copied from WebCore/platform/text/StringHash.h. + * wtf/text/StringImpl.cpp: Copied from WebCore/platform/text/StringImpl.cpp. + * wtf/text/StringImpl.h: Copied from WebCore/platform/text/StringImpl.h. + * wtf/text/WTFString.cpp: Copied from WebCore/platform/text/String.cpp. + (WebCore::charactersToFloat): + * wtf/text/WTFString.h: Copied from WebCore/platform/text/PlatformString.h. + +2010-04-20 Csaba Osztrogonác <ossy@webkit.org> + + [Qt] Unreviewed speculative buildfix for WinCE after r57882 + https://bugs.webkit.org/show_bug.cgi?id=37701 + + * JavaScriptCore.pri: missing wince* case added. + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix). + Speculative Chromium/Win build fix, attempt #2. + + * config.h: + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix). + Speculative Chromium/Win build fix. + + * config.h: JS_EXPORTDATA should do nothing on !JSC builds. + +2010-04-20 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed by Simon Hausmann. + + [Qt] Target(WebCore,jsc,...) must depends on static library of JavaScriptCore + https://bugs.webkit.org/show_bug.cgi?id=37701 + + * JavaScriptCore.pri: dependency added. + +2010-04-20 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Maciej Stachowiak (relanding r57829). + Added missing JS_EXPORTDATA + + * API/APIShims.h: + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): + (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): + (JSC::APICallbackShim::APICallbackShim): + (JSC::APICallbackShim::~APICallbackShim): + * API/JSContextRef.cpp: + * Android.mk: + * Android.v8.wtf.mk: + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/Completion.cpp: + (JSC::checkSyntax): + (JSC::evaluate): + * runtime/Identifier.cpp: + (JSC::Identifier::remove): + (JSC::Identifier::checkCurrentIdentifierTable): + * runtime/Identifier.h: + * runtime/InitializeThreading.cpp: + (JSC::initializeThreadingOnce): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::create): + * wtf/WTFThreadData.cpp: Copied from JavaScriptCore/wtf/WTFThreadData.cpp. + * wtf/WTFThreadData.h: Copied from JavaScriptCore/wtf/WTFThreadData.h. + +2010-04-19 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (rolling out r57829). + This broke windows. + + * API/APIShims.h: + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): + (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): + (JSC::APICallbackShim::APICallbackShim): + (JSC::APICallbackShim::~APICallbackShim): + * API/JSContextRef.cpp: + * Android.mk: + * Android.v8.wtf.mk: + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/Completion.cpp: + (JSC::checkSyntax): + (JSC::evaluate): + * runtime/Identifier.cpp: + (JSC::Identifier::remove): + (JSC::Identifier::checkCurrentIdentifierTable): + (JSC::createIdentifierTableSpecificCallback): + (JSC::createIdentifierTableSpecific): + * runtime/Identifier.h: + (JSC::ThreadIdentifierTableData::ThreadIdentifierTableData): + (JSC::defaultIdentifierTable): + (JSC::setDefaultIdentifierTable): + (JSC::currentIdentifierTable): + (JSC::setCurrentIdentifierTable): + (JSC::resetCurrentIdentifierTable): + * runtime/InitializeThreading.cpp: + (JSC::initializeThreadingOnce): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::create): + * wtf/WTFThreadData.cpp: Removed. + * wtf/WTFThreadData.h: Removed. + +2010-04-19 Douglas Gregor <dgregor@apple.com> + + Reviewed and landed by Anders Carlsson. + + * runtime/UStringImpl.h: + Fix class/struct declaration mismatches. + +2010-04-19 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Beth Dakin. + + Checked in these tests I wrote becuase Balazs Kelemen wanted to use them. + + * tests/perf: Added. + * tests/perf/bench-allocate-nonretained.js: Added. + * tests/perf/bench-allocate-retained.js: Added. + +2010-04-19 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-04-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=37745 + Move string uniquing tables to (new) WTFThreadData class. + + Remove AtomicString's dependency on ThreadGlobalData so that we can move + WebCore's string classes up to WTF. + + WTFThreadData.cpp/.h are based on ThreadGlobalData from WebCore. + Moved JSC & WebCore's string uniquing tables to this class. + + This patch introduces a temporary layering violation in providing forward + declarations of classes from JSC and WTF; this will be resolved as we move + more string code up to WTF. + + * API/APIShims.h: + (JSC::APIEntryShimWithoutLock::APIEntryShimWithoutLock): + (JSC::APIEntryShimWithoutLock::~APIEntryShimWithoutLock): + (JSC::APICallbackShim::APICallbackShim): + (JSC::APICallbackShim::~APICallbackShim): + * API/JSContextRef.cpp: + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/Completion.cpp: + (JSC::checkSyntax): + (JSC::evaluate): + * runtime/Identifier.cpp: + (JSC::Identifier::remove): + (JSC::Identifier::checkCurrentIdentifierTable): + * runtime/Identifier.h: + * runtime/InitializeThreading.cpp: + (JSC::initializeThreadingOnce): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::create): + * wtf/WTFThreadData.cpp: Copied from WebCore/platform/ThreadGlobalData.cpp. + (WTF::WTFThreadData::WTFThreadData): + (WTF::WTFThreadData::~WTFThreadData): + * wtf/WTFThreadData.h: Copied from WebCore/platform/ThreadGlobalData.h. + (WTF::WTFThreadData::atomicStringTable): + (WTF::WTFThreadData::initializeIdentifierTable): + (WTF::WTFThreadData::currentIdentifierTable): + (WTF::WTFThreadData::setCurrentIdentifierTable): + (WTF::WTFThreadData::resetCurrentIdentifierTable): + (WTF::wtfThreadData): + +2010-04-19 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Build fix for WinCE. + + Moved the include of the non-existing errno.h header file inside + platform guard macros. + + * jit/ExecutableAllocatorFixedVMPool.cpp: + +2010-04-18 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Laszlo Gombos. + + [WINCE] Don't define WTF_CPU_MIDDLE_ENDIAN=1 + https://bugs.webkit.org/show_bug.cgi?id=37434 + + Windows CE supports little-endian format only, so don't define + WTF_CPU_MIDDLE_ENDIAN=1. + + * wtf/Platform.h: + +2010-04-18 Simon Hausmann <simon.hausmann@nokia.com> + + Reviewed by Laszlo Gombos. + + [Qt] Fix JavaScriptCore's include path for WinCE builds + + https://bugs.webkit.org/show_bug.cgi?id=36751 + + * JavaScriptCore.pri: + +2010-04-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by nobody, build fix. + +2010-04-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by nobody, build fix. + +2010-04-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 37730 - Remove JSC::UString dependencies from WebCore::StringImpl + (Following on from bug #37675). + + Make the argument ordering for UStringImpl's constructor & create + methods match, when passed a shared buffer. + + * JavaScriptCore.exp: + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::create): + * runtime/UStringImpl.h: + +2010-04-15 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Fix memory leak in QScriptEngine::evaluate(). + + QScriptEnginePrivate::evaluate should release temporary variables. + + [Qt] QScriptEngine::evaluate has memory leak. + https://bugs.webkit.org/show_bug.cgi?id=37596 + + * qt/api/qscriptengine_p.cpp: + (QScriptEnginePrivate::evaluate): + * qt/api/qscriptengine_p.h: + +2010-04-14 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Fix a memory leak in QScriptValue::inherits. + + [Qt] QScriptValue::inherits has a memory leak. + https://bugs.webkit.org/show_bug.cgi?id=37617 + + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::inherits): + +2010-04-14 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Fix a few memory leaks in QScriptEngine. + + Syntax checking caused memory leak, not all temporary variables were released. + + [Qt] Syntax checking in the QtScript cause a memory leak. + https://bugs.webkit.org/show_bug.cgi?id=37610 + + * qt/api/qscriptengine_p.cpp: + (QScriptEnginePrivate::checkSyntax): + * qt/api/qscriptsyntaxcheckresult.cpp: + (QScriptSyntaxCheckResultPrivate::errorMessage): + (QScriptSyntaxCheckResultPrivate::errorLineNumber): + +2010-04-14 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Fix memory leak inside QScriptEnginePrivate::makeJSValue. + + QScriptEnginePrivate::makeJSValue should release temporary JSStringRef variable. + + [Qt] tst_QScriptValue::toString has a memory leak. + https://bugs.webkit.org/show_bug.cgi?id=37598 + + * qt/api/qscriptengine_p.h: + (QScriptEnginePrivate::makeJSValue): + +2010-04-14 Peter Varga <pvarga@inf.u-szeged.hu> + + Reviewed by Geoffrey Garen. + + Move the YARR JIT fallback detection from RegexJIT.cpp to + RegexCompiler.cpp. + + https://bugs.webkit.org/show_bug.cgi?id=37571 + + * yarr/RegexCompiler.cpp: + (JSC::Yarr::RegexPatternConstructor::atomBackReference): + (JSC::Yarr::RegexPatternConstructor::quantifyAtom): + * yarr/RegexJIT.cpp: + (JSC::Yarr::RegexGenerator::generateTerm): + (JSC::Yarr::RegexGenerator::RegexGenerator): + (JSC::Yarr::jitCompileRegex): + * yarr/RegexJIT.h: + (JSC::Yarr::RegexCodeBlock::operator!): + * yarr/RegexPattern.h: + (JSC::Yarr::RegexPattern::RegexPattern): + (JSC::Yarr::RegexPattern::reset): + +2010-04-14 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Maciej Stachowiak. + + Mac OS X: Use deployment target to determine whether memory tagging should be enabled + https://bugs.webkit.org/show_bug.cgi?id=34888 + + When building on (Snow) Leopard but targeting Tiger + (TARGETING_TIGER defined, BUILDING_ON_TIGER not defined), + WebKit would crash on Tiger because the tags passed to mmap + caused those function calls to fail. + + Conversely, when building on Tiger but targeting Leopard + (BUILDING_ON_TIGER defined, TARGETING_LEOPARD defined), WebKit + would crash on Leopard because the tags passed to vm_map and + vm_allocate caused those function calls to fail. + + Solution: Use TARGETING_TIGER rather than BUILDING_ON_TIGER to + govern the tag definitions. Use the same tags for vm_map and + vm_allocate regardless of target, since they work on + both. Fall back to the mmap tags that work on Tiger (that is, + "no tags") if targeting Tiger, since those tags also work on + Leopard. + + * wtf/VMTags.h: + +2010-04-12 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by nobody, build fix. + + [Qt] Build fix for Mac when building with build-webkit --qt + + Specifying no configuration on Mac builds WebCore both in debug + and release. JavaScriptCore has to follow this rule as well. + + * JavaScriptCore.pro: + +2010-04-11 Mark Rowe <mrowe@apple.com> + + Reviewed by Sam Weinig. + + <rdar://problem/7851332> Fix the build. + + * wtf/FastMalloc.cpp: + (WTF::TCMallocStats::): Initialize extra members of malloc_introspection_t to zero. + +2010-04-09 Mikhail Naganov <mnaganov@chromium.org> + + Reviewed by Pavel Feldman. + + Make CallIdentifier constructor to handle null urls. + + https://bugs.webkit.org/show_bug.cgi?id=37341 + + * profiler/CallIdentifier.h: + (JSC::CallIdentifier::CallIdentifier): + +2010-04-09 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Fix crashes with package builds in release + + Add NDEBUG to the defines for package build in JavaScriptCore.pri, + so that it's consistently used for JavaScriptCore, WebCore, jsc and all + other tools using wtf, etc. data structures directly. Mixing NDEBUG with + non-NDEBUG builds causes crashes due to differences in data structures when + assertions/checks are enabled. + + * JavaScriptCore.pri: + +2010-04-09 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Darin Adler. + + Implement NO_RETURN for COMPILER(MSVC). + https://bugs.webkit.org/show_bug.cgi?id=33056 + + Added NO_RETURN_WITH_VALUE for functions with non-void return type. + + * jsc.cpp: + * wtf/AlwaysInline.h: + * wtf/FastMalloc.cpp: + +2010-04-08 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Simon Hausmann. + + [WINCE] Check if ARM or _ARM_ is defined + https://bugs.webkit.org/show_bug.cgi?id=37200 + + MSVC defines ARM and _ARM_ for Windows CE ARM. Define WTF_CPU_ARM=1 + when either ARM or _ARM_ is defined. + + * wtf/Platform.h: + +2010-04-08 Csaba Osztrogonác <ossy@webkit.org> + + Reviewed Oliver Hunt. + + [Qt]r57240 broke Qt build (might be a gcc bug) + https://bugs.webkit.org/show_bug.cgi?id=37253 + + Workaround until fix. On PLATFORM(QT) use inline instead of ALWAYS_INLINE. + + * wtf/PassRefPtr.h: Qt guards added. + +2010-04-07 Oliver Hunt <oliver@apple.com> + + Reviewed by Anders Carlsson. + + Vector<UString> makes many needless calls to UString::UString and UString::~UString + + Add a VectorTrait<UString> specialisation to allow vector to simply memset/memcpy + data around. Only difference from the VectorTrait<RefPtr<T> > traits is the inability + to use memset to initialize data. + + * runtime/UString.h: + (WTF::): + +2010-04-07 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + Beat gcc with a clue bat -- force inlining of refIfNotNull and derefIfNotNull + + * wtf/PassRefPtr.h: + +2010-04-07 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Darin Adler. + + Replace isprint with isASCIIPrintable + https://bugs.webkit.org/show_bug.cgi?id=37223 + + WebKit does not use functions in <ctype.h> as they are dependent on the current + locale. Use the equivalent functions in <wtf/ASCIICType.h>. isASCIIPrintable + replaces isprint. + + * pcre/pcre_exec.cpp: + (pchars): + +2010-04-07 Enrica Casucci <enrica@apple.com> + + Reviewed by Darin Adler. + + https://bugs.webkit.org/show_bug.cgi?id=37219 + + This change disables text caret for the iPhone platflorm. + + * wtf/Platform.h: Disabled text caret for iPhone. + +2010-04-06 Adam Barth <abarth@webkit.org> + + Reviewed by Eric Seidel. + + REGRESSION: Worker termination via JS timeout may cause worker tests like fast/workers/worker-terminate.html fail. + https://bugs.webkit.org/show_bug.cgi?id=36646 + + Add a new exception type for forcibly terminating a JavaScript stack. + The new exception functions similarly to the + InterruptedExecutionException but is conceptually different because + execution is terminated instead of just interrupted. + + * GNUmakefile.am: + - Added new Terminator.h file. + * JavaScriptCore.gypi: + - Added new Terminator.h file. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + - Added new Terminator.h file. + * JavaScriptCore.xcodeproj/project.pbxproj: + - Added new Terminator.h file. + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): + - Fully unwind the stack for TerminatedExecutionException. + (JSC::Interpreter::privateExecute): + - Check if we've been terminated at the same time we check if we've + timed out. + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + - Check if we've been terminated at the same time we check if we've + timed out. + * runtime/Completion.cpp: + - Some exceptions define special completion types so that calls can + see why we terminated evaluation. + (JSC::evaluate): + * runtime/Completion.h: + - Define a new completion type for termination. + (JSC::): + * runtime/ExceptionHelpers.cpp: + - Define TerminatedExecutionException and refactor pseudo-RTTI + virtual function to be more semantic. + (JSC::InterruptedExecutionError::exceptionType): + (JSC::TerminatedExecutionError::TerminatedExecutionError): + (JSC::TerminatedExecutionError::exceptionType): + (JSC::TerminatedExecutionError::toString): + (JSC::createTerminatedExecutionException): + * runtime/ExceptionHelpers.h: + - Entry point for generating a TerminatedExecutionException. + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + - Add a Terminator object that can be used to asynchronously + terminate a JavaScript execution stack. + * runtime/JSGlobalData.h: + * runtime/JSObject.h: + (JSC::JSObject::exceptionType): + - Define that, by default, thrown objects have a normal exception + type. + * runtime/Terminator.h: Added. + - Added a new controller object that can be used to terminate + execution asynchronously. This object is more or less a + glorified bool. + (JSC::Terminator::Terminator): + (JSC::Terminator::termianteSoon): + (JSC::Terminator::shouldTerminate): + +2010-04-05 Oliver Hunt <oliver@apple.com> + + And another one. + + * JavaScriptCore.vcproj/jsc/jscCommon.vsprops: + +2010-04-05 Oliver Hunt <oliver@apple.com> + + And another build fix. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make: + +2010-04-05 Oliver Hunt <oliver@apple.com> + + Build fix + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2010-04-05 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Support weak maps in JSC + https://bugs.webkit.org/show_bug.cgi?id=37132 + + Expose an API to allow creation of a map for storing + weak JS references. + + * API/JSWeakObjectMapRefInternal.h: Added. + (OpaqueJSWeakObjectMap::create): + (OpaqueJSWeakObjectMap::map): + (OpaqueJSWeakObjectMap::~OpaqueJSWeakObjectMap): + (OpaqueJSWeakObjectMap::OpaqueJSWeakObjectMap): + * API/JSWeakObjectMapRefPrivate.cpp: Added. + * API/JSWeakObjectMapRefPrivate.h: Added. + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/JSGlobalObject.h: + (JSC::JSGlobalObject::registerWeakMap): + (JSC::JSGlobalObject::deregisterWeakMap): + +2010-04-05 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + [Symbian] Consolidate Symbian WINSCW environment configuration + https://bugs.webkit.org/show_bug.cgi?id=37100 + + Move the "undefinition" of WIN32 and _WIN32 from WebCore/config.h + to JavaScriptCore/wtf/Platform.h as it is not specific to WebCore. + + PLATFORM(WIN) and OS(WIN) no longer needs to be undefined as + undefining WIN32 takes care of it. + + * wtf/Platform.h: + +2010-04-03 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=37068 + Change UString to use a 0 rep for null strings instead of a null object. + + No performance impact. + + * JavaScriptCore.exp: + * runtime/InternalFunction.cpp: + (JSC::InternalFunction::InternalFunction): + * runtime/JSString.h: + (JSC::RopeBuilder::JSString): + * runtime/UString.cpp: + (JSC::initializeUString): + * runtime/UString.h: + (JSC::UString::UString): + (JSC::UString::data): + (JSC::UString::size): + (JSC::UString::isNull): + (JSC::UString::isEmpty): + (JSC::UString::cost): + +2010-04-03 Balazs Kelemen <kb@inf.u-szeged.hu> + + Reviewed by Oliver Hunt. + + Fix uninitalised members in CallLinkInfo and BytecodeGenerator. + + https://bugs.webkit.org/show_bug.cgi?id=36816 + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::CodeBlock): + * bytecode/CodeBlock.h: + (JSC::CallLinkInfo::CallLinkInfo): + +2010-04-03 yael aharon <yael.aharon@nokia.com> + + Reviewed by Darin Adler. + + Enable HTMLProgressElement for Safari on OSX + https://bugs.webkit.org/show_bug.cgi?id=36961 + + * Configurations/FeatureDefines.xcconfig: + +2010-04-02 Ruben Van Boxem <vanboxem.ruben@gmail.com> + + Reviewed by Eric Seidel. + + Mingw-w64 fixes for JavaScriptCore + https://bugs.webkit.org/show_bug.cgi?id=35607 + + * runtime/Collector.cpp: use the msvc code for mingw-w64 (but not mingw-w32) + (JSC::Heap::allocateBlock): + (JSC::Heap::freeBlockPtr): + (JSC::currentThreadStackBase): + (JSC::currentThreadStackBase): + * wtf/Platform.h: added COMPILER(MINGW64) check to differentiate between mingw.org and mingw-w64 functions + +2010-04-02 Geoffrey Garen <ggaren@apple.com> + + Build fix: updated the .def file. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-04-02 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Oliver Hunt. + + Inlined toThisString and toThisJSString to avoid virtual function call overhead + https://bugs.webkit.org/show_bug.cgi?id=37039 + + Maybe a 1% speedup on iBench JS. + + * JavaScriptCore.exp: New exports. + + * runtime/JSCell.cpp: + * runtime/JSCell.h: + * runtime/JSNumberCell.cpp: + * runtime/JSNumberCell.h: + * runtime/JSString.cpp: + * runtime/JSString.h: + * runtime/JSValue.h: + * runtime/JSZombie.h: + (JSC::JSZombie::toThisObject): Nixed the old virtual-type implementation. + + * runtime/JSObject.h: + (JSC::JSValue::toThisString): + (JSC::JSValue::toThisJSString): Added the inlined implementation. + +2010-04-02 Jeremy Moskovich <jeremy@chromium.org> + + Reviewed by Geoffrey Garen. + + Beef up documentation for ASSERT* and CRASH macros a bit. + + https://bugs.webkit.org/show_bug.cgi?id=36527 + + * wtf/Assertions.h: + +2010-04-02 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed, minor build fix. + + Change the order of the member initialisation list + in constructor to match declaration order + + * runtime/Collector.cpp: + (JSC::Heap::Heap): + +2010-04-01 Kinuko Yasuda <kinuko@chromium.org> + + Reviewed by Dmitry Titov. + + Add FileThread for async file operation support in FileReader and FileWriter + https://bugs.webkit.org/show_bug.cgi?id=36896 + + Add ENABLE_FILE_READER and ENABLE_FILE_WRITER flags. + + * Configurations/FeatureDefines.xcconfig: + +2010-03-31 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix pt II). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-31 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-31 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Bug 36871 - Remove JSC::CString + Use WTF::CString instead (which until recently was WebCore::CString). + + * JavaScriptCore.exp: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * runtime/UString.cpp: + * runtime/UString.h: + +2010-03-31 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed, fix after r56842. + + Add UNUSED_PARAM a to silence warning. + + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + +2010-03-31 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed, Symbian build fix. + + Refactor JITStubs.cpp so that the list of STUB_FUNCTIONs + are not dependent on the JSVALUE32_64 guard. + + * jit/JITStubs.cpp: Place the JSVALUE32_64 guard inside + the body of cti_op_eq_strings. + * jit/JITStubs.h: Remove JSVALUE32_64 guard from + cti_op_eq_strings stub. + +2010-03-30 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix). + + Fixing b0rked version of JavaScriptCore.vcproj - added lines were truncated. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + +2010-03-30 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Sam Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=36866 + Move CString to WTF + + * Android.mk: + * GNUmakefile.am: + * JavaScriptCore.exp: + * JavaScriptCore.gypi: + * JavaScriptCore.pro: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/WTF/WTF.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/text: Added. + * wtf/text/CString.cpp: Copied from WebCore/platform/text/CString.cpp. + * wtf/text/CString.h: Copied from WebCore/platform/text/CString.h. + (WTF::CStringBuffer::data): + (WTF::CStringBuffer::length): + (WTF::CStringBuffer::create): + (WTF::CStringBuffer::CStringBuffer): + (WTF::CStringBuffer::mutableData): + (WTF::CString::CString): + (WTF::CString::isNull): + (WTF::CString::buffer): + (WTF::operator!=): + +2010-03-30 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by nobody, build break. + + [Qt] Fix build break on Qt Mac. + + DESTDIR path on Mac do not include the configuration path by default + like on Windows. Have to force it. + + * JavaScriptCore.pro: + +2010-03-29 Alice Liu <alice.liu@apple.com> + + Reviewed by NOBODY (build fix). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make: + add JSObjectRefPrivate.h + +2010-03-29 Chao-ying Fu <fu@mips.com> + + Reviewed by Oliver Hunt. + + MIPS JIT Supports + https://bugs.webkit.org/show_bug.cgi?id=30144 + + The following changes enable MIPS JIT. + + * assembler/MIPSAssembler.h: + (JSC::MIPSAssembler::lbu): + (JSC::MIPSAssembler::linkWithOffset): + * assembler/MacroAssemblerMIPS.h: + (JSC::MacroAssemblerMIPS::load8): + (JSC::MacroAssemblerMIPS::branch8): + (JSC::MacroAssemblerMIPS::branchTest8): + (JSC::MacroAssemblerMIPS::setTest8): + (JSC::MacroAssemblerMIPS::setTest32): + * jit/JIT.h: + * jit/JITInlineMethods.h: + (JSC::JIT::preserveReturnAddressAfterCall): + (JSC::JIT::restoreReturnAddressBeforeReturn): + * jit/JITOpcodes.cpp: + * jit/JITStubs.cpp: + (JSC::JITThunks::JITThunks): + * jit/JITStubs.h: + (JSC::JITStackFrame::returnAddressSlot): + * wtf/Platform.h: + +2010-02-26 Kenneth Rohde Christiansen <kenneth@webkit.org> + + Reviewed by Simon Fraser. + + Add support for Widgets 1.0: View Mode Media Feature + https://bugs.webkit.org/show_bug.cgi?id=35446 + + Add an enable flag for the Widgets (http://www.w3.org/TR/widgets-reqs/) + and turn it on for Qt only. + + * wtf/Platform.h: + +2010-03-29 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Darin Adler. + + Corrected name of (u)int64_t compile time assert. + https://bugs.webkit.org/show_bug.cgi?id=36739 + + int64_t_is_four_bytes -> int64_t_is_eight_bytes + + * os-win32/stdint.h: + +2010-03-29 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Use the -l syntax for linking against JavaScriptCore on Windows. + This allow qmake to extract dependencies correctly when generating VS + solutions. + + * JavaScriptCore.pri: + +2010-03-29 Thomas Zander <t.zander@nokia.com> + + Reviewed by Simon Hausmann. + + https://bugs.webkit.org/show_bug.cgi?id=36742 + + gcc for Symbian doesn't support gcc extensions like atomicity.h - disable + + * wtf/Threading.h: also detect os symbian + +2010-03-28 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Remove the definition of WTF_CHANGES guards from the build system + https://bugs.webkit.org/show_bug.cgi?id=31670 + + * JavaScriptCore.pro: Remove the definition of WTF_CHANGES + as it is already defined in config.h + +2010-03-28 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Add API for reporting additional memory cost of JavaScript objects + https://bugs.webkit.org/show_bug.cgi?id=36650 + + * qt/api/qscriptengine.cpp: + (QScriptEngine::reportAdditionalMemoryCost): + * qt/api/qscriptengine.h: + * qt/api/qscriptengine_p.h: + (QScriptEnginePrivate::reportAdditionalMemoryCost): + * qt/tests/qscriptengine/tst_qscriptengine.cpp: + (tst_QScriptEngine::reportAdditionalMemoryCost): + +2010-03-28 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + QScriptEngine API was enriched by globalObject() method + which give an access to the global object. + + [Qt] QScriptEngine doesn't give an access to global object + https://bugs.webkit.org/show_bug.cgi?id=36603 + + * qt/api/qscriptengine.cpp: + (QScriptEngine::globalObject): + * qt/api/qscriptengine.h: + * qt/api/qscriptengine_p.cpp: + (QScriptEnginePrivate::globalObject): + * qt/api/qscriptengine_p.h: + * qt/tests/qscriptengine/tst_qscriptengine.cpp: + (tst_QScriptEngine::globalObject): + +2010-03-26 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Simon Hausmann. + + [Qt] Build JavaScriptCore as a static library. + https://bugs.webkit.org/show_bug.cgi?id=36590 + + This patch takes what was left of the unused JavaScriptCore.pro + and moved the compilation logic from JavaScriptCore.pri to + JavaScriptCore.pro. + + * JavaScriptCore.pri: + * JavaScriptCore.pro: + * jsc.pro: + * qt/api/QtScript.pro: + +2010-03-25 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix). + + * profiler/ProfileGenerator.cpp: + (JSC::ProfileGenerator::willExecute): + (JSC::ProfileGenerator::didExecute): + +2010-03-25 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Geoff Garen. + + Bug 36611 - Cleanup JSC::CString + Rename CString::c_str() -> CString::data(), CString::size() -> CString::length(), + remove UString::getCString() (all uses are wrong, should use UString::UTF8String()). + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::printUnaryOp): + (JSC::CodeBlock::printBinaryOp): + (JSC::CodeBlock::printConditionalJump): + (JSC::CodeBlock::printGetByIdOp): + (JSC::CodeBlock::printPutByIdOp): + (JSC::printGlobalResolveInfo): + (JSC::printStructureStubInfo): + (JSC::CodeBlock::printStructure): + (JSC::CodeBlock::printStructures): + (JSC::CodeBlock::dump): + * jsc.cpp: + (functionPrint): + (functionDebug): + (runInteractive): + (fillBufferWithContentsOfFile): + * profiler/CallIdentifier.h: + (JSC::CallIdentifier::c_str): + * profiler/Profile.cpp: + (JSC::Profile::debugPrintDataSampleStyle): + * profiler/ProfileNode.cpp: + (JSC::ProfileNode::debugPrintData): + (JSC::ProfileNode::debugPrintDataSampleStyle): + * runtime/DateConversion.cpp: + (JSC::parseDate): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::encode): + (JSC::globalFuncJSCPrint): + * runtime/UString.cpp: + (JSC::operator==): + (JSC::UString::toDouble): + * runtime/UString.h: + (JSC::CString::length): + (JSC::CString::data): + +2010-03-25 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by nobody, build fix. + + [Qt] Build fix on MSVC. Reverts r55633 for stdint.h + + This file gets included in generated moc files which don't + include the prefix header. + + * os-win32/stdint.h: + +2010-03-24 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (windows build fix). + +2010-03-24 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + Switch String::latin1, String::utf8, String::fromUTF8 to + use WTF's Unicode conversion methods rather than TextEncoder. + These methods only perform simple conversion, and don't need + really require TextEncoder's full capability (to look up arbitrary + encodings by name), switching to only be dependent on WTF will + make it easier if we chose to move WebCore::String to WTF. + + * JavaScriptCore.exp: + +2010-03-24 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Geoff Garen. + + * wtf/FastMalloc.h: Added a using directive for fastMallocSize, like we do for all public + WTF symbols. Also sorted the list alphabetically. + +2010-03-23 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (speculative windows build fix part II). + +2010-03-23 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (speculative windows build fix). + +2010-03-23 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 36519 - JSGlobalContextRelease is unnecessarily slow + + Since [ http://trac.webkit.org/changeset/35917 ], calling + JSGlobalContextRelease always triggers a GC heap collection + (if not a full destroy). As per 35917's changelog "This is + only really necessary when the (JSGlobalObject's) last + reference is released, but there is no way to determine that, + and no harm in collecting slightly more often." + + Well, we now know of cases of API clients who are harmed by + the performance penalty of collecting too often, so it's time + to add a way to determine whether a call to JSGlobalContextRelease + is removing the last protect from it's global object. If further + protects are retaining the global object (likely from other + JSGlobalContextRefs), then don't trigger a GC collection. + + * API/JSContextRef.cpp: + * runtime/Collector.cpp: + (JSC::Heap::unprotect): return a boolean indicating that the value is now unprotected. + * runtime/Collector.h: + * wtf/HashCountedSet.h: + (WTF::::remove): return a boolean indicating whether the value was removed from the set. + +2010-03-23 Mark Rowe <mrowe@apple.com> + + Build fix. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncSplice): Some versions of GCC emit a warning about the implicit 64- to 32-bit truncation + that takes place here. An explicit cast is sufficient to silence it. + +2010-03-23 Alexey Proskuryakov <ap@apple.com> + + Build fix. + + * runtime/ArrayPrototype.cpp: (JSC::arrayProtoFuncSplice): Fixed a typo - length doesn't + need to be converted with toInteger(). + +2010-03-23 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Geoff Garen. + + https://bugs.webkit.org/show_bug.cgi?id=36511 + <rdar://problem/7753498> Safari freezes when using SPUTNIK JavaScript conformance check + + Test: fast/js/sputnik-S15.4.4.12_A3_T3.html + + * runtime/ArrayPrototype.cpp: (JSC::arrayProtoFuncSplice): We were incorrectly computing + the start offset, and iterated over (almost) all integers. Note that this can be fixed + without using doubles, but the code would be much more complicated, and there is no important + reason to stick to integers here. + +2010-03-23 Kent Hansen <kent.hansen@nokia.com> + + Reviewed by Darin Adler. + + Fix compilation on Itanium in 32-bit mode + https://bugs.webkit.org/show_bug.cgi?id=36494 + + * wtf/Platform.h: Introduce CPU(IA64_32). Don't define + WTF_USE_JSVALUE64 if the CPU is in 32-bit mode. + +2010-03-23 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Mark Rowe. + + Interpreter fix for <rdar://problem/7728196> REGRESSION (r46701): -(-2147483648) + evaluates to -2147483648 on 32 bit (35842) + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): Only take the fast negate path if + a bit other than bit 31 is set. If none of bits 0-30 are set, then the + value we're negating can only be 0 or -2147483648, and neither can be + negated in int space. + + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_negate): + (JSC::JIT::emitSlow_op_negate): Updated the JIT implementation to match + the interpreter, since it's slightly simpler. + +2010-03-22 Siddharth Mathur <siddharth.mathur@nokia.com> + + Reviewed by Laszlo Gombos. + + [Symbian] More efficient aligned memory allocation for JSC Collector + https://bugs.webkit.org/show_bug.cgi?id=34350 + + * JavaScriptCore.pri: Added 2 new Symbian source files and HAL linkage + + * runtime/Collector.cpp: Reduced port-specific code and added private data member + (JSC::Heap::Heap): + (JSC::Heap::~Heap): + (JSC::Heap::destroy): + (JSC::Heap::allocateBlock): + (JSC::Heap::freeBlockPtr): + + * runtime/Collector.h: Added private data member + + * wtf/symbian: Added. + * wtf/symbian/BlockAllocatorSymbian.cpp: Added. + (WTF::AlignedBlockAllocator::AlignedBlockAllocator): Helper class to allocate + aligned blocks more efficiently as required by Collector + (WTF::AlignedBlockAllocator::alloc): + (WTF::AlignedBlockAllocator::free): + (WTF::AlignedBlockAllocator::destroy): + (WTF::AlignedBlockAllocator::~AlignedBlockAllocator): + * wtf/symbian/BlockAllocatorSymbian.h: Added. + +2010-03-22 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Fixed <rdar://problem/7728196> REGRESSION (r46701): -(-2147483648) + evaluates to -2147483648 on 32 bit (35842) + + Two ways to fix the same bug: + + 1. Check for overflow when negating, since negating the largest negative + int causes overflow. + + 2. Constant-fold even when negating a negative, since, like they say in + high school, "math works." + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::branchNeg32): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::branchNeg32): Added a branching version + of the negate operator. + + * jit/JITArithmetic.cpp: + (JSC::JIT::emit_op_negate): Use the branching version of the negate + operator to check for overflow. + + (JSC::JIT::emitSlow_op_negate): Link the check for overflow to a slow case. + (We could emit inline code for this, since we know what the result would + be, but that's probably just a waste of generated code.) + + * parser/Grammar.y: Constant fold even when negating a negative. + +2010-03-22 David Kilzer <ddkilzer@apple.com> + + <http://webkit.org/b/36431> Clean up 'int' use in UString.cpp after r54789 + + Reviewed by Darin Adler. + + * runtime/UString.cpp: + (JSC::UString::from): Changed argument type from 'unsigned int' + to 'unsigned' to match WebKit coding style. + (JSC::UString::find): Changed static_cast<int>() to + static_cast<unsigned>() now that this method returns unsigned. + (JSC::UString::rfind): Ditto. + * runtime/UString.h: + (JSC::UString::from): Changed argument type from 'unsigned int' + to 'unsigned' to match WebKit coding style. + +2010-03-22 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Kenneth Rohde Christiansen. + + Add support for syntax checking in the QtScript API. + + New class was created; the QScriptSyntaxCheckResult which main + responsibility is to provide results of the ECMA Script code + syntax check. The class is not fully functional as the JSC C API + doesn't expose an error column number, but it is a good start point + for a future development. + + [Qt] QtScript functionality should be extended by syntax checking. + https://bugs.webkit.org/show_bug.cgi?id=36123 + + * qt/api/QtScript.pro: + * qt/api/qscriptengine.cpp: + (QScriptEngine::checkSyntax): + * qt/api/qscriptengine.h: + * qt/api/qscriptengine_p.cpp: + (QScriptEnginePrivate::checkSyntax): + * qt/api/qscriptengine_p.h: + * qt/api/qscriptsyntaxcheckresult.cpp: Added. + (QScriptSyntaxCheckResult::QScriptSyntaxCheckResult): + (QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult): + (QScriptSyntaxCheckResult::operator=): + (QScriptSyntaxCheckResult::state): + (QScriptSyntaxCheckResult::errorLineNumber): + (QScriptSyntaxCheckResult::errorColumnNumber): + (QScriptSyntaxCheckResult::errorMessage): + * qt/api/qscriptsyntaxcheckresult.h: Added. + * qt/api/qscriptsyntaxcheckresult_p.cpp: Added. + (QScriptSyntaxCheckResultPrivate::~QScriptSyntaxCheckResultPrivate): + (QScriptSyntaxCheckResultPrivate::errorMessage): + (QScriptSyntaxCheckResultPrivate::errorLineNumber): + * qt/api/qscriptsyntaxcheckresult_p.h: Added. + (QScriptSyntaxCheckResultPrivate::get): + (QScriptSyntaxCheckResultPrivate::QScriptSyntaxCheckResultPrivate): + (QScriptSyntaxCheckResultPrivate::state): + (QScriptSyntaxCheckResultPrivate::errorColumnNumber): + * qt/tests/qscriptengine/tst_qscriptengine.cpp: + (tst_QScriptEngine::checkSyntax_data): + (tst_QScriptEngine::checkSyntax): + +2010-03-21 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + New class; QScriptProgram. + + The class should be used to evaluate the same script multiple times + more efficiently. + + [Qt] QtScript should have QScriptProgram class + https://bugs.webkit.org/show_bug.cgi?id=36008 + + * qt/api/QtScript.pro: + * qt/api/qscriptengine.cpp: + (QScriptEngine::evaluate): + * qt/api/qscriptengine.h: + * qt/api/qscriptengine_p.cpp: + (QScriptEnginePrivate::evaluate): + * qt/api/qscriptengine_p.h: + (QScriptEnginePrivate::evaluate): + * qt/api/qscriptprogram.cpp: Added. + (QScriptProgram::QScriptProgram): + (QScriptProgram::~QScriptProgram): + (QScriptProgram::operator=): + (QScriptProgram::isNull): + (QScriptProgram::sourceCode): + (QScriptProgram::fileName): + (QScriptProgram::firstLineNumber): + (QScriptProgram::operator==): + (QScriptProgram::operator!=): + * qt/api/qscriptprogram.h: Added. + * qt/api/qscriptprogram_p.h: Added. + (QScriptProgramPrivate::get): + (QScriptProgramPrivate::QScriptProgramPrivate): + (QScriptProgramPrivate::~QScriptProgramPrivate): + (QScriptProgramPrivate::isNull): + (QScriptProgramPrivate::sourceCode): + (QScriptProgramPrivate::fileName): + (QScriptProgramPrivate::firstLineNumber): + (QScriptProgramPrivate::operator==): + (QScriptProgramPrivate::operator!=): + (QScriptProgramPrivate::program): + (QScriptProgramPrivate::file): + (QScriptProgramPrivate::line): + * qt/tests/qscriptengine/tst_qscriptengine.cpp: + (tst_QScriptEngine::evaluateProgram): + +2010-03-21 David Kilzer <ddkilzer@apple.com> + + Blind attempt #2 to fix the Windows build after r56314 + + * API/tests/testapi.c: Include JSObjectRefPrivate.h for the new + methods instead of declaring them locally (and non-extern). + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + Backed out previous change. + +2010-03-21 David Kilzer <ddkilzer@apple.com> + + Blind attempt to fix the Windows build after r56314 + + Try to fix the following errors on the Windows buildbot: + + Linking... + testapi.obj : error LNK2001: unresolved external symbol "bool __cdecl JSObjectSetPrivateProperty(struct OpaqueJSContext const *,struct OpaqueJSValue *,struct OpaqueJSString *,struct OpaqueJSValue const *)" (?JSObjectSetPrivateProperty@@YA_NPBUOpaqueJSContext@@PAUOpaqueJSValue@@PAUOpaqueJSString@@PBU2@@Z) + testapi.obj : error LNK2001: unresolved external symbol "struct OpaqueJSValue const * __cdecl JSObjectGetPrivateProperty(struct OpaqueJSContext const *,struct OpaqueJSValue *,struct OpaqueJSString *)" (?JSObjectGetPrivateProperty@@YAPBUOpaqueJSValue@@PBUOpaqueJSContext@@PAU1@PAUOpaqueJSString@@@Z) + C:\cygwin\home\buildbot\slave\win-release\build\WebKitBuild\bin\testapi.exe : fatal error LNK1120: 2 unresolved externals + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Added + missing symbols to be exported. + +2010-03-21 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Documentation fix for previous patch. + + * API/JSObjectRefPrivate.h: + +2010-03-20 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + JSC needs an API to allow custom objects to have aprivate GC-accessible properties + https://bugs.webkit.org/show_bug.cgi?id=36420 + + Add new API methods to support "private" properties on custom + objects. + + * API/JSCallbackObject.h: + (JSC::JSCallbackObjectData::JSCallbackObjectData): + (JSC::JSCallbackObjectData::~JSCallbackObjectData): + (JSC::JSCallbackObjectData::getPrivateProperty): + (JSC::JSCallbackObjectData::setPrivateProperty): + (JSC::JSCallbackObjectData::deletePrivateProperty): + (JSC::JSCallbackObjectData::markChildren): + (JSC::JSCallbackObjectData::JSPrivatePropertyMap::getPrivateProperty): + (JSC::JSCallbackObjectData::JSPrivatePropertyMap::setPrivateProperty): + (JSC::JSCallbackObjectData::JSPrivatePropertyMap::deletePrivateProperty): + (JSC::JSCallbackObjectData::JSPrivatePropertyMap::markChildren): + (JSC::JSCallbackObject::getPrivateProperty): + (JSC::JSCallbackObject::setPrivateProperty): + (JSC::JSCallbackObject::deletePrivateProperty): + (JSC::JSCallbackObject::markChildren): + * API/JSObjectRef.cpp: + (JSObjectGetPrivateProperty): + (JSObjectSetPrivateProperty): + (JSObjectDeletePrivateProperty): + * API/JSObjectRefPrivate.h: Added. + * API/tests/testapi.c: + (main): + * JavaScriptCore.exp: + * JavaScriptCore.xcodeproj/project.pbxproj: + +2010-03-20 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Build fixes after introduction of Brew files. + + * wscript: + +2010-03-18 Tom Callaway <tcallawa@redhat.com> + + Reviewed by Darin Adler. + + Bug 35429: Fix compile on SPARC64 + https://bugs.webkit.org/show_bug.cgi?id=35429 + + * wtf/Platform.h: Set WTF_USE_JSVALUE64 for SPARC64 + +2010-03-18 Oliver Hunt <oliver@apple.com> + + Reviewed by Sam Weinig. + + Add API to directly expose JSON parsing + https://bugs.webkit.org/show_bug.cgi?id=34887 + + Add API to expose JSON parsing directly, and add tests to testapi + + * API/JSValueRef.cpp: + (JSValueMakeFromJSONString): + (JSValueCreateJSONString): + * API/tests/testapi.c: + (main): + * JavaScriptCore.exp: + * runtime/JSONObject.cpp: + (JSC::JSONStringify): + * runtime/JSONObject.h: + +2010-03-16 Sam Weinig <sam@webkit.org> + + Reviewed by Darin Adler and Mark Rowe. + + Update WebKit availability macros for release after 4.0. + + * API/WebKitAvailability.h: + +2010-03-17 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + undefined, NaN, and Infinity should be ReadOnly + https://bugs.webkit.org/show_bug.cgi?id=36263 + + Simply add the ReadOnly flag to these properties. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::reset): + +2010-03-17 Darin Adler <darin@apple.com> + + Reviewed by Oliver Hunt. + + Speed up Math.round a little by removing unneeded special case + https://bugs.webkit.org/show_bug.cgi?id=36107 + + Test: fast/js/math.html + + * runtime/MathObject.cpp: + (JSC::mathProtoFuncRound): This function had a special case for numbers + between -0.5 and -0.0 to return -0.0. But the algorithm in the function + already yields -0.0 for those cases, so the extra checking and branching + is unneeded. + +2010-03-17 Mike Homey <glandium@debian.org> + + Reviewed by Gustavo Noronha. + + Build fix for SPARC. Fix missing macro value. + + * wtf/Platform.h: + +2010-03-16 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt, Darin Adler. + + Bug 36083 - REGRESSION (r55772-r55834): Crash in JavaScriptCore RegExp code on PowerPC + + The problem is a bug in our port of PCRE - that a read may take place from the first character in an + empty string. For the time being, revert to using a valid pointer in the data segment rather than + an invalid non-null pointer into the zero-page for the empty string's data pointer. A better fix for + this will be to remove PCRE. + + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::empty): + +2010-03-16 Darin Adler <darin@apple.com> + + Rolled out r56081 since it broke the Windows build. + +2010-03-16 Zoltan Horvath <zoltan@webkit.org> + + Reviewed by Darin Adler. + + Remove extra <new> include and add guards to operator new/delete definitions + https://bugs.webkit.org/show_bug.cgi?id=35967 + + Remove extra <new> header include from FastAlloc.cpp since it is included in + FastAlloc.h. Add ENABLE(GLOBAL_FASTMALLOC_NEW) macro guard to operator + new/delete/new []/delete [] definitions. + + * wtf/FastMalloc.cpp: + +2010-03-15 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Eric Seidel. + + [BREWMP] Add a function to create a BREW instance without local variable declarations. + https://bugs.webkit.org/show_bug.cgi?id=34705 + + Add a template function to create a BREW instance in one line. + + * wtf/brew/ShellBrew.h: Added. + (WTF::createInstance): + +2010-03-15 Geoffrey Garen <ggaren@apple.com> + + Not reviewed. + + Removed a now-incorrect comment I forgot to remove in my last check-in. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::scavenge): + +2010-03-15 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Sam Weinig. + + Fixed a portion of: + <rdar://problem/7165917> | https://bugs.webkit.org/show_bug.cgi?id=28676 + Safari 4 does not release memory back to the operating system fast enough (28676) + + Every few seconds, release a percentage of the minimum unused page count + during that time period. + + SunSpider reports no change, command-line or in-browser, Mac or Windows. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::init): + (WTF::TCMalloc_PageHeap::signalScavenger): + (WTF::TCMalloc_PageHeap::initializeScavenger): Renamed shouldContinueScavenging + to shouldScavenge, since scavenging is no longer something that we interrupt. + + (WTF::TCMalloc_PageHeap::scavenge): The new scavenging algorithm. Fixes + a bug where the old code would release only one item from each size class + per scavenge, potentially leaving large numbers of large-sized objects + unreleased for a long time. + + (WTF::TCMalloc_PageHeap::shouldScavenge): + (WTF::TCMalloc_PageHeap::New): + (WTF::TCMalloc_PageHeap::AllocLarge): + (WTF::TCMalloc_PageHeap::Delete): + (WTF::TCMalloc_PageHeap::GrowHeap): + (WTF::TCMalloc_PageHeap::scavengerThread): + (WTF::TCMalloc_PageHeap::periodicScavenge): Updated to track the minimum + value of free_committed_pages_ during a given scavenge period. + +2010-03-15 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Sam Weinig. + + https://bugs.webkit.org/show_bug.cgi?id=35843 + Re-land reverted fix to JSString::getIndex() + + Calling getIndex() on a JSString in rope form may result in a JSException being thrown + if there is insuficient memory so value(exec) returns UString() with length zero, + which will be passed to jsSingleCharacterSubstring. + Add a slow case function to trap the error & return a safe null value, until the + exception is handled. + + * runtime/JSString.cpp: + (JSC::JSString::getIndexSlowCase): + (JSC::JSString::getStringPropertyDescriptor): + * runtime/JSString.h: + (JSC::jsSingleCharacterSubstring): + (JSC::JSString::getIndex): + (JSC::jsSingleCharacterString): + (JSC::JSString::getStringPropertySlot): + +2010-03-04 Kenneth Rohde Christiansen <kenneth@webkit.org> + + Reviewed by Adam Roben. + + Add a long long version of abs() for MSVC. + + * wtf/MathExtras.h: + (abs): + +2010-03-15 Gabor Loki <loki@webkit.org> + + Reviewed by Gavin Barraclough. + + Combine ctiTrampolines on ARM and Thumb-2 + https://bugs.webkit.org/show_bug.cgi?id=36014 + + * jit/JITStubs.cpp: + (JSC::JITThunks::JITThunks): + +2010-03-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-12 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (build fix). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-11 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 36075 - Clean up screwyness re static string impls & Identifiers. + + * API/JSClassRef.cpp: + (OpaqueJSClass::~OpaqueJSClass): Classname may be null/empty, and these are an identifer. This is okay, since the null/empty strings are shared across all threads. + * JavaScriptCore.exp: + * runtime/Identifier.cpp: + (JSC::Identifier::add): No need to explicitly hash null reps, this is done in the ststic UStringImpl constructor. + (JSC::Identifier::addSlowCase): UStringImpl::empty() handled & checkCurrentIdentifierTable now called in the header. + (JSC::Identifier::checkCurrentIdentifierTable): Replaces checkSameIdentifierTable (this no longer checked the rep since the identifierTable pointer was removed from UString::Rep long ago). + * runtime/Identifier.h: + (JSC::Identifier::add): Replace call to checkSameIdentifierTable with call to checkCurrentIdentifierTable at head of function. + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::~UStringImpl): Remove call to checkConsistency - this function no longer checks anything interesting. + * runtime/UStringImpl.h: + (JSC::UStringOrRopeImpl::UStringOrRopeImpl): Set s_refCountFlagIsIdentifier in static constructor. + (JSC::UStringImpl::UStringImpl): remove calls to checkConsistency (see above), add new ASSERT to substring constructor. + (JSC::UStringImpl::setHash): ASSERT not static (static strings set the hash in their constructor, should not reach this code path). + (JSC::UStringImpl::create): Add missing ASSERT. + (JSC::UStringImpl::setIsIdentifier): ASSERT !isStatic() (static strings hash set in constructor). + +2010-03-12 Peter Varga <pvarga@inf.u-szeged.hu> + + Reviewed by David Levin. + + Two functions tryConsumeCharacter() and tryConsumeCharacterClass() are + removed from yarr/RegexInterpreter.cpp because they are never called. + + * yarr/RegexInterpreter.cpp: + +2010-03-11 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + The JSNative state was renamed to JSPrimitive. The new name better + coresponds to the ECMAScript standard. + + Enum QScriptValuePrivate::States was renamed to State to obey Qt + coding style rules ("States" name suggests that a state could + mixed together with an other state using bitwise logic operators. + + [Qt] QScriptValuePrivate::States has naming issues + https://bugs.webkit.org/show_bug.cgi?id=35968 + + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::): + (QScriptValuePrivate::QScriptValuePrivate): + (QScriptValuePrivate::isBool): + (QScriptValuePrivate::isNumber): + (QScriptValuePrivate::isNull): + (QScriptValuePrivate::isString): + (QScriptValuePrivate::isUndefined): + (QScriptValuePrivate::toString): + (QScriptValuePrivate::toNumber): + (QScriptValuePrivate::toBool): + (QScriptValuePrivate::assignEngine): + (QScriptValuePrivate::refinedJSValue): + +2010-03-11 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (Windows build fix). + + Add export. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-11 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (Windows build fix). + + Add export. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-11 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Oliver Hunt. + + Remove nonsense comments used in development & commited in error. + + * runtime/UStringImpl.h: + +2010-03-11 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (Windows build fix). + + Remove export. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-11 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=36041 + Remove unnecessary differences in common code between WebCore::StringImpl & JSC::UStringImpl + + Much of the code in WebCore::StringImpl and JSC::UStringImpl is now very similar, + but has trivial and unnecessary formatting differences, such as the exact wording + of comments, missing ASSERTs, functions implemented in the .h vs .cpp etc. + + * runtime/Identifier.cpp: + (JSC::Identifier::add): UStringImpl::empty() now automatically hashes, uas per WebCore strings. + (JSC::Identifier::addSlowCase): UStringImpl::empty() now automatically hashes, uas per WebCore strings. + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::~UStringImpl): Only call bufferOwnership() once, add missing ASSERTs. + (JSC::UStringImpl::createUninitialized): Move from .h, not commonly called, no need to inline. + (JSC::UStringImpl::create): Move from .h, not commonly called, no need to inline. + (JSC::UStringImpl::sharedBuffer): Rewritten to more closely match WebCore implementation, remove need for separate baseSharedBuffer() method. + * runtime/UStringImpl.h: + (JSC::UStringImpl::UStringImpl): Automatically hash static strings, ASSERT m_data & m_length are non-null/non-zero in non-static strings. + (JSC::UStringImpl::setHash): Add missing ASSERT. + (JSC::UStringImpl::create): Moved to .cpp / added missing check for empty string creation. + (JSC::UStringImpl::adopt): Vector.size() returns size_t, not unsigned. + (JSC::UStringImpl::cost): Renamed m_bufferSubstring -> m_substringBuffer + (JSC::UStringImpl::hash): Reordered in file. + (JSC::UStringImpl::existingHash): Reordered in file. + (JSC::UStringImpl::computeHash): Reordered in file, renamed parameter. + (JSC::UStringImpl::checkConsistency): rewrote ASSERT. + (JSC::UStringImpl::bufferOwnership): Return type should be BufferOwnership. + (JSC::UStringImpl::): Moved friends to head of class. + +2010-03-11 Mark Rowe <mrowe@apple.com> + + Reviewed by David Kilzer. + + <rdar://problem/7745082> Make it possible to build WebKit for older Mac OS X versions from the current Mac OS X version + + Default to using the appropriate SDK if the target Mac OS X version is not the current Mac OS X version. + + * Configurations/Base.xcconfig: + +2010-03-11 Mark Rowe <mrowe@apple.com> + + Reviewed by Tim Hatcher. + + <rdar://problem/7745082> Make it possible to build WebKit for older Mac OS X versions from the current Mac OS X version + + Introduce TARGET_MAC_OS_X_VERSION_MAJOR to represent the Mac OS X version that is being targeted. It defaults to the + current Mac OS X version unless otherwise specified. + + Key off TARGET_MAC_OS_X_VERSION_MAJOR where we'd previously been keying off MAC_OS_X_VERSION_MAJOR. + + Explicitly map from the target Mac OS X version to the preferred compiler since Xcode's default compiler choice + may not be usable when targetting a different Mac OS X version. + + Key off TARGET_GCC_VERSION rather than MAC_OS_X_VERSION_MAJOR in locations where we'd previously been keying off + MAC_OS_X_VERSION_MAJOR but the decision is really related to the compiler version being used. + + * Configurations/Base.xcconfig: + * Configurations/DebugRelease.xcconfig: + * Configurations/FeatureDefines.xcconfig: + * Configurations/JavaScriptCore.xcconfig: + * Configurations/Version.xcconfig: + +2010-03-11 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Mark Rowe. + + Sort the project file. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2010-03-11 Simon Fraser <simon.fraser@apple.com> + + Reviewed by Mark Rowe. + + Sort the project file . + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2010-03-11 Gabor Loki <loki@webkit.org> + + Reviewed by Gavin Barraclough. + + Buildfix for Thumb-2 after r55684. Add branch8 and branchTest8 functions. + https://bugs.webkit.org/show_bug.cgi?id=35892 + + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::): + (JSC::ARMv7Assembler::ldrb): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::load8): + (JSC::MacroAssemblerARMv7::branch8): + (JSC::MacroAssemblerARMv7::branchTest8): + (JSC::MacroAssemblerARMv7::setTest8): + +2010-03-10 Gavin Barraclough <barraclough@apple.com> + + Rubber stamped by Oliver Hunt. + + Rename JSC::UStringImpl::data() to characters(), to match WebCore::StringImpl. + + * API/JSClassRef.cpp: + (OpaqueJSClassContextData::OpaqueJSClassContextData): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::keyForCharacterSwitch): + * bytecompiler/NodesCodegen.cpp: + (JSC::processClauseList): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + * runtime/Identifier.cpp: + (JSC::Identifier::equal): + (JSC::Identifier::addSlowCase): + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + * runtime/UString.cpp: + (JSC::UString::toStrictUInt32): + (JSC::equal): + * runtime/UString.h: + (JSC::UString::data): + * runtime/UStringImpl.h: + (JSC::UStringImpl::characters): + (JSC::UStringImpl::hash): + (JSC::UStringImpl::setHash): + +2010-03-10 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Darin Adler, Geoffrey Garen, Maciej Stachowiak. + + https://bugs.webkit.org/show_bug.cgi?id=35991 + Would be faster to not use a thread specific to implement StringImpl::empty() + + Change JSC::UStringImpl's implementation of empty() match to match StringImpl's new implementation + (use a static defined within the empty() method), and change the interface to match too (return + a pointer not a reference). + + ~0% performance impact (possible minor progression from moving empty() from .h to .cpp). + + * JavaScriptCore.exp: + * runtime/Identifier.cpp: + (JSC::Identifier::add): + (JSC::Identifier::addSlowCase): + * runtime/PropertyNameArray.cpp: + (JSC::PropertyNameArray::add): + * runtime/UString.cpp: + (JSC::initializeUString): + (JSC::UString::UString): + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::empty): + (JSC::UStringImpl::create): + * runtime/UStringImpl.h: + (JSC::UStringImpl::adopt): + (JSC::UStringImpl::createUninitialized): + (JSC::UStringImpl::tryCreateUninitialized): + +2010-03-10 Dmitry Titov <dimich@chromium.org> + + Not reviewed, fixing Snow Leopard build. + + * wtf/mac/MainThreadMac.mm: Forgot 'static' for a new local function. + (WTF::postTimer): + +2010-03-10 Dmitry Titov <dimich@chromium.org> + + Reviewed by Darin Adler. + + Make Document::postTask to use a single queue of tasks, to fire them in order + https://bugs.webkit.org/show_bug.cgi?id=35943 + + The patch uses CFRunLoopTimer to schedule execution of tasks instead of performSelectorOnMainThread which apparently can starve other event sources. + The timer is used when the schedule request is coming on the main thread itself. This happens when the task is posted on the main thread or + when too many tasks are posted and the queue does 'stop and re-schedule' to make sure run loop has a chance to execute other events. + + * wtf/mac/MainThreadMac.mm: + (WTF::timerFired): + (WTF::postTimer): + (WTF::scheduleDispatchFunctionsOnMainThread): Use timer posted to the current RunLoop if scheduling the task execution while on the main thread. + +2010-03-10 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: added new symbol. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-10 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: removed old symbol. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Alexey Proskuryakov, Darin Adler, and Sam Weinig. + + Refactored fastCheckConsistency to match some review comments: + - renamed fastCheckConsistency to fastMallocSize, and changed ValueCheck + to ASSERT that a pointer's fastMallocSize is not 0. + - implemented a version of fastMallocSize for tcmalloc. + + Also moved some pre-existing code around to avoid a problem related to + mismatched #define/#undef of malloc/free in this source file. + + * JavaScriptCore.exp: + * wtf/FastMalloc.cpp: + (WTF::fastMallocSize): Renamed. Fixed indentation. + + (WTF::TCMalloc_PageHeap::scavenge): Removed an incorrect ASSERT that + got in the way of testing the tcmalloc implementation. (More information + on why this ASSERT is incorrect is in <rdar://problem/7165917>.) + + (WTF::TCMallocStats::fastMallocSize): Implemented for tcmalloc. + + * wtf/FastMalloc.h: Updated for rename. + + * wtf/ValueCheck.h: + (WTF::): Moved the ASSERT that used to be in fastCheckConsistency here. + +2010-03-10 Kevin Ollivier <kevino@theolliviers.com> + + Reviewed by Eric Seidel. + + Make global new/delete operators configurable for all ports and disable it + for the wx port for now. + + * wtf/FastMalloc.h: + * wtf/Platform.h: + +2010-03-09 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (reverting r54510). + + This caused a performance regression, by breaking the code + generator's logic to calculate the skip level for resolving + variables (traced by rdar:7683350) Reverting for now. + + * parser/Grammar.y: + * parser/NodeConstructors.h: + (JSC::ContinueNode::ContinueNode): + (JSC::BreakNode::BreakNode): + (JSC::ForInNode::ForInNode): + * runtime/CommonIdentifiers.cpp: + (JSC::CommonIdentifiers::CommonIdentifiers): + * runtime/CommonIdentifiers.h: + * runtime/FunctionPrototype.cpp: + (JSC::FunctionPrototype::FunctionPrototype): + * runtime/Identifier.cpp: + (JSC::Identifier::add): + * runtime/PropertyNameArray.cpp: + (JSC::PropertyNameArray::add): + +2010-03-09 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Darin Adler. + + Changed FastMalloc statistics reporting to be a bit clearer. We now + report: + - Reserved VM Bytes: the VM that has been mapped into the process. + - Committed VM Bytes: the subset of Reserved VM Bytes actually in use. + - Free List Bytes: the subset of Committed VM Bytes in a free list. + + * wtf/FastMalloc.cpp: + (WTF::fastMallocStatistics): + (WTF::TCMallocStats::fastMallocStatistics): Updated to report the statistics + above. Standardized use of "ifdef WTF_CHANGES". Added a SpinLockHolder + around all statistics gathering, since it reads from the page heap. + + * wtf/FastMalloc.h: Updated to report the statistics above. + +2010-03-09 Gabor Loki <loki@webkit.org> + + Rubber-stamped by Maciej Stachowiak. + + Buildfix for ARM after r55684. Add branch8 and branchTest8 functions. + https://bugs.webkit.org/show_bug.cgi?id=35892 + + * assembler/ARMAssembler.cpp: + (JSC::ARMAssembler::dataTransfer32): + * assembler/ARMAssembler.h: + (JSC::ARMAssembler::): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::load8): + (JSC::MacroAssemblerARM::branch8): + (JSC::MacroAssemblerARM::branchTest8): + +2010-03-08 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: 'P' is not a type. Luckily, 'void' is. + + * wtf/FastMalloc.cpp: + (WTF::fastCheckConsistency): + +2010-03-08 Geoffrey Garen <ggaren@apple.com> + + Windows build fix: export a new symbol. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-08 Geoffrey Garen <ggaren@apple.com> + + Reviewed by Maciej Stachowiak. + + Switching malloc implementations requires a world rebuild + https://bugs.webkit.org/show_bug.cgi?id=35899 + + * wtf/FastMalloc.cpp: + (WTF::fastCheckConsistency): + (WTF::TCMallocStats::fastCheckConsistency): + * wtf/FastMalloc.h: + * wtf/ValueCheck.h: + (WTF::): Moved pointer checking into a helper function in FastMalloc.cpp, + so you can switch malloc implementations without rebuilding the world. + +2010-03-07 Oliver Hunt <oliver@apple.com> + + Reviewed by Darin Adler. + + TypeInfo is unnecessarily large + https://bugs.webkit.org/show_bug.cgi?id=35850 + + Reduce the size of the type and flags members to a single + byte each, reducing the size of Structure by 8 bytes. + + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::branch8): + (JSC::MacroAssemblerX86Common::branchTest8): + (JSC::MacroAssemblerX86Common::setTest8): + Add single byte branches, and correct setTest8 to do a + single byte read from memory, and actually store the result + * assembler/X86Assembler.h: + (JSC::X86Assembler::): + (JSC::X86Assembler::cmpb_im): + (JSC::X86Assembler::testb_im): + * jit/JITCall.cpp: + (JSC::JIT::emit_op_construct_verify): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_instanceof): + (JSC::JIT::emit_op_jeq_null): + (JSC::JIT::emit_op_jneq_null): + (JSC::JIT::emit_op_get_pnames): + (JSC::JIT::emit_op_convert_this): + (JSC::JIT::emit_op_construct_verify): + (JSC::JIT::emit_op_to_jsnumber): + (JSC::JIT::emit_op_eq_null): + (JSC::JIT::emit_op_neq_null): + * runtime/JSTypeInfo.h: + (JSC::TypeInfo::TypeInfo): + (JSC::TypeInfo::type): + +2010-03-08 Gavin Barraclough <barraclough@apple.com> + + Reviewed by NOBODY (reverting regression). + + Reverting 55035, this caused a regression. + (https://bugs.webkit.org/show_bug.cgi?id=35843) + + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + (JSC::JSString::getStringPropertyDescriptor): + * runtime/JSString.h: + (JSC::jsSingleCharacterSubstring): + (JSC::JSString::getIndex): + (JSC::JSString::getStringPropertySlot): + * runtime/UStringImpl.cpp: + * runtime/UStringImpl.h: + +2010-03-08 Stuart Morgan <stuartmorgan@chromium.org> + + Reviewed by Darin Adler. + + Added a new USE definition for secure text mode on the Mac. + https://bugs.webkit.org/show_bug.cgi?id=31265 + + * wtf/Platform.h: + +2010-03-08 Jian Li <jianli@chromium.org> + + Reviewed by Dmitry Titov. + + Blob.slice support. + https://bugs.webkit.org/show_bug.cgi?id=32993 + + Add ENABLE_BLOB_SLICE feature define. + Also fix a problem that JSValue.toInteger is not exposed on Windows. + + * Configurations/FeatureDefines.xcconfig: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-07 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + Small performance fix in the QScriptConverter::toString(). + + The QByteArray was replaced by the QVarLengthArray which doesn't + have to allocate any memory on heap. + + [Qt] QScriptConverter::toString() should use QVarLengthArray instead of QByteArray + https://bugs.webkit.org/show_bug.cgi?id=35577 + + * qt/api/qscriptconverter_p.h: + (QScriptConverter::toString): + +2010-03-06 Mark Rowe <mrowe@apple.com> + + Rubber-stamped by Sam Weinig. + + Remove unnecessary includes of wtf/Platform.h. This is already pulled in by config.h. + + * API/APICast.h: + * API/JSCallbackFunction.cpp: + * API/JSContextRef.cpp: + * API/JSObjectRef.cpp: + * API/JSValueRef.cpp: + * assembler/ARMAssembler.h: + * assembler/ARMv7Assembler.h: + * assembler/AbstractMacroAssembler.h: + * assembler/AssemblerBuffer.h: + * assembler/AssemblerBufferWithConstantPool.h: + * assembler/CodeLocation.h: + * assembler/LinkBuffer.h: + * assembler/MIPSAssembler.h: + * assembler/MacroAssembler.h: + * assembler/MacroAssemblerARM.h: + * assembler/MacroAssemblerARMv7.h: + * assembler/MacroAssemblerCodeRef.h: + * assembler/MacroAssemblerMIPS.h: + * assembler/MacroAssemblerX86.h: + * assembler/MacroAssemblerX86Common.h: + * assembler/MacroAssemblerX86_64.h: + * assembler/RepatchBuffer.h: + * assembler/X86Assembler.h: + * jit/JIT.h: + * jit/JITCode.h: + * jit/JITInlineMethods.h: + * jit/JITStubs.h: + * os-win32/stdint.h: + * runtime/JSAPIValueWrapper.h: + * runtime/JSImmediate.h: + * wtf/ASCIICType.h: + * wtf/StdLibExtras.h: + * wtf/VMTags.h: + * yarr/RegexCompiler.h: + * yarr/RegexInterpreter.h: + * yarr/RegexJIT.h: + * yarr/RegexParser.h: + * yarr/RegexPattern.h: + +2010-03-06 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Eric Seidel. + + [BREWMP] Share OwnPtr. + https://bugs.webkit.org/show_bug.cgi?id=35776 + + Share OwnPtr implementation with BREW MP and remove OwnPtrBrew. + + * wtf/OwnPtrBrew.cpp: Added. + (WTF::deleteOwnedPtr): + * wtf/OwnPtrCommon.h: + * wtf/brew/OwnPtrBrew.cpp: Removed. + * wtf/brew/OwnPtrBrew.h: Removed. + +2010-03-06 Patrick Gansterer <paroga@paroga.com> + + Reviewed by Eric Seidel. + + Implemented JIT_OPTIMIZE_NATIVE_CALL for WinCE + https://bugs.webkit.org/show_bug.cgi?id=33426 + + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + +2010-03-05 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (build fix). + + Add enw exports to windows + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-05 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + JSC should cache int to Identifier conversion as it does for ordinary strings + https://bugs.webkit.org/show_bug.cgi?id=35814 + + Make the NumericStrings cache cache unsigned ints in addition to signed. + We keep them separate from the int cache as it both simplifies code, and + also because the unsigned path is exclusive to property access and therefore + seems to have different usage patterns. + + The primary trigger for the unsigned to Identifier propertyName conversion + is the construction of array-like objects out of normal objects. Given these + tend to be relative small numbers, and the array-like behaviour lends itself + to sequential values this patch also adds a non-colliding cache for all small + numbers. + + * JavaScriptCore.exp: + * runtime/Identifier.cpp: + (JSC::Identifier::from): + * runtime/Identifier.h: + * runtime/NumericStrings.h: + (JSC::NumericStrings::add): + (JSC::NumericStrings::lookup): + (JSC::NumericStrings::lookupSmallString): + +2010-03-03 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Allow static property getters to interact with JSCs caching + https://bugs.webkit.org/show_bug.cgi?id=35716 + + Add new opcodes for handling cached lookup of static value getters. + More or less the same as with JS getters, all that changes is that + instead of calling through a JSFunction we always know that we have + a C function to call. + + For the patching routines in the JIT we now need to pass a few + new parameters to allow us to pass enough information to the stub + function to allow us to call the C function correctly. Logically + this shouldn't actually be necessary as all of these functions ignore + the identifier, but removing the ident parameter would require + somewhat involved changes to the way we implement getOwnPropertySlot, + etc. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + (JSC::CodeBlock::derefStructures): + (JSC::CodeBlock::refStructures): + * bytecode/Instruction.h: + (JSC::Instruction::Instruction): + (JSC::Instruction::): + * bytecode/Opcode.h: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::tryCacheGetByID): + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JIT.h: + (JSC::JIT::compileGetByIdProto): + (JSC::JIT::compileGetByIdSelfList): + (JSC::JIT::compileGetByIdProtoList): + (JSC::JIT::compileGetByIdChainList): + (JSC::JIT::compileGetByIdChain): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + * jit/JITStubs.cpp: + (JSC::JITThunks::tryCacheGetByID): + (JSC::DEFINE_STUB_FUNCTION): + * jit/JITStubs.h: + (JSC::): + * runtime/JSFunction.cpp: + (JSC::JSFunction::getOwnPropertySlot): + * runtime/Lookup.h: + (JSC::getStaticPropertySlot): + (JSC::getStaticValueSlot): + * runtime/PropertySlot.h: + (JSC::PropertySlot::): + (JSC::PropertySlot::PropertySlot): + (JSC::PropertySlot::cachedPropertyType): + (JSC::PropertySlot::isCacheable): + (JSC::PropertySlot::isCacheableValue): + (JSC::PropertySlot::setValueSlot): + (JSC::PropertySlot::setCacheableCustom): + (JSC::PropertySlot::setGetterSlot): + (JSC::PropertySlot::setCacheableGetterSlot): + (JSC::PropertySlot::clearOffset): + (JSC::PropertySlot::customGetter): + +2010-03-04 Shinichiro Hamaji <hamaji@chromium.org> + + Unreviewed. Remove a non-ASCII character introduced in the following bug. + + put_by_id does will incorrectly cache writes where a specific value exists, where at the point of caching the same value is being written. + https://bugs.webkit.org/show_bug.cgi?id=35537 + + * runtime/JSObject.h: + (JSC::JSObject::putDirectInternal): + +2010-03-04 Jocelyn Turcotte <jocelyn.turcotte@nokia.com> + + Reviewed by Tor Arne Vestbø. + + [Qt] Make the OUTPUT_DIR variable in qmake projects independent of build-webkit's logic. + + This also allows shadow builds relying only on qmake to work properly. + * jsc.pro: + * qt/api/QtScript.pro: + * qt/tests/qscriptengine/qscriptengine.pro: + * qt/tests/qscriptvalue/qscriptvalue.pro: + * qt/tests/tests.pri: + +2010-03-03 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + QScriptValue::isObject fix. + + Fix broken internal state evaluation from JSValue to JSNative / JSObject. + New function was introduced which should take care about promoting + JSValue state inside QScriptValuePrivate. It should be used instead of a + direct JSC C API call. + + The bug exposed a weakness in autotest suite, as the QScriptValuePrivate + is based on state machine with lazy state evaluation, there is a possibility + that serial sequencial calls to the same public const function could return + different results. The patch fix the issue. + + [Qt] Sometimes QScriptValue::isObject returns an incorrect value + https://bugs.webkit.org/show_bug.cgi?id=35387 + + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::isBool): + (QScriptValuePrivate::isNumber): + (QScriptValuePrivate::isNull): + (QScriptValuePrivate::isString): + (QScriptValuePrivate::isUndefined): + (QScriptValuePrivate::isError): + (QScriptValuePrivate::isObject): + (QScriptValuePrivate::isFunction): + (QScriptValuePrivate::call): + (QScriptValuePrivate::refineJSValue): + * qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp: + (tst_QScriptValue::initScriptValues): + (tst_QScriptValue::isValid_makeData): + (tst_QScriptValue::isValid_test): + (tst_QScriptValue::isBool_makeData): + (tst_QScriptValue::isBool_test): + (tst_QScriptValue::isBoolean_makeData): + (tst_QScriptValue::isBoolean_test): + (tst_QScriptValue::isNumber_makeData): + (tst_QScriptValue::isNumber_test): + (tst_QScriptValue::isFunction_test): + (tst_QScriptValue::isNull_makeData): + (tst_QScriptValue::isNull_test): + (tst_QScriptValue::isString_makeData): + (tst_QScriptValue::isString_test): + (tst_QScriptValue::isUndefined_makeData): + (tst_QScriptValue::isUndefined_test): + (tst_QScriptValue::isObject_makeData): + (tst_QScriptValue::isObject_test): + (tst_QScriptValue::toString_makeData): + (tst_QScriptValue::toString_test): + (tst_QScriptValue::toNumber_makeData): + (tst_QScriptValue::toNumber_test): + (tst_QScriptValue::toBool_makeData): + (tst_QScriptValue::toBool_test): + (tst_QScriptValue::toBoolean_makeData): + (tst_QScriptValue::toBoolean_test): + (tst_QScriptValue::toInteger_makeData): + (tst_QScriptValue::toInteger_test): + (tst_QScriptValue::toInt32_makeData): + (tst_QScriptValue::toInt32_test): + (tst_QScriptValue::toUInt32_makeData): + (tst_QScriptValue::toUInt32_test): + (tst_QScriptValue::toUInt16_makeData): + (tst_QScriptValue::toUInt16_test): + +2010-03-03 Chao-ying Fu <fu@mips.com> + + Reviewed by Gavin Barraclough. + + MIPS JIT Supports + https://bugs.webkit.org/show_bug.cgi?id=30144 + + The following changes enable MIPS YARR and YARR_JIT. + + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::Imm32::Imm32): + * assembler/MIPSAssembler.h: Added. + (JSC::MIPSRegisters::): + (JSC::MIPSAssembler::MIPSAssembler): + (JSC::MIPSAssembler::): + (JSC::MIPSAssembler::JmpSrc::JmpSrc): + (JSC::MIPSAssembler::JmpDst::JmpDst): + (JSC::MIPSAssembler::JmpDst::isUsed): + (JSC::MIPSAssembler::JmpDst::used): + (JSC::MIPSAssembler::emitInst): + (JSC::MIPSAssembler::nop): + (JSC::MIPSAssembler::loadDelayNop): + (JSC::MIPSAssembler::copDelayNop): + (JSC::MIPSAssembler::move): + (JSC::MIPSAssembler::li): + (JSC::MIPSAssembler::lui): + (JSC::MIPSAssembler::addiu): + (JSC::MIPSAssembler::addu): + (JSC::MIPSAssembler::subu): + (JSC::MIPSAssembler::mult): + (JSC::MIPSAssembler::mfhi): + (JSC::MIPSAssembler::mflo): + (JSC::MIPSAssembler::mul): + (JSC::MIPSAssembler::andInsn): + (JSC::MIPSAssembler::andi): + (JSC::MIPSAssembler::nor): + (JSC::MIPSAssembler::orInsn): + (JSC::MIPSAssembler::ori): + (JSC::MIPSAssembler::xorInsn): + (JSC::MIPSAssembler::xori): + (JSC::MIPSAssembler::slt): + (JSC::MIPSAssembler::sltu): + (JSC::MIPSAssembler::sltiu): + (JSC::MIPSAssembler::sll): + (JSC::MIPSAssembler::sllv): + (JSC::MIPSAssembler::sra): + (JSC::MIPSAssembler::srav): + (JSC::MIPSAssembler::lw): + (JSC::MIPSAssembler::lwl): + (JSC::MIPSAssembler::lwr): + (JSC::MIPSAssembler::lhu): + (JSC::MIPSAssembler::sw): + (JSC::MIPSAssembler::jr): + (JSC::MIPSAssembler::jalr): + (JSC::MIPSAssembler::jal): + (JSC::MIPSAssembler::bkpt): + (JSC::MIPSAssembler::bgez): + (JSC::MIPSAssembler::bltz): + (JSC::MIPSAssembler::beq): + (JSC::MIPSAssembler::bne): + (JSC::MIPSAssembler::bc1t): + (JSC::MIPSAssembler::bc1f): + (JSC::MIPSAssembler::newJmpSrc): + (JSC::MIPSAssembler::appendJump): + (JSC::MIPSAssembler::addd): + (JSC::MIPSAssembler::subd): + (JSC::MIPSAssembler::muld): + (JSC::MIPSAssembler::lwc1): + (JSC::MIPSAssembler::ldc1): + (JSC::MIPSAssembler::swc1): + (JSC::MIPSAssembler::sdc1): + (JSC::MIPSAssembler::mtc1): + (JSC::MIPSAssembler::mfc1): + (JSC::MIPSAssembler::truncwd): + (JSC::MIPSAssembler::cvtdw): + (JSC::MIPSAssembler::ceqd): + (JSC::MIPSAssembler::cngtd): + (JSC::MIPSAssembler::cnged): + (JSC::MIPSAssembler::cltd): + (JSC::MIPSAssembler::cled): + (JSC::MIPSAssembler::cueqd): + (JSC::MIPSAssembler::coled): + (JSC::MIPSAssembler::coltd): + (JSC::MIPSAssembler::culed): + (JSC::MIPSAssembler::cultd): + (JSC::MIPSAssembler::label): + (JSC::MIPSAssembler::align): + (JSC::MIPSAssembler::getRelocatedAddress): + (JSC::MIPSAssembler::getDifferenceBetweenLabels): + (JSC::MIPSAssembler::size): + (JSC::MIPSAssembler::executableCopy): + (JSC::MIPSAssembler::getCallReturnOffset): + (JSC::MIPSAssembler::linkJump): + (JSC::MIPSAssembler::linkCall): + (JSC::MIPSAssembler::linkPointer): + (JSC::MIPSAssembler::relinkJump): + (JSC::MIPSAssembler::relinkCall): + (JSC::MIPSAssembler::repatchInt32): + (JSC::MIPSAssembler::repatchPointer): + (JSC::MIPSAssembler::repatchLoadPtrToLEA): + (JSC::MIPSAssembler::relocateJumps): + (JSC::MIPSAssembler::linkWithOffset): + (JSC::MIPSAssembler::linkCallInternal): + * assembler/MacroAssembler.h: + * assembler/MacroAssemblerMIPS.h: Added. + (JSC::MacroAssemblerMIPS::MacroAssemblerMIPS): + (JSC::MacroAssemblerMIPS::): + (JSC::MacroAssemblerMIPS::add32): + (JSC::MacroAssemblerMIPS::and32): + (JSC::MacroAssemblerMIPS::lshift32): + (JSC::MacroAssemblerMIPS::mul32): + (JSC::MacroAssemblerMIPS::not32): + (JSC::MacroAssemblerMIPS::or32): + (JSC::MacroAssemblerMIPS::rshift32): + (JSC::MacroAssemblerMIPS::sub32): + (JSC::MacroAssemblerMIPS::xor32): + (JSC::MacroAssemblerMIPS::load32): + (JSC::MacroAssemblerMIPS::load32WithUnalignedHalfWords): + (JSC::MacroAssemblerMIPS::load32WithAddressOffsetPatch): + (JSC::MacroAssemblerMIPS::loadPtrWithPatchToLEA): + (JSC::MacroAssemblerMIPS::loadPtrWithAddressOffsetPatch): + (JSC::MacroAssemblerMIPS::load16): + (JSC::MacroAssemblerMIPS::store32WithAddressOffsetPatch): + (JSC::MacroAssemblerMIPS::store32): + (JSC::MacroAssemblerMIPS::supportsFloatingPoint): + (JSC::MacroAssemblerMIPS::supportsFloatingPointTruncate): + (JSC::MacroAssemblerMIPS::pop): + (JSC::MacroAssemblerMIPS::push): + (JSC::MacroAssemblerMIPS::move): + (JSC::MacroAssemblerMIPS::swap): + (JSC::MacroAssemblerMIPS::signExtend32ToPtr): + (JSC::MacroAssemblerMIPS::zeroExtend32ToPtr): + (JSC::MacroAssemblerMIPS::branch32): + (JSC::MacroAssemblerMIPS::branch32WithUnalignedHalfWords): + (JSC::MacroAssemblerMIPS::branch16): + (JSC::MacroAssemblerMIPS::branchTest32): + (JSC::MacroAssemblerMIPS::jump): + (JSC::MacroAssemblerMIPS::branchAdd32): + (JSC::MacroAssemblerMIPS::branchMul32): + (JSC::MacroAssemblerMIPS::branchSub32): + (JSC::MacroAssemblerMIPS::breakpoint): + (JSC::MacroAssemblerMIPS::nearCall): + (JSC::MacroAssemblerMIPS::call): + (JSC::MacroAssemblerMIPS::ret): + (JSC::MacroAssemblerMIPS::set32): + (JSC::MacroAssemblerMIPS::setTest32): + (JSC::MacroAssemblerMIPS::moveWithPatch): + (JSC::MacroAssemblerMIPS::branchPtrWithPatch): + (JSC::MacroAssemblerMIPS::storePtrWithPatch): + (JSC::MacroAssemblerMIPS::tailRecursiveCall): + (JSC::MacroAssemblerMIPS::makeTailRecursiveCall): + (JSC::MacroAssemblerMIPS::loadDouble): + (JSC::MacroAssemblerMIPS::storeDouble): + (JSC::MacroAssemblerMIPS::addDouble): + (JSC::MacroAssemblerMIPS::subDouble): + (JSC::MacroAssemblerMIPS::mulDouble): + (JSC::MacroAssemblerMIPS::convertInt32ToDouble): + (JSC::MacroAssemblerMIPS::insertRelaxationWords): + (JSC::MacroAssemblerMIPS::branchTrue): + (JSC::MacroAssemblerMIPS::branchFalse): + (JSC::MacroAssemblerMIPS::branchEqual): + (JSC::MacroAssemblerMIPS::branchNotEqual): + (JSC::MacroAssemblerMIPS::branchDouble): + (JSC::MacroAssemblerMIPS::branchTruncateDoubleToInt32): + (JSC::MacroAssemblerMIPS::linkCall): + (JSC::MacroAssemblerMIPS::repatchCall): + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::cacheFlush): + * wtf/Platform.h: + * yarr/RegexJIT.cpp: + (JSC::Yarr::RegexGenerator::generateEnter): + (JSC::Yarr::RegexGenerator::generateReturn): + +2010-03-03 Steve Falkenburg <sfalken@apple.com> + + Windows build fix. + + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + * JavaScriptCore.vcproj/jsc/jscCommon.vsprops: + +2010-03-03 Steve Falkenburg <sfalken@apple.com> + + Windows build fix. + + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + +2010-03-03 Mark Rowe <mrowe@apple.com> + + Reviewed by Geoff Garen. + + Add virtual memory tags for TCMalloc and WebCore's purgeable buffers. + + * wtf/TCSystemAlloc.cpp: + (TryMmap): Use the VM tag. + * wtf/VMTags.h: Make use of VM_MEMORY_TCMALLOC and VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS. + +2010-03-03 Steve Falkenburg <sfalken@apple.com> + + Rubber stamped by Adam Roben. + + Fix bogus xcopy that was polluting source tree at build time. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + +2010-03-02 Fridrich Strba <fridrich.strba@bluewin.ch> + + Reviewed by Oliver Hunt. + + Allow building smoothly on win32 and win64 using GCC + https://bugs.webkit.org/show_bug.cgi?id=35607 + + * jit/JITStubs.h: + * runtime/Collector.cpp: + (JSC::Heap::allocateBlock): + (JSC::Heap::freeBlockPtr): + (JSC::currentThreadStackBase): + +2010-03-02 Jeremy Orlow <jorlow@chromium.org> + + Reviewed by David Levin. + + Revert database thread changes that are no longer required + https://bugs.webkit.org/show_bug.cgi?id=35519 + + Jochen Eisinger created 55214 and 55247 to track which database + owns which thread. Dmitry suggested that this could also + be done via TLS, though. After exploring the options, Jochen + chose to go the TLS route, so these patches are no longer needed. + + * wtf/Threading.h: + * wtf/ThreadingNone.cpp: + (WTF::isMainThread): + * wtf/ThreadingPthreads.cpp: + (WTF::identifierByPthreadHandle): + (WTF::establishIdentifierForPthreadHandle): + (WTF::pthreadHandleForIdentifier): + (WTF::createThreadInternal): + (WTF::currentThread): + * wtf/ThreadingWin.cpp: + (WTF::threadMap): + (WTF::storeThreadHandleByIdentifier): + (WTF::threadHandleForIdentifier): + (WTF::createThreadInternal): + +2010-03-02 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + Fix QScriptValue::toString(). + + More ECMA Script compliance, especially for values as NaN, Inifinite + and really big/small numbers. + + [Qt] QScriptValue::toString() returns incorrect values + https://bugs.webkit.org/show_bug.cgi?id=34850 + + * qt/api/qscriptconverter_p.h: + (QScriptConverter::toString): + * qt/api/qscriptvalue_p.h: + (QScriptValuePrivate::toString): + * qt/tests/qscriptvalue/tst_qscriptvalue.cpp: + * qt/tests/qscriptvalue/tst_qscriptvalue.h: + * qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp: + (tst_QScriptValue::toString_initData): + (tst_QScriptValue::toString_makeData): + (tst_QScriptValue::toString_test): + +2010-03-02 Jedrzej Nowacki <jedrzej.nowacki@nokia.com> + + Reviewed by Simon Hausmann. + + Introduce a new class; QScriptString. + + The QScriptString class should act as a handle to "interned" + strings in a QScriptEngine. + + [Qt] QtScript should provide QScriptString + https://bugs.webkit.org/show_bug.cgi?id=34843 + + * qt/api/QtScript.pro: + * qt/api/qscriptengine.cpp: + (QScriptEngine::toStringHandle): + * qt/api/qscriptengine.h: + * qt/api/qscriptengine_p.h: + (QScriptEnginePrivate::toStringHandle): + * qt/api/qscriptstring.cpp: Added. + (QScriptString::QScriptString): + (QScriptString::~QScriptString): + (QScriptString::operator=): + (QScriptString::isValid): + (QScriptString::operator==): + (QScriptString::operator!=): + (QScriptString::toArrayIndex): + (QScriptString::toString): + (QScriptString::operator QString): + (qHash): + * qt/api/qscriptstring.h: Added. + * qt/api/qscriptstring_p.h: Added. + (QScriptStringPrivate::QScriptStringPrivate): + (QScriptStringPrivate::~QScriptStringPrivate): + (QScriptStringPrivate::get): + (QScriptStringPrivate::isValid): + (QScriptStringPrivate::operator==): + (QScriptStringPrivate::operator!=): + (QScriptStringPrivate::toArrayIndex): + (QScriptStringPrivate::toString): + (QScriptStringPrivate::id): + * qt/tests/qscriptstring/qscriptstring.pro: Added. + * qt/tests/qscriptstring/tst_qscriptstring.cpp: Added. + (tst_QScriptString::tst_QScriptString): + (tst_QScriptString::~tst_QScriptString): + (tst_QScriptString::test): + (tst_QScriptString::hash): + (tst_QScriptString::toArrayIndex_data): + (tst_QScriptString::toArrayIndex): + * qt/tests/tests.pro: + +2010-03-02 Oliver Hunt <oliver@apple.com> + + Reviewed by NOBODY (Build fix). + + Export function on windows. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2010-03-01 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Refactor named getter function signature to be in line with indexing getter signature + https://bugs.webkit.org/show_bug.cgi?id=35563 + + This removes the PropertySlot argument from getter functions, and makes them directly + pass the slot base. This makes the semantics for the functions match that of the + indexing getters. + + On the down side, this means that we can no longer simply use a proxy function for + JS getters, so we now add another marker value to indicate that a getter is present + and branch accordingly. + + Against all rationality sunspider reports this as a perf win, but i suspect it's just noise. + + * API/JSCallbackObject.h: + * API/JSCallbackObjectFunctions.h: + (JSC::::staticValueGetter): + (JSC::::staticFunctionGetter): + (JSC::::callbackGetter): + * JavaScriptCore.exp: + * runtime/JSActivation.cpp: + (JSC::JSActivation::argumentsGetter): + * runtime/JSActivation.h: + * runtime/JSFunction.cpp: + (JSC::JSFunction::argumentsGetter): + (JSC::JSFunction::callerGetter): + (JSC::JSFunction::lengthGetter): + * runtime/JSFunction.h: + * runtime/NumberConstructor.cpp: + (JSC::numberConstructorNaNValue): + (JSC::numberConstructorNegInfinity): + (JSC::numberConstructorPosInfinity): + (JSC::numberConstructorMaxValue): + (JSC::numberConstructorMinValue): + * runtime/PropertySlot.cpp: + (JSC::PropertySlot::functionGetter): + * runtime/PropertySlot.h: + (JSC::PropertySlot::getValue): + (JSC::PropertySlot::setGetterSlot): + (JSC::PropertySlot::setCacheableGetterSlot): + * runtime/RegExpConstructor.cpp: + (JSC::regExpConstructorDollar1): + (JSC::regExpConstructorDollar2): + (JSC::regExpConstructorDollar3): + (JSC::regExpConstructorDollar4): + (JSC::regExpConstructorDollar5): + (JSC::regExpConstructorDollar6): + (JSC::regExpConstructorDollar7): + (JSC::regExpConstructorDollar8): + (JSC::regExpConstructorDollar9): + (JSC::regExpConstructorInput): + (JSC::regExpConstructorMultiline): + (JSC::regExpConstructorLastMatch): + (JSC::regExpConstructorLastParen): + (JSC::regExpConstructorLeftContext): + (JSC::regExpConstructorRightContext): + * runtime/RegExpObject.cpp: + (JSC::regExpObjectGlobal): + (JSC::regExpObjectIgnoreCase): + (JSC::regExpObjectMultiline): + (JSC::regExpObjectSource): + (JSC::regExpObjectLastIndex): + +2010-03-01 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + PropertySlot::getValue(ExecState, unsigned) unnecessarily converts index to an Identifier + https://bugs.webkit.org/show_bug.cgi?id=35561 + + Fix this by defining a separate property getter function for index getters. This allows + us to pass an unsigned number without the conversion to an Identifier. We then update + setCustomIndex to take this new getter type. + + * runtime/PropertySlot.h: + (JSC::PropertySlot::getValue): + (JSC::PropertySlot::setCustom): + (JSC::PropertySlot::setCustomIndex): + +2010-03-01 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Bug 35537 - put_by_id does will incorrectly cache writes where a specific value exists, + where at the point of caching the same value is being written. + + When performing a put_by_id that is replacing a property already present on the object, + there are three interesting cases regarding the state of the specific value: + + (1) No specific value set - nothing to do, leave the structure in it's current state, + can cache. + (2) A specific value was set, the new put is not of a specified value (i.e. function), + or is of a different specific value - in these cases we need to perform a despecifying + transition to clear the specific value in the structure, but having done so this is a + normal property so as such we can again cache normally. + (3) A specific value was set, and we are overwriting with the same value - in these cases + leave the structure unchanged, but since a specific value is set we cannot cache this + put (we would need the JIT to dynamically check the value being written matched). + + Unfortunately, the current behaviour does not match this. the checks for a specific value + being present & the value matching are combined in such a way that in case (2), above we + will unnecessarily prevent the transition being cached, but in case (3) we will incorrectly + fail to prevent caching. + + The bug exposes itself if multiple puts of the same specific value are performed to a + property, and erroneously the put is allowed to be cached by the JIT. Method checks may be + generated caching calls of this structure. Subsequent puts performed from JIT code may + write different values without triggering a despecify transition, and as such cached method + checks will continue to pass, despite the value having changed. + + * runtime/JSObject.h: + (JSC::JSObject::putDirectInternal): + +2010-03-01 Tor Arne Vestbø <tor.arne.vestbo@nokia.com> + + Reviewed by Simon Hausmann. + + Fix the Qt build on Mac OS X/Cocoa 64-bit + + * JavaScriptCore.pri: Add missing implementation file to resolve JSC symbols + +2010-02-26 Gavin Barraclough <barraclough@apple.com> + + Rubber Stamped by Geoff Garen. + + Remove wrec. All builds should have switched to yarr by now. + + * Android.mk: + * GNUmakefile.am: + * JavaScriptCore.gypi: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + * JavaScriptCore.vcproj/jsc/jscCommon.vsprops: + * JavaScriptCore.xcodeproj/project.pbxproj: + * runtime/RegExp.cpp: + (JSC::RegExp::match): + * runtime/RegExp.h: + * wrec: Removed. + * wrec/CharacterClass.cpp: Removed. + * wrec/CharacterClass.h: Removed. + * wrec/CharacterClassConstructor.cpp: Removed. + * wrec/CharacterClassConstructor.h: Removed. + * wrec/Escapes.h: Removed. + * wrec/Quantifier.h: Removed. + * wrec/WREC.cpp: Removed. + * wrec/WREC.h: Removed. + * wrec/WRECFunctors.cpp: Removed. + * wrec/WRECFunctors.h: Removed. + * wrec/WRECGenerator.cpp: Removed. + * wrec/WRECGenerator.h: Removed. + * wrec/WRECParser.cpp: Removed. + * wrec/WRECParser.h: Removed. + * wscript: + +2010-02-26 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + Make the lookup table generator include an explicit cast to expected + type of the function. We do this because otherwise the blind intptr_t + cast that is subsequently applied allows incorrectly typed functions + to be inserted into the table, where they will only fail at runtime. + This change makes such errors produce a compile time failure. + + * create_hash_table: + +2010-02-26 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Simon Hausmann. + + [Qt] Symbian specific getCPUTime implemetation + https://bugs.webkit.org/show_bug.cgi?id=34742 + + Default implementation doesn't work on Symbian devices. + This change adds a proper implementation by + asking thread execution time from the current thread. + + * runtime/TimeoutChecker.cpp: + (JSC::getCPUTime): + +2010-02-25 Alexey Proskuryakov <ap@apple.com> + + Reviewed by Anders Carlsson. + + https://bugs.webkit.org/show_bug.cgi?id=35406 + <rdar://problem/6945502> Make generic array methods work with JavaArray + + Renamed lazyCreationData to subclassData. This is extra data that can be used by JSArray + subclasses (you can't add new data members, because it wouldn't fit in JSCell otherwise). + + * JavaScriptCore.exp: + * runtime/JSArray.cpp: + (JSC::JSArray::JSArray): + (JSC::JSArray::subclassData): + (JSC::JSArray::setSubclassData): + * runtime/JSArray.h: + * runtime/RegExpConstructor.cpp: + (JSC::RegExpMatchesArray::RegExpMatchesArray): + (JSC::RegExpMatchesArray::~RegExpMatchesArray): + (JSC::RegExpMatchesArray::fillArrayInstance): + * runtime/RegExpMatchesArray.h: + (JSC::RegExpMatchesArray::getOwnPropertySlot): + (JSC::RegExpMatchesArray::getOwnPropertyDescriptor): + (JSC::RegExpMatchesArray::put): + (JSC::RegExpMatchesArray::deleteProperty): + (JSC::RegExpMatchesArray::getOwnPropertyNames): + +2010-02-25 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoff Garen. + + JSC crashes like crazy in the JSPropertyNameIterator destructor + + Add back null check of m_cachedStructure. Curse last minute changes. + + * runtime/JSPropertyNameIterator.cpp: + (JSC::JSPropertyNameIterator::~JSPropertyNameIterator): + +2010-02-25 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Race condition in JSPropertyNameIterator and Structure destruction + https://bugs.webkit.org/show_bug.cgi?id=35398 + + JSPropertyNameIterator and Structure have a cyclic dependency that they + manage by clearing the appropriate reference in each other during their + destruction. However if the Structure is destroyed while the + JSPropertyNameIterator is dead but not yet finalized the Structures + WeakGCPtr will return null, and so prevent Structure from clearing + the m_cachedStructure pointer of the iterator. When the iterator is + then finalised the m_cachedStructure is invalid, and the attempt to + clear the structures back reference fails. + + To fix this we simply make JSPropertyNameIterator keep the Structure + alive, using the weak pointer to break the ref cycle. + + * runtime/JSPropertyNameIterator.cpp: + (JSC::JSPropertyNameIterator::~JSPropertyNameIterator): + The iterator now keeps m_cachedStructure alive itself, so no longer needs + to check for it being cleared + * runtime/JSPropertyNameIterator.h: + (JSC::JSPropertyNameIterator::setCachedStructure): + Add an assertion to ensure correct usage + (JSC::JSPropertyNameIterator::cachedStructure): + Add .get() + * runtime/Structure.cpp: + (JSC::Structure::~Structure): + Add an assertion that our iterator isn't already dead, and remove + the now unnecessary attempt to clear the ref in the iterator + * runtime/WeakGCPtr.h: + (JSC::WeakGCPtr::hasDeadObject): + An assert-only function to allow us to assert correct behaviour + in the Structure destructor + +2010-02-25 Jochen Eisinger <jochen@chromium.org> + + Reviewed by Jeremy Orlow. + + Make the context that was passed to the ThreadFunction accessible. + https://bugs.webkit.org/show_bug.cgi?id=35379 + + When a database is opened, right now you + don't have any context from where it is opened. The problem is that + the actual calls that open a database go through the sqlite3 vfs + layer, so there's no easy way to pass this function down to to + platform/sql/chromium/SQLFileSystemChromium*.cpp + + This patch will allow you to get from anywhere within webkit a pointer + to the Thread object that actually created the thread you're currently + on (in case of the database, this can be either a thread forked of + from the main thread or from a worker thread), and query the object + for context information. + + * wtf/Threading.h: + * wtf/ThreadingNone.cpp: + (WTF::threadContext): + * wtf/ThreadingPthreads.cpp: + (WTF::): + (WTF::identifierByPthreadHandle): + (WTF::establishIdentifierForPthreadHandle): + (WTF::pthreadHandleForIdentifier): + (WTF::contextForIdentifier): + (WTF::createThreadInternal): + (WTF::currentThread): + (WTF::threadContext): + * wtf/ThreadingWin.cpp: + (WTF::): + (WTF::threadMap): + (WTF::storeThreadHandleByIdentifier): + (WTF::threadHandleForIdentifier): + (WTF::contextForIdentifier): + (WTF::createThreadInternal): + (WTF::threadContext): + +2010-02-25 Jeremy Orlow <jorlow@chromium.org> + + Reverting to re-submit with better change log. + + * wtf/Threading.h: + * wtf/ThreadingNone.cpp: + (WTF::isMainThread): + * wtf/ThreadingPthreads.cpp: + (WTF::identifierByPthreadHandle): + (WTF::establishIdentifierForPthreadHandle): + (WTF::pthreadHandleForIdentifier): + (WTF::createThreadInternal): + (WTF::currentThread): + * wtf/ThreadingWin.cpp: + (WTF::threadMap): + (WTF::storeThreadHandleByIdentifier): + (WTF::threadHandleForIdentifier): + (WTF::createThreadInternal): + +2010-02-25 Jochen Eisinger <jochen@chromium.org> + + Reviewed by Jeremy Orlow. + + Make the context that was passed to the ThreadFunction accessible. + https://bugs.webkit.org/show_bug.cgi?id=35379 + + * wtf/Threading.h: + * wtf/ThreadingNone.cpp: + (WTF::threadContext): + * wtf/ThreadingPthreads.cpp: + (WTF::): + (WTF::identifierByPthreadHandle): + (WTF::establishIdentifierForPthreadHandle): + (WTF::pthreadHandleForIdentifier): + (WTF::contextForIdentifier): + (WTF::createThreadInternal): + (WTF::currentThread): + (WTF::threadContext): + * wtf/ThreadingWin.cpp: + (WTF::): + (WTF::threadMap): + (WTF::storeThreadHandleByIdentifier): + (WTF::threadHandleForIdentifier): + (WTF::contextForIdentifier): + (WTF::createThreadInternal): + (WTF::threadContext): + +2010-02-24 Oliver Hunt <oliver@apple.com> + + Reviewed by Geoffrey Garen. + + [REGRESSION in r55185] EXC_BAD_ACCESS on opening inspector. + https://bugs.webkit.org/show_bug.cgi?id=35335 + + compileGetDirectOffset modifies the contents of the object register + when the object is not using the inline storage array. As the object + register contains our 'this' pointer we can't allow it to be clobbered. + The fix is simply to copy the register into a separate scratch register + when we're loading off an object that doesn't use inline storage. + + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompileGetByIdSelfList): + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::privateCompileGetByIdSelfList): + +2010-02-24 Oliver Hunt <oliver@apple.com> + + Reviewed by Gavin Barraclough. + + Speed up getter performance in the jit + https://bugs.webkit.org/show_bug.cgi?id=35332 + + Implement getter lookup caching in the interpreter. + The getter stubs are generated through basically the + same code paths as the normal get_by_id caching. + Instead of simply loading a property and returning, + we load the getter slot, and pass the getter, base value + and return address to a shared stub used for getter + dispatch. + + * jit/JIT.h: + (JSC::JIT::compileGetByIdProto): + (JSC::JIT::compileGetByIdSelfList): + (JSC::JIT::compileGetByIdProtoList): + (JSC::JIT::compileGetByIdChainList): + (JSC::JIT::compileGetByIdChain): + * jit/JITPropertyAccess.cpp: + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + * jit/JITStubs.cpp: + (JSC::JITThunks::tryCacheGetByID): + (JSC::DEFINE_STUB_FUNCTION): + * jit/JITStubs.h: + (JSC::): + * runtime/GetterSetter.h: + +2010-02-23 Oliver Hunt <oliver@apple.com> + + Reviewed by Maciej Stachowiak. + + Web Inspector: Regression: r55027+: Inspector broken + https://bugs.webkit.org/show_bug.cgi?id=35253 + + op_get_by_id_getter_chain was not passing the correct this parameter. + The bug was caused by incorrect use of baseCell instead of baseValue, + baseValue contains the original object for the lookup (and hence the + correct this object), baseCell is clobbered as part of walking the + prototype chain. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + +2010-02-23 Gustavo Noronha Silva <gns@gnome.org> + + Rubber-stamped by Dimitri Glazkov. + + Chromium build fix. + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2010-02-23 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Gustavo Noronha Silva. + + Changes references of GOwnPtr to reflect their new place. + http://webkit.org/b/35084 + + * JavaScriptCore/JavaScriptCore.gypi: + * JavaScriptCore/wtf/Threading.h: + * JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h: + +2010-02-23 Leandro Pereira <leandro@profusion.mobi> + + Reviewed by Kenneth Rohde Christiansen. + + Adding the EFL implementation of JavaScriptCore. + See https://bugs.webkit.org/show_bug.cgi?id=35084 for details. + + * GNUmakefile.am: Updated to reflect the new location of GOwnPtr and + GRefPtr. + * wtf/efl/MainThreadEfl.cpp: Added. + * wtf/gobject/GOwnPtr.cpp: Moved from wtf/gtk. + * wtf/gobject/GOwnPtr.h: Moved from wtf/gtk. + * wtf/gobject/GRefPtr.cpp: Moved from wtf/gtk. + * wtf/gobject/GRefPtr.h: Moved from wtf/gtk. + +2010-02-22 Julien Chaffraix <jchaffraix@webkit.org> + + Reviewed by Darin Adler. + + Remove auto_ptr usage in JavaScriptCore. + https://bugs.webkit.org/show_bug.cgi?id=35221 + + * parser/Nodes.h: Removed now unneeded adopt method. + * parser/Parser.cpp: Removed <memory> include as it is not required anymore. + * wtf/OwnPtr.h: Removed the constructor from auto_ptr. + * wtf/VectorTraits.h: Removed a template specialization for auto_ptr. + * wtf/unicode/Collator.h: Made userDefault return a PassOwnPtr. + * wtf/unicode/CollatorDefault.cpp: + (WTF::Collator::userDefault): Changed the method to match the next signature. + * wtf/unicode/icu/CollatorICU.cpp: + (WTF::Collator::userDefault): Ditto. + +2010-02-22 Huahui Wu <hwu@google.com> + + Reviewed by Eric Seidel. + + Add code that enables SquirrelFish Extreme (a.k.a JSCX, JSC JIT) + in Android. It's disabled by default, but is enabled when the + enveronment variable ENABLE_JSC_JIT is set to true. + https://bugs.webkit.org/show_bug.cgi?id=34855 + + * Android.mk: + * wtf/Platform.h: + +2010-02-22 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + JSStringBuilder should not CRASH if allocation fails, it should throw a JSException. + + * runtime/JSGlobalObjectFunctions.cpp: + * runtime/JSStringBuilder.h: + (JSC::JSStringBuilder::JSStringBuilder): + (JSC::JSStringBuilder::append): + (JSC::JSStringBuilder::build): + * runtime/StringBuilder.h: + (JSC::StringBuilder::build): + * wtf/Vector.h: + (WTF::VectorBufferBase::tryAllocateBuffer): + (WTF::): + (WTF::VectorBuffer::tryAllocateBuffer): + (WTF::::tryExpandCapacity): + (WTF::::tryReserveCapacity): + (WTF::::tryAppend): + +2010-02-22 Kwang Yul Seo <skyul@company100.net> + + Reviewed by Eric Seidel. + + [BREWMP] Map FastMalloc to BREW memory allocator + https://bugs.webkit.org/show_bug.cgi?id=33570 + + Use MALLOC macro instead of the standard malloc function. + Although RVCT provides malloc, we can't use it in BREW + because the loader does not initialize the base address properly. + + * wtf/FastMalloc.cpp: + * wtf/brew/SystemMallocBrew.h: Added. + (mallocBrew): + (callocBrew): + (freeBrew): + (reallocBrew): + +2010-02-22 Gustavo Noronha Silva <gustavo.noronha@collabora.co.uk> + + Build fix for make distcheck. + + * GNUmakefile.am: + +2010-02-22 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Unreviewed build fix. + + [Qt] Build fix for RVCT. + + Fix after r55024. The "-i" option is for perl not for the + script. + + * DerivedSources.pro: + +2010-02-21 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + Make UString::m_data be const, and make the UChar owned/ref-counted by CrossThreadRefCounted be const too. + + * runtime/UStringImpl.cpp: + (JSC::UStringImpl::baseSharedBuffer): + (JSC::UStringImpl::~UStringImpl): + * runtime/UStringImpl.h: + (JSC::UStringImpl::create): + (JSC::UStringImpl::data): + (JSC::UStringImpl::UStringImpl): + * wtf/OwnFastMallocPtr.h: + (WTF::OwnFastMallocPtr::~OwnFastMallocPtr): + +2010-02-21 Yuta Kitamura <yutak@chromium.org> + + Reviewed by Darin Adler. + + HashMapTranslatorAdapter::translate() needs to set the mapped value. + + HTTPHeaderMap::add(const char*, const String&) does not work + https://bugs.webkit.org/show_bug.cgi?id=35227 + + * wtf/HashMap.h: + (WTF::HashMapTranslatorAdapter::translate): + +2010-02-19 Maciej Stachowiak <mjs@apple.com> + + Reviewed by David Levin. + + Add an ENABLE flag for sandboxed iframes to make it possible to disable it in releases + https://bugs.webkit.org/show_bug.cgi?id=35147 + + * Configurations/FeatureDefines.xcconfig: + +2010-02-19 Gavin Barraclough <barraclough@apple.com> + + Reviewed by Oliver Hunt. + + JSString::getIndex() calls value() to resolve the string value (is a rope) + to a UString, then passes the result to jsSingleCharacterSubstring without + checking for an exception. In case of out-of-memory the returned UString + is null(), which may result in an out-of-buounds substring being created. + This is bad. + + Simple fix is to be able to get an index from a rope without resolving to + UString. This may be a useful optimization in some test cases. + + The same bug exists in some other methods is JSString, these can be fixed + by changing them to call getIndex(). + + * runtime/JSString.cpp: + (JSC::JSString::resolveRope): + (JSC::JSString::getStringPropertyDescriptor): + * runtime/JSString.h: + (JSC::jsSingleCharacterSubstring): + (JSC::JSString::getIndex): + (JSC::jsSingleCharacterString): + (JSC::JSString::getStringPropertySlot): + * runtime/UStringImpl.cpp: + (JSC::singleCharacterSubstring): + * runtime/UStringImpl.h: + (JSC::UStringImpl::singleCharacterSubstring): + 2010-02-19 Oliver Hunt <oliver@apple.com> RS = Gavin Barraclough. @@ -196,7 +3857,7 @@ another rope node. A low bit in each pointer is used to distinguish between rope & string elements, in a fashion similar to the recently-removed PtrAndFlags class (see https://bugs.webkit.org/show_bug.cgi?id=33731 ). Again, - this causes a problem for Leaks – refactor to remove the magic pointer + this causes a problem for Leaks - refactor to remove the magic pointer mangling. Move Rope out from JSString.h and rename to URopeImpl, to match UStringImpl. @@ -639,6 +4300,40 @@ 2010-02-12 Janne Koskinen <janne.p.koskinen@digia.com> + Reviewed by Tor Arne Vestbø. + + Additional refptr/passrefptr workarounds for WINSCW compiler + https://bugs.webkit.org/show_bug.cgi?id=28054 + + * wtf/PassRefPtr.h: + (WTF::refIfNotNull): + (WTF::PassRefPtr::PassRefPtr): + (WTF::PassRefPtr::~PassRefPtr): + (WTF::PassRefPtr::clear): + (WTF::::operator): + * wtf/RefPtr.h: + (WTF::RefPtr::RefPtr): + (WTF::::operator): + +2010-02-12 Janne Koskinen <janne.p.koskinen@digia.com> + + Reviewed by Tor Arne Vestbø. + + Additional refptr/passrefptr workarounds for WINSCW compiler + https://bugs.webkit.org/show_bug.cgi?id=28054 + + * wtf/PassRefPtr.h: + (WTF::refIfNotNull): + (WTF::PassRefPtr::PassRefPtr): + (WTF::PassRefPtr::~PassRefPtr): + (WTF::PassRefPtr::clear): + (WTF::::operator): + * wtf/RefPtr.h: + (WTF::RefPtr::RefPtr): + (WTF::::operator): + +2010-02-12 Janne Koskinen <janne.p.koskinen@digia.com> + Reviewed by Simon Hausmann. Don't import the cmath functions from std:: for WINSCW. @@ -7672,7 +11367,7 @@ The very last cell in the block is not allocated -- should not be marked. 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 + 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 diff --git a/JavaScriptCore/Configurations/Base.xcconfig b/JavaScriptCore/Configurations/Base.xcconfig index c338eb7..4854b64 100644 --- a/JavaScriptCore/Configurations/Base.xcconfig +++ b/JavaScriptCore/Configurations/Base.xcconfig @@ -67,6 +67,8 @@ REAL_PLATFORM_NAME_iphoneos = iphoneos; REAL_PLATFORM_NAME_iphonesimulator = iphonesimulator; REAL_PLATFORM_NAME_macosx = macosx; +TARGET_MAC_OS_X_VERSION_MAJOR = $(MAC_OS_X_VERSION_MAJOR); + // DEBUG_DEFINES, GCC_OPTIMIZATION_LEVEL, STRIP_INSTALLED_PRODUCT and DEAD_CODE_STRIPPING vary between the debug and normal variants. // We set up the values for each variant here, and have the Debug configuration in the Xcode project use the _debug variant. @@ -92,16 +94,36 @@ SECTORDER_FLAGS = -sectorder __TEXT __text JavaScriptCore.order; // Note that Xcode versions as new as 3.1.2 use XCODE_VERSION_ACTUAL for the minor version // number. Newer versions of Xcode use XCODE_VERSION_MINOR for the minor version, and // XCODE_VERSION_ACTUAL for the full version number. -GCC_VERSION = $(GCC_VERSION_$(XCODE_VERSION_MINOR)); -GCC_VERSION_ = $(GCC_VERSION_$(XCODE_VERSION_ACTUAL)); -GCC_VERSION_0310 = 4.2; +TARGET_GCC_VERSION = $(TARGET_GCC_VERSION_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +TARGET_GCC_VERSION_ = $(TARGET_GCC_VERSION_1040); +TARGET_GCC_VERSION_1040 = GCC_40; +TARGET_GCC_VERSION_1050 = $(TARGET_GCC_VERSION_1050_$(XCODE_VERSION_MINOR)); +TARGET_GCC_VERSION_1050_ = $(TARGET_GCC_VERSION_1050_$(XCODE_VERSION_ACTUAL)); +TARGET_GCC_VERSION_1050_0310 = GCC_42; +TARGET_GCC_VERSION_1050_0320 = GCC_42; +TARGET_GCC_VERSION_1060 = GCC_42; +TARGET_GCC_VERSION_1070 = LLVM_GCC_42; + +GCC_VERSION = $(GCC_VERSION_$(TARGET_GCC_VERSION)); +GCC_VERSION_GCC_40 = 4.0; +GCC_VERSION_GCC_42 = 4.2; +GCC_VERSION_LLVM_GCC_42 = com.apple.compilers.llvmgcc42; + +// If the target Mac OS X version does not match the current Mac OS X version then we'll want to build using the target version's SDK. +SDKROOT = $(SDKROOT_$(MAC_OS_X_VERSION_MAJOR)_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +SDKROOT_1050_1040 = macosx10.4; +SDKROOT_1060_1040 = macosx10.4; +SDKROOT_1060_1050 = macosx10.5; +SDKROOT_1070_1040 = macosx10.4; +SDKROOT_1070_1050 = macosx10.5; +SDKROOT_1070_1060 = macosx10.6; // HAVE_DTRACE is disabled on Leopard due to <rdar://problem/5628149> HAVE_DTRACE = $(HAVE_DTRACE_$(REAL_PLATFORM_NAME)); HAVE_DTRACE_iphoneos = 1; HAVE_DTRACE_iphonesimulator = 0; -HAVE_DTRACE_macosx = $(HAVE_DTRACE_macosx_$(MAC_OS_X_VERSION_MAJOR)); +HAVE_DTRACE_macosx = $(HAVE_DTRACE_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)); HAVE_DTRACE_macosx_ = $(HAVE_DTRACE_macosx_1040); HAVE_DTRACE_macosx_1040 = 0; HAVE_DTRACE_macosx_1050 = 0; diff --git a/JavaScriptCore/Configurations/DebugRelease.xcconfig b/JavaScriptCore/Configurations/DebugRelease.xcconfig index cbb0c8b..1e981f8 100644 --- a/JavaScriptCore/Configurations/DebugRelease.xcconfig +++ b/JavaScriptCore/Configurations/DebugRelease.xcconfig @@ -26,7 +26,7 @@ ARCHS = $(ARCHS_$(REAL_PLATFORM_NAME)); ARCHS_iphoneos = $(ARCHS_UNIVERSAL_IPHONE_OS); ARCHS_iphonesimulator = $(NATIVE_ARCH); -ARCHS_macosx = $(ARCHS_macosx_$(MAC_OS_X_VERSION_MAJOR)); +ARCHS_macosx = $(ARCHS_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)); ARCHS_macosx_ = $(ARCHS_macosx_1040); ARCHS_macosx_1040 = $(NATIVE_ARCH); ARCHS_macosx_1050 = $(NATIVE_ARCH); @@ -35,7 +35,7 @@ ARCHS_macosx_1070 = $(ARCHS_STANDARD_32_64_BIT); ONLY_ACTIVE_ARCH = YES; -MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(MAC_OS_X_VERSION_MAJOR)); +MACOSX_DEPLOYMENT_TARGET = $(MACOSX_DEPLOYMENT_TARGET_$(TARGET_MAC_OS_X_VERSION_MAJOR)); MACOSX_DEPLOYMENT_TARGET_ = 10.4; MACOSX_DEPLOYMENT_TARGET_1040 = 10.4; MACOSX_DEPLOYMENT_TARGET_1050 = 10.5; diff --git a/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/JavaScriptCore/Configurations/FeatureDefines.xcconfig index 8343ce7..881c788 100644 --- a/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -31,16 +31,17 @@ // Set any ENABLE_FEATURE_NAME macro to an empty string to disable that feature. -ENABLE_3D_CANVAS = $(ENABLE_3D_CANVAS_$(MAC_OS_X_VERSION_MAJOR)); +ENABLE_3D_CANVAS = $(ENABLE_3D_CANVAS_$(TARGET_MAC_OS_X_VERSION_MAJOR)); ENABLE_3D_CANVAS_1050 = ENABLE_3D_CANVAS; ENABLE_3D_CANVAS_1060 = ENABLE_3D_CANVAS; ENABLE_3D_CANVAS_1070 = ENABLE_3D_CANVAS; -ENABLE_3D_RENDERING = $(ENABLE_3D_RENDERING_$(MAC_OS_X_VERSION_MAJOR)); +ENABLE_3D_RENDERING = $(ENABLE_3D_RENDERING_$(TARGET_MAC_OS_X_VERSION_MAJOR)); ENABLE_3D_RENDERING_1050 = ENABLE_3D_RENDERING; ENABLE_3D_RENDERING_1060 = ENABLE_3D_RENDERING; ENABLE_3D_RENDERING_1070 = ENABLE_3D_RENDERING; +ENABLE_BLOB_SLICE = ENABLE_BLOB_SLICE; ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING; ENABLE_CLIENT_BASED_GEOLOCATION = ENABLE_CLIENT_BASED_GEOLOCATION; ENABLE_DATABASE = ENABLE_DATABASE; @@ -49,6 +50,8 @@ ENABLE_DATALIST = ENABLE_DATALIST; ENABLE_DOM_STORAGE = ENABLE_DOM_STORAGE; ENABLE_EVENTSOURCE = ENABLE_EVENTSOURCE; ENABLE_FILTERS = ENABLE_FILTERS; +ENABLE_FILE_READER = ; +ENABLE_FILE_WRITER = ; ENABLE_GEOLOCATION = ENABLE_GEOLOCATION; ENABLE_ICONDATABASE = ENABLE_ICONDATABASE; ENABLE_INDEXED_DATABASE = ; @@ -56,7 +59,9 @@ ENABLE_JAVASCRIPT_DEBUGGER = ENABLE_JAVASCRIPT_DEBUGGER; ENABLE_MATHML = ; ENABLE_NOTIFICATIONS = ; ENABLE_OFFLINE_WEB_APPLICATIONS = ENABLE_OFFLINE_WEB_APPLICATIONS; +ENABLE_PROGRESS_TAG = ENABLE_PROGRESS_TAG; ENABLE_RUBY = ENABLE_RUBY; +ENABLE_SANDBOX = ENABLE_SANDBOX; ENABLE_SHARED_WORKERS = ENABLE_SHARED_WORKERS; ENABLE_SVG = ENABLE_SVG; ENABLE_SVG_ANIMATION = ENABLE_SVG_ANIMATION; @@ -73,4 +78,4 @@ ENABLE_XHTMLMP = ; ENABLE_XPATH = ENABLE_XPATH; ENABLE_XSLT = ENABLE_XSLT; -FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_RUBY) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); +FEATURE_DEFINES = $(ENABLE_3D_CANVAS) $(ENABLE_3D_RENDERING) $(ENABLE_BLOB_SLICE) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_DATABASE) $(ENABLE_DATAGRID) $(ENABLE_DATALIST) $(ENABLE_DOM_STORAGE) $(ENABLE_EVENTSOURCE) $(ENABLE_FILTERS) $(ENABLE_FILE_READER) $(ENABLE_FILE_WRITER) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_MATHML) $(ENABLE_NOTIFICATIONS) $(ENABLE_OFFLINE_WEB_APPLICATIONS) $(ENABLE_PROGRESS_TAG) $(ENABLE_RUBY) $(ENABLE_SANDBOX) $(ENABLE_SHARED_WORKERS) $(ENABLE_SVG) $(ENABLE_SVG_ANIMATION) $(ENABLE_SVG_AS_IMAGE) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_SVG_FOREIGN_OBJECT) $(ENABLE_SVG_USE) $(ENABLE_VIDEO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WML) $(ENABLE_WORKERS) $(ENABLE_XHTMLMP) $(ENABLE_XPATH) $(ENABLE_XSLT); diff --git a/JavaScriptCore/Configurations/JavaScriptCore.xcconfig b/JavaScriptCore/Configurations/JavaScriptCore.xcconfig index f8d6c2c..b6ba560 100644 --- a/JavaScriptCore/Configurations/JavaScriptCore.xcconfig +++ b/JavaScriptCore/Configurations/JavaScriptCore.xcconfig @@ -44,8 +44,7 @@ INSTALL_PATH = $(SYSTEM_LIBRARY_DIR)/Frameworks; PRODUCT_NAME = JavaScriptCore; OTHER_CFLAGS = $(OTHER_CFLAGS_$(CONFIGURATION)_$(CURRENT_VARIANT)); -OTHER_CFLAGS_Release_normal = $(OTHER_CFLAGS_normal_$(XCODE_VERSION_ACTUAL)); -OTHER_CFLAGS_Production_normal = $(OTHER_CFLAGS_normal_$(XCODE_VERSION_ACTUAL)); -OTHER_CFLAGS_normal_0310 = $(OTHER_CFLAGS_normal_GCC_42); -OTHER_CFLAGS_normal_0320 = $(OTHER_CFLAGS_normal_GCC_42); +OTHER_CFLAGS_Release_normal = $(OTHER_CFLAGS_normal_$(TARGET_GCC_VERSION)); +OTHER_CFLAGS_Production_normal = $(OTHER_CFLAGS_normal_$(TARGET_GCC_VERSION)); OTHER_CFLAGS_normal_GCC_42 = -fomit-frame-pointer -funwind-tables; +OTHER_CFLAGS_normal_LLVM_GCC_42 = $(OTHER_CFLAGS_normal_GCC_42); diff --git a/JavaScriptCore/Configurations/Version.xcconfig b/JavaScriptCore/Configurations/Version.xcconfig index 0e289b1..6aeb263 100644 --- a/JavaScriptCore/Configurations/Version.xcconfig +++ b/JavaScriptCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 533; -MINOR_VERSION = 1; +MINOR_VERSION = 6; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); @@ -31,7 +31,7 @@ BUNDLE_VERSION = $(BUNDLE_VERSION_$(CONFIGURATION)); SHORT_VERSION_STRING = $(SHORT_VERSION_STRING_$(CONFIGURATION)) // The system version prefix is based on the current system version. -SYSTEM_VERSION_PREFIX = $(SYSTEM_VERSION_PREFIX_$(MAC_OS_X_VERSION_MAJOR)); +SYSTEM_VERSION_PREFIX = $(SYSTEM_VERSION_PREFIX_$(TARGET_MAC_OS_X_VERSION_MAJOR)); SYSTEM_VERSION_PREFIX_ = 4; // Some Tiger versions of Xcode don't set MAC_OS_X_VERSION_MAJOR. SYSTEM_VERSION_PREFIX_1040 = 4; SYSTEM_VERSION_PREFIX_1050 = 5; diff --git a/JavaScriptCore/DerivedSources.make b/JavaScriptCore/DerivedSources.make index 9eaccab..4fc9cad 100644 --- a/JavaScriptCore/DerivedSources.make +++ b/JavaScriptCore/DerivedSources.make @@ -48,6 +48,7 @@ all : \ RegExpObject.lut.h \ StringPrototype.lut.h \ docs/bytecode.html \ + RegExpJitTables.h \ # # lookup tables for classes @@ -74,3 +75,7 @@ chartables.c : dftables docs/bytecode.html: make-bytecode-docs.pl Interpreter.cpp perl $^ $@ + +#character tables for Yarr +RegExpJitTables.h: create_regex_tables + python $^ > $@ diff --git a/JavaScriptCore/DerivedSources.pro b/JavaScriptCore/DerivedSources.pro index 28a229d..7c5aad8 100644 --- a/JavaScriptCore/DerivedSources.pro +++ b/JavaScriptCore/DerivedSources.pro @@ -78,7 +78,7 @@ addExtraCompiler(jscbison) # GENERATOR 3: JIT Stub functions for RVCT rvctstubs.output = $${JSC_GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP}Generated${QMAKE_FILE_BASE}_RVCT.h rvctstubs.wkScript = $$PWD/create_jit_stubs -rvctstubs.commands = perl $$rvctstubs.wkScript --prefix RVCT ${QMAKE_FILE_NAME} -i > ${QMAKE_FILE_OUT} +rvctstubs.commands = perl -i $$rvctstubs.wkScript --prefix RVCT ${QMAKE_FILE_NAME} > ${QMAKE_FILE_OUT} rvctstubs.depends = ${QMAKE_FILE_NAME} rvctstubs.input = RVCT_STUB_FILES rvctstubs.CONFIG += no_link @@ -93,3 +93,9 @@ ctgen.commands = perl $$ctgen.wkScript ${QMAKE_FILE_OUT} $$PREPROCESSOR ctgen.clean = ${QMAKE_FILE_OUT} ${QMAKE_VAR_JSC_GENERATED_SOURCES_DIR}${QMAKE_FILE_BASE} addExtraCompiler(ctgen) +#GENERATOR: "RegExpJitTables.h": tables used by Yarr +retgen.output = $$JSC_GENERATED_SOURCES_DIR/RegExpJitTables.h +retgen.wkScript = $$PWD/create_regex_tables +retgen.input = retgen.wkScript +retgen.commands = python $$retgen.wkScript > ${QMAKE_FILE_OUT} +addExtraCompiler(retgen) diff --git a/JavaScriptCore/GNUmakefile.am b/JavaScriptCore/GNUmakefile.am index 53e3c65..2d024c1 100644 --- a/JavaScriptCore/GNUmakefile.am +++ b/JavaScriptCore/GNUmakefile.am @@ -10,11 +10,13 @@ javascriptcore_cppflags += \ -I$(srcdir)/JavaScriptCore/pcre \ -I$(srcdir)/JavaScriptCore/profiler \ -I$(srcdir)/JavaScriptCore/runtime \ - -I$(srcdir)/JavaScriptCore/wrec \ -I$(srcdir)/JavaScriptCore/jit \ -I$(srcdir)/JavaScriptCore/assembler \ + -I$(srcdir)/JavaScriptCore/wtf \ + -I$(srcdir)/JavaScriptCore/wtf/text \ -I$(srcdir)/JavaScriptCore/wtf/unicode \ -I$(srcdir)/JavaScriptCore/yarr \ + -I$(top_builddir)/JavaScriptCore \ -I$(top_builddir)/JavaScriptCore/pcre \ -I$(top_builddir)/JavaScriptCore/parser \ -I$(top_builddir)/JavaScriptCore/runtime @@ -33,6 +35,7 @@ javascriptcore_h_api += \ javascriptcore_built_nosources += \ DerivedSources/Lexer.lut.h \ + JavaScriptCore/RegExpJitTables.h \ JavaScriptCore/runtime/ArrayPrototype.lut.h \ JavaScriptCore/runtime/DatePrototype.lut.h \ JavaScriptCore/runtime/JSONObject.lut.h \ @@ -210,19 +213,12 @@ javascriptcore_sources += \ JavaScriptCore/runtime/StructureChain.cpp \ JavaScriptCore/runtime/StructureChain.h \ JavaScriptCore/runtime/StructureTransitionTable.h \ + JavaScriptCore/runtime/Terminator.h \ JavaScriptCore/runtime/TimeoutChecker.cpp \ JavaScriptCore/runtime/TimeoutChecker.h \ JavaScriptCore/runtime/JSTypeInfo.h \ JavaScriptCore/runtime/WeakGCMap.h \ JavaScriptCore/runtime/WeakGCPtr.h \ - JavaScriptCore/wrec/CharacterClass.h \ - JavaScriptCore/wrec/CharacterClassConstructor.h \ - JavaScriptCore/wrec/Escapes.h \ - JavaScriptCore/wrec/Quantifier.h \ - JavaScriptCore/wrec/WREC.h \ - JavaScriptCore/wrec/WRECFunctors.h \ - JavaScriptCore/wrec/WRECGenerator.h \ - JavaScriptCore/wrec/WRECParser.h \ JavaScriptCore/wtf/ASCIICType.h \ JavaScriptCore/wtf/AVLTree.h \ JavaScriptCore/wtf/AlwaysInline.h \ @@ -264,7 +260,6 @@ javascriptcore_sources += \ JavaScriptCore/wtf/PassRefPtr.h \ JavaScriptCore/wtf/Platform.h \ JavaScriptCore/wtf/PossiblyNull.h \ - JavaScriptCore/wtf/PtrAndFlags.h \ JavaScriptCore/wtf/RandomNumber.cpp \ JavaScriptCore/wtf/RandomNumber.h \ JavaScriptCore/wtf/RandomNumberSeed.h \ @@ -275,6 +270,7 @@ javascriptcore_sources += \ JavaScriptCore/wtf/RefPtrHashMap.h \ JavaScriptCore/wtf/RetainPtr.h \ JavaScriptCore/wtf/SegmentedVector.h \ + JavaScriptCore/wtf/StaticConstructors.h \ JavaScriptCore/wtf/StdLibExtras.h \ JavaScriptCore/wtf/StringExtras.h \ JavaScriptCore/wtf/StringHashFunctions.h \ @@ -293,12 +289,24 @@ javascriptcore_sources += \ JavaScriptCore/wtf/ValueCheck.h \ JavaScriptCore/wtf/Vector.h \ JavaScriptCore/wtf/VectorTraits.h \ - JavaScriptCore/wtf/gtk/GOwnPtr.cpp \ - JavaScriptCore/wtf/gtk/GOwnPtr.h \ - JavaScriptCore/wtf/gtk/GRefPtr.cpp \ - JavaScriptCore/wtf/gtk/GRefPtr.h \ + JavaScriptCore/wtf/WTFThreadData.cpp \ + JavaScriptCore/wtf/WTFThreadData.h \ + JavaScriptCore/wtf/gobject/GOwnPtr.cpp \ + JavaScriptCore/wtf/gobject/GOwnPtr.h \ + JavaScriptCore/wtf/gobject/GRefPtr.cpp \ + JavaScriptCore/wtf/gobject/GRefPtr.h \ JavaScriptCore/wtf/gtk/MainThreadGtk.cpp \ JavaScriptCore/wtf/gtk/ThreadingGtk.cpp \ + JavaScriptCore/wtf/text/AtomicString.cpp \ + JavaScriptCore/wtf/text/AtomicString.h \ + JavaScriptCore/wtf/text/AtomicStringImpl.h \ + JavaScriptCore/wtf/text/CString.cpp \ + JavaScriptCore/wtf/text/CString.h \ + JavaScriptCore/wtf/text/StringHash.h \ + JavaScriptCore/wtf/text/StringImpl.cpp \ + JavaScriptCore/wtf/text/StringImpl.h \ + JavaScriptCore/wtf/text/WTFString.cpp \ + JavaScriptCore/wtf/text/WTFString.h \ JavaScriptCore/wtf/unicode/Collator.h \ JavaScriptCore/wtf/unicode/CollatorDefault.cpp \ JavaScriptCore/wtf/unicode/UTF8.cpp \ @@ -494,6 +502,8 @@ javascriptcore_sources += \ JavaScriptCore/runtime/RegExpObject.h \ JavaScriptCore/runtime/RegExpPrototype.cpp \ JavaScriptCore/runtime/RegExpPrototype.h \ + JavaScriptCore/runtime/RopeImpl.cpp \ + JavaScriptCore/runtime/RopeImpl.h \ JavaScriptCore/runtime/ScopeChain.cpp \ JavaScriptCore/runtime/ScopeChain.h \ JavaScriptCore/runtime/ScopeChainMark.h \ @@ -508,7 +518,6 @@ javascriptcore_sources += \ JavaScriptCore/runtime/Tracing.h \ JavaScriptCore/runtime/UString.cpp \ JavaScriptCore/runtime/UString.h \ - JavaScriptCore/runtime/UStringImpl.cpp \ JavaScriptCore/runtime/UStringImpl.h \ JavaScriptCore/runtime/WeakRandom.h \ JavaScriptCore/wtf/FastAllocBase.h \ @@ -538,6 +547,9 @@ DerivedSources/Lexer.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/parser JavaScriptCore/%.lut.h: $(CREATE_HASH_TABLE) $(srcdir)/JavaScriptCore/%.cpp $(PERL) $^ -i > $@ +JavaScriptCore/RegExpJitTables.h: $(srcdir)/JavaScriptCore/create_regex_tables + $(PYTHON) $(srcdir)/JavaScriptCore/create_regex_tables > $@ + JavaScriptCore/pcre/chartables.c: $(srcdir)/JavaScriptCore/pcre/dftables $(PERL) $^ $@ @@ -598,6 +610,7 @@ Programs_jsc_LDADD = \ javascriptcore_dist += \ $(CREATE_HASH_TABLE) \ + $(CREATE_REGEXP_TABLES) \ JavaScriptCore/AUTHORS \ JavaScriptCore/COPYING.LIB \ JavaScriptCore/ChangeLog \ diff --git a/JavaScriptCore/JavaScriptCore.exp b/JavaScriptCore/JavaScriptCore.exp index 9355321..e8e34ee 100644 --- a/JavaScriptCore/JavaScriptCore.exp +++ b/JavaScriptCore/JavaScriptCore.exp @@ -18,8 +18,10 @@ _JSGlobalContextRetain _JSObjectCallAsConstructor _JSObjectCallAsFunction _JSObjectCopyPropertyNames +_JSObjectDeletePrivateProperty _JSObjectDeleteProperty _JSObjectGetPrivate +_JSObjectGetPrivateProperty _JSObjectGetProperty _JSObjectGetPropertyAtIndex _JSObjectGetPrototype @@ -35,6 +37,7 @@ _JSObjectMakeFunction _JSObjectMakeFunctionWithCallback _JSObjectMakeRegExp _JSObjectSetPrivate +_JSObjectSetPrivateProperty _JSObjectSetProperty _JSObjectSetPropertyAtIndex _JSObjectSetPrototype @@ -57,6 +60,7 @@ _JSStringIsEqual _JSStringIsEqualToUTF8CString _JSStringRelease _JSStringRetain +_JSValueCreateJSONString _JSValueGetType _JSValueIsBoolean _JSValueIsEqual @@ -69,6 +73,7 @@ _JSValueIsStrictEqual _JSValueIsString _JSValueIsUndefined _JSValueMakeBoolean +_JSValueMakeFromJSONString _JSValueMakeNull _JSValueMakeNumber _JSValueMakeString @@ -79,6 +84,10 @@ _JSValueToNumber _JSValueToObject _JSValueToStringCopy _JSValueUnprotect +_JSWeakObjectMapClear +_JSWeakObjectMapCreate +_JSWeakObjectMapGet +_JSWeakObjectMapSet _WTFLog _WTFLogVerbose _WTFReportArgumentAssertionFailure @@ -90,12 +99,14 @@ __Z12jsRegExpFreeP8JSRegExp __Z15jsRegExpCompilePKti24JSRegExpIgnoreCaseOption23JSRegExpMultilineOptionPjPPKc __Z15jsRegExpExecutePK8JSRegExpPKtiiPii __ZN14OpaqueJSString6createERKN3JSC7UStringE -__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPNS_11UStringImplE -__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPNS_11UStringImplE -__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_12JSGlobalDataEPNS_11UStringImplE -__ZN3JSC10Identifier24checkSameIdentifierTableEPNS_9ExecStateEPNS_11UStringImplE +__ZN3JSC10Identifier11addSlowCaseEPNS_12JSGlobalDataEPN7WebCore10StringImplE +__ZN3JSC10Identifier11addSlowCaseEPNS_9ExecStateEPN7WebCore10StringImplE +__ZN3JSC10Identifier27checkCurrentIdentifierTableEPNS_12JSGlobalDataE +__ZN3JSC10Identifier27checkCurrentIdentifierTableEPNS_9ExecStateE __ZN3JSC10Identifier3addEPNS_9ExecStateEPKc -__ZN3JSC10Identifier5equalEPKNS_11UStringImplEPKc +__ZN3JSC10Identifier4fromEPNS_9ExecStateEi +__ZN3JSC10Identifier4fromEPNS_9ExecStateEj +__ZN3JSC10Identifier5equalEPKN7WebCore10StringImplEPKc __ZN3JSC10JSFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeE __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeEPKc @@ -103,23 +114,20 @@ __ZN3JSC10throwErrorEPNS_9ExecStateENS_9ErrorTypeERKNS_7UStringE __ZN3JSC11JSByteArray15createStructureENS_7JSValueE __ZN3JSC11JSByteArrayC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEPNS3_9ByteArrayEPKNS_9ClassInfoE __ZN3JSC11ParserArena5resetEv -__ZN3JSC11UStringImpl12sharedBufferEv -__ZN3JSC11UStringImpl7s_emptyE -__ZN3JSC11UStringImplD1Ev __ZN3JSC11checkSyntaxEPNS_9ExecStateERKNS_10SourceCodeE __ZN3JSC12DateInstance4infoE __ZN3JSC12DateInstanceC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEd __ZN3JSC12DateInstanceC1EPNS_9ExecStateEd __ZN3JSC12JSGlobalData10ClientDataD2Ev __ZN3JSC12JSGlobalData11jsArrayVPtrE -__ZN3JSC12JSGlobalData12createLeakedEv +__ZN3JSC12JSGlobalData12createLeakedENS_15ThreadStackTypeE __ZN3JSC12JSGlobalData12jsStringVPtrE __ZN3JSC12JSGlobalData12stopSamplingEv __ZN3JSC12JSGlobalData13startSamplingEv __ZN3JSC12JSGlobalData14dumpSampleDataEPNS_9ExecStateE __ZN3JSC12JSGlobalData14resetDateCacheEv __ZN3JSC12JSGlobalData14sharedInstanceEv -__ZN3JSC12JSGlobalData6createEv +__ZN3JSC12JSGlobalData6createENS_15ThreadStackTypeE __ZN3JSC12JSGlobalDataD1Ev __ZN3JSC12SamplingTool5setupEv __ZN3JSC12SmallStrings17createEmptyStringEPNS_12JSGlobalDataE @@ -163,7 +171,7 @@ __ZN3JSC16JSVariableObject14symbolTableGetERKNS_10IdentifierERNS_18PropertyDescr __ZN3JSC16JSVariableObject19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE __ZN3JSC16toUInt32SlowCaseEdRb __ZN3JSC17BytecodeGenerator21setDumpsGeneratedCodeEb -__ZN3JSC17PropertyNameArray3addEPNS_11UStringImplE +__ZN3JSC17PropertyNameArray3addEPN7WebCore10StringImplE __ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEN3WTF17NonNullPassRefPtrINS_9StructureEEEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectESA_RKNS_7ArgListEE __ZN3JSC17PrototypeFunctionC1EPNS_9ExecStateEiRKNS_10IdentifierEPFNS_7JSValueES2_PNS_8JSObjectES6_RKNS_7ArgListEE __ZN3JSC17constructFunctionEPNS_9ExecStateERKNS_7ArgListERKNS_10IdentifierERKNS_7UStringEi @@ -184,8 +192,6 @@ __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectENS_7JSValueERKNS_ __ZN3JSC23setUpStaticFunctionSlotEPNS_9ExecStateEPKNS_9HashEntryEPNS_8JSObjectERKNS_10IdentifierERNS_12PropertySlotE __ZN3JSC24createStackOverflowErrorEPNS_9ExecStateE __ZN3JSC25evaluateInGlobalCallFrameERKNS_7UStringERNS_7JSValueEPNS_14JSGlobalObjectE -__ZN3JSC25g_identifierTableSpecificE -__ZN3JSC29createIdentifierTableSpecificEv __ZN3JSC35createInterruptedExecutionExceptionEPNS_12JSGlobalDataE __ZN3JSC3NaNE __ZN3JSC4Heap14primaryHeapEndEv @@ -203,12 +209,10 @@ __ZN3JSC4Heap7protectENS_7JSValueE __ZN3JSC4Heap8allocateEm __ZN3JSC4Heap9unprotectENS_7JSValueE __ZN3JSC4callEPNS_9ExecStateENS_7JSValueENS_8CallTypeERKNS_8CallDataES2_RKNS_7ArgListE -__ZN3JSC5equalEPKNS_11UStringImplES2_ __ZN3JSC6JSCell11getCallDataERNS_8CallDataE __ZN3JSC6JSCell11getJSNumberEv __ZN3JSC6JSCell14deletePropertyEPNS_9ExecStateERKNS_10IdentifierE __ZN3JSC6JSCell14deletePropertyEPNS_9ExecStateEj -__ZN3JSC6JSCell14toThisJSStringEPNS_9ExecStateE __ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE __ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE __ZN3JSC6JSCell18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE @@ -224,12 +228,14 @@ __ZN3JSC6JSLock6unlockENS_14JSLockBehaviorE __ZN3JSC6JSLock9lockCountEv __ZN3JSC6JSLockC1EPNS_9ExecStateE __ZN3JSC6Parser5parseEPNS_12JSGlobalDataEPiPNS_7UStringE -__ZN3JSC7CStringD1Ev -__ZN3JSC7CStringaSERKS0_ +__ZN3JSC7JSArray12markChildrenERNS_9MarkStackE +__ZN3JSC7JSArray15setSubclassDataEPv __ZN3JSC7JSArray4infoE __ZN3JSC7JSArray9setLengthEj __ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEE __ZN3JSC7JSArrayC1EN3WTF17NonNullPassRefPtrINS_9StructureEEERKNS_7ArgListE +__ZN3JSC7JSArrayC2EN3WTF17NonNullPassRefPtrINS_9StructureEEE +__ZN3JSC7JSArrayD2Ev __ZN3JSC7Profile10restoreAllEv __ZN3JSC7Profile5focusEPKNS_11ProfileNodeE __ZN3JSC7Profile7excludeEPKNS_11ProfileNodeE @@ -238,7 +244,6 @@ __ZN3JSC7UString4fromEd __ZN3JSC7UString4fromEi __ZN3JSC7UString4fromEj __ZN3JSC7UString4fromEl -__ZN3JSC7UString9s_nullRepE __ZN3JSC7UStringC1EPKc __ZN3JSC7UStringC1EPKtj __ZN3JSC8Debugger23recompileAllJSFunctionsEPNS_12JSGlobalDataE @@ -280,7 +285,7 @@ __ZN3JSC9MarkStack10s_pageSizeE __ZN3JSC9MarkStack12releaseStackEPvm __ZN3JSC9MarkStack13allocateStackEm __ZN3JSC9MarkStack18initializePagesizeEv -__ZN3JSC9Structure13hasTransitionEPNS_11UStringImplEj +__ZN3JSC9Structure13hasTransitionEPN7WebCore10StringImplEj __ZN3JSC9Structure17stopIgnoringLeaksEv __ZN3JSC9Structure18startIgnoringLeaksEv __ZN3JSC9Structure21addPropertyTransitionEPS0_RKNS_10IdentifierEjPNS_6JSCellERm @@ -289,7 +294,7 @@ __ZN3JSC9Structure25changePrototypeTransitionEPS0_NS_7JSValueE __ZN3JSC9Structure27despecifyDictionaryFunctionERKNS_10IdentifierE __ZN3JSC9Structure27despecifyFunctionTransitionEPS0_RKNS_10IdentifierE __ZN3JSC9Structure28addPropertyWithoutTransitionERKNS_10IdentifierEjPNS_6JSCellE -__ZN3JSC9Structure3getEPKNS_11UStringImplERjRPNS_6JSCellE +__ZN3JSC9Structure3getEPKN7WebCore10StringImplERjRPNS_6JSCellE __ZN3JSC9Structure40addPropertyTransitionToExistingStructureEPS0_RKNS_10IdentifierEjPNS_6JSCellERm __ZN3JSC9StructureC1ENS_7JSValueERKNS_8TypeInfoEj __ZN3JSC9StructureD1Ev @@ -307,9 +312,13 @@ __ZN3WTF12createThreadEPFPvS0_ES0_PKc __ZN3WTF12detachThreadEj __ZN3WTF12isMainThreadEv __ZN3WTF12randomNumberEv +__ZN3WTF13WTFThreadData10staticDataE +__ZN3WTF13WTFThreadDataC1Ev +__ZN3WTF13WTFThreadDataD1Ev __ZN3WTF13currentThreadEv __ZN3WTF13tryFastCallocEmm __ZN3WTF13tryFastMallocEm +__ZN3WTF14fastMallocSizeEPKv __ZN3WTF15ThreadCondition4waitERNS_5MutexE __ZN3WTF15ThreadCondition6signalEv __ZN3WTF15ThreadCondition9broadcastEv @@ -343,7 +352,12 @@ __ZN3WTF5Mutex7tryLockEv __ZN3WTF5MutexC1Ev __ZN3WTF5MutexD1Ev __ZN3WTF6strtodEPKcPPc +__ZN3WTF7CString11mutableDataEv +__ZN3WTF7CString16newUninitializedEmRPc +__ZN3WTF7CStringC1EPKc +__ZN3WTF7CStringC1EPKcj __ZN3WTF7Unicode18convertUTF16ToUTF8EPPKtS2_PPcS4_b +__ZN3WTF7Unicode18convertUTF8ToUTF16EPPKcS2_PPtS4_b __ZN3WTF8Collator18setOrderLowerFirstEb __ZN3WTF8CollatorC1EPKc __ZN3WTF8CollatorD1Ev @@ -351,9 +365,93 @@ __ZN3WTF8fastFreeEPv __ZN3WTF8msToYearEd __ZN3WTF9ByteArray6createEm __ZN3WTF9dayInYearEdi +__ZN3WTFeqERKNS_7CStringES2_ +__ZN7WebCore10StringImpl11reverseFindEPS0_ib +__ZN7WebCore10StringImpl11reverseFindEti +__ZN7WebCore10StringImpl12sharedBufferEv +__ZN7WebCore10StringImpl18simplifyWhiteSpaceEv +__ZN7WebCore10StringImpl19characterStartingAtEj +__ZN7WebCore10StringImpl19createUninitializedEjRPt +__ZN7WebCore10StringImpl22containsOnlyWhitespaceEv +__ZN7WebCore10StringImpl23defaultWritingDirectionEv +__ZN7WebCore10StringImpl37createStrippingNullCharactersSlowCaseEPKtj +__ZN7WebCore10StringImpl4findEPFbtEi +__ZN7WebCore10StringImpl4findEPKcib +__ZN7WebCore10StringImpl4findEPS0_ib +__ZN7WebCore10StringImpl4findEti +__ZN7WebCore10StringImpl5adoptERNS_12StringBufferE +__ZN7WebCore10StringImpl5emptyEv +__ZN7WebCore10StringImpl5lowerEv +__ZN7WebCore10StringImpl5toIntEPb +__ZN7WebCore10StringImpl5upperEv +__ZN7WebCore10StringImpl6createEPKc +__ZN7WebCore10StringImpl6createEPKtj +__ZN7WebCore10StringImpl6createEPKtjN3WTF10PassRefPtrINS3_21CrossThreadRefCountedINS3_16OwnFastMallocPtrIS1_EEEEEE +__ZN7WebCore10StringImpl6secureEt +__ZN7WebCore10StringImpl7replaceEPS0_S1_ +__ZN7WebCore10StringImpl7replaceEjjPS0_ +__ZN7WebCore10StringImpl7replaceEtPS0_ +__ZN7WebCore10StringImpl7replaceEtt +__ZN7WebCore10StringImpl8endsWithEPS0_b +__ZN7WebCore10StringImpl9substringEjj +__ZN7WebCore10StringImplD1Ev +__ZN7WebCore11commentAtomE +__ZN7WebCore12AtomicString3addEPKc +__ZN7WebCore12AtomicString3addEPKt +__ZN7WebCore12AtomicString3addEPKtj +__ZN7WebCore12AtomicString3addEPKtjj +__ZN7WebCore12AtomicString3addEPNS_10StringImplE +__ZN7WebCore12AtomicString4findEPKtjj +__ZN7WebCore12AtomicString4initEv +__ZN7WebCore15charactersToIntEPKtmPb +__ZN7WebCore17charactersToFloatEPKtmPb +__ZN7WebCore17equalIgnoringCaseEPKtPKcj +__ZN7WebCore17equalIgnoringCaseEPNS_10StringImplEPKc +__ZN7WebCore17equalIgnoringCaseEPNS_10StringImplES1_ +__ZN7WebCore18charactersToDoubleEPKtmPb +__ZN7WebCore20equalIgnoringNullityEPNS_10StringImplES1_ +__ZN7WebCore21charactersToIntStrictEPKtmPbi +__ZN7WebCore22charactersToUIntStrictEPKtmPbi +__ZN7WebCore5equalEPKNS_10StringImplEPKc +__ZN7WebCore5equalEPKNS_10StringImplES2_ +__ZN7WebCore6String26fromUTF8WithLatin1FallbackEPKcm +__ZN7WebCore6String29charactersWithNullTerminationEv +__ZN7WebCore6String6appendEPKtj +__ZN7WebCore6String6appendERKS0_ +__ZN7WebCore6String6appendEc +__ZN7WebCore6String6appendEt +__ZN7WebCore6String6formatEPKcz +__ZN7WebCore6String6insertERKS0_j +__ZN7WebCore6String6numberEd +__ZN7WebCore6String6numberEi +__ZN7WebCore6String6numberEj +__ZN7WebCore6String6numberEl +__ZN7WebCore6String6numberEm +__ZN7WebCore6String6numberEt +__ZN7WebCore6String6numberEx +__ZN7WebCore6String6numberEy +__ZN7WebCore6String6removeEji +__ZN7WebCore6String8fromUTF8EPKc +__ZN7WebCore6String8fromUTF8EPKcm +__ZN7WebCore6String8truncateEj +__ZN7WebCore6StringC1EPKc +__ZN7WebCore6StringC1EPKcj +__ZN7WebCore6StringC1EPKt +__ZN7WebCore6StringC1EPKtj +__ZN7WebCore7xmlAtomE +__ZN7WebCore8nullAtomE +__ZN7WebCore8starAtomE +__ZN7WebCore8textAtomE +__ZN7WebCore9emptyAtomE +__ZN7WebCore9xmlnsAtomE +__ZN7WebCoreeqERKNS_12AtomicStringEPKc +__ZN7WebCoreplEPKcRKNS_6StringE +__ZN7WebCoreplERKNS_6StringEPKc +__ZN7WebCoreplERKNS_6StringES2_ __ZNK3JSC10JSFunction23isHostFunctionNonInlineEv __ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_16InternalFunctionE __ZNK3JSC11Interpreter18retrieveLastCallerEPNS_9ExecStateERiRlRNS_7UStringERNS_7JSValueE +__ZNK3JSC12PropertySlot14functionGetterEPNS_9ExecStateE __ZNK3JSC14JSGlobalObject14isDynamicScopeEv __ZNK3JSC16InternalFunction9classInfoEv __ZNK3JSC16JSVariableObject16isVariableObjectEv @@ -373,7 +471,6 @@ __ZNK3JSC4Heap10statisticsEv __ZNK3JSC4Heap11objectCountEv __ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE __ZNK3JSC6JSCell12toThisObjectEPNS_9ExecStateE -__ZNK3JSC6JSCell12toThisStringEPNS_9ExecStateE __ZNK3JSC6JSCell14isGetterSetterEv __ZNK3JSC6JSCell8toNumberEPNS_9ExecStateE __ZNK3JSC6JSCell8toObjectEPNS_9ExecStateE @@ -384,6 +481,7 @@ __ZNK3JSC6JSCell9getStringEPNS_9ExecStateERNS_7UStringE __ZNK3JSC6JSCell9getUInt32ERj __ZNK3JSC6JSCell9toBooleanEPNS_9ExecStateE __ZNK3JSC7ArgList8getSliceEiRS0_ +__ZNK3JSC7JSArray12subclassDataEv __ZNK3JSC7JSValue16toObjectSlowCaseEPNS_9ExecStateE __ZNK3JSC7JSValue19synthesizePrototypeEPNS_9ExecStateE __ZNK3JSC7JSValue20toThisObjectSlowCaseEPNS_9ExecStateE @@ -407,7 +505,39 @@ __ZNK3JSC8JSObject9toBooleanEPNS_9ExecStateE __ZNK3JSC8JSString11resolveRopeEPNS_9ExecStateE __ZNK3JSC9HashTable11createTableEPNS_12JSGlobalDataE __ZNK3JSC9HashTable11deleteTableEv +__ZNK3WTF7CString4dataEv +__ZNK3WTF7CString6lengthEv __ZNK3WTF8Collator7collateEPKtmS2_m +__ZNK7WebCore12AtomicString5lowerEv +__ZNK7WebCore6String10charactersEv +__ZNK7WebCore6String11toIntStrictEPbi +__ZNK7WebCore6String12toUIntStrictEPbi +__ZNK7WebCore6String14threadsafeCopyEv +__ZNK7WebCore6String15stripWhiteSpaceEv +__ZNK7WebCore6String16removeCharactersEPFbtE +__ZNK7WebCore6String17crossThreadStringEv +__ZNK7WebCore6String18simplifyWhiteSpaceEv +__ZNK7WebCore6String19characterStartingAtEj +__ZNK7WebCore6String4utf8Ev +__ZNK7WebCore6String5asciiEv +__ZNK7WebCore6String5lowerEv +__ZNK7WebCore6String5splitERKS0_RN3WTF6VectorIS0_Lm0EEE +__ZNK7WebCore6String5splitERKS0_bRN3WTF6VectorIS0_Lm0EEE +__ZNK7WebCore6String5splitEtRN3WTF6VectorIS0_Lm0EEE +__ZNK7WebCore6String5splitEtbRN3WTF6VectorIS0_Lm0EEE +__ZNK7WebCore6String5toIntEPb +__ZNK7WebCore6String5upperEv +__ZNK7WebCore6String6latin1Ev +__ZNK7WebCore6String6lengthEv +__ZNK7WebCore6String6toUIntEPb +__ZNK7WebCore6String7isEmptyEv +__ZNK7WebCore6String7toFloatEPb +__ZNK7WebCore6String8foldCaseEv +__ZNK7WebCore6String8toDoubleEPb +__ZNK7WebCore6String8toIntPtrEPb +__ZNK7WebCore6String8toUInt64EPb +__ZNK7WebCore6String9substringEjj +__ZNK7WebCore6StringixEj __ZTVN3JSC12StringObjectE __ZTVN3JSC14JSGlobalObjectE __ZTVN3JSC15JSWrapperObjectE diff --git a/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp b/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp index 66f40e9..b2ccf1a 100644 --- a/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp +++ b/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp @@ -114,7 +114,7 @@ # ... Then include what we want. ['include', '../wtf/'], # GLib/GTK, even though its name doesn't really indicate. - ['exclude', '/(gtk|glib)/.*\\.(cpp|h)$'], + ['exclude', '/(gtk|glib|gobject)/.*\\.(cpp|h)$'], ['exclude', '(Default|Gtk|Mac|None|Qt|Win|Wx)\\.(cpp|mm)$'], ['exclude', 'wtf/CurrentTime\\.cpp$'], ['exclude', 'wtf/TC.*\\.(cpp|h)$'], diff --git a/JavaScriptCore/JavaScriptCore.gypi b/JavaScriptCore/JavaScriptCore.gypi index c0eb086..ad2d09e 100644 --- a/JavaScriptCore/JavaScriptCore.gypi +++ b/JavaScriptCore/JavaScriptCore.gypi @@ -325,26 +325,13 @@ 'runtime/StructureChain.h', 'runtime/StructureTransitionTable.h', 'runtime/SymbolTable.h', + 'runtime/Terminator.h', 'runtime/TimeoutChecker.cpp', 'runtime/TimeoutChecker.h', 'runtime/Tracing.h', 'runtime/UString.cpp', 'runtime/UString.h', 'runtime/WeakRandom.h', - 'wrec/CharacterClass.cpp', - 'wrec/CharacterClass.h', - 'wrec/CharacterClassConstructor.cpp', - 'wrec/CharacterClassConstructor.h', - 'wrec/Escapes.h', - 'wrec/Quantifier.h', - 'wrec/WREC.cpp', - 'wrec/WREC.h', - 'wrec/WRECFunctors.cpp', - 'wrec/WRECFunctors.h', - 'wrec/WRECGenerator.cpp', - 'wrec/WRECGenerator.h', - 'wrec/WRECParser.cpp', - 'wrec/WRECParser.h', 'wtf/AlwaysInline.h', 'wtf/ASCIICType.h', 'wtf/Assertions.cpp', @@ -368,8 +355,8 @@ 'wtf/FastMalloc.h', 'wtf/Forward.h', 'wtf/GetPtr.h', - 'wtf/gtk/GOwnPtr.cpp', - 'wtf/gtk/GOwnPtr.h', + 'wtf/gobject/GOwnPtr.cpp', + 'wtf/gobject/GOwnPtr.h', 'wtf/gtk/MainThreadGtk.cpp', 'wtf/gtk/ThreadingGtk.cpp', 'wtf/HashCountedSet.h', @@ -409,11 +396,13 @@ 'wtf/RefPtrHashMap.h', 'wtf/RetainPtr.h', 'wtf/SegmentedVector.h', + 'wtf/StaticConstructors.h', 'wtf/StdLibExtras.h', 'wtf/StringExtras.h', 'wtf/StringHashFunctions.h', 'wtf/TCPackedCache.h', 'wtf/qt/MainThreadQt.cpp', + 'wtf/qt/StringQt.cpp', 'wtf/qt/ThreadingQt.cpp', 'wtf/TCPageMap.h', 'wtf/TCSpinLock.h', @@ -430,6 +419,16 @@ 'wtf/ThreadSpecificWin.cpp', 'wtf/TypeTraits.cpp', 'wtf/TypeTraits.h', + 'wtf/text/AtomicString.cpp', + 'wtf/text/AtomicString.h', + 'wtf/text/AtomicStringImpl.h', + 'wtf/text/CString.cpp', + 'wtf/text/CString.h', + 'wtf/text/StringHash.h', + 'wtf/text/StringImpl.cpp', + 'wtf/text/StringImpl.h', + 'wtf/text/WTFString.cpp', + 'wtf/text/WTFString.h', 'wtf/unicode/Collator.h', 'wtf/unicode/CollatorDefault.cpp', 'wtf/unicode/glib/UnicodeGLib.cpp', @@ -446,6 +445,8 @@ 'wtf/Vector.h', 'wtf/VectorTraits.h', 'wtf/VMTags.h', + 'wtf/WTFThreadData.cpp', + 'wtf/WTFThreadData.h', 'wtf/win/MainThreadWin.cpp', 'wtf/wx/MainThreadWx.cpp', 'yarr/RegexCompiler.cpp', diff --git a/JavaScriptCore/JavaScriptCore.pri b/JavaScriptCore/JavaScriptCore.pri index d4cfe10..24c8ce5 100644 --- a/JavaScriptCore/JavaScriptCore.pri +++ b/JavaScriptCore/JavaScriptCore.pri @@ -1,5 +1,6 @@ # JavaScriptCore - Qt4 build info VPATH += $$PWD +JAVASCRIPTCORE_TARGET = jscore CONFIG(standalone_package) { isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = $$PWD/generated @@ -7,15 +8,12 @@ CONFIG(standalone_package) { isEmpty(JSC_GENERATED_SOURCES_DIR):JSC_GENERATED_SOURCES_DIR = generated } -CONFIG(debug, debug|release) { - OBJECTS_DIR = obj/debug -} else { # Release - OBJECTS_DIR = obj/release -} +CONFIG(standalone_package): DEFINES *= NDEBUG symbian: { # Need to guarantee this comes before system includes of /epoc32/include MMP_RULES += "USERINCLUDE ../JavaScriptCore/profiler" + LIBS += -lhal } INCLUDEPATH = \ @@ -31,8 +29,8 @@ INCLUDEPATH = \ $$PWD/pcre \ $$PWD/profiler \ $$PWD/runtime \ - $$PWD/wrec \ $$PWD/wtf \ + $$PWD/wtf/symbian \ $$PWD/wtf/unicode \ $$PWD/yarr \ $$PWD/API \ @@ -40,11 +38,10 @@ INCLUDEPATH = \ $$JSC_GENERATED_SOURCES_DIR \ $$INCLUDEPATH +win32-*: DEFINES += _HAS_TR1=0 + DEFINES += BUILDING_QT__ BUILDING_JavaScriptCore BUILDING_WTF -win32-* { - LIBS += -lwinmm -} contains(JAVASCRIPTCORE_JIT,yes) { DEFINES+=ENABLE_JIT=1 DEFINES+=ENABLE_YARR_JIT=1 @@ -56,177 +53,48 @@ contains(JAVASCRIPTCORE_JIT,no) { DEFINES+=ENABLE_YARR=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) { - QMAKE_CXXFLAGS += -fno-stack-protector - QMAKE_CFLAGS += -fno-stack-protector - } -} - wince* { INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/ce-compat - SOURCES += $$QT_SOURCE_TREE/src/3rdparty/ce-compat/ce_time.c DEFINES += WINCEBASIC -} -include(pcre/pcre.pri) - -SOURCES += \ - API/JSBase.cpp \ - API/JSCallbackConstructor.cpp \ - API/JSCallbackFunction.cpp \ - API/JSCallbackObject.cpp \ - API/JSClassRef.cpp \ - API/JSContextRef.cpp \ - API/JSObjectRef.cpp \ - API/JSStringRef.cpp \ - API/JSValueRef.cpp \ - API/OpaqueJSString.cpp \ - assembler/ARMAssembler.cpp \ - assembler/MacroAssemblerARM.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/JITPropertyAccess32_64.cpp \ - jit/JITStubs.cpp \ - 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 \ - runtime/ArrayPrototype.cpp \ - runtime/BooleanConstructor.cpp \ - runtime/BooleanObject.cpp \ - runtime/BooleanPrototype.cpp \ - runtime/CallData.cpp \ - runtime/Collector.cpp \ - runtime/CommonIdentifiers.cpp \ - runtime/Completion.cpp \ - runtime/ConstructData.cpp \ - runtime/DateConstructor.cpp \ - runtime/DateConversion.cpp \ - runtime/DateInstance.cpp \ - runtime/DatePrototype.cpp \ - runtime/ErrorConstructor.cpp \ - runtime/Error.cpp \ - runtime/ErrorInstance.cpp \ - runtime/ErrorPrototype.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/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 \ - 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 \ - runtime/NumberConstructor.cpp \ - runtime/NumberObject.cpp \ - runtime/NumberPrototype.cpp \ - runtime/ObjectConstructor.cpp \ - runtime/ObjectPrototype.cpp \ - runtime/Operations.cpp \ - runtime/PropertyDescriptor.cpp \ - runtime/PropertyNameArray.cpp \ - runtime/PropertySlot.cpp \ - runtime/PrototypeFunction.cpp \ - runtime/RegExpConstructor.cpp \ - runtime/RegExp.cpp \ - runtime/RegExpObject.cpp \ - runtime/RegExpPrototype.cpp \ - runtime/ScopeChain.cpp \ - runtime/SmallStrings.cpp \ - runtime/StringConstructor.cpp \ - runtime/StringObject.cpp \ - runtime/StringPrototype.cpp \ - runtime/StructureChain.cpp \ - runtime/Structure.cpp \ - runtime/TimeoutChecker.cpp \ - runtime/UString.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/TypeTraits.cpp \ - wtf/unicode/CollatorDefault.cpp \ - wtf/unicode/icu/CollatorICU.cpp \ - wtf/unicode/UTF8.cpp \ - yarr/RegexCompiler.cpp \ - yarr/RegexInterpreter.cpp \ - yarr/RegexJIT.cpp - -# Generated files, simply list them for JavaScriptCore -SOURCES += \ - $${JSC_GENERATED_SOURCES_DIR}/Grammar.cpp - -!contains(DEFINES, USE_SYSTEM_MALLOC) { - SOURCES += wtf/TCSystemAlloc.cpp + INCLUDEPATH += $$PWD/../JavaScriptCore/os-wince + INCLUDEPATH += $$PWD/../JavaScriptCore/os-win32 } + +defineTest(addJavaScriptCoreLib) { + pathToJavaScriptCoreOutput = $$ARGS + CONFIG(debug_and_release):CONFIG(debug, debug|release): pathToJavaScriptCoreOutput = $$pathToJavaScriptCoreOutput/debug + CONFIG(debug_and_release):CONFIG(release, debug|release): pathToJavaScriptCoreOutput = $$pathToJavaScriptCoreOutput/release + + win32-msvc*|wince* { + LIBS += -L$$pathToJavaScriptCoreOutput + LIBS += -l$$JAVASCRIPTCORE_TARGET + POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}$${JAVASCRIPTCORE_TARGET}.lib + } else:symbian { + LIBS += -l$${JAVASCRIPTCORE_TARGET}.lib + POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}$${JAVASCRIPTCORE_TARGET}.lib + } else { + # Make sure jscore will be early in the list of libraries to workaround a bug in MinGW + # that can't resolve symbols from QtCore if libjscore comes after. + QMAKE_LIBDIR = $$pathToJavaScriptCoreOutput $$QMAKE_LIBDIR + LIBS += -l$$JAVASCRIPTCORE_TARGET + POST_TARGETDEPS += $${pathToJavaScriptCoreOutput}$${QMAKE_DIR_SEP}lib$${JAVASCRIPTCORE_TARGET}.a + } + + win32-* { + LIBS += -lwinmm + } + + # The following line is to prevent qmake from adding jscore to libQtWebKit's prl dependencies. + # The compromise we have to accept by disabling explicitlib is to drop support to link QtWebKit and QtScript + # statically in applications (which isn't used often because, among other things, of licensing obstacles). + CONFIG -= explicitlib + + export(QMAKE_LIBDIR) + export(LIBS) + export(POST_TARGETDEPS) + export(CONFIG) + + return(true) +} diff --git a/JavaScriptCore/JavaScriptCore.pro b/JavaScriptCore/JavaScriptCore.pro index 0d6becb..f33be05 100644 --- a/JavaScriptCore/JavaScriptCore.pro +++ b/JavaScriptCore/JavaScriptCore.pro @@ -1,28 +1,21 @@ # JavaScriptCore - qmake build info CONFIG += building-libs include($$PWD/../WebKit.pri) +include(JavaScriptCore.pri) TEMPLATE = lib CONFIG += staticlib -TARGET = JavaScriptCore +# Don't use JavaScriptCore as the target name. qmake would create a JavaScriptCore.vcproj for msvc +# which already exists as a directory +TARGET = $$JAVASCRIPTCORE_TARGET +QT += core CONFIG += depend_includepath contains(QT_CONFIG, embedded):CONFIG += embedded -CONFIG(QTDIR_build) { - GENERATED_SOURCES_DIR = $$PWD/generated - OLDDESTDIR = $$DESTDIR - include($$QT_SOURCE_TREE/src/qbase.pri) - INSTALLS = - DESTDIR = $$OLDDESTDIR - DEFINES *= NDEBUG -} - -isEmpty(GENERATED_SOURCES_DIR):GENERATED_SOURCES_DIR = tmp -GENERATED_SOURCES_DIR_SLASH = $${GENERATED_SOURCES_DIR}$${QMAKE_DIR_SEP} - -INCLUDEPATH += $$GENERATED_SOURCES_DIR +CONFIG(debug_and_release):CONFIG(debug, debug|release): DESTDIR = debug +CONFIG(debug_and_release):CONFIG(release, debug|release): DESTDIR = release !CONFIG(QTDIR_build) { CONFIG(debug, debug|release) { @@ -30,20 +23,16 @@ INCLUDEPATH += $$GENERATED_SOURCES_DIR } else { # Release OBJECTS_DIR = obj/release } + # Make sure that build_all follows the build_all config in WebCore + mac:contains(QT_CONFIG, qt_framework):!CONFIG(webkit_no_framework):!build_pass:CONFIG += build_all } -CONFIG(release):!CONFIG(QTDIR_build) { - contains(QT_CONFIG, reduce_exports):CONFIG += hide_symbols - unix:contains(QT_CONFIG, reduce_relocations):CONFIG += bsymbolic_functions +CONFIG(QTDIR_build) { + # Remove the following 2 lines if you want debug information in JavaScriptCore + CONFIG -= separate_debug_info + CONFIG += no_debug_info } -linux-*: DEFINES += HAVE_STDINT_H -freebsd-*: DEFINES += HAVE_PTHREAD_NP_H - -DEFINES += BUILD_WEBKIT - -win32-*: DEFINES += _HAS_TR1=0 - # Pick up 3rdparty libraries from INCLUDE/LIB just like with MSVC win32-g++ { TMPPATH = $$quote($$(INCLUDE)) @@ -52,11 +41,185 @@ win32-g++ { QMAKE_LIBDIR_POST += $$split(TMPPATH,";") } -DEFINES += WTF_CHANGES=1 +*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2 +*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3 -include(JavaScriptCore.pri) +# 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) { + QMAKE_CXXFLAGS += -fno-stack-protector + QMAKE_CFLAGS += -fno-stack-protector + } +} -QMAKE_EXTRA_TARGETS += generated_files +wince* { + SOURCES += $$QT_SOURCE_TREE/src/3rdparty/ce-compat/ce_time.c +} -*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2 -*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3 +include(pcre/pcre.pri) + +SOURCES += \ + API/JSBase.cpp \ + API/JSCallbackConstructor.cpp \ + API/JSCallbackFunction.cpp \ + API/JSCallbackObject.cpp \ + API/JSClassRef.cpp \ + API/JSContextRef.cpp \ + API/JSObjectRef.cpp \ + API/JSStringRef.cpp \ + API/JSValueRef.cpp \ + API/OpaqueJSString.cpp \ + assembler/ARMAssembler.cpp \ + assembler/MacroAssemblerARM.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/ExecutableAllocatorFixedVMPool.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/JITPropertyAccess32_64.cpp \ + jit/JITStubs.cpp \ + 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 \ + runtime/ArrayPrototype.cpp \ + runtime/BooleanConstructor.cpp \ + runtime/BooleanObject.cpp \ + runtime/BooleanPrototype.cpp \ + runtime/CallData.cpp \ + runtime/Collector.cpp \ + runtime/CommonIdentifiers.cpp \ + runtime/Completion.cpp \ + runtime/ConstructData.cpp \ + runtime/DateConstructor.cpp \ + runtime/DateConversion.cpp \ + runtime/DateInstance.cpp \ + runtime/DatePrototype.cpp \ + runtime/ErrorConstructor.cpp \ + runtime/Error.cpp \ + runtime/ErrorInstance.cpp \ + runtime/ErrorPrototype.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/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 \ + 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 \ + runtime/NumberConstructor.cpp \ + runtime/NumberObject.cpp \ + runtime/NumberPrototype.cpp \ + runtime/ObjectConstructor.cpp \ + runtime/ObjectPrototype.cpp \ + runtime/Operations.cpp \ + runtime/PropertyDescriptor.cpp \ + runtime/PropertyNameArray.cpp \ + runtime/PropertySlot.cpp \ + runtime/PrototypeFunction.cpp \ + runtime/RegExpConstructor.cpp \ + runtime/RegExp.cpp \ + runtime/RegExpObject.cpp \ + runtime/RegExpPrototype.cpp \ + runtime/RopeImpl.cpp \ + runtime/ScopeChain.cpp \ + runtime/SmallStrings.cpp \ + runtime/StringConstructor.cpp \ + runtime/StringObject.cpp \ + runtime/StringPrototype.cpp \ + runtime/StructureChain.cpp \ + runtime/Structure.cpp \ + runtime/TimeoutChecker.cpp \ + runtime/UString.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/StringQt.cpp \ + wtf/qt/ThreadingQt.cpp \ + wtf/RandomNumber.cpp \ + wtf/RefCountedLeakCounter.cpp \ + wtf/symbian/BlockAllocatorSymbian.cpp \ + wtf/ThreadingNone.cpp \ + wtf/Threading.cpp \ + wtf/TypeTraits.cpp \ + wtf/WTFThreadData.cpp \ + wtf/text/AtomicString.cpp \ + wtf/text/CString.cpp \ + wtf/text/StringImpl.cpp \ + wtf/text/WTFString.cpp \ + wtf/unicode/CollatorDefault.cpp \ + wtf/unicode/icu/CollatorICU.cpp \ + wtf/unicode/UTF8.cpp \ + yarr/RegexCompiler.cpp \ + yarr/RegexInterpreter.cpp \ + yarr/RegexJIT.cpp + +# Generated files, simply list them for JavaScriptCore +SOURCES += \ + $${JSC_GENERATED_SOURCES_DIR}/Grammar.cpp + +!contains(DEFINES, USE_SYSTEM_MALLOC) { + SOURCES += wtf/TCSystemAlloc.cpp +} diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index 9e1e74a..76f2fa7 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -1,5 +1,7 @@ EXPORTS - + + ??0CString@WTF@@QAE@PBD@Z + ??0CString@WTF@@QAE@PBDI@Z ??0Collator@WTF@@QAE@PBD@Z ??0DateInstance@JSC@@QAE@PAVExecState@1@N@Z ??0DateInstance@JSC@@QAE@PAVExecState@1@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@N@Z @@ -13,12 +15,16 @@ EXPORTS ??0PrototypeFunction@JSC@@QAE@PAVExecState@1@HABVIdentifier@1@P6I?AVJSValue@1@0PAVJSObject@1@V41@ABVArgList@1@@Z@Z ??0PrototypeFunction@JSC@@QAE@PAVExecState@1@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@HABVIdentifier@1@P6I?AVJSValue@1@0PAVJSObject@1@V61@ABVArgList@1@@Z@Z ??0RefCountedLeakCounter@WTF@@QAE@PBD@Z + ??0String@WebCore@@QAE@PBD@Z + ??0String@WebCore@@QAE@PBDI@Z + ??0String@WebCore@@QAE@PB_W@Z + ??0String@WebCore@@QAE@PB_WI@Z ??0StringObject@JSC@@QAE@PAVExecState@1@V?$NonNullPassRefPtr@VStructure@JSC@@@WTF@@ABVUString@1@@Z ??0Structure@JSC@@AAE@VJSValue@1@ABVTypeInfo@1@I@Z ??0ThreadCondition@WTF@@QAE@XZ ??0UString@JSC@@QAE@PBD@Z ??0UString@JSC@@QAE@PB_WI@Z - ??1CString@JSC@@QAE@XZ + ??0WTFThreadData@WTF@@QAE@XZ ??1ClientData@JSGlobalData@JSC@@UAE@XZ ??1Collator@WTF@@QAE@XZ ??1Debugger@JSC@@UAE@XZ @@ -27,23 +33,40 @@ EXPORTS ??1JSGlobalObject@JSC@@UAE@XZ ??1Mutex@WTF@@QAE@XZ ??1RefCountedLeakCounter@WTF@@QAE@XZ + ??1StringImpl@WebCore@@QAE@XZ ??1Structure@JSC@@QAE@XZ ??1ThreadCondition@WTF@@QAE@XZ - ??1UStringImpl@JSC@@AAE@XZ + ??1WTFThreadData@WTF@@QAE@XZ ??2JSGlobalObject@JSC@@SAPAXIPAVJSGlobalData@1@@Z ??8JSC@@YA_NABVUString@0@0@Z + ??8WTF@@YA_NABVCString@0@0@Z + ??8WebCore@@YA_NABVAtomicString@0@PBD@Z + ??AString@WebCore@@QBE_WI@Z + ??HWebCore@@YA?AVString@0@ABV10@0@Z + ??HWebCore@@YA?AVString@0@ABV10@PBD@Z + ??HWebCore@@YA?AVString@0@PBDABV10@@Z ?NaN@JSC@@3NB - ?UTF8String@UString@JSC@@QBE?AVCString@2@_N@Z + ?UTF8String@UString@JSC@@QBE?AVCString@WTF@@_N@Z + ?add@AtomicString@WebCore@@CA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PAVStringImpl@2@@Z + ?add@AtomicString@WebCore@@CA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PBD@Z + ?add@AtomicString@WebCore@@CA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PB_W@Z + ?add@AtomicString@WebCore@@CA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PB_WI@Z + ?add@AtomicString@WebCore@@CA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PB_WII@Z + ?add@Identifier@JSC@@SA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PAVExecState@2@PBD@Z + ?add@PropertyNameArray@JSC@@QAEXPAVStringImpl@WebCore@@@Z ?addPropertyTransition@Structure@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@PAV12@ABVIdentifier@2@IPAVJSCell@2@AAI@Z ?addPropertyTransitionToExistingStructure@Structure@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@PAV12@ABVIdentifier@2@IPAVJSCell@2@AAI@Z ?addPropertyWithoutTransition@Structure@JSC@@QAEIABVIdentifier@2@IPAVJSCell@2@@Z - ?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VUStringImpl@JSC@@@WTF@@PAVExecState@2@PAVUStringImpl@2@@Z - ?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VUStringImpl@JSC@@@WTF@@PAVJSGlobalData@2@PAVUStringImpl@2@@Z - ?add@Identifier@JSC@@SA?AV?$PassRefPtr@VUStringImpl@JSC@@@WTF@@PAVExecState@2@PBD@Z - ?add@PropertyNameArray@JSC@@QAEXPAVUStringImpl@2@@Z + ?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PAVExecState@2@PAVStringImpl@WebCore@@@Z + ?adopt@StringImpl@WebCore@@SA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@AAVStringBuffer@2@@Z ?allocate@Heap@JSC@@QAEPAXI@Z ?allocatePropertyStorage@JSObject@JSC@@QAEXII@Z ?allocateStack@MarkStack@JSC@@CAPAXI@Z + ?append@String@WebCore@@QAEXABV12@@Z + ?append@String@WebCore@@QAEXD@Z + ?append@String@WebCore@@QAEXPB_WI@Z + ?append@String@WebCore@@QAEX_W@Z + ?ascii@String@WebCore@@QBE?AV?$Vector@D$0A@@WTF@@XZ ?ascii@UString@JSC@@QBEPADXZ ?attach@Debugger@JSC@@QAEXPAVJSGlobalObject@2@@Z ?broadcast@ThreadCondition@WTF@@QAEXXZ @@ -52,43 +75,62 @@ EXPORTS ?callOnMainThread@WTF@@YAXP6AXPAX@Z0@Z ?callOnMainThreadAndWait@WTF@@YAXP6AXPAX@Z0@Z ?changePrototypeTransition@Structure@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@PAV12@VJSValue@2@@Z - ?checkSameIdentifierTable@Identifier@JSC@@CAXPAVExecState@2@PAVUStringImpl@2@@Z - ?checkSameIdentifierTable@Identifier@JSC@@CAXPAVJSGlobalData@2@PAVUStringImpl@2@@Z + ?characterStartingAt@String@WebCore@@QBEHI@Z + ?characters@String@WebCore@@QBEPB_WXZ + ?charactersToDouble@WebCore@@YANPB_WIPA_N@Z + ?charactersToFloat@WebCore@@YAMPB_WIPA_N@Z + ?charactersToInt@WebCore@@YAHPB_WIPA_N@Z + ?charactersToIntStrict@WebCore@@YAHPB_WIPA_NH@Z + ?charactersToUIntStrict@WebCore@@YAIPB_WIPA_NH@Z + ?charactersWithNullTermination@String@WebCore@@QAEPB_WXZ + ?checkCurrentIdentifierTable@Identifier@JSC@@CAXPAVExecState@2@@Z + ?checkCurrentIdentifierTable@Identifier@JSC@@CAXPAVJSGlobalData@2@@Z ?checkSyntax@JSC@@YA?AVCompletion@1@PAVExecState@1@ABVSourceCode@1@@Z ?classInfo@InternalFunction@JSC@@UBEPBUClassInfo@2@XZ ?classInfo@JSCell@JSC@@UBEPBUClassInfo@2@XZ ?className@JSObject@JSC@@UBE?AVUString@2@XZ ?collate@Collator@WTF@@QBE?AW4Result@12@PB_WI0I@Z ?collectAllGarbage@Heap@JSC@@QAEXXZ + ?commentAtom@WebCore@@3VAtomicString@1@B ?configurable@PropertyDescriptor@JSC@@QBE_NXZ ?construct@JSC@@YAPAVJSObject@1@PAVExecState@1@VJSValue@1@W4ConstructType@1@ABTConstructData@1@ABVArgList@1@@Z ?constructArray@JSC@@YAPAVJSArray@1@PAVExecState@1@ABVArgList@1@@Z ?constructEmptyArray@JSC@@YAPAVJSArray@1@PAVExecState@1@@Z ?constructEmptyObject@JSC@@YAPAVJSObject@1@PAVExecState@1@@Z ?constructFunction@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVArgList@1@ABVIdentifier@1@ABVUString@1@H@Z + ?containsOnlyWhitespace@StringImpl@WebCore@@QAE_NXZ ?convertUTF16ToUTF8@Unicode@WTF@@YA?AW4ConversionResult@12@PAPB_WPB_WPAPADPAD_N@Z + ?convertUTF8ToUTF16@Unicode@WTF@@YA?AW4ConversionResult@12@PAPBDPBDPAPA_WPA_W_N@Z ?create@ByteArray@WTF@@SA?AV?$PassRefPtr@VByteArray@WTF@@@2@I@Z - ?create@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@XZ + ?create@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@W4ThreadStackType@2@@Z ?create@OpaqueJSString@@SA?AV?$PassRefPtr@UOpaqueJSString@@@WTF@@ABVUString@JSC@@@Z + ?create@StringImpl@WebCore@@SA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PBD@Z + ?create@StringImpl@WebCore@@SA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PB_WI@Z + ?create@StringImpl@WebCore@@SA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PB_WIV?$PassRefPtr@V?$CrossThreadRefCounted@V?$OwnFastMallocPtr@$$CB_W@WTF@@@WTF@@@4@@Z ?createEmptyString@SmallStrings@JSC@@AAEXPAVJSGlobalData@2@@Z ?createInheritorID@JSObject@JSC@@AAEPAVStructure@2@XZ ?createInterruptedExecutionException@JSC@@YA?AVJSValue@1@PAVJSGlobalData@1@@Z - ?createLeaked@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@XZ + ?createLeaked@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@W4ThreadStackType@2@@Z ?createSingleCharacterString@SmallStrings@JSC@@AAEXPAVJSGlobalData@2@E@Z ?createStackOverflowError@JSC@@YA?AVJSValue@1@PAVExecState@1@@Z + ?createStrippingNullCharactersSlowCase@StringImpl@WebCore@@CA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PB_WI@Z ?createStructure@JSByteArray@JSC@@SA?AV?$PassRefPtr@VStructure@JSC@@@WTF@@VJSValue@2@@Z ?createTable@HashTable@JSC@@ABEXPAVJSGlobalData@2@@Z ?createThread@WTF@@YAIP6APAXPAX@Z0@Z ?createThread@WTF@@YAIP6APAXPAX@Z0PBD@Z ?createTypeError@JSC@@YA?AVJSValue@1@PAVExecState@1@PBD@Z + ?createUninitialized@StringImpl@WebCore@@SA?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@IAAPA_W@Z + ?crossThreadString@String@WebCore@@QBE?AV12@XZ ?currentThread@WTF@@YAIXZ ?currentTime@WTF@@YANXZ + ?data@CString@WTF@@QBEPBDXZ ?dateToDaysFrom1970@WTF@@YANHHH@Z ?dayInMonthFromDayInYear@WTF@@YAHH_N@Z ?dayInYear@WTF@@YAHNH@Z ?decrement@RefCountedLeakCounter@WTF@@QAEXXZ ?defaultAttributes@PropertyDescriptor@JSC@@0IA ?defaultValue@JSObject@JSC@@UBE?AVJSValue@2@PAVExecState@2@W4PreferredPrimitiveType@2@@Z + ?defaultWritingDirection@StringImpl@WebCore@@QAE?AW4Direction@Unicode@WTF@@XZ ?defineGetter@JSGlobalObject@JSC@@UAEXPAVExecState@2@ABVIdentifier@2@PAVJSObject@2@I@Z ?defineGetter@JSObject@JSC@@UAEXPAVExecState@2@ABVIdentifier@2@PAV12@I@Z ?defineOwnProperty@JSObject@JSC@@UAE_NPAVExecState@2@ABVIdentifier@2@AAVPropertyDescriptor@2@_N@Z @@ -113,24 +155,47 @@ EXPORTS ?didTimeOut@TimeoutChecker@JSC@@QAE_NPAVExecState@2@@Z ?doubleToStringInJavaScriptFormat@WTF@@YAXNQADPAI@Z ?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z + ?empty@StringImpl@WebCore@@SAPAV12@XZ + ?emptyAtom@WebCore@@3VAtomicString@1@B + ?endsWith@StringImpl@WebCore@@QAE_NPAV12@_N@Z ?enumerable@PropertyDescriptor@JSC@@QBE_NXZ - ?equal@Identifier@JSC@@SA_NPBVUStringImpl@2@PBD@Z - ?equal@JSC@@YA_NPBVUStringImpl@1@0@Z + ?equal@Identifier@JSC@@SA_NPBVStringImpl@WebCore@@PBD@Z + ?equal@WebCore@@YA_NPBVStringImpl@1@0@Z + ?equal@WebCore@@YA_NPBVStringImpl@1@PBD@Z + ?equalIgnoringCase@WebCore@@YA_NPAVStringImpl@1@0@Z + ?equalIgnoringCase@WebCore@@YA_NPAVStringImpl@1@PBD@Z + ?equalIgnoringCase@WebCore@@YA_NPB_WPBDI@Z + ?equalIgnoringNullity@WebCore@@YA_NPAVStringImpl@1@0@Z ?evaluate@DebuggerCallFrame@JSC@@QBE?AVJSValue@2@ABVUString@2@AAV32@@Z ?evaluate@JSC@@YA?AVCompletion@1@PAVExecState@1@AAVScopeChain@1@ABVSourceCode@1@VJSValue@1@@Z ?exclude@Profile@JSC@@QAEXPBVProfileNode@2@@Z ?fastCalloc@WTF@@YAPAXII@Z ?fastFree@WTF@@YAXPAX@Z ?fastMalloc@WTF@@YAPAXI@Z + ?fastMallocSize@WTF@@YAIPBX@Z ?fastRealloc@WTF@@YAPAXPAXI@Z ?fastStrDup@WTF@@YAPADPBD@Z ?fastZeroedMalloc@WTF@@YAPAXI@Z ?fillGetterPropertySlot@JSObject@JSC@@QAEXAAVPropertySlot@2@PAVJSValue@2@@Z + ?find@AtomicString@WebCore@@SAPAVAtomicStringImpl@2@PB_WII@Z + ?find@StringImpl@WebCore@@QAEHP6A_N_W@ZH@Z + ?find@StringImpl@WebCore@@QAEHPAV12@H_N@Z + ?find@StringImpl@WebCore@@QAEHPBDH_N@Z + ?find@StringImpl@WebCore@@QAEH_WH@Z ?focus@Profile@JSC@@QAEXPBVProfileNode@2@@Z + ?foldCase@String@WebCore@@QBE?AV12@XZ + ?format@String@WebCore@@SA?AV12@PBDZZ + ?from@Identifier@JSC@@SA?AV12@PAVExecState@2@H@Z + ?from@Identifier@JSC@@SA?AV12@PAVExecState@2@I@Z ?from@UString@JSC@@SA?AV12@H@Z ?from@UString@JSC@@SA?AV12@I@Z ?from@UString@JSC@@SA?AV12@N@Z + ?fromUTF8@String@WebCore@@SA?AV12@PBD@Z + ?fromUTF8@String@WebCore@@SA?AV12@PBDI@Z + ?fromUTF8WithLatin1Fallback@String@WebCore@@SA?AV12@PBDI@Z + ?functionGetter@PropertySlot@JSC@@ABE?AVJSValue@2@PAVExecState@2@@Z ?functionName@DebuggerCallFrame@JSC@@QBEPBVUString@2@XZ + ?get@Structure@JSC@@QAEIPBVStringImpl@WebCore@@AAIAAPAVJSCell@2@@Z ?getCallData@JSCell@JSC@@UAE?AW4CallType@2@AATCallData@2@@Z ?getConstructData@JSCell@JSC@@UAE?AW4ConstructType@2@AATConstructData@2@@Z ?getJSNumber@JSCell@JSC@@UAE?AVJSValue@2@XZ @@ -157,25 +222,27 @@ EXPORTS ?getString@JSCell@JSC@@QBE?AVUString@2@PAVExecState@2@@Z ?getString@JSCell@JSC@@QBE_NPAVExecState@2@AAVUString@2@@Z ?getUInt32@JSCell@JSC@@UBE_NAAI@Z - ?get@Structure@JSC@@QAEIPBVUStringImpl@2@AAIAAPAVJSCell@2@@Z ?getter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ ?globalExec@JSGlobalObject@JSC@@UAEPAVExecState@2@XZ ?globalObjectCount@Heap@JSC@@QAEIXZ ?hasInstance@JSObject@JSC@@UAE_NPAVExecState@2@VJSValue@2@1@Z ?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@ABVIdentifier@2@@Z ?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@I@Z - ?hasTransition@Structure@JSC@@QAE_NPAVUStringImpl@2@I@Z + ?hasTransition@Structure@JSC@@QAE_NPAVStringImpl@WebCore@@I@Z ?heap@Heap@JSC@@SAPAV12@VJSValue@2@@Z ?increment@RefCountedLeakCounter@WTF@@QAEXXZ + ?init@AtomicString@WebCore@@SAXXZ ?init@JSGlobalObject@JSC@@AAEXPAVJSObject@2@@Z ?initializeMainThread@WTF@@YAXXZ ?initializeThreading@JSC@@YAXXZ ?initializeThreading@WTF@@YAXXZ + ?insert@String@WebCore@@QAEXABV12@I@Z ?is8Bit@UString@JSC@@QBE_NXZ ?isAccessorDescriptor@PropertyDescriptor@JSC@@QBE_NXZ ?isBusy@Heap@JSC@@QAE_NXZ ?isDataDescriptor@PropertyDescriptor@JSC@@QBE_NXZ ?isDynamicScope@JSGlobalObject@JSC@@UBE_NXZ + ?isEmpty@String@WebCore@@QBE_NXZ ?isGetterSetter@JSCell@JSC@@UBE_NXZ ?isHostFunctionNonInline@JSFunction@JSC@@ABE_NXZ ?isMainThread@WTF@@YA_NXZ @@ -186,11 +253,17 @@ EXPORTS ?jsRegExpExecute@@YAHPBUJSRegExp@@PB_WHHPAHH@Z ?jsRegExpFree@@YAXPAUJSRegExp@@@Z ?jsString@JSC@@YAPAVJSString@1@PAVJSGlobalData@1@ABVUString@1@@Z + ?latin1@String@WebCore@@QBE?AVCString@WTF@@XZ + ?length@CString@WTF@@QBEIXZ + ?length@String@WebCore@@QBEIXZ ?lock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z ?lock@Mutex@WTF@@QAEXXZ ?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ ?lookupGetter@JSObject@JSC@@UAE?AVJSValue@2@PAVExecState@2@ABVIdentifier@2@@Z ?lookupSetter@JSObject@JSC@@UAE?AVJSValue@2@PAVExecState@2@ABVIdentifier@2@@Z + ?lower@AtomicString@WebCore@@QBE?AV12@XZ + ?lower@String@WebCore@@QBE?AV12@XZ + ?lower@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@XZ ?markChildren@JSGlobalObject@JSC@@UAEXAAVMarkStack@2@@Z ?markChildren@JSObject@JSC@@UAEXAAVMarkStack@2@@Z ?markChildren@JSWrapperObject@JSC@@EAEXAAVMarkStack@2@@Z @@ -198,7 +271,17 @@ EXPORTS ?monthFromDayInYear@WTF@@YAHH_N@Z ?msToYear@WTF@@YAHN@Z ?name@InternalFunction@JSC@@QAEABVUString@2@PAVExecState@2@@Z + ?newUninitialized@CString@WTF@@SA?AV12@IAAPAD@Z ?nonInlineNaN@JSC@@YANXZ + ?nullAtom@WebCore@@3VAtomicString@1@B + ?number@String@WebCore@@SA?AV12@G@Z + ?number@String@WebCore@@SA?AV12@H@Z + ?number@String@WebCore@@SA?AV12@I@Z + ?number@String@WebCore@@SA?AV12@J@Z + ?number@String@WebCore@@SA?AV12@K@Z + ?number@String@WebCore@@SA?AV12@N@Z + ?number@String@WebCore@@SA?AV12@_J@Z + ?number@String@WebCore@@SA?AV12@_K@Z ?objectCount@Heap@JSC@@QBEIXZ ?objectProtoFuncToString@JSC@@YI?AVJSValue@1@PAVExecState@1@PAVJSObject@1@V21@ABVArgList@1@@Z ?parse@Parser@JSC@@AAEXPAVJSGlobalData@2@PAHPAVUString@2@@Z @@ -223,6 +306,12 @@ EXPORTS ?recompileAllJSFunctions@Debugger@JSC@@QAEXPAVJSGlobalData@2@@Z ?recordExtraCost@Heap@JSC@@AAEXI@Z ?releaseStack@MarkStack@JSC@@CAXPAXI@Z + ?remove@String@WebCore@@QAEXIH@Z + ?removeCharacters@String@WebCore@@QBE?AV12@P6A_N_W@Z@Z + ?replace@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@IIPAV12@@Z + ?replace@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@PAV12@0@Z + ?replace@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@_W0@Z + ?replace@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@_WPAV12@@Z ?reset@ParserArena@JSC@@QAEXXZ ?reset@TimeoutChecker@JSC@@QAEXXZ ?resetDateCache@JSGlobalData@JSC@@QAEXXZ @@ -230,6 +319,9 @@ EXPORTS ?restoreAll@Profile@JSC@@QAEXXZ ?retrieveCaller@Interpreter@JSC@@QBE?AVJSValue@2@PAVExecState@2@PAVInternalFunction@2@@Z ?retrieveLastCaller@Interpreter@JSC@@QBEXPAVExecState@2@AAH1AAVUString@2@AAVJSValue@2@@Z + ?reverseFind@StringImpl@WebCore@@QAEHPAV12@H_N@Z + ?reverseFind@StringImpl@WebCore@@QAEH_WH@Z + ?secure@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@_W@Z ?setAccessorDescriptor@PropertyDescriptor@JSC@@QAEXVJSValue@2@0I@Z ?setConfigurable@PropertyDescriptor@JSC@@QAEX_N@Z ?setDescriptor@PropertyDescriptor@JSC@@QAEXVJSValue@2@I@Z @@ -245,20 +337,33 @@ EXPORTS ?setUpStaticFunctionSlot@JSC@@YAXPAVExecState@1@PBVHashEntry@1@PAVJSObject@1@ABVIdentifier@1@AAVPropertySlot@1@@Z ?setWritable@PropertyDescriptor@JSC@@QAEX_N@Z ?setter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ - ?sharedBuffer@UStringImpl@JSC@@QAEPAV?$CrossThreadRefCounted@V?$OwnFastMallocPtr@_W@WTF@@@WTF@@XZ + ?sharedBuffer@StringImpl@WebCore@@QAEPAV?$CrossThreadRefCounted@V?$OwnFastMallocPtr@$$CB_W@WTF@@@WTF@@XZ ?signal@ThreadCondition@WTF@@QAEXXZ + ?simplifyWhiteSpace@String@WebCore@@QBE?AV12@XZ + ?simplifyWhiteSpace@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@XZ ?slowAppend@MarkedArgumentBuffer@JSC@@AAEXVJSValue@2@@Z + ?split@String@WebCore@@QBEXABV12@AAV?$Vector@VString@WebCore@@$0A@@WTF@@@Z + ?split@String@WebCore@@QBEXABV12@_NAAV?$Vector@VString@WebCore@@$0A@@WTF@@@Z + ?split@String@WebCore@@QBEX_WAAV?$Vector@VString@WebCore@@$0A@@WTF@@@Z + ?split@String@WebCore@@QBEX_W_NAAV?$Vector@VString@WebCore@@$0A@@WTF@@@Z + ?starAtom@WebCore@@3VAtomicString@1@B ?startIgnoringLeaks@Structure@JSC@@SAXXZ ?startProfiling@Profiler@JSC@@QAEXPAVExecState@2@ABVUString@2@@Z ?startSampling@JSGlobalData@JSC@@QAEXXZ + ?staticData@WTFThreadData@WTF@@0PAV?$ThreadSpecific@VWTFThreadData@WTF@@@2@A ?stopIgnoringLeaks@Structure@JSC@@SAXXZ ?stopProfiling@Profiler@JSC@@QAE?AV?$PassRefPtr@VProfile@JSC@@@WTF@@PAVExecState@2@ABVUString@2@@Z ?stopSampling@JSGlobalData@JSC@@QAEXXZ + ?stripWhiteSpace@String@WebCore@@QBE?AV12@XZ ?strtod@WTF@@YANPBDPAPAD@Z ?substr@UString@JSC@@QBE?AV12@II@Z + ?substring@String@WebCore@@QBE?AV12@II@Z + ?substring@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@II@Z ?symbolTableGet@JSVariableObject@JSC@@IAE_NABVIdentifier@2@AAVPropertyDescriptor@2@@Z ?synthesizePrototype@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z + ?textAtom@WebCore@@3VAtomicString@1@B ?thisObject@DebuggerCallFrame@JSC@@QBEPAVJSObject@2@XZ + ?threadsafeCopy@String@WebCore@@QBE?AV12@XZ ?throwError@JSC@@YAPAVJSObject@1@PAVExecState@1@W4ErrorType@1@@Z ?throwError@JSC@@YAPAVJSObject@1@PAVExecState@1@W4ErrorType@1@ABVUString@1@@Z ?throwError@JSC@@YAPAVJSObject@1@PAVExecState@1@W4ErrorType@1@PBD@Z @@ -268,7 +373,14 @@ EXPORTS ?toBoolean@JSCell@JSC@@UBE_NPAVExecState@2@@Z ?toBoolean@JSObject@JSC@@UBE_NPAVExecState@2@@Z ?toBoolean@JSString@JSC@@EBE_NPAVExecState@2@@Z + ?toDouble@String@WebCore@@QBENPA_N@Z + ?toFloat@String@WebCore@@QBEMPA_N@Z ?toInt32SlowCase@JSC@@YAHNAA_N@Z + ?toInt@String@WebCore@@QBEHPA_N@Z + ?toInt@StringImpl@WebCore@@QAEHPA_N@Z + ?toIntPtr@String@WebCore@@QBEHPA_N@Z + ?toIntStrict@String@WebCore@@QBEHPA_NH@Z + ?toInteger@JSValue@JSC@@QBENPAVExecState@2@@Z ?toNumber@JSCell@JSC@@UBENPAVExecState@2@@Z ?toNumber@JSObject@JSC@@UBENPAVExecState@2@@Z ?toNumber@JSString@JSC@@EBENPAVExecState@2@@Z @@ -282,17 +394,17 @@ EXPORTS ?toString@JSCell@JSC@@UBE?AVUString@2@PAVExecState@2@@Z ?toString@JSObject@JSC@@UBE?AVUString@2@PAVExecState@2@@Z ?toString@JSString@JSC@@EBE?AVUString@2@PAVExecState@2@@Z - ?toThisJSString@JSCell@JSC@@UAEPAVJSString@2@PAVExecState@2@@Z - ?toThisJSString@JSString@JSC@@EAEPAV12@PAVExecState@2@@Z ?toThisObject@JSCell@JSC@@UBEPAVJSObject@2@PAVExecState@2@@Z ?toThisObject@JSObject@JSC@@UBEPAV12@PAVExecState@2@@Z ?toThisObject@JSString@JSC@@EBEPAVJSObject@2@PAVExecState@2@@Z ?toThisObjectSlowCase@JSValue@JSC@@ABEPAVJSObject@2@PAVExecState@2@@Z - ?toThisString@JSCell@JSC@@UBE?AVUString@2@PAVExecState@2@@Z - ?toThisString@JSString@JSC@@EBE?AVUString@2@PAVExecState@2@@Z ?toUInt32@UString@JSC@@QBEIPA_N@Z ?toUInt32@UString@JSC@@QBEIPA_N_N@Z ?toUInt32SlowCase@JSC@@YAINAA_N@Z + ?toUInt64@String@WebCore@@QBE_KPA_N@Z + ?toUInt@String@WebCore@@QBEIPA_N@Z + ?toUIntStrict@String@WebCore@@QBEIPA_NH@Z + ?truncate@String@WebCore@@QAEXI@Z ?tryFastCalloc@WTF@@YA?AUTryMallocReturnValue@1@II@Z ?tryFastMalloc@WTF@@YA?AUTryMallocReturnValue@1@I@Z ?tryLock@Mutex@WTF@@QAE_NXZ @@ -300,11 +412,16 @@ EXPORTS ?unlock@JSLock@JSC@@SAXW4JSLockBehavior@2@@Z ?unlock@Mutex@WTF@@QAEXXZ ?unlockAtomicallyInitializedStaticMutex@WTF@@YAXXZ - ?unprotect@Heap@JSC@@QAEXVJSValue@2@@Z + ?unprotect@Heap@JSC@@QAE_NVJSValue@2@@Z ?unwrappedObject@JSObject@JSC@@UAEPAV12@XZ + ?upper@String@WebCore@@QBE?AV12@XZ + ?upper@StringImpl@WebCore@@QAE?AV?$PassRefPtr@VStringImpl@WebCore@@@WTF@@XZ + ?utf8@String@WebCore@@QBE?AVCString@WTF@@XZ ?wait@ThreadCondition@WTF@@QAEXAAVMutex@2@@Z ?waitForThreadCompletion@WTF@@YAHIPAPAX@Z ?writable@PropertyDescriptor@JSC@@QBE_NXZ + ?xmlAtom@WebCore@@3VAtomicString@1@B + ?xmlnsAtom@WebCore@@3VAtomicString@1@B WTFLog WTFLogVerbose WTFReportArgumentAssertionFailure diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index 60022dd..158621a 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -74,6 +74,7 @@ />
<Tool
Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -136,6 +137,7 @@ />
<Tool
Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -197,6 +199,7 @@ />
<Tool
Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -260,6 +263,7 @@ />
<Tool
Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -323,6 +327,7 @@ />
<Tool
Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -384,6 +389,7 @@ />
<Tool
Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -446,6 +452,7 @@ />
<Tool
Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
<Configuration
@@ -507,6 +514,7 @@ />
<Tool
Name="VCPostBuildEventTool"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\text\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
</Configuration>
</Configurations>
@@ -1133,6 +1141,14 @@ >
</File>
<File
+ RelativePath="..\..\runtime\RopeImpl.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\runtime\RopeImpl.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\ScopeChain.cpp"
>
</File>
@@ -1205,6 +1221,10 @@ >
</File>
<File
+ RelativePath="..\..\runtime\Terminator.h"
+ >
+ </File>
+ <File
RelativePath="..\..\runtime\TimeoutChecker.cpp"
>
</File>
@@ -1221,10 +1241,6 @@ >
</File>
<File
- RelativePath="..\..\runtime\UStringImpl.cpp"
- >
- </File>
- <File
RelativePath="..\..\runtime\UStringImpl.h"
>
</File>
@@ -1397,6 +1413,18 @@ >
</File>
<File
+ RelativePath="..\..\API\JSWeakObjectMapRefInternal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\API\JSWeakObjectMapRefPrivate.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\API\JSWeakObjectMapRefPrivate.h"
+ >
+ </File>
+ <File
RelativePath="..\..\API\JSValueRef.cpp"
>
</File>
@@ -1578,66 +1606,6 @@ </File>
</Filter>
<Filter
- Name="wrec"
- >
- <File
- RelativePath="..\..\wrec\CharacterClass.cpp"
- >
- </File>
- <File
- RelativePath="..\..\wrec\CharacterClass.h"
- >
- </File>
- <File
- RelativePath="..\..\wrec\CharacterClassConstructor.cpp"
- >
- </File>
- <File
- RelativePath="..\..\wrec\CharacterClassConstructor.h"
- >
- </File>
- <File
- RelativePath="..\..\wrec\Escapes.h"
- >
- </File>
- <File
- RelativePath="..\..\wrec\Quantifier.h"
- >
- </File>
- <File
- RelativePath="..\..\wrec\WREC.cpp"
- >
- </File>
- <File
- RelativePath="..\..\wrec\WREC.h"
- >
- </File>
- <File
- RelativePath="..\..\wrec\WRECFunctors.cpp"
- >
- </File>
- <File
- RelativePath="..\..\wrec\WRECFunctors.h"
- >
- </File>
- <File
- RelativePath="..\..\wrec\WRECGenerator.cpp"
- >
- </File>
- <File
- RelativePath="..\..\wrec\WRECGenerator.h"
- >
- </File>
- <File
- RelativePath="..\..\wrec\WRECParser.cpp"
- >
- </File>
- <File
- RelativePath="..\..\wrec\WRECParser.h"
- >
- </File>
- </Filter>
- <Filter
Name="yarr"
>
<File
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops index f489e79..4470819 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops @@ -6,7 +6,7 @@ >
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../parser/;../../bytecompiler/;../../jit/;../../runtime/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../wrec/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitOutputDir)\include\private";"$(WebKitLibrariesDir)\include\pthreads""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../pcre/;../../parser/;../../bytecompiler/;../../jit/;../../runtime/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\JavaScriptCore";"$(WebKitOutputDir)\include\private";"$(WebKitLibrariesDir)\include\pthreads""
PreprocessorDefinitions="__STD_C"
/>
<Tool
@@ -17,7 +17,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wrec\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
+ CommandLine="mkdir 2>NUL "$(WebKitOutputDir)\include\private\JavaScriptCore"

xcopy /y /d "$(ProjectDir)\..\..\wtf\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\wtf\unicode\icu\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\parser\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\runtime\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\VM\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\bytecode\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\interpreter\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\assembler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\jit\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\debugger\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\profiler\*.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\create_hash_table" "$(WebKitOutputDir)\include\private\JavaScriptCore"
xcopy /y /d "$(ProjectDir)\..\..\pcre\pcre.h" "$(WebKitOutputDir)\include\private\JavaScriptCore"

mkdir 2>NUL "$(OutDir)\JavaScriptCore.resources"
xcopy /y /d "$(ProjectDir)..\$(ProjectName).resources\*" "$(OutDir)\$(ProjectName).resources"

if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"
"
/>
<Tool
Name="VCPreBuildEventTool"
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make index 92479bb..098ff08 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make +++ b/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.make @@ -9,12 +9,16 @@ all: xcopy /y /d "..\..\API\JSContextRef.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\JSContextRefPrivate.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\JSObjectRef.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" + xcopy /y /d "..\..\API\JSObjectRefPrivate.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\JSStringRef.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\JSStringRefCF.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\JSStringRefBSTR.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\JSValueRef.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\JavaScriptCore.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\JSRetainPtr.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" + xcopy /y /d "..\..\API\JSWeakObjectMapRefInternal.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" + xcopy /y /d "..\..\API\JSWeakObjectMapRefPrivate.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" + xcopy /y /d "..\..\API\JSRetainPtr.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\OpaqueJSString.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" xcopy /y /d "..\..\API\WebKitAvailability.h" "$(WEBKITOUTPUTDIR)\include\JavaScriptCore" -del "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore\stdbool.h" "$(WEBKITOUTPUTDIR)\include\private\JavaScriptCore\stdint.h" diff --git a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj index c5b826c..0145311 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj +++ b/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj @@ -537,6 +537,46 @@ >
</File>
<File
+ RelativePath="..\..\wtf\text\AtomicString.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\AtomicString.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\AtomicStringImpl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\CString.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\CString.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\StringHash.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\StringImpl.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\StringImpl.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\WTFString.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\text\WTFString.h"
+ >
+ </File>
+ <File
RelativePath="..\..\wtf\unicode\UTF8.cpp"
>
</File>
@@ -556,6 +596,14 @@ RelativePath="..\..\wtf\VectorTraits.h"
>
</File>
+ <File
+ RelativePath="..\..\wtf\WTFThreadData.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\wtf\WTFThreadData.h"
+ >
+ </File>
</Files>
<Globals>
</Globals>
diff --git a/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscCommon.vsprops b/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscCommon.vsprops index 61594e1..45fe975 100644 --- a/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscCommon.vsprops +++ b/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscCommon.vsprops @@ -6,7 +6,7 @@ >
<Tool
Name="VCCLCompilerTool"
- AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../wrec/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;../../profiler;../../jit/;"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\include""
+ AdditionalIncludeDirectories=""$(WebKitOutputDir)\include";"$(WebKitOutputDir)\include\private";"$(WebKitOutputDir)\obj\JavaScriptCore\$(ConfigurationName)\DerivedSources\";../../;"../../os-win32/";../../pcre/;../../assembler/;../../API/;../../parser/;../../runtime/;../../VM/;../../bytecode/;../../interpreter/;../../wtf/;../../debugger/;../../bytecompiler/;../../profiler;../../jit/;"$(WebKitLibrariesDir)\include\pthreads";"$(WebKitLibrariesDir)\include""
PreprocessorDefinitions="__STD_C"
/>
<Tool
@@ -16,7 +16,7 @@ />
<Tool
Name="VCPostBuildEventTool"
- CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
if exist "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\ASL$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\ASL$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"

cmd /c
"
+ CommandLine="if exist "$(WebKitOutputDir)\buildfailed" del "$(WebKitOutputDir)\buildfailed"

mkdir 2>NUL "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc40$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42.dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42.dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icudt42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuin42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\icuuc42$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\CoreFoundation$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" xcopy /y /d /e /i "$(WebKitLibrariesDir)\bin\CoreFoundation.resources" "$(WebKitOutputDir)\bin\CoreFoundation.resources"
if exist "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\pthreadVC2$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\objc$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\ASL$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\ASL$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"
if exist "$(WebKitLibrariesDir)\bin\libdispatch$(LibraryConfigSuffix).dll" xcopy /y /d "$(WebKitLibrariesDir)\bin\libdispatch$(LibraryConfigSuffix).dll" "$(WebKitOutputDir)\bin"

cmd /c
"
/>
<Tool
Name="VCPreBuildEventTool"
diff --git a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index 2410466..9dff7ef 100644 --- a/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -78,15 +78,6 @@ 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429D8DC0ED2205B00B89619 /* CallFrame.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1429D92F0ED22D7000B89619 /* JIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429D92D0ED22D7000B89619 /* JIT.cpp */; }; 1429D9300ED22D7000B89619 /* JIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429D92E0ED22D7000B89619 /* JIT.h */; }; - 1429D9C40ED23C3900B89619 /* CharacterClass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429D9C20ED23C3900B89619 /* CharacterClass.cpp */; }; - 1429D9C50ED23C3900B89619 /* CharacterClass.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429D9C30ED23C3900B89619 /* CharacterClass.h */; }; - 1429DA4A0ED245EC00B89619 /* Quantifier.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429DA490ED245EC00B89619 /* Quantifier.h */; }; - 1429DA820ED2482900B89619 /* WRECFunctors.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429DA800ED2482900B89619 /* WRECFunctors.cpp */; }; - 1429DA830ED2482900B89619 /* WRECFunctors.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429DA810ED2482900B89619 /* WRECFunctors.h */; }; - 1429DABF0ED263E700B89619 /* WRECParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429DABD0ED263E700B89619 /* WRECParser.h */; }; - 1429DAC00ED263E700B89619 /* WRECParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429DABE0ED263E700B89619 /* WRECParser.cpp */; }; - 1429DAE00ED2645B00B89619 /* WRECGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429DADE0ED2645B00B89619 /* WRECGenerator.h */; }; - 1429DAE10ED2645B00B89619 /* WRECGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429DADF0ED2645B00B89619 /* WRECGenerator.cpp */; }; 142D3939103E4560007DCB52 /* NumericStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 142D3938103E4560007DCB52 /* NumericStrings.h */; settings = {ATTRIBUTES = (Private, ); }; }; 143A97E60A4A06E200456B66 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; }; 1440057F0A5335640005F061 /* JSNode.c in Sources */ = {isa = PBXBuildFile; fileRef = 1440F6420A4F8B6A0005F061 /* JSNode.c */; }; @@ -195,8 +186,6 @@ 655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 655EB29A10CE2581001A990E /* NodesCodegen.cpp */; }; 65DFC93308EA173A00F7300B /* HashTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65DFC92D08EA173A00F7300B /* HashTable.cpp */; }; 65FDE49C0BDD1D4A00E80111 /* Assertions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65E217B808E7EECC0023E5F6 /* Assertions.cpp */; settings = {COMPILER_FLAGS = "-Wno-missing-format-attribute"; }; }; - 7E2ADD8E0E79AAD500D50C51 /* CharacterClassConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E2ADD8D0E79AAD500D50C51 /* CharacterClassConstructor.h */; }; - 7E2ADD900E79AC1100D50C51 /* CharacterClassConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E2ADD8F0E79AC1100D50C51 /* CharacterClassConstructor.cpp */; }; 7E4EE7090EBB7963005934AA /* StructureChain.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E4EE7080EBB7963005934AA /* StructureChain.h */; settings = {ATTRIBUTES = (Private, ); }; }; 7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E4EE70E0EBB7A5B005934AA /* StructureChain.cpp */; }; 7EFF00640EC05A9A00AA7C93 /* NodeInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 7EFF00630EC05A9A00AA7C93 /* NodeInfo.h */; }; @@ -206,16 +195,28 @@ 860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */; }; 860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */; }; 863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 86565742115BE3DA00291F40 /* CString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86565740115BE3DA00291F40 /* CString.cpp */; }; + 86565743115BE3DA00291F40 /* CString.h in Headers */ = {isa = PBXBuildFile; fileRef = 86565741115BE3DA00291F40 /* CString.h */; settings = {ATTRIBUTES = (Private, ); }; }; 865F408810E7D56300947361 /* APIShims.h in Headers */ = {isa = PBXBuildFile; fileRef = 865F408710E7D56300947361 /* APIShims.h */; }; - 869083150E6518D7000D36ED /* WREC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 869083130E6518D7000D36ED /* WREC.cpp */; }; - 869083160E6518D7000D36ED /* WREC.h in Headers */ = {isa = PBXBuildFile; fileRef = 869083140E6518D7000D36ED /* WREC.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA00117CEFD100B908B1 /* AtomicString.cpp */; }; + 868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA01117CEFD100B908B1 /* AtomicString.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 868BFA0A117CEFD100B908B1 /* AtomicStringImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA02117CEFD100B908B1 /* AtomicStringImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 868BFA0D117CEFD100B908B1 /* StringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA05117CEFD100B908B1 /* StringHash.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA06117CEFD100B908B1 /* StringImpl.cpp */; }; + 868BFA0F117CEFD100B908B1 /* StringImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA07117CEFD100B908B1 /* StringImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA15117CF19900B908B1 /* WTFString.cpp */; }; + 868BFA18117CF19900B908B1 /* WTFString.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA16117CF19900B908B1 /* WTFString.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 868BFA5F117D048200B908B1 /* StaticConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; }; 8698B86910D44D9400D8D01B /* StringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 8698B86810D44D9400D8D01B /* StringBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; }; 8698BB3910D86BAF00D8D01B /* UStringImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 8698BB3710D86BAF00D8D01B /* UStringImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 8698BB3A10D86BAF00D8D01B /* UStringImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8698BB3810D86BAF00D8D01B /* UStringImpl.cpp */; }; 869EBCB70E8C6D4A008722CC /* ResultType.h in Headers */ = {isa = PBXBuildFile; fileRef = 869EBCB60E8C6D4A008722CC /* ResultType.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86A90ED00EE7D51F00AB350D /* JITArithmetic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */; }; 86ADD1450FDDEA980006EEC2 /* ARMv7Assembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */; }; 86ADD1460FDDEA980006EEC2 /* MacroAssemblerARMv7.h in Headers */ = {isa = PBXBuildFile; fileRef = 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */; }; + 86B99AB8117E391E00DF5A90 /* RopeImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86B99AB6117E391E00DF5A90 /* RopeImpl.cpp */; }; + 86B99AB9117E391E00DF5A90 /* RopeImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AB7117E391E00DF5A90 /* RopeImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE1117E578100DF5A90 /* StringBuffer.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 86B99AE4117E578100DF5A90 /* StringImplBase.h in Headers */ = {isa = PBXBuildFile; fileRef = 86B99AE2117E578100DF5A90 /* StringImplBase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86C36EEA0EE1289D00B3DF59 /* MacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */; }; 86CA032E1038E8440028A609 /* Executable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CA032D1038E8440028A609 /* Executable.cpp */; }; 86CAFEE31035DDE60028A609 /* Executable.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CAFEE21035DDE60028A609 /* Executable.h */; settings = {ATTRIBUTES = (); }; }; @@ -223,6 +224,8 @@ 86CC85A30EE79B7400288682 /* JITCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85A20EE79B7400288682 /* JITCall.cpp */; }; 86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */; }; 86CCEFDE0F413F8900FD7F9E /* JITCode.h in Headers */ = {isa = PBXBuildFile; fileRef = 86CCEFDD0F413F8900FD7F9E /* JITCode.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D08D5111793613006E5ED0 /* WTFThreadData.cpp */; }; + 86D08D5411793613006E5ED0 /* WTFThreadData.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D08D5211793613006E5ED0 /* WTFThreadData.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D3B2BF10156BDE002865E7 /* ARMAssembler.cpp */; }; 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C010156BDE002865E7 /* ARMAssembler.h */; }; 86D3B2C510156BDE002865E7 /* AssemblerBufferWithConstantPool.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */; }; @@ -279,11 +282,15 @@ 969A07990ED1D3AE00F1F681 /* Instruction.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07930ED1D3AE00F1F681 /* Instruction.h */; }; 969A079A0ED1D3AE00F1F681 /* Opcode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 969A07940ED1D3AE00F1F681 /* Opcode.cpp */; }; 969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */ = {isa = PBXBuildFile; fileRef = 969A07950ED1D3AE00F1F681 /* Opcode.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 96A746410EDDF70600904779 /* Escapes.h in Headers */ = {isa = PBXBuildFile; fileRef = 96A7463F0EDDF70600904779 /* Escapes.h */; }; 96DD73790F9DA3100027FBCC /* VMTags.h in Headers */ = {isa = PBXBuildFile; fileRef = 96DD73780F9DA3100027FBCC /* VMTags.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 971EDEA61169E0D3005E4262 /* Terminator.h in Headers */ = {isa = PBXBuildFile; fileRef = 97F6903A1169DF7F00A6BB46 /* Terminator.h */; settings = {ATTRIBUTES = (Private, ); }; }; A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72700780DAC605600E548D7 /* JSNotAnObject.cpp */; }; A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; }; A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; }; + A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A7482B9411671147003B0712 /* JSWeakObjectMapRefPrivate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */; }; + A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */; settings = {ATTRIBUTES = (Private, ); }; }; A74B3499102A5F8E0032AB98 /* MarkStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A74B3498102A5F8E0032AB98 /* MarkStack.cpp */; }; A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; A76EE6590FAE59D5003F069A /* NativeFunctionWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = A76EE6580FAE59D5003F069A /* NativeFunctionWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -565,7 +572,6 @@ 088FA5B90EF76D4300578E6F /* RandomNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RandomNumber.cpp; sourceTree = "<group>"; }; 088FA5BA0EF76D4300578E6F /* RandomNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomNumber.h; sourceTree = "<group>"; }; 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomNumberSeed.h; sourceTree = "<group>"; }; - 0B1F921B0F17502D0036468E /* PtrAndFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PtrAndFlags.h; sourceTree = "<group>"; }; 0B330C260F38C62300692DE3 /* TypeTraits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeTraits.cpp; sourceTree = "<group>"; }; 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeTraits.h; sourceTree = "<group>"; }; 0BDFFAD10FC616EC00D69EF4 /* OwnFastMallocPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnFastMallocPtr.h; sourceTree = "<group>"; }; @@ -589,15 +595,6 @@ 1429D8DC0ED2205B00B89619 /* CallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallFrame.h; sourceTree = "<group>"; }; 1429D92D0ED22D7000B89619 /* JIT.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JIT.cpp; sourceTree = "<group>"; }; 1429D92E0ED22D7000B89619 /* JIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JIT.h; sourceTree = "<group>"; }; - 1429D9C20ED23C3900B89619 /* CharacterClass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CharacterClass.cpp; sourceTree = "<group>"; }; - 1429D9C30ED23C3900B89619 /* CharacterClass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CharacterClass.h; sourceTree = "<group>"; }; - 1429DA490ED245EC00B89619 /* Quantifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Quantifier.h; sourceTree = "<group>"; }; - 1429DA800ED2482900B89619 /* WRECFunctors.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WRECFunctors.cpp; sourceTree = "<group>"; }; - 1429DA810ED2482900B89619 /* WRECFunctors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WRECFunctors.h; sourceTree = "<group>"; }; - 1429DABD0ED263E700B89619 /* WRECParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WRECParser.h; sourceTree = "<group>"; }; - 1429DABE0ED263E700B89619 /* WRECParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WRECParser.cpp; sourceTree = "<group>"; }; - 1429DADE0ED2645B00B89619 /* WRECGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WRECGenerator.h; sourceTree = "<group>"; }; - 1429DADF0ED2645B00B89619 /* WRECGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WRECGenerator.cpp; sourceTree = "<group>"; }; 142D3938103E4560007DCB52 /* NumericStrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NumericStrings.h; sourceTree = "<group>"; }; 1440051F0A531D3B0005F061 /* Node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Node.h; path = tests/Node.h; sourceTree = "<group>"; }; 144005200A531D3B0005F061 /* Node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = Node.c; path = tests/Node.c; sourceTree = "<group>"; }; @@ -731,8 +728,6 @@ 65EA73630BAE35D1001BB560 /* CommonIdentifiers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CommonIdentifiers.h; sourceTree = "<group>"; }; 65FB3F4809D11B2400F49DEB /* Grammar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = Grammar.cpp; sourceTree = "<group>"; }; 704FD35305697E6D003DBED9 /* BooleanObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = BooleanObject.h; sourceTree = "<group>"; tabWidth = 8; }; - 7E2ADD8D0E79AAD500D50C51 /* CharacterClassConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CharacterClassConstructor.h; sourceTree = "<group>"; }; - 7E2ADD8F0E79AC1100D50C51 /* CharacterClassConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CharacterClassConstructor.cpp; sourceTree = "<group>"; }; 7E2C6C980D31C6B6002D44E2 /* ScopeChainMark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScopeChainMark.h; sourceTree = "<group>"; }; 7E4EE7080EBB7963005934AA /* StructureChain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureChain.h; sourceTree = "<group>"; }; 7E4EE70E0EBB7A5B005934AA /* StructureChain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureChain.cpp; sourceTree = "<group>"; }; @@ -742,16 +737,28 @@ 860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86_64.h; sourceTree = "<group>"; }; 860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86Common.h; sourceTree = "<group>"; }; 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerCodeRef.h; sourceTree = "<group>"; }; + 86565740115BE3DA00291F40 /* CString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CString.cpp; path = text/CString.cpp; sourceTree = "<group>"; }; + 86565741115BE3DA00291F40 /* CString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CString.h; path = text/CString.h; sourceTree = "<group>"; }; 865F408710E7D56300947361 /* APIShims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIShims.h; sourceTree = "<group>"; }; - 869083130E6518D7000D36ED /* WREC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WREC.cpp; sourceTree = "<group>"; }; - 869083140E6518D7000D36ED /* WREC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WREC.h; sourceTree = "<group>"; }; + 868BFA00117CEFD100B908B1 /* AtomicString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AtomicString.cpp; path = text/AtomicString.cpp; sourceTree = "<group>"; }; + 868BFA01117CEFD100B908B1 /* AtomicString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicString.h; path = text/AtomicString.h; sourceTree = "<group>"; }; + 868BFA02117CEFD100B908B1 /* AtomicStringImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicStringImpl.h; path = text/AtomicStringImpl.h; sourceTree = "<group>"; }; + 868BFA05117CEFD100B908B1 /* StringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringHash.h; path = text/StringHash.h; sourceTree = "<group>"; }; + 868BFA06117CEFD100B908B1 /* StringImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringImpl.cpp; path = text/StringImpl.cpp; sourceTree = "<group>"; }; + 868BFA07117CEFD100B908B1 /* StringImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringImpl.h; path = text/StringImpl.h; sourceTree = "<group>"; }; + 868BFA15117CF19900B908B1 /* WTFString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WTFString.cpp; path = text/WTFString.cpp; sourceTree = "<group>"; }; + 868BFA16117CF19900B908B1 /* WTFString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WTFString.h; path = text/WTFString.h; sourceTree = "<group>"; }; + 868BFA5F117D048200B908B1 /* StaticConstructors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticConstructors.h; sourceTree = "<group>"; }; 8698B86810D44D9400D8D01B /* StringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringBuilder.h; sourceTree = "<group>"; }; 8698BB3710D86BAF00D8D01B /* UStringImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UStringImpl.h; sourceTree = "<group>"; }; - 8698BB3810D86BAF00D8D01B /* UStringImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UStringImpl.cpp; sourceTree = "<group>"; }; 869EBCB60E8C6D4A008722CC /* ResultType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResultType.h; sourceTree = "<group>"; }; 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITArithmetic.cpp; sourceTree = "<group>"; }; 86ADD1430FDDEA980006EEC2 /* ARMv7Assembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMv7Assembler.h; sourceTree = "<group>"; }; 86ADD1440FDDEA980006EEC2 /* MacroAssemblerARMv7.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARMv7.h; sourceTree = "<group>"; }; + 86B99AB6117E391E00DF5A90 /* RopeImpl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RopeImpl.cpp; sourceTree = "<group>"; }; + 86B99AB7117E391E00DF5A90 /* RopeImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RopeImpl.h; sourceTree = "<group>"; }; + 86B99AE1117E578100DF5A90 /* StringBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringBuffer.h; path = text/StringBuffer.h; sourceTree = "<group>"; }; + 86B99AE2117E578100DF5A90 /* StringImplBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringImplBase.h; path = text/StringImplBase.h; sourceTree = "<group>"; }; 86C36EE90EE1289D00B3DF59 /* MacroAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssembler.h; sourceTree = "<group>"; }; 86CA032D1038E8440028A609 /* Executable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Executable.cpp; sourceTree = "<group>"; }; 86CAFEE21035DDE60028A609 /* Executable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Executable.h; sourceTree = "<group>"; }; @@ -759,6 +766,8 @@ 86CC85A20EE79B7400288682 /* JITCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITCall.cpp; sourceTree = "<group>"; }; 86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITPropertyAccess.cpp; sourceTree = "<group>"; }; 86CCEFDD0F413F8900FD7F9E /* JITCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCode.h; sourceTree = "<group>"; }; + 86D08D5111793613006E5ED0 /* WTFThreadData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WTFThreadData.cpp; sourceTree = "<group>"; }; + 86D08D5211793613006E5ED0 /* WTFThreadData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WTFThreadData.h; sourceTree = "<group>"; }; 86D3B2BF10156BDE002865E7 /* ARMAssembler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ARMAssembler.cpp; sourceTree = "<group>"; }; 86D3B2C010156BDE002865E7 /* ARMAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ARMAssembler.h; sourceTree = "<group>"; }; 86D3B2C110156BDE002865E7 /* AssemblerBufferWithConstantPool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AssemblerBufferWithConstantPool.h; sourceTree = "<group>"; }; @@ -844,19 +853,25 @@ 969A07940ED1D3AE00F1F681 /* Opcode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Opcode.cpp; sourceTree = "<group>"; }; 969A07950ED1D3AE00F1F681 /* Opcode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Opcode.h; sourceTree = "<group>"; }; 969A09220ED1E09C00F1F681 /* Completion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Completion.cpp; sourceTree = "<group>"; }; - 96A7463F0EDDF70600904779 /* Escapes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Escapes.h; sourceTree = "<group>"; }; 96DD73780F9DA3100027FBCC /* VMTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMTags.h; sourceTree = "<group>"; }; + 97F6903A1169DF7F00A6BB46 /* Terminator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Terminator.h; sourceTree = "<group>"; }; + A718F61A11754A21002465A7 /* RegExpJitTables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpJitTables.h; sourceTree = "<group>"; }; + A718F8211178EB4B002465A7 /* create_regex_tables */ = {isa = PBXFileReference; explicitFileType = text.script.python; fileEncoding = 4; path = create_regex_tables; sourceTree = "<group>"; }; A72700770DAC605600E548D7 /* JSNotAnObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSNotAnObject.h; sourceTree = "<group>"; }; A72700780DAC605600E548D7 /* JSNotAnObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSNotAnObject.cpp; sourceTree = "<group>"; }; A72701B30DADE94900E548D7 /* ExceptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHelpers.h; sourceTree = "<group>"; }; A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; }; A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; }; + A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakObjectMapRefPrivate.h; sourceTree = "<group>"; }; + A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWeakObjectMapRefPrivate.cpp; sourceTree = "<group>"; }; + A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakObjectMapRefInternal.h; sourceTree = "<group>"; }; A74B3498102A5F8E0032AB98 /* MarkStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkStack.cpp; sourceTree = "<group>"; }; A76EE6580FAE59D5003F069A /* NativeFunctionWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeFunctionWrapper.h; sourceTree = "<group>"; }; A779558F101A74D500114E55 /* MarkStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkStack.h; sourceTree = "<group>"; }; A782F1A40EEC9FA20036273F /* ExecutableAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorPosix.cpp; sourceTree = "<group>"; }; A791EF260F11E07900AE1F68 /* JSByteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSByteArray.h; sourceTree = "<group>"; }; A791EF270F11E07900AE1F68 /* JSByteArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSByteArray.cpp; sourceTree = "<group>"; }; + A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectRefPrivate.h; sourceTree = "<group>"; }; A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ByteArray.cpp; sourceTree = "<group>"; }; A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ByteArray.h; sourceTree = "<group>"; }; A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableAllocator.h; sourceTree = "<group>"; }; @@ -1102,6 +1117,7 @@ 0867D691FE84028FC02AAC07 /* JavaScriptCore */ = { isa = PBXGroup; children = ( + A718F8211178EB4B002465A7 /* create_regex_tables */, 937B63CC09E766D200A671DD /* DerivedSources.make */, F692A8540255597D01FF60F7 /* create_hash_table */, 14B8ECA60A5653980062BE54 /* JavaScriptCore.exp */, @@ -1120,7 +1136,6 @@ 95AB831A0DA42C6900BC83F3 /* profiler */, 7EF6E0BB0EB7A1EC0079AFAF /* runtime */, 141211000A48772600480255 /* tests */, - 869083120E6518D7000D36ED /* wrec */, 65162EF108E6A21C007556CD /* wtf */, 86EAC48C0F93E8B9008EC948 /* yarr */, 1C90513E0BA9E8830081E9D0 /* Configurations */, @@ -1190,10 +1205,10 @@ 86CC85A00EE79A4700288682 /* JITInlineMethods.h */, BCDD51E90FB8DF74004A8BDC /* JITOpcodes.cpp */, 86CC85C30EE7A89400288682 /* JITPropertyAccess.cpp */, + A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */, 960626950FB8EC02009798AB /* JITStubCall.h */, 14A23D6C0F4E19CE0023CDAD /* JITStubs.cpp */, 14A6581A0F4E36F4000150FD /* JITStubs.h */, - A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */, ); path = jit; sourceTree = "<group>"; @@ -1224,6 +1239,7 @@ 148CD1D7108CF902008163C6 /* JSContextRefPrivate.h */, 1482B7E20A43076000517CFC /* JSObjectRef.cpp */, 1482B7E10A43076000517CFC /* JSObjectRef.h */, + A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */, 95988BA90E477BEC00D28D4D /* JSProfilerPrivate.cpp */, 952C63AC0E4777D600C13936 /* JSProfilerPrivate.h */, 95C18D3E0C90E7EF00E72F73 /* JSRetainPtr.h */, @@ -1236,6 +1252,9 @@ E124A8F60E555775003091F1 /* OpaqueJSString.cpp */, E124A8F50E555775003091F1 /* OpaqueJSString.h */, 5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */, + A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */, + A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */, + A7482E37116A697B003B0712 /* JSWeakObjectMapRefInternal.h */, ); path = API; sourceTree = "<group>"; @@ -1290,6 +1309,7 @@ 650FDF8D09D0FCA700769E54 /* Derived Sources */ = { isa = PBXGroup; children = ( + A718F61A11754A21002465A7 /* RegExpJitTables.h */, BC18C5230E16FC8A00B34460 /* ArrayPrototype.lut.h */, 65B174BE09D1000200820339 /* chartables.c */, BCD203E70E1718F4002C7E82 /* DatePrototype.lut.h */, @@ -1314,6 +1334,7 @@ isa = PBXGroup; children = ( 06D358A00DAAD9C4003B174E /* mac */, + 8656573E115BE35200291F40 /* text */, E195678D09E7CF1200B89D13 /* unicode */, 93AA4F770957251F0084B3A7 /* AlwaysInline.h */, 938C4F690CA06BC700D9310A /* ASCIICType.h */, @@ -1362,7 +1383,6 @@ 6580F795094070560082C219 /* PassRefPtr.h */, 65D6D87E09B5A32E0002E4D7 /* Platform.h */, A7D649A91015224E009B2E1B /* PossiblyNull.h */, - 0B1F921B0F17502D0036468E /* PtrAndFlags.h */, 088FA5B90EF76D4300578E6F /* RandomNumber.cpp */, 088FA5BA0EF76D4300578E6F /* RandomNumber.h */, 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */, @@ -1373,6 +1393,7 @@ 148A1ECD0D10C23B0069A47C /* RefPtrHashMap.h */, 51F648D60BB4E2CA0033D760 /* RetainPtr.h */, 969A07290ED1CE6900F1F681 /* SegmentedVector.h */, + 868BFA5F117D048200B908B1 /* StaticConstructors.h */, FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */, E11D51750B2E798D0056C188 /* StringExtras.h */, 5D63E9AC10F2BD6E00FC8AE9 /* StringHashFunctions.h */, @@ -1394,6 +1415,8 @@ 6592C316098B7DE10003D4F6 /* Vector.h */, 6592C317098B7DE10003D4F6 /* VectorTraits.h */, 96DD73780F9DA3100027FBCC /* VMTags.h */, + 86D08D5111793613006E5ED0 /* WTFThreadData.cpp */, + 86D08D5211793613006E5ED0 /* WTFThreadData.h */, ); path = wtf; sourceTree = "<group>"; @@ -1611,6 +1634,8 @@ F692A87C0255597D01FF60F7 /* RegExpObject.h */, BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */, BCD202C00E1706A7002C7E82 /* RegExpPrototype.h */, + 86B99AB6117E391E00DF5A90 /* RopeImpl.cpp */, + 86B99AB7117E391E00DF5A90 /* RopeImpl.h */, 9374D3A8038D9D74008635CE /* ScopeChain.cpp */, 9374D3A7038D9D74008635CE /* ScopeChain.h */, 7E2C6C980D31C6B6002D44E2 /* ScopeChainMark.h */, @@ -1630,13 +1655,13 @@ 7E4EE7080EBB7963005934AA /* StructureChain.h */, BC9041470EB9250900FE26FA /* StructureTransitionTable.h */, 14A396A60CD2933100B5B4FF /* SymbolTable.h */, + 97F6903A1169DF7F00A6BB46 /* Terminator.h */, 14A42E3D0F4F60EE00599099 /* TimeoutChecker.cpp */, 14A42E3E0F4F60EE00599099 /* TimeoutChecker.h */, 5D53726D0E1C546B0021E549 /* Tracing.d */, 5D53726E0E1C54880021E549 /* Tracing.h */, F692A8850255597D01FF60F7 /* UString.cpp */, F692A8860255597D01FF60F7 /* UString.h */, - 8698BB3810D86BAF00D8D01B /* UStringImpl.cpp */, 8698BB3710D86BAF00D8D01B /* UStringImpl.h */, 14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */, 14035DB010DBFB2A00FFFFE7 /* WeakGCPtr.h */, @@ -1645,25 +1670,23 @@ path = runtime; sourceTree = "<group>"; }; - 869083120E6518D7000D36ED /* wrec */ = { + 8656573E115BE35200291F40 /* text */ = { isa = PBXGroup; children = ( - 1429D9C20ED23C3900B89619 /* CharacterClass.cpp */, - 1429D9C30ED23C3900B89619 /* CharacterClass.h */, - 7E2ADD8F0E79AC1100D50C51 /* CharacterClassConstructor.cpp */, - 7E2ADD8D0E79AAD500D50C51 /* CharacterClassConstructor.h */, - 96A7463F0EDDF70600904779 /* Escapes.h */, - 1429DA490ED245EC00B89619 /* Quantifier.h */, - 869083130E6518D7000D36ED /* WREC.cpp */, - 869083140E6518D7000D36ED /* WREC.h */, - 1429DA800ED2482900B89619 /* WRECFunctors.cpp */, - 1429DA810ED2482900B89619 /* WRECFunctors.h */, - 1429DADF0ED2645B00B89619 /* WRECGenerator.cpp */, - 1429DADE0ED2645B00B89619 /* WRECGenerator.h */, - 1429DABE0ED263E700B89619 /* WRECParser.cpp */, - 1429DABD0ED263E700B89619 /* WRECParser.h */, - ); - path = wrec; + 868BFA00117CEFD100B908B1 /* AtomicString.cpp */, + 868BFA01117CEFD100B908B1 /* AtomicString.h */, + 868BFA02117CEFD100B908B1 /* AtomicStringImpl.h */, + 86565740115BE3DA00291F40 /* CString.cpp */, + 86565741115BE3DA00291F40 /* CString.h */, + 86B99AE1117E578100DF5A90 /* StringBuffer.h */, + 868BFA05117CEFD100B908B1 /* StringHash.h */, + 868BFA06117CEFD100B908B1 /* StringImpl.cpp */, + 868BFA07117CEFD100B908B1 /* StringImpl.h */, + 86B99AE2117E578100DF5A90 /* StringImplBase.h */, + 868BFA15117CF19900B908B1 /* WTFString.cpp */, + 868BFA16117CF19900B908B1 /* WTFString.h */, + ); + name = text; sourceTree = "<group>"; }; 86EAC48C0F93E8B9008EC948 /* yarr */ = { @@ -1817,8 +1840,6 @@ BC18C3ED0E16F5CD00B34460 /* CallData.h in Headers */, 1429D8DE0ED2205B00B89619 /* CallFrame.h in Headers */, 95E3BC050E1AE68200B2D1C1 /* CallIdentifier.h in Headers */, - 1429D9C50ED23C3900B89619 /* CharacterClass.h in Headers */, - 7E2ADD8E0E79AAD500D50C51 /* CharacterClassConstructor.h in Headers */, BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */, 969A07970ED1D3AE00F1F681 /* CodeBlock.h in Headers */, 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */, @@ -1849,7 +1870,6 @@ BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */, BC02E98D0E183E38000F9297 /* ErrorInstance.h in Headers */, BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */, - 96A746410EDDF70600904779 /* Escapes.h in Headers */, 969A07980ED1D3AE00F1F681 /* EvalCodeCache.h in Headers */, BC18C4000E16F5CD00B34460 /* ExceptionHelpers.h in Headers */, 86CAFEE31035DDE60028A609 /* Executable.h in Headers */, @@ -1910,6 +1930,7 @@ 9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */, BC18C4260E16F5CD00B34460 /* JSRetainPtr.h in Headers */, BC18C4270E16F5CD00B34460 /* JSString.h in Headers */, + 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */, BC18C4280E16F5CD00B34460 /* JSStringRef.h in Headers */, BC18C4290E16F5CD00B34460 /* JSStringRefCF.h in Headers */, BC18C42A0E16F5CD00B34460 /* JSType.h in Headers */, @@ -1984,7 +2005,6 @@ BC18C4560E16F5CD00B34460 /* Protect.h in Headers */, BC257DF40E1F53740016B6C9 /* PrototypeFunction.h in Headers */, 147B84630E6DE6B1004775A4 /* PutPropertySlot.h in Headers */, - 1429DA4A0ED245EC00B89619 /* Quantifier.h in Headers */, 088FA5BC0EF76D4300578E6F /* RandomNumber.h in Headers */, 08E279E90EF83B10007DB523 /* RandomNumberSeed.h in Headers */, BC18C4570E16F5CD00B34460 /* RefCounted.h in Headers */, @@ -2035,6 +2055,7 @@ 18BAB55410DAE066000D945B /* ThreadIdentifierDataPthreads.h in Headers */, BC18C4700E16F5CD00B34460 /* Threading.h in Headers */, BC18C4710E16F5CD00B34460 /* ThreadSpecific.h in Headers */, + 971EDEA61169E0D3005E4262 /* Terminator.h in Headers */, 14A42E400F4F60EE00599099 /* TimeoutChecker.h in Headers */, 5D53726F0E1C54880021E549 /* Tracing.h in Headers */, 0B4D7E630F319AC800AD7E58 /* TypeTraits.h in Headers */, @@ -2045,6 +2066,7 @@ BC18C4760E16F5CD00B34460 /* UString.h in Headers */, 8698BB3910D86BAF00D8D01B /* UStringImpl.h in Headers */, BC18C4770E16F5CD00B34460 /* UTF8.h in Headers */, + E17FF771112131D200076A19 /* ValueCheck.h in Headers */, BC18C4780E16F5CD00B34460 /* Vector.h in Headers */, BC18C4790E16F5CD00B34460 /* VectorTraits.h in Headers */, 96DD73790F9DA3100027FBCC /* VMTags.h in Headers */, @@ -2052,13 +2074,21 @@ 14035DB110DBFB2A00FFFFE7 /* WeakGCPtr.h in Headers */, 1420BE7B10AA6DDB00F455D2 /* WeakRandom.h in Headers */, BC18C47A0E16F5CD00B34460 /* WebKitAvailability.h in Headers */, - 869083160E6518D7000D36ED /* WREC.h in Headers */, - 1429DA830ED2482900B89619 /* WRECFunctors.h in Headers */, - 1429DAE00ED2645B00B89619 /* WRECGenerator.h in Headers */, - 1429DABF0ED263E700B89619 /* WRECParser.h in Headers */, 9688CB160ED12B4E001D649F /* X86Assembler.h in Headers */, - 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */, - E17FF771112131D200076A19 /* ValueCheck.h in Headers */, + A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */, + 86565743115BE3DA00291F40 /* CString.h in Headers */, + A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */, + A7482E93116A7CAD003B0712 /* JSWeakObjectMapRefInternal.h in Headers */, + 86D08D5411793613006E5ED0 /* WTFThreadData.h in Headers */, + 868BFA09117CEFD100B908B1 /* AtomicString.h in Headers */, + 868BFA0A117CEFD100B908B1 /* AtomicStringImpl.h in Headers */, + 868BFA0D117CEFD100B908B1 /* StringHash.h in Headers */, + 868BFA0F117CEFD100B908B1 /* StringImpl.h in Headers */, + 868BFA18117CF19900B908B1 /* WTFString.h in Headers */, + 868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */, + 86B99AB9117E391E00DF5A90 /* RopeImpl.h in Headers */, + 86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */, + 86B99AE4117E578100DF5A90 /* StringImplBase.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2358,8 +2388,6 @@ 148F21AA107EC53A0042EC2C /* BytecodeGenerator.cpp in Sources */, 1428082D107EC0570013E7B2 /* CallData.cpp in Sources */, 1429D8DD0ED2205B00B89619 /* CallFrame.cpp in Sources */, - 1429D9C40ED23C3900B89619 /* CharacterClass.cpp in Sources */, - 7E2ADD900E79AC1100D50C51 /* CharacterClassConstructor.cpp in Sources */, 969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */, E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */, E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */, @@ -2402,6 +2430,7 @@ 86CC85A30EE79B7400288682 /* JITCall.cpp in Sources */, BCDD51EB0FB8DF74004A8BDC /* JITOpcodes.cpp in Sources */, 86CC85C40EE7A89400288682 /* JITPropertyAccess.cpp in Sources */, + A7C1E8E4112E72EF00A37F98 /* JITPropertyAccess32_64.cpp in Sources */, 14A23D750F4E1ABB0023CDAD /* JITStubs.cpp in Sources */, 140B7D1D0DC69AF7009C42B8 /* JSActivation.cpp in Sources */, 140566C4107EC255005DBC8D /* JSAPIValueWrapper.cpp in Sources */, @@ -2499,13 +2528,14 @@ 14A42E3F0F4F60EE00599099 /* TimeoutChecker.cpp in Sources */, 0B330C270F38C62300692DE3 /* TypeTraits.cpp in Sources */, 14469DEE107EC7E700650446 /* UString.cpp in Sources */, - 8698BB3A10D86BAF00D8D01B /* UStringImpl.cpp in Sources */, E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */, - 869083150E6518D7000D36ED /* WREC.cpp in Sources */, - 1429DA820ED2482900B89619 /* WRECFunctors.cpp in Sources */, - 1429DAE10ED2645B00B89619 /* WRECGenerator.cpp in Sources */, - 1429DAC00ED263E700B89619 /* WRECParser.cpp in Sources */, - A7C1E8E4112E72EF00A37F98 /* JITPropertyAccess32_64.cpp in Sources */, + 86565742115BE3DA00291F40 /* CString.cpp in Sources */, + A7482B9411671147003B0712 /* JSWeakObjectMapRefPrivate.cpp in Sources */, + 86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */, + 868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */, + 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */, + 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */, + 86B99AB8117E391E00DF5A90 /* RopeImpl.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JavaScriptCore/assembler/ARMAssembler.cpp b/JavaScriptCore/assembler/ARMAssembler.cpp index 6dd2b87..7393aa1 100644 --- a/JavaScriptCore/assembler/ARMAssembler.cpp +++ b/JavaScriptCore/assembler/ARMAssembler.cpp @@ -262,28 +262,29 @@ ARMWord ARMAssembler::encodeComplexImm(ARMWord imm, int dest) // Memory load/store helpers -void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset) +void ARMAssembler::dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset, bool bytes) { + ARMWord transferFlag = bytes ? DT_BYTE : 0; if (offset >= 0) { if (offset <= 0xfff) - dtr_u(isLoad, srcDst, base, offset); + dtr_u(isLoad, srcDst, base, offset | transferFlag); else if (offset <= 0xfffff) { add_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8)); - dtr_u(isLoad, srcDst, ARMRegisters::S0, offset & 0xfff); + dtr_u(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff) | transferFlag); } else { ARMWord reg = getImm(offset, ARMRegisters::S0); - dtr_ur(isLoad, srcDst, base, reg); + dtr_ur(isLoad, srcDst, base, reg | transferFlag); } } else { offset = -offset; if (offset <= 0xfff) - dtr_d(isLoad, srcDst, base, offset); + dtr_d(isLoad, srcDst, base, offset | transferFlag); else if (offset <= 0xfffff) { sub_r(ARMRegisters::S0, base, OP2_IMM | (offset >> 12) | (10 << 8)); - dtr_d(isLoad, srcDst, ARMRegisters::S0, offset & 0xfff); + dtr_d(isLoad, srcDst, ARMRegisters::S0, (offset & 0xfff) | transferFlag); } else { ARMWord reg = getImm(offset, ARMRegisters::S0); - dtr_dr(isLoad, srcDst, base, reg); + dtr_dr(isLoad, srcDst, base, reg | transferFlag); } } } diff --git a/JavaScriptCore/assembler/ARMAssembler.h b/JavaScriptCore/assembler/ARMAssembler.h index 6967b37..f93db68 100644 --- a/JavaScriptCore/assembler/ARMAssembler.h +++ b/JavaScriptCore/assembler/ARMAssembler.h @@ -27,8 +27,6 @@ #ifndef ARMAssembler_h #define ARMAssembler_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) #include "AssemblerBufferWithConstantPool.h" @@ -155,6 +153,7 @@ namespace JSC { SET_CC = (1 << 20), OP2_OFSREG = (1 << 25), DT_UP = (1 << 23), + DT_BYTE = (1 << 22), DT_WB = (1 << 21), // This flag is inlcuded in LDR and STR DT_PRE = (1 << 24), @@ -780,7 +779,7 @@ namespace JSC { // Memory load/store helpers - void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset); + void dataTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, int32_t offset, bool bytes = false); void baseIndexTransfer32(bool isLoad, RegisterID srcDst, RegisterID base, RegisterID index, int scale, int32_t offset); void doubleTransfer(bool isLoad, FPRegisterID srcDst, RegisterID base, int32_t offset); diff --git a/JavaScriptCore/assembler/ARMv7Assembler.h b/JavaScriptCore/assembler/ARMv7Assembler.h index 4e394b2..21279f5 100644 --- a/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/JavaScriptCore/assembler/ARMv7Assembler.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 University of Szeged * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,8 +27,6 @@ #ifndef ARMAssembler_h #define ARMAssembler_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) && CPU(ARM_THUMB2) #include "AssemblerBuffer.h" @@ -582,11 +581,13 @@ private: OP_MOV_reg_T1 = 0x4600, OP_BLX = 0x4700, OP_BX = 0x4700, - OP_LDRH_reg_T1 = 0x5A00, OP_STR_reg_T1 = 0x5000, OP_LDR_reg_T1 = 0x5800, + OP_LDRH_reg_T1 = 0x5A00, + OP_LDRB_reg_T1 = 0x5C00, OP_STR_imm_T1 = 0x6000, OP_LDR_imm_T1 = 0x6800, + OP_LDRB_imm_T1 = 0x7800, OP_LDRH_imm_T1 = 0x8800, OP_STR_imm_T2 = 0x9000, OP_LDR_imm_T2 = 0x9800, @@ -631,12 +632,15 @@ private: OP_SUB_imm_T4 = 0xF2A0, OP_MOVT = 0xF2C0, OP_NOP_T2a = 0xF3AF, + OP_LDRB_imm_T3 = 0xF810, + OP_LDRB_reg_T2 = 0xF810, OP_LDRH_reg_T2 = 0xF830, OP_LDRH_imm_T3 = 0xF830, OP_STR_imm_T4 = 0xF840, OP_STR_reg_T2 = 0xF840, OP_LDR_imm_T4 = 0xF850, OP_LDR_reg_T2 = 0xF850, + OP_LDRB_imm_T2 = 0xF890, OP_LDRH_imm_T2 = 0xF8B0, OP_STR_imm_T3 = 0xF8C0, OP_LDR_imm_T3 = 0xF8D0, @@ -1080,6 +1084,52 @@ public: m_formatter.twoWordOp12Reg4FourFours(OP_LDRH_reg_T2, rn, FourFours(rt, 0, shift, rm)); } + void ldrb(RegisterID rt, RegisterID rn, ARMThumbImmediate imm) + { + ASSERT(rn != ARMRegisters::pc); // LDR (literal) + ASSERT(imm.isUInt12()); + + if (!((rt | rn) & 8) && imm.isUInt5()) + m_formatter.oneWordOp5Imm5Reg3Reg3(OP_LDRB_imm_T1, imm.getUInt5(), rn, rt); + else + m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T2, rn, rt, imm.getUInt12()); + } + + void ldrb(RegisterID rt, RegisterID rn, int offset, bool index, bool wback) + { + ASSERT(rt != ARMRegisters::pc); + ASSERT(rn != ARMRegisters::pc); + ASSERT(index || wback); + ASSERT(!wback | (rt != rn)); + + bool add = true; + if (offset < 0) { + add = false; + offset = -offset; + } + + ASSERT(!(offset & ~0xff)); + + offset |= (wback << 8); + offset |= (add << 9); + offset |= (index << 10); + offset |= (1 << 11); + + m_formatter.twoWordOp12Reg4Reg4Imm12(OP_LDRB_imm_T3, rn, rt, offset); + } + + void ldrb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0) + { + ASSERT(rn != ARMRegisters::pc); // LDR (literal) + ASSERT(!BadReg(rm)); + ASSERT(shift <= 3); + + if (!shift && !((rt | rn | rm) & 8)) + m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRB_reg_T1, rm, rn, rt); + else + m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm)); + } + void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount) { ASSERT(!BadReg(rd)); diff --git a/JavaScriptCore/assembler/AbstractMacroAssembler.h b/JavaScriptCore/assembler/AbstractMacroAssembler.h index 198e8d1..f96e34a 100644 --- a/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -26,8 +26,6 @@ #ifndef AbstractMacroAssembler_h #define AbstractMacroAssembler_h -#include <wtf/Platform.h> - #include <MacroAssemblerCodeRef.h> #include <CodeLocation.h> #include <wtf/Noncopyable.h> @@ -83,6 +81,17 @@ public: int32_t offset; }; + struct ExtendedAddress { + explicit ExtendedAddress(RegisterID base, intptr_t offset = 0) + : base(base) + , offset(offset) + { + } + + RegisterID base; + intptr_t offset; + }; + // ImplicitAddress: // // This class is used for explicit 'load' and 'store' operations @@ -173,7 +182,7 @@ public: struct Imm32 { explicit Imm32(int32_t value) : m_value(value) -#if CPU(ARM) +#if CPU(ARM) || CPU(MIPS) , m_isPointer(false) #endif { @@ -182,7 +191,7 @@ public: #if !CPU(X86_64) explicit Imm32(ImmPtr ptr) : m_value(ptr.asIntptr()) -#if CPU(ARM) +#if CPU(ARM) || CPU(MIPS) , m_isPointer(true) #endif { @@ -190,13 +199,14 @@ public: #endif int32_t m_value; -#if CPU(ARM) +#if CPU(ARM) || CPU(MIPS) // 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. // To avoid this problem, always generate pointers (and thus Imm32s constructed // from ImmPtrs) with a code sequence that is able to represent any pointer // value - don't use a more compact form in these cases. + // Same for MIPS. bool m_isPointer; #endif }; diff --git a/JavaScriptCore/assembler/AssemblerBuffer.h b/JavaScriptCore/assembler/AssemblerBuffer.h index 073906a..e2fb8a1 100644 --- a/JavaScriptCore/assembler/AssemblerBuffer.h +++ b/JavaScriptCore/assembler/AssemblerBuffer.h @@ -26,8 +26,6 @@ #ifndef AssemblerBuffer_h #define AssemblerBuffer_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) #include "stdint.h" diff --git a/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h b/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h index af3c3be..b1c537e 100644 --- a/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h +++ b/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h @@ -27,8 +27,6 @@ #ifndef AssemblerBufferWithConstantPool_h #define AssemblerBufferWithConstantPool_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) #include "AssemblerBuffer.h" diff --git a/JavaScriptCore/assembler/CodeLocation.h b/JavaScriptCore/assembler/CodeLocation.h index b910b6f..cab28cd 100644 --- a/JavaScriptCore/assembler/CodeLocation.h +++ b/JavaScriptCore/assembler/CodeLocation.h @@ -26,7 +26,6 @@ #ifndef CodeLocation_h #define CodeLocation_h -#include <wtf/Platform.h> #include <MacroAssemblerCodeRef.h> diff --git a/JavaScriptCore/assembler/LinkBuffer.h b/JavaScriptCore/assembler/LinkBuffer.h index 6d08117..47cac5a 100644 --- a/JavaScriptCore/assembler/LinkBuffer.h +++ b/JavaScriptCore/assembler/LinkBuffer.h @@ -26,8 +26,6 @@ #ifndef LinkBuffer_h #define LinkBuffer_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) #include <MacroAssembler.h> diff --git a/JavaScriptCore/assembler/MIPSAssembler.h b/JavaScriptCore/assembler/MIPSAssembler.h new file mode 100644 index 0000000..ea35268 --- /dev/null +++ b/JavaScriptCore/assembler/MIPSAssembler.h @@ -0,0 +1,944 @@ +/* + * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2009 University of Szeged + * All rights reserved. + * Copyright (C) 2010 MIPS Technologies, 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 MIPS TECHNOLOGIES, 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 MIPS TECHNOLOGIES, 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 MIPSAssembler_h +#define MIPSAssembler_h + +#if ENABLE(ASSEMBLER) && CPU(MIPS) + +#include "AssemblerBuffer.h" +#include <wtf/Assertions.h> +#include <wtf/SegmentedVector.h> + +namespace JSC { + +typedef uint32_t MIPSWord; + +namespace MIPSRegisters { +typedef enum { + r0 = 0, + r1, + r2, + r3, + r4, + r5, + r6, + r7, + r8, + r9, + r10, + r11, + r12, + r13, + r14, + r15, + r16, + r17, + r18, + r19, + r20, + r21, + r22, + r23, + r24, + r25, + r26, + r27, + r28, + r29, + r30, + r31, + zero = r0, + at = r1, + v0 = r2, + v1 = r3, + a0 = r4, + a1 = r5, + a2 = r6, + a3 = r7, + t0 = r8, + t1 = r9, + t2 = r10, + t3 = r11, + t4 = r12, + t5 = r13, + t6 = r14, + t7 = r15, + s0 = r16, + s1 = r17, + s2 = r18, + s3 = r19, + s4 = r20, + s5 = r21, + s6 = r22, + s7 = r23, + t8 = r24, + t9 = r25, + k0 = r26, + k1 = r27, + gp = r28, + sp = r29, + fp = r30, + ra = r31 +} RegisterID; + +typedef enum { + f0, + f1, + f2, + f3, + f4, + f5, + f6, + f7, + f8, + f9, + f10, + f11, + f12, + f13, + f14, + f15, + f16, + f17, + f18, + f19, + f20, + f21, + f22, + f23, + f24, + f25, + f26, + f27, + f28, + f29, + f30, + f31 +} FPRegisterID; + +} // namespace MIPSRegisters + +class MIPSAssembler { +public: + typedef MIPSRegisters::RegisterID RegisterID; + typedef MIPSRegisters::FPRegisterID FPRegisterID; + typedef SegmentedVector<int, 64> Jumps; + + MIPSAssembler() + { + } + + // MIPS instruction opcode field position + enum { + OP_SH_RD = 11, + OP_SH_RT = 16, + OP_SH_RS = 21, + OP_SH_SHAMT = 6, + OP_SH_CODE = 16, + OP_SH_FD = 6, + OP_SH_FS = 11, + OP_SH_FT = 16 + }; + + class JmpSrc { + friend class MIPSAssembler; + public: + JmpSrc() + : m_offset(-1) + { + } + + private: + JmpSrc(int offset) + : m_offset(offset) + { + } + + int m_offset; + }; + + class JmpDst { + friend class MIPSAssembler; + public: + JmpDst() + : m_offset(-1) + , m_used(false) + { + } + + bool isUsed() const { return m_used; } + void used() { m_used = true; } + private: + JmpDst(int offset) + : m_offset(offset) + , m_used(false) + { + ASSERT(m_offset == offset); + } + + int m_offset : 31; + int m_used : 1; + }; + + void emitInst(MIPSWord op) + { + void* oldBase = m_buffer.data(); + + m_buffer.putInt(op); + + void* newBase = m_buffer.data(); + if (oldBase != newBase) + relocateJumps(oldBase, newBase); + } + + void nop() + { + emitInst(0x00000000); + } + + /* Need to insert one load data delay nop for mips1. */ + void loadDelayNop() + { +#if WTF_MIPS_ISA(1) + nop(); +#endif + } + + /* Need to insert one coprocessor access delay nop for mips1. */ + void copDelayNop() + { +#if WTF_MIPS_ISA(1) + nop(); +#endif + } + + void move(RegisterID rd, RegisterID rs) + { + /* addu */ + emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS)); + } + + /* Set an immediate value to a register. This may generate 1 or 2 + instructions. */ + void li(RegisterID dest, int imm) + { + if (imm >= -32768 && imm <= 32767) + addiu(dest, MIPSRegisters::zero, imm); + else if (imm >= 0 && imm < 65536) + ori(dest, MIPSRegisters::zero, imm); + else { + lui(dest, imm >> 16); + if (imm & 0xffff) + ori(dest, dest, imm); + } + } + + void lui(RegisterID rt, int imm) + { + emitInst(0x3c000000 | (rt << OP_SH_RT) | (imm & 0xffff)); + } + + void addiu(RegisterID rt, RegisterID rs, int imm) + { + emitInst(0x24000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (imm & 0xffff)); + } + + void addu(RegisterID rd, RegisterID rs, RegisterID rt) + { + emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS) + | (rt << OP_SH_RT)); + } + + void subu(RegisterID rd, RegisterID rs, RegisterID rt) + { + emitInst(0x00000023 | (rd << OP_SH_RD) | (rs << OP_SH_RS) + | (rt << OP_SH_RT)); + } + + void mult(RegisterID rs, RegisterID rt) + { + emitInst(0x00000018 | (rs << OP_SH_RS) | (rt << OP_SH_RT)); + } + + void mfhi(RegisterID rd) + { + emitInst(0x00000010 | (rd << OP_SH_RD)); + } + + void mflo(RegisterID rd) + { + emitInst(0x00000012 | (rd << OP_SH_RD)); + } + + void mul(RegisterID rd, RegisterID rs, RegisterID rt) + { +#if WTF_MIPS_ISA_AT_LEAST(32) + emitInst(0x70000002 | (rd << OP_SH_RD) | (rs << OP_SH_RS) + | (rt << OP_SH_RT)); +#else + mult(rs, rt); + mflo(rd); +#endif + } + + void andInsn(RegisterID rd, RegisterID rs, RegisterID rt) + { + emitInst(0x00000024 | (rd << OP_SH_RD) | (rs << OP_SH_RS) + | (rt << OP_SH_RT)); + } + + void andi(RegisterID rt, RegisterID rs, int imm) + { + emitInst(0x30000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (imm & 0xffff)); + } + + void nor(RegisterID rd, RegisterID rs, RegisterID rt) + { + emitInst(0x00000027 | (rd << OP_SH_RD) | (rs << OP_SH_RS) + | (rt << OP_SH_RT)); + } + + void orInsn(RegisterID rd, RegisterID rs, RegisterID rt) + { + emitInst(0x00000025 | (rd << OP_SH_RD) | (rs << OP_SH_RS) + | (rt << OP_SH_RT)); + } + + void ori(RegisterID rt, RegisterID rs, int imm) + { + emitInst(0x34000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (imm & 0xffff)); + } + + void xorInsn(RegisterID rd, RegisterID rs, RegisterID rt) + { + emitInst(0x00000026 | (rd << OP_SH_RD) | (rs << OP_SH_RS) + | (rt << OP_SH_RT)); + } + + void xori(RegisterID rt, RegisterID rs, int imm) + { + emitInst(0x38000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (imm & 0xffff)); + } + + void slt(RegisterID rd, RegisterID rs, RegisterID rt) + { + emitInst(0x0000002a | (rd << OP_SH_RD) | (rs << OP_SH_RS) + | (rt << OP_SH_RT)); + } + + void sltu(RegisterID rd, RegisterID rs, RegisterID rt) + { + emitInst(0x0000002b | (rd << OP_SH_RD) | (rs << OP_SH_RS) + | (rt << OP_SH_RT)); + } + + void sltiu(RegisterID rt, RegisterID rs, int imm) + { + emitInst(0x2c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (imm & 0xffff)); + } + + void sll(RegisterID rd, RegisterID rt, int shamt) + { + emitInst(0x00000000 | (rd << OP_SH_RD) | (rt << OP_SH_RT) + | ((shamt & 0x1f) << OP_SH_SHAMT)); + } + + void sllv(RegisterID rd, RegisterID rt, int rs) + { + emitInst(0x00000004 | (rd << OP_SH_RD) | (rt << OP_SH_RT) + | (rs << OP_SH_RS)); + } + + void sra(RegisterID rd, RegisterID rt, int shamt) + { + emitInst(0x00000003 | (rd << OP_SH_RD) | (rt << OP_SH_RT) + | ((shamt & 0x1f) << OP_SH_SHAMT)); + } + + void srav(RegisterID rd, RegisterID rt, RegisterID rs) + { + emitInst(0x00000007 | (rd << OP_SH_RD) | (rt << OP_SH_RT) + | (rs << OP_SH_RS)); + } + + void lbu(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0x90000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + loadDelayNop(); + } + + void lw(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0x8c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + loadDelayNop(); + } + + void lwl(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0x88000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + loadDelayNop(); + } + + void lwr(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0x98000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + loadDelayNop(); + } + + void lhu(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0x94000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + loadDelayNop(); + } + + void sw(RegisterID rt, RegisterID rs, int offset) + { + emitInst(0xac000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + } + + void jr(RegisterID rs) + { + emitInst(0x00000008 | (rs << OP_SH_RS)); + } + + void jalr(RegisterID rs) + { + emitInst(0x0000f809 | (rs << OP_SH_RS)); + } + + void jal() + { + emitInst(0x0c000000); + } + + void bkpt() + { + int value = 512; /* BRK_BUG */ + emitInst(0x0000000d | ((value & 0x3ff) << OP_SH_CODE)); + } + + void bgez(RegisterID rs, int imm) + { + emitInst(0x04010000 | (rs << OP_SH_RS) | (imm & 0xffff)); + } + + void bltz(RegisterID rs, int imm) + { + emitInst(0x04000000 | (rs << OP_SH_RS) | (imm & 0xffff)); + } + + void beq(RegisterID rs, RegisterID rt, int imm) + { + emitInst(0x10000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff)); + } + + void bne(RegisterID rs, RegisterID rt, int imm) + { + emitInst(0x14000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff)); + } + + void bc1t() + { + emitInst(0x45010000); + } + + void bc1f() + { + emitInst(0x45000000); + } + + JmpSrc newJmpSrc() + { + return JmpSrc(m_buffer.size()); + } + + void appendJump() + { + m_jumps.append(m_buffer.size()); + } + + void addd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200000 | (fd << OP_SH_FD) | (fs << OP_SH_FS) + | (ft << OP_SH_FT)); + } + + void subd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200001 | (fd << OP_SH_FD) | (fs << OP_SH_FS) + | (ft << OP_SH_FT)); + } + + void muld(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200002 | (fd << OP_SH_FD) | (fs << OP_SH_FS) + | (ft << OP_SH_FT)); + } + + void lwc1(FPRegisterID ft, RegisterID rs, int offset) + { + emitInst(0xc4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + copDelayNop(); + } + + void ldc1(FPRegisterID ft, RegisterID rs, int offset) + { + emitInst(0xd4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + } + + void swc1(FPRegisterID ft, RegisterID rs, int offset) + { + emitInst(0xe4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + } + + void sdc1(FPRegisterID ft, RegisterID rs, int offset) + { + emitInst(0xf4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS) + | (offset & 0xffff)); + } + + void mtc1(RegisterID rt, FPRegisterID fs) + { + emitInst(0x44800000 | (fs << OP_SH_FS) | (rt << OP_SH_RT)); + copDelayNop(); + } + + void mfc1(RegisterID rt, FPRegisterID fs) + { + emitInst(0x44000000 | (fs << OP_SH_FS) | (rt << OP_SH_RT)); + copDelayNop(); + } + + void truncwd(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x4620000d | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + + void cvtdw(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46800021 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + + void ceqd(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200032 | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + void cngtd(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x4620003f | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + void cnged(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x4620003d | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + void cltd(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x4620003c | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + void cled(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x4620003e | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + void cueqd(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200033 | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + void coled(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200036 | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + void coltd(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200034 | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + void culed(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200037 | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + void cultd(FPRegisterID fs, FPRegisterID ft) + { + emitInst(0x46200035 | (fs << OP_SH_FS) | (ft << OP_SH_FT)); + copDelayNop(); + } + + // General helpers + + JmpDst label() + { + return JmpDst(m_buffer.size()); + } + + JmpDst align(int alignment) + { + while (!m_buffer.isAligned(alignment)) + bkpt(); + + return label(); + } + + static void* getRelocatedAddress(void* code, JmpSrc jump) + { + ASSERT(jump.m_offset != -1); + void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + jump.m_offset); + return b; + } + + static void* getRelocatedAddress(void* code, JmpDst label) + { + void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + label.m_offset); + return b; + } + + static int getDifferenceBetweenLabels(JmpDst from, JmpDst to) + { + return to.m_offset - from.m_offset; + } + + static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to) + { + return to.m_offset - from.m_offset; + } + + static int getDifferenceBetweenLabels(JmpSrc from, JmpDst to) + { + return to.m_offset - from.m_offset; + } + + // Assembler admin methods: + + size_t size() const + { + return m_buffer.size(); + } + + void* executableCopy(ExecutablePool* allocator) + { + void *result = m_buffer.executableCopy(allocator); + if (!result) + return 0; + + relocateJumps(m_buffer.data(), result); + return result; + } + + static unsigned getCallReturnOffset(JmpSrc call) + { + // The return address is after a call and a delay slot instruction + return call.m_offset; + } + + // Linking & patching: + // + // 'link' and 'patch' methods are for use on unprotected code - such as the code + // within the AssemblerBuffer, and code being patched by the patch buffer. Once + // code has been finalized it is (platform support permitting) within a non- + // writable region of memory; to modify the code in an execute-only execuable + // pool the 'repatch' and 'relink' methods should be used. + + void linkJump(JmpSrc from, JmpDst to) + { + ASSERT(to.m_offset != -1); + ASSERT(from.m_offset != -1); + MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + from.m_offset); + MIPSWord* toPos = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + to.m_offset); + + ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5))); + insn = insn - 6; + linkWithOffset(insn, toPos); + } + + static void linkJump(void* code, JmpSrc from, void* to) + { + ASSERT(from.m_offset != -1); + MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset); + + ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5))); + insn = insn - 6; + linkWithOffset(insn, to); + } + + static void linkCall(void* code, JmpSrc from, void* to) + { + MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset); + linkCallInternal(insn, to); + } + + static void linkPointer(void* code, JmpDst from, void* to) + { + MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset); + ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui + *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff); + insn++; + ASSERT((*insn & 0xfc000000) == 0x34000000); // ori + *insn = (*insn & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff); + } + + static void relinkJump(void* from, void* to) + { + MIPSWord* insn = reinterpret_cast<MIPSWord*>(from); + + ASSERT(!(*(insn - 1)) && !(*(insn - 5))); + insn = insn - 6; + int flushSize = linkWithOffset(insn, to); + + ExecutableAllocator::cacheFlush(insn, flushSize); + } + + static void relinkCall(void* from, void* to) + { + void* start; + int size = linkCallInternal(from, to); + if (size == sizeof(MIPSWord)) + start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 2 * sizeof(MIPSWord)); + else + start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 4 * sizeof(MIPSWord)); + + ExecutableAllocator::cacheFlush(start, size); + } + + static void repatchInt32(void* from, int32_t to) + { + MIPSWord* insn = reinterpret_cast<MIPSWord*>(from); + ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui + *insn = (*insn & 0xffff0000) | ((to >> 16) & 0xffff); + insn++; + ASSERT((*insn & 0xfc000000) == 0x34000000); // ori + *insn = (*insn & 0xffff0000) | (to & 0xffff); + insn--; + ExecutableAllocator::cacheFlush(insn, 2 * sizeof(MIPSWord)); + } + + static void repatchPointer(void* from, void* to) + { + repatchInt32(from, reinterpret_cast<int32_t>(to)); + } + + static void repatchLoadPtrToLEA(void* from) + { + MIPSWord* insn = reinterpret_cast<MIPSWord*>(from); + insn = insn + 3; + ASSERT((*insn & 0xfc000000) == 0x8c000000); // lw + /* lw -> addiu */ + *insn = 0x24000000 | (*insn & 0x03ffffff); + + ExecutableAllocator::cacheFlush(insn, sizeof(MIPSWord)); + } + +private: + + /* Update each jump in the buffer of newBase. */ + void relocateJumps(void* oldBase, void* newBase) + { + // Check each jump + for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) { + int pos = *iter; + MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(newBase) + pos); + insn = insn + 2; + // Need to make sure we have 5 valid instructions after pos + if ((unsigned int)pos >= m_buffer.size() - 5 * sizeof(MIPSWord)) + continue; + + if ((*insn & 0xfc000000) == 0x08000000) { // j + int offset = *insn & 0x03ffffff; + int oldInsnAddress = (int)insn - (int)newBase + (int)oldBase; + int topFourBits = (oldInsnAddress + 4) >> 28; + int oldTargetAddress = (topFourBits << 28) | (offset << 2); + int newTargetAddress = oldTargetAddress - (int)oldBase + (int)newBase; + int newInsnAddress = (int)insn; + if (((newInsnAddress + 4) >> 28) == (newTargetAddress >> 28)) + *insn = 0x08000000 | ((newTargetAddress >> 2) & 0x3ffffff); + else { + /* lui */ + *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff); + /* ori */ + *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff); + /* jr */ + *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS); + } + } else if ((*insn & 0xffe00000) == 0x3c000000) { // lui + int high = (*insn & 0xffff) << 16; + int low = *(insn + 1) & 0xffff; + int oldTargetAddress = high | low; + int newTargetAddress = oldTargetAddress - (int)oldBase + (int)newBase; + /* lui */ + *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff); + /* ori */ + *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff); + } + } + } + + static int linkWithOffset(MIPSWord* insn, void* to) + { + ASSERT((*insn & 0xfc000000) == 0x10000000 // beq + || (*insn & 0xfc000000) == 0x14000000 // bne + || (*insn & 0xffff0000) == 0x45010000 // bc1t + || (*insn & 0xffff0000) == 0x45000000); // bc1f + intptr_t diff = (reinterpret_cast<intptr_t>(to) + - reinterpret_cast<intptr_t>(insn) - 4) >> 2; + + if (diff < -32768 || diff > 32767 || *(insn + 2) != 0x10000003) { + /* + Convert the sequence: + beq $2, $3, target + nop + b 1f + nop + nop + nop + 1: + + to the new sequence if possible: + bne $2, $3, 1f + nop + j target + nop + nop + nop + 1: + + OR to the new sequence: + bne $2, $3, 1f + nop + lui $25, target >> 16 + ori $25, $25, target & 0xffff + jr $25 + nop + 1: + + Note: beq/bne/bc1t/bc1f are converted to bne/beq/bc1f/bc1t. + */ + + if (*(insn + 2) == 0x10000003) { + if ((*insn & 0xfc000000) == 0x10000000) // beq + *insn = (*insn & 0x03ff0000) | 0x14000005; // bne + else if ((*insn & 0xfc000000) == 0x14000000) // bne + *insn = (*insn & 0x03ff0000) | 0x10000005; // beq + else if ((*insn & 0xffff0000) == 0x45010000) // bc1t + *insn = 0x45000005; // bc1f + else if ((*insn & 0xffff0000) == 0x45000000) // bc1f + *insn = 0x45010005; // bc1t + else + ASSERT(0); + } + + insn = insn + 2; + if ((reinterpret_cast<intptr_t>(insn) + 4) >> 28 + == reinterpret_cast<intptr_t>(to) >> 28) { + *insn = 0x08000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff); + *(insn + 1) = 0; + return 4 * sizeof(MIPSWord); + } + + intptr_t newTargetAddress = reinterpret_cast<intptr_t>(to); + /* lui */ + *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff); + /* ori */ + *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff); + /* jr */ + *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS); + return 5 * sizeof(MIPSWord); + } + + *insn = (*insn & 0xffff0000) | (diff & 0xffff); + return sizeof(MIPSWord); + } + + static int linkCallInternal(void* from, void* to) + { + MIPSWord* insn = reinterpret_cast<MIPSWord*>(from); + insn = insn - 4; + + if ((*(insn + 2) & 0xfc000000) == 0x0c000000) { // jal + if ((reinterpret_cast<intptr_t>(from) - 4) >> 28 + == reinterpret_cast<intptr_t>(to) >> 28) { + *(insn + 2) = 0x0c000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff); + return sizeof(MIPSWord); + } + + /* lui $25, (to >> 16) & 0xffff */ + *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff); + /* ori $25, $25, to & 0xffff */ + *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (reinterpret_cast<intptr_t>(to) & 0xffff); + /* jalr $25 */ + *(insn + 2) = 0x0000f809 | (MIPSRegisters::t9 << OP_SH_RS); + return 3 * sizeof(MIPSWord); + } + + ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui + ASSERT((*(insn + 1) & 0xfc000000) == 0x34000000); // ori + + /* lui */ + *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff); + /* ori */ + *(insn + 1) = (*(insn + 1) & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff); + return 2 * sizeof(MIPSWord); + } + + AssemblerBuffer m_buffer; + Jumps m_jumps; +}; + +} // namespace JSC + +#endif // ENABLE(ASSEMBLER) && CPU(MIPS) + +#endif // MIPSAssembler_h diff --git a/JavaScriptCore/assembler/MacroAssembler.h b/JavaScriptCore/assembler/MacroAssembler.h index 76bd205..ce1be78 100644 --- a/JavaScriptCore/assembler/MacroAssembler.h +++ b/JavaScriptCore/assembler/MacroAssembler.h @@ -26,8 +26,6 @@ #ifndef MacroAssembler_h #define MacroAssembler_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) #if CPU(ARM_THUMB2) @@ -38,6 +36,12 @@ namespace JSC { typedef MacroAssemblerARMv7 MacroAssemblerBase; }; #include "MacroAssemblerARM.h" namespace JSC { typedef MacroAssemblerARM MacroAssemblerBase; }; +#elif CPU(MIPS) +#include "MacroAssemblerMIPS.h" +namespace JSC { +typedef MacroAssemblerMIPS MacroAssemblerBase; +}; + #elif CPU(X86) #include "MacroAssemblerX86.h" namespace JSC { typedef MacroAssemblerX86 MacroAssemblerBase; }; @@ -327,6 +331,11 @@ public: { return branchSub32(cond, imm, dest); } + using MacroAssemblerBase::branchTest8; + Jump branchTest8(Condition cond, ExtendedAddress address, Imm32 mask = Imm32(-1)) + { + return MacroAssemblerBase::branchTest8(cond, Address(address.base, address.offset), mask); + } #endif }; diff --git a/JavaScriptCore/assembler/MacroAssemblerARM.h b/JavaScriptCore/assembler/MacroAssemblerARM.h index 21b8de8..52c4fa2 100644 --- a/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -28,8 +28,6 @@ #ifndef MacroAssemblerARM_h #define MacroAssemblerARM_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) && CPU(ARM_TRADITIONAL) #include "ARMAssembler.h" @@ -214,6 +212,11 @@ public: m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } + void load8(ImplicitAddress address, RegisterID dest) + { + m_assembler.dataTransfer32(true, dest, address.base, address.offset, true); + } + void load32(ImplicitAddress address, RegisterID dest) { m_assembler.dataTransfer32(true, dest, address.base, address.offset); @@ -359,6 +362,12 @@ public: move(src, dest); } + Jump branch8(Condition cond, Address left, Imm32 right) + { + load8(left, ARMRegisters::S1); + return branch32(cond, ARMRegisters::S1, right); + } + Jump branch32(Condition cond, RegisterID left, RegisterID right, int useConstantPool = 0) { m_assembler.cmp_r(left, right); @@ -422,6 +431,12 @@ public: return m_assembler.jmp(ARMCondition(cond)); } + Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1)) + { + load8(address, ARMRegisters::S1); + return branchTest32(cond, ARMRegisters::S1, mask); + } + Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask) { ASSERT((cond == Zero) || (cond == NonZero)); @@ -530,6 +545,13 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } + Jump branchNeg32(Condition cond, RegisterID srcDest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + neg32(srcDest); + return Jump(m_assembler.jmp(ARMCondition(cond))); + } + Jump branchOr32(Condition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); diff --git a/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/JavaScriptCore/assembler/MacroAssemblerARMv7.h index 532a9cf..3d08f0e 100644 --- a/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 University of Szeged * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,8 +27,6 @@ #ifndef MacroAssemblerARMv7_h #define MacroAssemblerARMv7_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) #include "ARMv7Assembler.h" @@ -368,6 +367,20 @@ private: } } + void load8(ArmAddress address, RegisterID dest) + { + if (address.type == ArmAddress::HasIndex) + m_assembler.ldrb(dest, address.base, address.u.index, address.u.scale); + else if (address.u.offset >= 0) { + ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12(address.u.offset); + ASSERT(armImm.isValid()); + m_assembler.ldrb(dest, address.base, armImm); + } else { + ASSERT(address.u.offset >= -255); + m_assembler.ldrb(dest, address.base, address.u.offset, true, false); + } + } + void store32(RegisterID src, ArmAddress address) { if (address.type == ArmAddress::HasIndex) @@ -404,6 +417,11 @@ public: m_assembler.ldr(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0)); } + void load8(ImplicitAddress address, RegisterID dest) + { + load8(setupArmAddress(address), dest); + } + DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) { DataLabel32 label = moveWithPatch(Imm32(address.offset), dataTempRegister); @@ -793,6 +811,19 @@ public: return branch32(cond, addressTempRegister, Imm32(right.m_value << 16)); } + Jump branch8(Condition cond, RegisterID left, Imm32 right) + { + compare32(left, right); + return Jump(makeBranch(cond)); + } + + Jump branch8(Condition cond, Address left, Imm32 right) + { + // use addressTempRegister incase the branch8 we call uses dataTempRegister. :-/ + load8(left, addressTempRegister); + return branch8(cond, addressTempRegister, right); + } + Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask) { ASSERT((cond == Zero) || (cond == NonZero)); @@ -823,6 +854,21 @@ public: return branchTest32(cond, addressTempRegister, mask); } + Jump branchTest8(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + { + ASSERT((cond == Zero) || (cond == NonZero)); + test32(reg, mask); + return Jump(makeBranch(cond)); + } + + Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1)) + { + ASSERT((cond == Zero) || (cond == NonZero)); + // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ + load8(address, addressTempRegister); + return branchTest8(cond, addressTempRegister, mask); + } + Jump jump() { return Jump(makeJump()); @@ -973,6 +1019,14 @@ public: m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0)); } + void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest) + { + load8(address, dataTempRegister); + test32(dataTempRegister, mask); + m_assembler.it(armV7Condition(cond), false); + m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(1)); + m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(0)); + } DataLabel32 moveWithPatch(Imm32 imm, RegisterID dst) { diff --git a/JavaScriptCore/assembler/MacroAssemblerCodeRef.h b/JavaScriptCore/assembler/MacroAssemblerCodeRef.h index cae8bf6..543b0fa 100644 --- a/JavaScriptCore/assembler/MacroAssemblerCodeRef.h +++ b/JavaScriptCore/assembler/MacroAssemblerCodeRef.h @@ -26,8 +26,6 @@ #ifndef MacroAssemblerCodeRef_h #define MacroAssemblerCodeRef_h -#include <wtf/Platform.h> - #include "ExecutableAllocator.h" #include "PassRefPtr.h" #include "RefPtr.h" diff --git a/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/JavaScriptCore/assembler/MacroAssemblerMIPS.h new file mode 100644 index 0000000..9853c34 --- /dev/null +++ b/JavaScriptCore/assembler/MacroAssemblerMIPS.h @@ -0,0 +1,1711 @@ +/* + * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2010 MIPS Technologies, 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 MIPS TECHNOLOGIES, 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 MIPS TECHNOLOGIES, 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 MacroAssemblerMIPS_h +#define MacroAssemblerMIPS_h + +#if ENABLE(ASSEMBLER) && CPU(MIPS) + +#include "AbstractMacroAssembler.h" +#include "MIPSAssembler.h" + +namespace JSC { + +class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> { +public: + + MacroAssemblerMIPS() + : m_fixedWidth(false) + { + } + + static const Scale ScalePtr = TimesFour; + + // For storing immediate number + static const RegisterID immTempRegister = MIPSRegisters::t0; + // For storing data loaded from the memory + static const RegisterID dataTempRegister = MIPSRegisters::t1; + // For storing address base + static const RegisterID addrTempRegister = MIPSRegisters::t2; + // For storing compare result + static const RegisterID cmpTempRegister = MIPSRegisters::t3; + + // FP temp register + static const FPRegisterID fpTempRegister = MIPSRegisters::f16; + + enum Condition { + Equal, + NotEqual, + Above, + AboveOrEqual, + Below, + BelowOrEqual, + GreaterThan, + GreaterThanOrEqual, + LessThan, + LessThanOrEqual, + Overflow, + Signed, + Zero, + NonZero + }; + + enum DoubleCondition { + DoubleEqual, + DoubleNotEqual, + DoubleGreaterThan, + DoubleGreaterThanOrEqual, + DoubleLessThan, + DoubleLessThanOrEqual, + DoubleEqualOrUnordered, + DoubleNotEqualOrUnordered, + DoubleGreaterThanOrUnordered, + DoubleGreaterThanOrEqualOrUnordered, + DoubleLessThanOrUnordered, + DoubleLessThanOrEqualOrUnordered + }; + + static const RegisterID stackPointerRegister = MIPSRegisters::sp; + static const RegisterID returnAddressRegister = MIPSRegisters::ra; + + // Integer arithmetic operations: + // + // Operations are typically two operand - operation(source, srcDst) + // For many operations the source may be an Imm32, the srcDst operand + // may often be a memory location (explictly described using an Address + // object). + + void add32(RegisterID src, RegisterID dest) + { + m_assembler.addu(dest, dest, src); + } + + void add32(Imm32 imm, RegisterID dest) + { + add32(imm, dest, dest); + } + + void add32(Imm32 imm, RegisterID src, RegisterID dest) + { + if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 + && !m_fixedWidth) { + /* + addiu dest, src, imm + */ + m_assembler.addiu(dest, src, imm.m_value); + } else { + /* + li immTemp, imm + addu dest, src, immTemp + */ + move(imm, immTempRegister); + m_assembler.addu(dest, src, immTempRegister); + } + } + + void add32(Imm32 imm, Address address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + lw dataTemp, offset(base) + li immTemp, imm + addu dataTemp, dataTemp, immTemp + sw dataTemp, offset(base) + */ + m_assembler.lw(dataTempRegister, address.base, address.offset); + if (!imm.m_isPointer + && imm.m_value >= -32768 && imm.m_value <= 32767 + && !m_fixedWidth) + m_assembler.addiu(dataTempRegister, dataTempRegister, + imm.m_value); + else { + move(imm, immTempRegister); + m_assembler.addu(dataTempRegister, dataTempRegister, + immTempRegister); + } + m_assembler.sw(dataTempRegister, address.base, address.offset); + } else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + lw dataTemp, (offset & 0xffff)(addrTemp) + li immtemp, imm + addu dataTemp, dataTemp, immTemp + sw dataTemp, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lw(dataTempRegister, addrTempRegister, address.offset); + + if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) + m_assembler.addiu(dataTempRegister, dataTempRegister, + imm.m_value); + else { + move(imm, immTempRegister); + m_assembler.addu(dataTempRegister, dataTempRegister, + immTempRegister); + } + m_assembler.sw(dataTempRegister, addrTempRegister, address.offset); + } + } + + void add32(Address src, RegisterID dest) + { + load32(src, dataTempRegister); + add32(dataTempRegister, dest); + } + + void add32(RegisterID src, Address dest) + { + if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) { + /* + lw dataTemp, offset(base) + addu dataTemp, dataTemp, src + sw dataTemp, offset(base) + */ + m_assembler.lw(dataTempRegister, dest.base, dest.offset); + m_assembler.addu(dataTempRegister, dataTempRegister, src); + m_assembler.sw(dataTempRegister, dest.base, dest.offset); + } else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + lw dataTemp, (offset & 0xffff)(addrTemp) + addu dataTemp, dataTemp, src + sw dataTemp, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (dest.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, dest.base); + m_assembler.lw(dataTempRegister, addrTempRegister, dest.offset); + m_assembler.addu(dataTempRegister, dataTempRegister, src); + m_assembler.sw(dataTempRegister, addrTempRegister, dest.offset); + } + } + + void add32(Imm32 imm, AbsoluteAddress address) + { + /* + li addrTemp, address + li immTemp, imm + lw dataTemp, 0(addrTemp) + addu dataTemp, dataTemp, immTemp + sw dataTemp, 0(addrTemp) + */ + move(ImmPtr(address.m_ptr), addrTempRegister); + m_assembler.lw(dataTempRegister, addrTempRegister, 0); + if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 + && !m_fixedWidth) + m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); + else { + move(imm, immTempRegister); + m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister); + } + m_assembler.sw(dataTempRegister, addrTempRegister, 0); + } + + void and32(RegisterID src, RegisterID dest) + { + m_assembler.andInsn(dest, dest, src); + } + + void and32(Imm32 imm, RegisterID dest) + { + if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + move(MIPSRegisters::zero, dest); + else if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535 + && !m_fixedWidth) + m_assembler.andi(dest, dest, imm.m_value); + else { + /* + li immTemp, imm + and dest, dest, immTemp + */ + move(imm, immTempRegister); + m_assembler.andInsn(dest, dest, immTempRegister); + } + } + + void lshift32(Imm32 imm, RegisterID dest) + { + m_assembler.sll(dest, dest, imm.m_value); + } + + void lshift32(RegisterID shiftAmount, RegisterID dest) + { + m_assembler.sllv(dest, dest, shiftAmount); + } + + void mul32(RegisterID src, RegisterID dest) + { + m_assembler.mul(dest, dest, src); + } + + void mul32(Imm32 imm, RegisterID src, RegisterID dest) + { + if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + move(MIPSRegisters::zero, dest); + else if (!imm.m_isPointer && imm.m_value == 1 && !m_fixedWidth) + move(src, dest); + else { + /* + li dataTemp, imm + mul dest, src, dataTemp + */ + move(imm, dataTempRegister); + m_assembler.mul(dest, src, dataTempRegister); + } + } + + void not32(RegisterID srcDest) + { + m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero); + } + + void or32(RegisterID src, RegisterID dest) + { + m_assembler.orInsn(dest, dest, src); + } + + void or32(Imm32 imm, RegisterID dest) + { + if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + return; + + if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535 + && !m_fixedWidth) { + m_assembler.ori(dest, dest, imm.m_value); + return; + } + + /* + li dataTemp, imm + or dest, dest, dataTemp + */ + move(imm, dataTempRegister); + m_assembler.orInsn(dest, dest, dataTempRegister); + } + + void rshift32(RegisterID shiftAmount, RegisterID dest) + { + m_assembler.srav(dest, dest, shiftAmount); + } + + void rshift32(Imm32 imm, RegisterID dest) + { + m_assembler.sra(dest, dest, imm.m_value); + } + + void sub32(RegisterID src, RegisterID dest) + { + m_assembler.subu(dest, dest, src); + } + + void sub32(Imm32 imm, RegisterID dest) + { + if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 + && !m_fixedWidth) { + /* + addiu dest, src, imm + */ + m_assembler.addiu(dest, dest, -imm.m_value); + } else { + /* + li immTemp, imm + subu dest, src, immTemp + */ + move(imm, immTempRegister); + m_assembler.subu(dest, dest, immTempRegister); + } + } + + void sub32(Imm32 imm, Address address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + lw dataTemp, offset(base) + li immTemp, imm + subu dataTemp, dataTemp, immTemp + sw dataTemp, offset(base) + */ + m_assembler.lw(dataTempRegister, address.base, address.offset); + if (!imm.m_isPointer + && imm.m_value >= -32767 && imm.m_value <= 32768 + && !m_fixedWidth) + m_assembler.addiu(dataTempRegister, dataTempRegister, + -imm.m_value); + else { + move(imm, immTempRegister); + m_assembler.subu(dataTempRegister, dataTempRegister, + immTempRegister); + } + m_assembler.sw(dataTempRegister, address.base, address.offset); + } else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + lw dataTemp, (offset & 0xffff)(addrTemp) + li immtemp, imm + subu dataTemp, dataTemp, immTemp + sw dataTemp, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lw(dataTempRegister, addrTempRegister, address.offset); + + if (!imm.m_isPointer + && imm.m_value >= -32767 && imm.m_value <= 32768 + && !m_fixedWidth) + m_assembler.addiu(dataTempRegister, dataTempRegister, + -imm.m_value); + else { + move(imm, immTempRegister); + m_assembler.subu(dataTempRegister, dataTempRegister, + immTempRegister); + } + m_assembler.sw(dataTempRegister, addrTempRegister, address.offset); + } + } + + void sub32(Address src, RegisterID dest) + { + load32(src, dataTempRegister); + sub32(dataTempRegister, dest); + } + + void sub32(Imm32 imm, AbsoluteAddress address) + { + /* + li addrTemp, address + li immTemp, imm + lw dataTemp, 0(addrTemp) + subu dataTemp, dataTemp, immTemp + sw dataTemp, 0(addrTemp) + */ + move(ImmPtr(address.m_ptr), addrTempRegister); + m_assembler.lw(dataTempRegister, addrTempRegister, 0); + + if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 + && !m_fixedWidth) { + m_assembler.addiu(dataTempRegister, dataTempRegister, + -imm.m_value); + } else { + move(imm, immTempRegister); + m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister); + } + m_assembler.sw(dataTempRegister, addrTempRegister, 0); + } + + void xor32(RegisterID src, RegisterID dest) + { + m_assembler.xorInsn(dest, dest, src); + } + + void xor32(Imm32 imm, RegisterID dest) + { + /* + li immTemp, imm + xor dest, dest, immTemp + */ + move(imm, immTempRegister); + m_assembler.xorInsn(dest, dest, immTempRegister); + } + + // Memory access operations: + // + // Loads are of the form load(address, destination) and stores of the form + // store(source, address). The source for a store may be an Imm32. Address + // operand objects to loads and store will be implicitly constructed if a + // register is passed. + + /* Need to use zero-extened load byte for load8. */ + void load8(ImplicitAddress address, RegisterID dest) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) + m_assembler.lbu(dest, address.base, address.offset); + else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + lbu dest, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lbu(dest, addrTempRegister, address.offset); + } + } + + void load32(ImplicitAddress address, RegisterID dest) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) + m_assembler.lw(dest, address.base, address.offset); + else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + lw dest, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lw(dest, addrTempRegister, address.offset); + } + } + + void load32(BaseIndex address, RegisterID dest) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lw dest, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lw(dest, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + lw dest, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, + immTempRegister); + m_assembler.lw(dest, addrTempRegister, address.offset); + } + } + + void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) + { + if (address.offset >= -32768 && address.offset <= 32764 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + (Big-Endian) + lwl dest, address.offset(addrTemp) + lwr dest, address.offset+3(addrTemp) + (Little-Endian) + lwl dest, address.offset+3(addrTemp) + lwr dest, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); +#if CPU(BIG_ENDIAN) + m_assembler.lwl(dest, addrTempRegister, address.offset); + m_assembler.lwr(dest, addrTempRegister, address.offset + 3); +#else + m_assembler.lwl(dest, addrTempRegister, address.offset + 3); + m_assembler.lwr(dest, addrTempRegister, address.offset); + +#endif + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, address.offset >> 16 + ori immTemp, immTemp, address.offset & 0xffff + addu addrTemp, addrTemp, immTemp + (Big-Endian) + lw dest, 0(at) + lw dest, 3(at) + (Little-Endian) + lw dest, 3(at) + lw dest, 0(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, address.offset >> 16); + m_assembler.ori(immTempRegister, immTempRegister, address.offset); + m_assembler.addu(addrTempRegister, addrTempRegister, + immTempRegister); +#if CPU(BIG_ENDIAN) + m_assembler.lwl(dest, addrTempRegister, 0); + m_assembler.lwr(dest, addrTempRegister, 3); +#else + m_assembler.lwl(dest, addrTempRegister, 3); + m_assembler.lwr(dest, addrTempRegister, 0); +#endif + } + } + + void load32(void* address, RegisterID dest) + { + /* + li addrTemp, address + lw dest, 0(addrTemp) + */ + move(ImmPtr(address), addrTempRegister); + m_assembler.lw(dest, addrTempRegister, 0); + } + + DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) + { + m_fixedWidth = true; + /* + lui addrTemp, address.offset >> 16 + ori addrTemp, addrTemp, address.offset & 0xffff + addu addrTemp, addrTemp, address.base + lw dest, 0(addrTemp) + */ + DataLabel32 dataLabel(this); + move(Imm32(address.offset), addrTempRegister); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lw(dest, addrTempRegister, 0); + m_fixedWidth = false; + return dataLabel; + } + + Label loadPtrWithPatchToLEA(Address address, RegisterID dest) + { + m_fixedWidth = true; + /* + lui addrTemp, address.offset >> 16 + ori addrTemp, addrTemp, address.offset & 0xffff + addu addrTemp, addrTemp, address.base + lw dest, 0(addrTemp) + */ + Label label(this); + move(Imm32(address.offset), addrTempRegister); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lw(dest, addrTempRegister, 0); + m_fixedWidth = false; + return label; + } + + Label loadPtrWithAddressOffsetPatch(Address address, RegisterID dest) + { + return loadPtrWithPatchToLEA(address, dest); + } + + /* Need to use zero-extened load half-word for load16. */ + void load16(BaseIndex address, RegisterID dest) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lhu dest, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lhu(dest, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + lhu dest, (address.offset & 0xffff)(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, + immTempRegister); + m_assembler.lhu(dest, addrTempRegister, address.offset); + } + } + + DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) + { + m_fixedWidth = true; + /* + lui addrTemp, address.offset >> 16 + ori addrTemp, addrTemp, address.offset & 0xffff + addu addrTemp, addrTemp, address.base + sw src, 0(addrTemp) + */ + DataLabel32 dataLabel(this); + move(Imm32(address.offset), addrTempRegister); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sw(src, addrTempRegister, 0); + m_fixedWidth = false; + return dataLabel; + } + + void store32(RegisterID src, ImplicitAddress address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) + m_assembler.sw(src, address.base, address.offset); + else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + sw src, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sw(src, addrTempRegister, address.offset); + } + } + + void store32(RegisterID src, BaseIndex address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + sw src, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sw(src, addrTempRegister, address.offset); + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + sw src, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, + immTempRegister); + m_assembler.sw(src, addrTempRegister, address.offset); + } + } + + void store32(Imm32 imm, ImplicitAddress address) + { + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + if (!imm.m_isPointer && !imm.m_value) + m_assembler.sw(MIPSRegisters::zero, address.base, + address.offset); + else { + move(imm, immTempRegister); + m_assembler.sw(immTempRegister, address.base, address.offset); + } + } else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + sw immTemp, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + m_assembler.sw(MIPSRegisters::zero, addrTempRegister, + address.offset); + else { + move(imm, immTempRegister); + m_assembler.sw(immTempRegister, addrTempRegister, + address.offset); + } + } + } + + void store32(RegisterID src, void* address) + { + /* + li addrTemp, address + sw src, 0(addrTemp) + */ + move(ImmPtr(address), addrTempRegister); + m_assembler.sw(src, addrTempRegister, 0); + } + + void store32(Imm32 imm, void* address) + { + /* + li immTemp, imm + li addrTemp, address + sw src, 0(addrTemp) + */ + if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) { + move(ImmPtr(address), addrTempRegister); + m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0); + } else { + move(imm, immTempRegister); + move(ImmPtr(address), addrTempRegister); + m_assembler.sw(immTempRegister, addrTempRegister, 0); + } + } + + // Floating-point operations: + + bool supportsFloatingPoint() const + { +#if WTF_MIPS_DOUBLE_FLOAT + return true; +#else + return false; +#endif + } + + bool supportsFloatingPointTruncate() const + { +#if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2) + return true; +#else + return false; +#endif + } + + // Stack manipulation operations: + // + // The ABI is assumed to provide a stack abstraction to memory, + // containing machine word sized units of data. Push and pop + // operations add and remove a single register sized unit of data + // to or from the stack. Peek and poke operations read or write + // values on the stack, without moving the current stack position. + + void pop(RegisterID dest) + { + m_assembler.lw(dest, MIPSRegisters::sp, 0); + m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 4); + } + + void push(RegisterID src) + { + m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -4); + m_assembler.sw(src, MIPSRegisters::sp, 0); + } + + void push(Address address) + { + load32(address, dataTempRegister); + push(dataTempRegister); + } + + void push(Imm32 imm) + { + move(imm, immTempRegister); + push(immTempRegister); + } + + // Register move operations: + // + // Move values in registers. + + void move(Imm32 imm, RegisterID dest) + { + if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + move(MIPSRegisters::zero, dest); + else if (imm.m_isPointer || m_fixedWidth) { + m_assembler.lui(dest, imm.m_value >> 16); + m_assembler.ori(dest, dest, imm.m_value); + } else + m_assembler.li(dest, imm.m_value); + } + + void move(RegisterID src, RegisterID dest) + { + if (src != dest || m_fixedWidth) + m_assembler.move(dest, src); + } + + void move(ImmPtr imm, RegisterID dest) + { + move(Imm32(imm), dest); + } + + void swap(RegisterID reg1, RegisterID reg2) + { + move(reg1, immTempRegister); + move(reg2, reg1); + move(immTempRegister, reg2); + } + + void signExtend32ToPtr(RegisterID src, RegisterID dest) + { + if (src != dest || m_fixedWidth) + move(src, dest); + } + + void zeroExtend32ToPtr(RegisterID src, RegisterID dest) + { + if (src != dest || m_fixedWidth) + move(src, dest); + } + + // Forwards / external control flow operations: + // + // This set of jump and conditional branch operations return a Jump + // object which may linked at a later point, allow forwards jump, + // or jumps that will require external linkage (after the code has been + // relocated). + // + // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge + // respecitvely, for unsigned comparisons the names b, a, be, and ae are + // used (representing the names 'below' and 'above'). + // + // Operands to the comparision are provided in the expected order, e.g. + // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when + // treated as a signed 32bit value, is less than or equal to 5. + // + // jz and jnz test whether the first operand is equal to zero, and take + // an optional second operand of a mask under which to perform the test. + + Jump branch8(Condition cond, Address left, Imm32 right) + { + // Make sure the immediate value is unsigned 8 bits. + ASSERT(!(right.m_value & 0xFFFFFF00)); + load8(left, dataTempRegister); + move(right, immTempRegister); + return branch32(cond, dataTempRegister, immTempRegister); + } + + Jump branch32(Condition cond, RegisterID left, RegisterID right) + { + if (cond == Equal || cond == Zero) + return branchEqual(left, right); + if (cond == NotEqual || cond == NonZero) + return branchNotEqual(left, right); + if (cond == Above) { + m_assembler.sltu(cmpTempRegister, right, left); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == AboveOrEqual) { + m_assembler.sltu(cmpTempRegister, left, right); + return branchEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Below) { + m_assembler.sltu(cmpTempRegister, left, right); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == BelowOrEqual) { + m_assembler.sltu(cmpTempRegister, right, left); + return branchEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == GreaterThan) { + m_assembler.slt(cmpTempRegister, right, left); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == GreaterThanOrEqual) { + m_assembler.slt(cmpTempRegister, left, right); + return branchEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == LessThan) { + m_assembler.slt(cmpTempRegister, left, right); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == LessThanOrEqual) { + m_assembler.slt(cmpTempRegister, right, left); + return branchEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Overflow) { + /* + xor cmpTemp, left, right + bgez No_overflow, cmpTemp # same sign bit -> no overflow + nop + subu cmpTemp, left, right + xor cmpTemp, cmpTemp, left + bgez No_overflow, cmpTemp # same sign bit -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + m_assembler.xorInsn(cmpTempRegister, left, right); + m_assembler.bgez(cmpTempRegister, 11); + m_assembler.nop(); + m_assembler.subu(cmpTempRegister, left, right); + m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + m_assembler.subu(cmpTempRegister, left, right); + // Check if the result is negative. + m_assembler.slt(cmpTempRegister, cmpTempRegister, + MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + ASSERT(0); + + return Jump(); + } + + Jump branch32(Condition cond, RegisterID left, Imm32 right) + { + move(right, immTempRegister); + return branch32(cond, left, immTempRegister); + } + + Jump branch32(Condition cond, RegisterID left, Address right) + { + load32(right, dataTempRegister); + return branch32(cond, left, dataTempRegister); + } + + Jump branch32(Condition cond, Address left, RegisterID right) + { + load32(left, dataTempRegister); + return branch32(cond, dataTempRegister, right); + } + + Jump branch32(Condition cond, Address left, Imm32 right) + { + load32(left, dataTempRegister); + move(right, immTempRegister); + return branch32(cond, dataTempRegister, immTempRegister); + } + + Jump branch32(Condition cond, BaseIndex left, Imm32 right) + { + load32(left, dataTempRegister); + // Be careful that the previous load32() uses immTempRegister. + // So, we need to put move() after load32(). + move(right, immTempRegister); + return branch32(cond, dataTempRegister, immTempRegister); + } + + Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right) + { + load32WithUnalignedHalfWords(left, dataTempRegister); + // Be careful that the previous load32WithUnalignedHalfWords() + // uses immTempRegister. + // So, we need to put move() after load32WithUnalignedHalfWords(). + move(right, immTempRegister); + return branch32(cond, dataTempRegister, immTempRegister); + } + + Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right) + { + load32(left.m_ptr, dataTempRegister); + return branch32(cond, dataTempRegister, right); + } + + Jump branch32(Condition cond, AbsoluteAddress left, Imm32 right) + { + load32(left.m_ptr, dataTempRegister); + move(right, immTempRegister); + return branch32(cond, dataTempRegister, immTempRegister); + } + + Jump branch16(Condition cond, BaseIndex left, RegisterID right) + { + load16(left, dataTempRegister); + return branch32(cond, dataTempRegister, right); + } + + Jump branch16(Condition cond, BaseIndex left, Imm32 right) + { + ASSERT(!(right.m_value & 0xFFFF0000)); + load16(left, dataTempRegister); + // Be careful that the previous load16() uses immTempRegister. + // So, we need to put move() after load16(). + move(right, immTempRegister); + return branch32(cond, dataTempRegister, immTempRegister); + } + + Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask) + { + ASSERT((cond == Zero) || (cond == NonZero)); + m_assembler.andInsn(cmpTempRegister, reg, mask); + if (cond == Zero) + return branchEqual(cmpTempRegister, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + + Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1)) + { + ASSERT((cond == Zero) || (cond == NonZero)); + if (mask.m_value == -1 && !m_fixedWidth) { + if (cond == Zero) + return branchEqual(reg, MIPSRegisters::zero); + return branchNotEqual(reg, MIPSRegisters::zero); + } + move(mask, immTempRegister); + return branchTest32(cond, reg, immTempRegister); + } + + Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1)) + { + load32(address, dataTempRegister); + return branchTest32(cond, dataTempRegister, mask); + } + + Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + { + load32(address, dataTempRegister); + return branchTest32(cond, dataTempRegister, mask); + } + + Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1)) + { + load8(address, dataTempRegister); + return branchTest32(cond, dataTempRegister, mask); + } + + Jump jump() + { + return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero); + } + + void jump(RegisterID target) + { + m_assembler.jr(target); + m_assembler.nop(); + } + + void jump(Address address) + { + m_fixedWidth = true; + load32(address, MIPSRegisters::t9); + m_assembler.jr(MIPSRegisters::t9); + m_assembler.nop(); + m_fixedWidth = false; + } + + // Arithmetic control flow operations: + // + // This set of conditional branch operations branch based + // on the result of an arithmetic operation. The operation + // is performed as normal, storing the result. + // + // * jz operations branch if the result is zero. + // * jo operations branch if the (signed) arithmetic + // operation caused an overflow to occur. + + Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + move dest, dataTemp + xor cmpTemp, dataTemp, src + bltz cmpTemp, No_overflow # diff sign bit -> no overflow + addu dest, dataTemp, src + xor cmpTemp, dest, dataTemp + bgez cmpTemp, No_overflow # same sign big -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + move(dest, dataTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src); + m_assembler.bltz(cmpTempRegister, 10); + m_assembler.addu(dest, dataTempRegister, src); + m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + add32(src, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + add32(src, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + add32(src, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + + Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + return branchAdd32(cond, immTempRegister, dest); + } + + Jump branchMul32(Condition cond, RegisterID src, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + mult src, dest + mfhi dataTemp + mflo dest + sra addrTemp, dest, 31 + beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + m_assembler.mult(src, dest); + m_assembler.mfhi(dataTempRegister); + m_assembler.mflo(dest); + m_assembler.sra(addrTempRegister, dest, 31); + m_assembler.beq(dataTempRegister, addrTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + mul32(src, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + mul32(src, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + mul32(src, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + + Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest) + { + move(imm, immTempRegister); + move(src, dest); + return branchMul32(cond, immTempRegister, dest); + } + + Jump branchSub32(Condition cond, RegisterID src, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + move dest, dataTemp + xor cmpTemp, dataTemp, src + bgez cmpTemp, No_overflow # same sign bit -> no overflow + subu dest, dataTemp, src + xor cmpTemp, dest, dataTemp + bgez cmpTemp, No_overflow # same sign bit -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + move(dest, dataTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src); + m_assembler.bgez(cmpTempRegister, 10); + m_assembler.subu(dest, dataTempRegister, src); + m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + sub32(src, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + sub32(src, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + sub32(src, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + + Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + return branchSub32(cond, immTempRegister, dest); + } + + // Miscellaneous operations: + + void breakpoint() + { + m_assembler.bkpt(); + } + + Call nearCall() + { + /* We need two words for relaxation. */ + m_assembler.nop(); + m_assembler.nop(); + m_assembler.jal(); + m_assembler.nop(); + return Call(m_assembler.newJmpSrc(), Call::LinkableNear); + } + + Call call() + { + m_assembler.lui(MIPSRegisters::t9, 0); + m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0); + m_assembler.jalr(MIPSRegisters::t9); + m_assembler.nop(); + return Call(m_assembler.newJmpSrc(), Call::Linkable); + } + + Call call(RegisterID target) + { + m_assembler.jalr(target); + m_assembler.nop(); + return Call(m_assembler.newJmpSrc(), Call::None); + } + + Call call(Address address) + { + m_fixedWidth = true; + load32(address, MIPSRegisters::t9); + m_assembler.jalr(MIPSRegisters::t9); + m_assembler.nop(); + m_fixedWidth = false; + return Call(m_assembler.newJmpSrc(), Call::None); + } + + void ret() + { + m_assembler.jr(MIPSRegisters::ra); + m_assembler.nop(); + } + + void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest) + { + if (cond == Equal || cond == Zero) { + m_assembler.xorInsn(dest, left, right); + m_assembler.sltiu(dest, dest, 1); + } else if (cond == NotEqual || cond == NonZero) { + m_assembler.xorInsn(dest, left, right); + m_assembler.sltu(dest, MIPSRegisters::zero, dest); + } else if (cond == Above) + m_assembler.sltu(dest, right, left); + else if (cond == AboveOrEqual) { + m_assembler.sltu(dest, left, right); + m_assembler.xori(dest, dest, 1); + } else if (cond == Below) + m_assembler.sltu(dest, left, right); + else if (cond == BelowOrEqual) { + m_assembler.sltu(dest, right, left); + m_assembler.xori(dest, dest, 1); + } else if (cond == GreaterThan) + m_assembler.slt(dest, right, left); + else if (cond == GreaterThanOrEqual) { + m_assembler.slt(dest, left, right); + m_assembler.xori(dest, dest, 1); + } else if (cond == LessThan) + m_assembler.slt(dest, left, right); + else if (cond == LessThanOrEqual) { + m_assembler.slt(dest, right, left); + m_assembler.xori(dest, dest, 1); + } else if (cond == Overflow) { + /* + xor cmpTemp, left, right + bgez Done, cmpTemp # same sign bit -> no overflow + move dest, 0 + subu cmpTemp, left, right + xor cmpTemp, cmpTemp, left # diff sign bit -> overflow + slt dest, cmpTemp, 0 + Done: + */ + m_assembler.xorInsn(cmpTempRegister, left, right); + m_assembler.bgez(cmpTempRegister, 4); + m_assembler.move(dest, MIPSRegisters::zero); + m_assembler.subu(cmpTempRegister, left, right); + m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left); + m_assembler.slt(dest, cmpTempRegister, MIPSRegisters::zero); + } else if (cond == Signed) { + m_assembler.subu(dest, left, right); + // Check if the result is negative. + m_assembler.slt(dest, dest, MIPSRegisters::zero); + } + } + + void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest) + { + move(right, immTempRegister); + set32(cond, left, immTempRegister, dest); + } + + void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest) + { + ASSERT((cond == Zero) || (cond == NonZero)); + load8(address, dataTempRegister); + if (mask.m_value == -1 && !m_fixedWidth) { + if (cond == Zero) + m_assembler.sltiu(dest, dataTempRegister, 1); + else + m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister); + } else { + move(mask, immTempRegister); + m_assembler.andInsn(cmpTempRegister, dataTempRegister, + immTempRegister); + if (cond == Zero) + m_assembler.sltiu(dest, cmpTempRegister, 1); + else + m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister); + } + } + + void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest) + { + ASSERT((cond == Zero) || (cond == NonZero)); + load32(address, dataTempRegister); + if (mask.m_value == -1 && !m_fixedWidth) { + if (cond == Zero) + m_assembler.sltiu(dest, dataTempRegister, 1); + else + m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister); + } else { + move(mask, immTempRegister); + m_assembler.andInsn(cmpTempRegister, dataTempRegister, + immTempRegister); + if (cond == Zero) + m_assembler.sltiu(dest, cmpTempRegister, 1); + else + m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister); + } + } + + DataLabel32 moveWithPatch(Imm32 imm, RegisterID dest) + { + m_fixedWidth = true; + DataLabel32 label(this); + move(imm, dest); + m_fixedWidth = false; + return label; + } + + DataLabelPtr moveWithPatch(ImmPtr initialValue, RegisterID dest) + { + m_fixedWidth = true; + DataLabelPtr label(this); + move(initialValue, dest); + m_fixedWidth = false; + return label; + } + + Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + { + m_fixedWidth = true; + dataLabel = moveWithPatch(initialRightValue, immTempRegister); + Jump temp = branch32(cond, left, immTempRegister); + m_fixedWidth = false; + return temp; + } + + Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0)) + { + m_fixedWidth = true; + load32(left, dataTempRegister); + dataLabel = moveWithPatch(initialRightValue, immTempRegister); + Jump temp = branch32(cond, dataTempRegister, immTempRegister); + m_fixedWidth = false; + return temp; + } + + DataLabelPtr storePtrWithPatch(ImmPtr initialValue, ImplicitAddress address) + { + m_fixedWidth = true; + DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister); + store32(dataTempRegister, address); + m_fixedWidth = false; + return dataLabel; + } + + DataLabelPtr storePtrWithPatch(ImplicitAddress address) + { + return storePtrWithPatch(ImmPtr(0), address); + } + + Call tailRecursiveCall() + { + // Like a normal call, but don't update the returned address register + m_fixedWidth = true; + move(Imm32(0), MIPSRegisters::t9); + m_assembler.jr(MIPSRegisters::t9); + m_assembler.nop(); + m_fixedWidth = false; + return Call(m_assembler.newJmpSrc(), Call::Linkable); + } + + Call makeTailRecursiveCall(Jump oldJump) + { + oldJump.link(this); + return tailRecursiveCall(); + } + + void loadDouble(ImplicitAddress address, FPRegisterID dest) + { +#if WTF_MIPS_ISA(1) + /* + li addrTemp, address.offset + addu addrTemp, addrTemp, base + lwc1 dest, 0(addrTemp) + lwc1 dest+1, 4(addrTemp) + */ + move(Imm32(address.offset), addrTempRegister); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lwc1(dest, addrTempRegister, 0); + m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4); +#else + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) { + m_assembler.ldc1(dest, address.base, address.offset); + } else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + ldc1 dest, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.ldc1(dest, addrTempRegister, address.offset); + } +#endif + } + + void storeDouble(FPRegisterID src, ImplicitAddress address) + { +#if WTF_MIPS_ISA(1) + /* + li addrTemp, address.offset + addu addrTemp, addrTemp, base + swc1 dest, 0(addrTemp) + swc1 dest+1, 4(addrTemp) + */ + move(Imm32(address.offset), addrTempRegister); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.swc1(src, addrTempRegister, 0); + m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4); +#else + if (address.offset >= -32768 && address.offset <= 32767 + && !m_fixedWidth) + m_assembler.sdc1(src, address.base, address.offset); + else { + /* + lui addrTemp, (offset + 0x8000) >> 16 + addu addrTemp, addrTemp, base + sdc1 src, (offset & 0xffff)(addrTemp) + */ + m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.sdc1(src, addrTempRegister, address.offset); + } +#endif + } + + void addDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.addd(dest, dest, src); + } + + void addDouble(Address src, FPRegisterID dest) + { + loadDouble(src, fpTempRegister); + m_assembler.addd(dest, dest, fpTempRegister); + } + + void subDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.subd(dest, dest, src); + } + + void subDouble(Address src, FPRegisterID dest) + { + loadDouble(src, fpTempRegister); + m_assembler.subd(dest, dest, fpTempRegister); + } + + void mulDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.muld(dest, dest, src); + } + + void mulDouble(Address src, FPRegisterID dest) + { + loadDouble(src, fpTempRegister); + m_assembler.muld(dest, dest, fpTempRegister); + } + + void convertInt32ToDouble(RegisterID src, FPRegisterID dest) + { + m_assembler.mtc1(src, fpTempRegister); + m_assembler.cvtdw(dest, fpTempRegister); + } + + void insertRelaxationWords() + { + /* We need four words for relaxation. */ + m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 3); // Jump over nops; + m_assembler.nop(); + m_assembler.nop(); + m_assembler.nop(); + } + + Jump branchTrue() + { + m_assembler.appendJump(); + m_assembler.bc1t(); + m_assembler.nop(); + insertRelaxationWords(); + return Jump(m_assembler.newJmpSrc()); + } + + Jump branchFalse() + { + m_assembler.appendJump(); + m_assembler.bc1f(); + m_assembler.nop(); + insertRelaxationWords(); + return Jump(m_assembler.newJmpSrc()); + } + + Jump branchEqual(RegisterID rs, RegisterID rt) + { + m_assembler.appendJump(); + m_assembler.beq(rs, rt, 0); + m_assembler.nop(); + insertRelaxationWords(); + return Jump(m_assembler.newJmpSrc()); + } + + Jump branchNotEqual(RegisterID rs, RegisterID rt) + { + m_assembler.appendJump(); + m_assembler.bne(rs, rt, 0); + m_assembler.nop(); + insertRelaxationWords(); + return Jump(m_assembler.newJmpSrc()); + } + + Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) + { + if (cond == DoubleEqual) { + m_assembler.ceqd(left, right); + return branchTrue(); + } + if (cond == DoubleNotEqual) { + m_assembler.ceqd(left, right); + return branchFalse(); // false + } + if (cond == DoubleGreaterThan) { + m_assembler.cngtd(left, right); + return branchFalse(); // false + } + if (cond == DoubleGreaterThanOrEqual) { + m_assembler.cnged(right, left); + return branchFalse(); // false + } + if (cond == DoubleLessThan) { + m_assembler.cltd(left, right); + return branchTrue(); + } + if (cond == DoubleLessThanOrEqual) { + m_assembler.cled(left, right); + return branchTrue(); + } + if (cond == DoubleEqualOrUnordered) { + m_assembler.cueqd(left, right); + return branchTrue(); + } + if (cond == DoubleGreaterThanOrUnordered) { + m_assembler.coled(left, right); + return branchFalse(); // false + } + if (cond == DoubleGreaterThanOrEqualOrUnordered) { + m_assembler.coltd(left, right); + return branchFalse(); // false + } + if (cond == DoubleLessThanOrUnordered) { + m_assembler.cultd(left, right); + return branchTrue(); + } + if (cond == DoubleLessThanOrEqualOrUnordered) { + m_assembler.culed(left, right); + return branchTrue(); + } + ASSERT(0); + + return Jump(); + } + + // Truncates '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, INT_MAX 0x7fffffff). + Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) + { + m_assembler.truncwd(fpTempRegister, src); + m_assembler.mfc1(dest, fpTempRegister); + return branch32(Equal, dest, Imm32(0x7fffffff)); + } + +private: + // If m_fixedWidth is true, we will generate a fixed number of instructions. + // Otherwise, we can emit any number of instructions. + bool m_fixedWidth; + + friend class LinkBuffer; + friend class RepatchBuffer; + + static void linkCall(void* code, Call call, FunctionPtr function) + { + MIPSAssembler::linkCall(code, call.m_jmp, function.value()); + } + + static void repatchCall(CodeLocationCall call, CodeLocationLabel destination) + { + MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress()); + } + + static void repatchCall(CodeLocationCall call, FunctionPtr destination) + { + MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress()); + } + +}; + +} + +#endif // ENABLE(ASSEMBLER) && CPU(MIPS) + +#endif // MacroAssemblerMIPS_h diff --git a/JavaScriptCore/assembler/MacroAssemblerX86.h b/JavaScriptCore/assembler/MacroAssemblerX86.h index ca7c31a..0366541 100644 --- a/JavaScriptCore/assembler/MacroAssemblerX86.h +++ b/JavaScriptCore/assembler/MacroAssemblerX86.h @@ -26,8 +26,6 @@ #ifndef MacroAssemblerX86_h #define MacroAssemblerX86_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) && CPU(X86) #include "MacroAssemblerX86Common.h" diff --git a/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/JavaScriptCore/assembler/MacroAssemblerX86Common.h index 449df86..27c2f15 100644 --- a/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -26,8 +26,6 @@ #ifndef MacroAssemblerX86Common_h #define MacroAssemblerX86Common_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) #include "X86Assembler.h" @@ -620,6 +618,12 @@ public: // an optional second operand of a mask under which to perform the test. public: + Jump branch8(Condition cond, Address left, Imm32 right) + { + m_assembler.cmpb_im(right.m_value, left.offset, left.base); + return Jump(m_assembler.jCC(x86Condition(cond))); + } + Jump branch32(Condition cond, RegisterID left, RegisterID right) { m_assembler.cmpl_rr(right, left); @@ -717,6 +721,26 @@ public: m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale); return Jump(m_assembler.jCC(x86Condition(cond))); } + + Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1)) + { + ASSERT((cond == Zero) || (cond == NonZero)); + if (mask.m_value == -1) + m_assembler.cmpb_im(0, address.offset, address.base); + else + m_assembler.testb_im(mask.m_value, address.offset, address.base); + return Jump(m_assembler.jCC(x86Condition(cond))); + } + + Jump branchTest8(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1)) + { + ASSERT((cond == Zero) || (cond == NonZero)); + if (mask.m_value == -1) + m_assembler.cmpb_im(0, address.offset, address.base, address.index, address.scale); + else + m_assembler.testb_im(mask.m_value, address.offset, address.base, address.index, address.scale); + return Jump(m_assembler.jCC(x86Condition(cond))); + } Jump jump() { @@ -836,6 +860,13 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } + Jump branchNeg32(Condition cond, RegisterID srcDest) + { + ASSERT((cond == Overflow) || (cond == Zero) || (cond == NonZero)); + neg32(srcDest); + return Jump(m_assembler.jCC(x86Condition(cond))); + } + Jump branchOr32(Condition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -917,10 +948,11 @@ public: void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest) { if (mask.m_value == -1) - m_assembler.cmpl_im(0, address.offset, address.base); + m_assembler.cmpb_im(0, address.offset, address.base); else - m_assembler.testl_i32m(mask.m_value, address.offset, address.base); + m_assembler.testb_im(mask.m_value, address.offset, address.base); m_assembler.setCC_r(x86Condition(cond), dest); + m_assembler.movzbl_rr(dest, dest); } void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest) diff --git a/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/JavaScriptCore/assembler/MacroAssemblerX86_64.h index ec93f8c..339eaa4 100644 --- a/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -26,8 +26,6 @@ #ifndef MacroAssemblerX86_64_h #define MacroAssemblerX86_64_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) && CPU(X86_64) #include "MacroAssemblerX86Common.h" @@ -411,6 +409,14 @@ public: return label; } + using MacroAssemblerX86Common::branchTest8; + Jump branchTest8(Condition cond, ExtendedAddress address, Imm32 mask = Imm32(-1)) + { + ImmPtr addr(reinterpret_cast<void*>(address.offset)); + MacroAssemblerX86Common::move(addr, scratchRegister); + return MacroAssemblerX86Common::branchTest8(cond, BaseIndex(scratchRegister, address.base, TimesOne), mask); + } + Label loadPtrWithPatchToLEA(Address address, RegisterID dest) { Label label(this); diff --git a/JavaScriptCore/assembler/RepatchBuffer.h b/JavaScriptCore/assembler/RepatchBuffer.h index 89cbf06..72cf6b2 100644 --- a/JavaScriptCore/assembler/RepatchBuffer.h +++ b/JavaScriptCore/assembler/RepatchBuffer.h @@ -26,8 +26,6 @@ #ifndef RepatchBuffer_h #define RepatchBuffer_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) #include <MacroAssembler.h> diff --git a/JavaScriptCore/assembler/X86Assembler.h b/JavaScriptCore/assembler/X86Assembler.h index ab3d05f..14a02f7 100644 --- a/JavaScriptCore/assembler/X86Assembler.h +++ b/JavaScriptCore/assembler/X86Assembler.h @@ -26,8 +26,6 @@ #ifndef X86Assembler_h #define X86Assembler_h -#include <wtf/Platform.h> - #if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64)) #include "AssemblerBuffer.h" @@ -130,6 +128,7 @@ private: PRE_SSE_66 = 0x66, OP_PUSH_Iz = 0x68, OP_IMUL_GvEvIz = 0x69, + OP_GROUP1_EbIb = 0x80, OP_GROUP1_EvIz = 0x81, OP_GROUP1_EvIb = 0x83, OP_TEST_EvGv = 0x85, @@ -760,7 +759,7 @@ public: m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst); m_formatter.immediate32(imm); } - + void cmpl_im(int imm, int offset, RegisterID base) { if (CAN_SIGN_EXTEND_8_32(imm)) { @@ -771,6 +770,18 @@ public: m_formatter.immediate32(imm); } } + + void cmpb_im(int imm, int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, offset); + m_formatter.immediate8(imm); + } + + void cmpb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) + { + m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, index, scale, offset); + m_formatter.immediate8(imm); + } void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale) { @@ -890,6 +901,18 @@ public: m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset); m_formatter.immediate32(imm); } + + void testb_im(int imm, int offset, RegisterID base) + { + m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, offset); + m_formatter.immediate8(imm); + } + + void testb_im(int imm, int offset, RegisterID base, RegisterID index, int scale) + { + m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, index, scale, offset); + m_formatter.immediate8(imm); + } void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale) { diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp index 68debb2..8e77e12 100644 --- a/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/JavaScriptCore/bytecode/CodeBlock.cpp @@ -89,25 +89,6 @@ CString CodeBlock::registerName(ExecState* exec, int r) const return makeString("r", UString::from(r)).UTF8String(); } -static UString regexpToSourceString(RegExp* regExp) -{ - char postfix[5] = { '/', 0, 0, 0, 0 }; - int index = 1; - if (regExp->global()) - postfix[index++] = 'g'; - if (regExp->ignoreCase()) - postfix[index++] = 'i'; - if (regExp->multiline()) - postfix[index] = 'm'; - - return makeString("/", regExp->pattern(), postfix); -} - -static CString regexpName(int re, RegExp* regexp) -{ - return makeString(regexpToSourceString(regexp), "(@re", UString::from(re), ")").UTF8String(); -} - static UString pointerToSourceString(void* p) { char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0 @@ -141,7 +122,7 @@ void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>: int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).c_str(), registerName(exec, r1).c_str()); + printf("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data()); } void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const @@ -149,14 +130,14 @@ void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction> 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(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str()); + printf("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); } 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(exec, r0).c_str(), offset, location + offset); + printf("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).data(), offset, location + offset); } void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const @@ -164,7 +145,7 @@ void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction 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(exec, r0).c_str(), registerName(exec, r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); it += 4; } @@ -173,7 +154,7 @@ void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction 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(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str()); + printf("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); it += 4; } @@ -223,32 +204,32 @@ static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instructio static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset) { - printf(" [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).UTF8String().c_str()); + printf(" [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).UTF8String().data()); } static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset) { switch (stubInfo.accessType) { case access_get_by_id_self: - printf(" [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().c_str()); + printf(" [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().data()); return; case access_get_by_id_proto: - printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().c_str()); + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().data(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().data()); return; case access_get_by_id_chain: - printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().c_str()); + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().data(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().data()); return; case access_get_by_id_self_list: - printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().c_str(), stubInfo.u.getByIdSelfList.listSize); + printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().data(), stubInfo.u.getByIdSelfList.listSize); return; case access_get_by_id_proto_list: - printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().c_str(), stubInfo.u.getByIdProtoList.listSize); + printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().data(), stubInfo.u.getByIdProtoList.listSize); return; case access_put_by_id_transition: - printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().c_str()); + printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().data(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().data(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().data()); return; case access_put_by_id_replace: - printf(" [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().c_str()); + printf(" [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().data()); return; case access_get_by_id: printf(" [%4d] %s\n", instructionOffset, "get_by_id"); @@ -277,7 +258,7 @@ static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned i void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const { unsigned instructionOffset = vPC - m_instructions.begin(); - printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().c_str()); + printf(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).UTF8String().data()); } void CodeBlock::printStructures(const Instruction* vPC) const @@ -294,15 +275,15 @@ void CodeBlock::printStructures(const Instruction* vPC) const return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) { - printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str()); + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structure).UTF8String().data()); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) { - printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str()); + printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structure).UTF8String().data(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().data()); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) { - printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().c_str()); + printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(vPC[4].u.structure).UTF8String().data(), pointerToSourceString(vPC[5].u.structureChain).UTF8String().data()); return; } if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id)) { @@ -364,15 +345,6 @@ void CodeBlock::dump(ExecState* exec) const } while (i < m_constantRegisters.size()); } - if (m_rareData && !m_rareData->m_regexps.isEmpty()) { - printf("\nm_regexps:\n"); - size_t i = 0; - do { - printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).ascii()); - ++i; - } while (i < m_rareData->m_regexps.size()); - } - #if ENABLE(JIT) if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty()) printf("\nStructures:\n"); @@ -482,7 +454,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(exec, r0).c_str()); + printf("[%4d] enter_with_activation %s\n", location, registerName(exec, r0).data()); break; } case op_create_arguments: { @@ -495,31 +467,25 @@ 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(exec, r0).c_str()); + printf("[%4d] convert_this %s\n", location, registerName(exec, r0).data()); break; } case op_new_object: { int r0 = (++it)->u.operand; - printf("[%4d] new_object\t %s\n", location, registerName(exec, r0).c_str()); + printf("[%4d] new_object\t %s\n", location, registerName(exec, r0).data()); 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(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(exec, r0).c_str(), regexpName(re0, regexp(re0)).c_str()); + printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc); break; } case op_mov: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str()); + printf("[%4d] mov\t\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); break; } case op_not: { @@ -560,12 +526,12 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_pre_inc: { int r0 = (++it)->u.operand; - printf("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).c_str()); + printf("[%4d] pre_inc\t\t %s\n", location, registerName(exec, r0).data()); break; } case op_pre_dec: { int r0 = (++it)->u.operand; - printf("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).c_str()); + printf("[%4d] pre_dec\t\t %s\n", location, registerName(exec, r0).data()); break; } case op_post_inc: { @@ -644,7 +610,7 @@ 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(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str(), registerName(exec, r3).c_str()); + printf("[%4d] instanceof\t\t %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data()); break; } case op_typeof: { @@ -682,21 +648,21 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& case op_resolve: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - printf("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve\t\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); 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(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), skipLevels); + printf("[%4d] resolve_skip\t %s, %s, %d\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), 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(exec, 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).data(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).data()); it += 2; break; } @@ -704,41 +670,41 @@ 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(exec, r0).c_str(), index, skipLevels); + printf("[%4d] get_scoped_var\t %s, %d, %d\n", location, registerName(exec, r0).data(), 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(exec, r0).c_str()); + printf("[%4d] put_scoped_var\t %d, %d, %s\n", location, index, skipLevels, registerName(exec, r0).data()); 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(exec, r0).c_str(), valueToSourceString(exec, scope).ascii(), index); + printf("[%4d] get_global_var\t %s, %s, %d\n", location, registerName(exec, r0).data(), 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(exec, r0).c_str()); + printf("[%4d] put_global_var\t %s, %d, %s\n", location, valueToSourceString(exec, scope).ascii(), index, registerName(exec, r0).data()); 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(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve_base\t %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); 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(exec, r0).c_str(), registerName(exec, r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); break; } case op_get_by_id: { @@ -785,6 +751,26 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printGetByIdOp(exec, location, it, "get_by_id_getter_chain"); break; } + case op_get_by_id_custom_self: { + printGetByIdOp(exec, location, it, "get_by_id_custom_self"); + break; + } + case op_get_by_id_custom_self_list: { + printGetByIdOp(exec, location, it, "get_by_id_custom_self_list"); + break; + } + case op_get_by_id_custom_proto: { + printGetByIdOp(exec, location, it, "get_by_id_custom_proto"); + break; + } + case op_get_by_id_custom_proto_list: { + printGetByIdOp(exec, location, it, "get_by_id_custom_proto_list"); + break; + } + case op_get_by_id_custom_chain: { + printGetByIdOp(exec, location, it, "get_by_id_custom_chain"); + break; + } case op_get_by_id_generic: { printGetByIdOp(exec, location, it, "get_by_id_generic"); break; @@ -817,14 +803,14 @@ 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] 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()); + printf("[%4d] put_getter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); 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(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str()); + printf("[%4d] put_setter\t %s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); break; } case op_method_check: { @@ -835,14 +821,14 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& 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(exec, r0).c_str(), registerName(exec, r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); + printf("[%4d] del_by_id\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); 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(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str()); + printf("[%4d] get_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); break; } case op_get_by_pname: { @@ -852,28 +838,28 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& 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()); + printf("[%4d] get_by_pname\t %s, %s, %s, %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), registerName(exec, r4).data(), registerName(exec, r5).data()); 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(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str()); + printf("[%4d] put_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 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(exec, r0).c_str(), registerName(exec, r1).c_str(), registerName(exec, r2).c_str()); + printf("[%4d] del_by_val\t %s, %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data()); 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(exec, r0).c_str(), n0, registerName(exec, r1).c_str()); + printf("[%4d] put_by_index\t %s, %u, %s\n", location, registerName(exec, r0).data(), n0, registerName(exec, r1).data()); break; } case op_jmp: { @@ -914,75 +900,75 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& 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(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); + printf("[%4d] jneq_ptr\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), 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(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); + printf("[%4d] jnless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), 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(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); + printf("[%4d] jnlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), 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(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); + printf("[%4d] loop_if_less\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), 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); + printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), 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(exec, r0).c_str(), registerName(exec, r1).c_str(), offset, location + offset); + printf("[%4d] loop_if_lesseq\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), 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, location + defaultTarget, registerName(exec, scrutineeRegister).c_str()); + printf("[%4d] switch_imm\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); 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, location + defaultTarget, registerName(exec, scrutineeRegister).c_str()); + printf("[%4d] switch_char\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); 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, location + defaultTarget, registerName(exec, scrutineeRegister).c_str()); + printf("[%4d] switch_string\t %d, %d(->%d), %s\n", location, tableIndex, defaultTarget, location + defaultTarget, registerName(exec, scrutineeRegister).data()); 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(exec, r0).c_str(), f0); + printf("[%4d] new_func\t\t %s, f%d\n", location, registerName(exec, r0).data(), 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(exec, r0).c_str(), f0); + printf("[%4d] new_func_exp\t %s, f%d\n", location, registerName(exec, r0).data(), f0); break; } case op_call: { @@ -990,7 +976,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(exec, dst).c_str(), registerName(exec, func).c_str(), argCount, registerOffset); + printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset); break; } case op_call_eval: { @@ -998,7 +984,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(exec, dst).c_str(), registerName(exec, func).c_str(), argCount, registerOffset); + printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset); break; } case op_call_varargs: { @@ -1006,7 +992,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_varargs\t %s, %s, %s, %d\n", location, registerName(exec, dst).c_str(), registerName(exec, func).c_str(), registerName(exec, argCount).c_str(), registerOffset); + printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), registerName(exec, argCount).data(), registerOffset); break; } case op_load_varargs: { @@ -1015,7 +1001,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_tear_off_activation: { int r0 = (++it)->u.operand; - printf("[%4d] tear_off_activation\t %s\n", location, registerName(exec, r0).c_str()); + printf("[%4d] tear_off_activation\t %s\n", location, registerName(exec, r0).data()); break; } case op_tear_off_arguments: { @@ -1024,7 +1010,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(exec, r0).c_str()); + printf("[%4d] ret\t\t %s\n", location, registerName(exec, r0).data()); break; } case op_construct: { @@ -1034,26 +1020,26 @@ 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(exec, dst).c_str(), registerName(exec, func).c_str(), argCount, registerOffset, registerName(exec, proto).c_str(), registerName(exec, thisRegister).c_str()); + printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset, registerName(exec, proto).data(), registerName(exec, thisRegister).data()); 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(exec, r0).c_str(), registerName(exec, r1).c_str()); + printf("[%4d] construct_verify\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); break; } case op_strcat: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int count = (++it)->u.operand; - printf("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str(), count); + printf("[%4d] strcat\t\t %s, %s, %d\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), count); break; } case op_to_primitive: { int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; - printf("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).c_str(), registerName(exec, r1).c_str()); + printf("[%4d] to_primitive\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data()); break; } case op_get_pnames: { @@ -1062,7 +1048,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& 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); + printf("[%4d] get_pnames\t %s, %s, %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data(), registerName(exec, r3).data(), offset, location + offset); it += OPCODE_LENGTH(op_get_pnames) - 1; break; } @@ -1070,13 +1056,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& 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); + printf("[%4d] next_pname\t %s, %s, %d(->%d)\n", location, registerName(exec, dest).data(), registerName(exec, iter).data(), 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(exec, r0).c_str()); + printf("[%4d] push_scope\t %s\n", location, registerName(exec, r0).data()); break; } case op_pop_scope: { @@ -1087,7 +1073,7 @@ 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(exec, r0).c_str(), idName(id0, m_identifiers[id0]).c_str(), registerName(exec, r1).c_str()); + printf("[%4d] push_new_scope \t%s, %s, %s\n", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, r1).data()); break; } case op_jmp_scopes: { @@ -1098,30 +1084,30 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_catch: { int r0 = (++it)->u.operand; - printf("[%4d] catch\t\t %s\n", location, registerName(exec, r0).c_str()); + printf("[%4d] catch\t\t %s\n", location, registerName(exec, r0).data()); break; } case op_throw: { int r0 = (++it)->u.operand; - printf("[%4d] throw\t\t %s\n", location, registerName(exec, r0).c_str()); + printf("[%4d] throw\t\t %s\n", location, registerName(exec, r0).data()); 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(exec, r0).c_str(), errorType, constantName(exec, k0, getConstant(k0)).c_str()); + printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(exec, r0).data(), errorType, constantName(exec, k0, getConstant(k0)).data()); 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(exec, retAddrDst).c_str(), offset, location + offset); + printf("[%4d] jsr\t\t %s, %d(->%d)\n", location, registerName(exec, retAddrDst).data(), offset, location + offset); break; } case op_sret: { int retAddrSrc = (++it)->u.operand; - printf("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).c_str()); + printf("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).data()); break; } case op_debug: { @@ -1133,17 +1119,17 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_profile_will_call: { int function = (++it)->u.operand; - printf("[%4d] profile_will_call %s\n", location, registerName(exec, function).c_str()); + printf("[%4d] profile_will_call %s\n", location, registerName(exec, function).data()); break; } case op_profile_did_call: { int function = (++it)->u.operand; - printf("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).c_str()); + printf("[%4d] profile_did_call\t %s\n", location, registerName(exec, function).data()); break; } case op_end: { int r0 = (++it)->u.operand; - printf("[%4d] end\t\t %s\n", location, registerName(exec, r0).c_str()); + printf("[%4d] end\t\t %s\n", location, registerName(exec, r0).data()); break; } } @@ -1301,6 +1287,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassR #endif , m_needsFullScopeChain(ownerExecutable->needsActivation()) , m_usesEval(ownerExecutable->usesEval()) + , m_usesArguments(false) , m_isNumericCompareFunction(false) , m_codeType(codeType) , m_source(sourceProvider) @@ -1375,7 +1362,7 @@ void CodeBlock::derefStructures(Instruction* vPC) const { Interpreter* interpreter = m_globalData->interpreter; - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) { vPC[4].u.structure->deref(); return; } @@ -1422,7 +1409,7 @@ void CodeBlock::refStructures(Instruction* vPC) const { Interpreter* interpreter = m_globalData->interpreter; - if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self)) { + if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self)) { vPC[4].u.structure->ref(); return; } @@ -1686,7 +1673,6 @@ void CodeBlock::shrinkToFit() if (m_rareData) { m_rareData->m_exceptionHandlers.shrinkToFit(); - m_rareData->m_regexps.shrinkToFit(); m_rareData->m_immediateSwitchJumpTables.shrinkToFit(); m_rareData->m_characterSwitchJumpTables.shrinkToFit(); m_rareData->m_stringSwitchJumpTables.shrinkToFit(); diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h index d92dc9d..1bbb265 100644 --- a/JavaScriptCore/bytecode/CodeBlock.h +++ b/JavaScriptCore/bytecode/CodeBlock.h @@ -102,9 +102,11 @@ namespace JSC { struct CallLinkInfo { CallLinkInfo() : callee(0) + , position(0) + , hasSeenShouldRepatch(0) { } - + unsigned bytecodeIndex; CodeLocationNearCall callReturnLocation; CodeLocationDataLabelPtr hotPathBegin; @@ -456,10 +458,6 @@ namespace JSC { 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; } - RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); } - - // Jump Tables size_t numberOfImmediateSwitchJumpTables() const { return m_rareData ? m_rareData->m_immediateSwitchJumpTables.size() : 0; } @@ -554,9 +552,6 @@ namespace JSC { struct RareData : FastAllocBase { Vector<HandlerInfo> m_exceptionHandlers; - // Rare Constants - Vector<RefPtr<RegExp> > m_regexps; - // Jump Tables Vector<SimpleJumpTable> m_immediateSwitchJumpTables; Vector<SimpleJumpTable> m_characterSwitchJumpTables; diff --git a/JavaScriptCore/bytecode/EvalCodeCache.h b/JavaScriptCore/bytecode/EvalCodeCache.h index a036dd4..27c479d 100644 --- a/JavaScriptCore/bytecode/EvalCodeCache.h +++ b/JavaScriptCore/bytecode/EvalCodeCache.h @@ -37,6 +37,7 @@ #include "UString.h" #include <wtf/HashMap.h> #include <wtf/RefPtr.h> +#include <wtf/text/StringHash.h> namespace JSC { diff --git a/JavaScriptCore/bytecode/Instruction.h b/JavaScriptCore/bytecode/Instruction.h index bcef7fb..ab6659f 100644 --- a/JavaScriptCore/bytecode/Instruction.h +++ b/JavaScriptCore/bytecode/Instruction.h @@ -31,6 +31,7 @@ #include "MacroAssembler.h" #include "Opcode.h" +#include "PropertySlot.h" #include "Structure.h" #include <wtf/VectorTraits.h> @@ -144,6 +145,7 @@ namespace JSC { Instruction(StructureChain* structureChain) { u.structureChain = structureChain; } Instruction(JSCell* jsCell) { u.jsCell = jsCell; } Instruction(PolymorphicAccessStructureList* polymorphicStructures) { u.polymorphicStructures = polymorphicStructures; } + Instruction(PropertySlot::GetValueFunc getterFunc) { u.getterFunc = getterFunc; } union { Opcode opcode; @@ -152,6 +154,7 @@ namespace JSC { StructureChain* structureChain; JSCell* jsCell; PolymorphicAccessStructureList* polymorphicStructures; + PropertySlot::GetValueFunc getterFunc; } u; }; diff --git a/JavaScriptCore/bytecode/JumpTable.cpp b/JavaScriptCore/bytecode/JumpTable.cpp index 175c1b3..ef7098b 100644 --- a/JavaScriptCore/bytecode/JumpTable.cpp +++ b/JavaScriptCore/bytecode/JumpTable.cpp @@ -30,6 +30,8 @@ #include "config.h" #include "JumpTable.h" +#include <wtf/text/StringHash.h> + namespace JSC { int32_t SimpleJumpTable::offsetForValue(int32_t value, int32_t defaultOffset) diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h index 56555f3..0a7f3fa 100644 --- a/JavaScriptCore/bytecode/Opcode.h +++ b/JavaScriptCore/bytecode/Opcode.h @@ -46,7 +46,6 @@ namespace JSC { \ macro(op_new_object, 2) \ macro(op_new_array, 4) \ - macro(op_new_regexp, 3) \ macro(op_mov, 3) \ \ macro(op_not, 3) \ @@ -109,6 +108,11 @@ namespace JSC { macro(op_get_by_id_getter_proto, 8) \ macro(op_get_by_id_getter_proto_list, 8) \ macro(op_get_by_id_getter_chain, 8) \ + macro(op_get_by_id_custom_self, 8) \ + macro(op_get_by_id_custom_self_list, 8) \ + macro(op_get_by_id_custom_proto, 8) \ + macro(op_get_by_id_custom_proto_list, 8) \ + macro(op_get_by_id_custom_chain, 8) \ macro(op_get_by_id_generic, 8) \ macro(op_get_array_length, 8) \ macro(op_get_string_length, 8) \ diff --git a/JavaScriptCore/bytecode/SamplingTool.cpp b/JavaScriptCore/bytecode/SamplingTool.cpp index 3f0babc..8522e45 100644 --- a/JavaScriptCore/bytecode/SamplingTool.cpp +++ b/JavaScriptCore/bytecode/SamplingTool.cpp @@ -337,7 +337,7 @@ void SamplingTool::dump(ExecState* exec) if (blockPercent >= 1) { //Instruction* code = codeBlock->instructions().begin(); - printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_executable->sourceURL().UTF8String().c_str(), codeBlock->lineNumberForBytecodeOffset(exec, 0), record->m_sampleCount, m_sampleCount, blockPercent); + printf("#%d: %s:%d: %d / %lld (%.3f%%)\n", i + 1, record->m_executable->sourceURL().ascii(), codeBlock->lineNumberForBytecodeOffset(exec, 0), record->m_sampleCount, m_sampleCount, blockPercent); if (i < 10) { HashMap<unsigned,unsigned> lineCounts; codeBlock->dump(exec); diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index f2193b0..aa5c5f9 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -34,6 +34,8 @@ #include "PrototypeFunction.h" #include "JSFunction.h" #include "Interpreter.h" +#include "RegExp.h" +#include "RegExpObject.h" #include "UString.h" using namespace std; @@ -827,11 +829,6 @@ RegisterID* BytecodeGenerator::addConstantValue(JSValue v) return &m_constantPoolRegisters[index]; } -unsigned BytecodeGenerator::addRegExp(RegExp* r) -{ - return m_codeBlock->addRegExp(r); -} - RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, RegisterID* src) { emitOpcode(op_mov); @@ -982,6 +979,12 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& ident return emitLoad(dst, JSValue(stringInMap)); } +RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, RegExp* regExp) +{ + JSValue jsRegExp = new (globalData()) RegExpObject(m_scopeChain->globalObject()->regExpStructure(), regExp); + return emitLoad(dst, jsRegExp); +} + RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, JSValue v) { RegisterID* constantID = addConstantValue(v); @@ -1361,15 +1364,6 @@ RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode return dst; } -RegisterID* BytecodeGenerator::emitNewRegExp(RegisterID* dst, RegExp* regExp) -{ - emitOpcode(op_new_regexp); - instructions().append(dst->index()); - instructions().append(addRegExp(regExp)); - return dst; -} - - RegisterID* BytecodeGenerator::emitNewFunctionExpression(RegisterID* r0, FuncExprNode* n) { FunctionBodyNode* function = n->body(); @@ -1942,7 +1936,7 @@ static int32_t keyForCharacterSwitch(ExpressionNode* node, int32_t min, int32_t UString::Rep* clause = static_cast<StringNode*>(node)->value().ustring().rep(); ASSERT(clause->length() == 1); - int32_t key = clause->data()[0]; + int32_t key = clause->characters()[0]; ASSERT(key >= min); ASSERT(key <= max); return key - min; diff --git a/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/JavaScriptCore/bytecompiler/BytecodeGenerator.h index 8b6a425..919183e 100644 --- a/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -264,6 +264,7 @@ namespace JSC { RegisterID* emitLoad(RegisterID* dst, bool); RegisterID* emitLoad(RegisterID* dst, double); RegisterID* emitLoad(RegisterID* dst, const Identifier&); + RegisterID* emitLoad(RegisterID* dst, RegExp* regExp); RegisterID* emitLoad(RegisterID* dst, JSValue); RegisterID* emitUnaryOp(OpcodeID, RegisterID* dst, RegisterID* src); @@ -276,7 +277,6 @@ namespace JSC { RegisterID* emitNewFunction(RegisterID* dst, FunctionBodyNode* body); RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func); - RegisterID* emitNewRegExp(RegisterID* dst, RegExp* regExp); RegisterID* emitMove(RegisterID* dst, RegisterID* src); @@ -446,7 +446,6 @@ namespace JSC { unsigned addConstant(const Identifier&); RegisterID* addConstantValue(JSValue); - unsigned addRegExp(RegExp*); PassRefPtr<FunctionExecutable> makeFunction(ExecState* exec, FunctionBodyNode* body) { diff --git a/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/JavaScriptCore/bytecompiler/NodesCodegen.cpp index 4162873..aaf2dd1 100644 --- a/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -149,7 +149,7 @@ RegisterID* RegExpNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d return emitThrowError(generator, SyntaxError, "Invalid regular expression: %s", regExp->errorMessage()); if (dst == generator.ignoredResult()) return 0; - return generator.emitNewRegExp(generator.finalDestination(dst), regExp.get()); + return generator.emitLoad(generator.finalDestination(dst), regExp.get()); } // ------------------------------ ThisNode ------------------------------------- @@ -1699,7 +1699,7 @@ static void processClauseList(ClauseListNode* list, Vector<ExpressionNode*, 8>& } const UString& value = static_cast<StringNode*>(clauseExpression)->value().ustring(); if (singleCharacterSwitch &= value.size() == 1) { - int32_t intVal = value.rep()->data()[0]; + int32_t intVal = value.rep()->characters()[0]; if (intVal < min_num) min_num = intVal; if (intVal > max_num) diff --git a/JavaScriptCore/config.h b/JavaScriptCore/config.h index d5fdfe9..791564a 100644 --- a/JavaScriptCore/config.h +++ b/JavaScriptCore/config.h @@ -25,7 +25,7 @@ #include <wtf/Platform.h> -#if OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC) +#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !defined(BUILDING_WX__) && !COMPILER(GCC) #if defined(BUILDING_JavaScriptCore) || defined(BUILDING_WTF) #define JS_EXPORTDATA __declspec(dllexport) #else @@ -75,6 +75,12 @@ #include <wtf/DisallowCType.h> #endif +#if COMPILER(MSVC) +#define SKIP_STATIC_CONSTRUCTORS_ON_MSVC 1 +#else +#define SKIP_STATIC_CONSTRUCTORS_ON_GCC 1 +#endif + #if PLATFORM(CHROMIUM) #if !defined(WTF_USE_V8) #define WTF_USE_V8 1 diff --git a/JavaScriptCore/create_hash_table b/JavaScriptCore/create_hash_table index 4184500..77463fb 100755 --- a/JavaScriptCore/create_hash_table +++ b/JavaScriptCore/create_hash_table @@ -252,18 +252,21 @@ sub output() { foreach my $key (@keys) { my $firstValue = ""; my $secondValue = ""; + my $castStr = ""; if ($values[$i]{"type"} eq "Function") { + $castStr = "static_cast<NativeFunction>"; $firstValue = $values[$i]{"function"}; $secondValue = $values[$i]{"params"}; } elsif ($values[$i]{"type"} eq "Property") { + $castStr = "static_cast<PropertySlot::GetValueFunc>"; $firstValue = $values[$i]{"get"}; $secondValue = $values[$i]{"put"}; } elsif ($values[$i]{"type"} eq "Lexer") { $firstValue = $values[$i]{"value"}; $secondValue = "0"; } - print " { \"$key\", $attrs[$i], (intptr_t)$firstValue, (intptr_t)$secondValue },\n"; + print " { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue },\n"; $i++; } print " { 0, 0, 0, 0 }\n"; diff --git a/JavaScriptCore/create_regex_tables b/JavaScriptCore/create_regex_tables new file mode 100644 index 0000000..b436eee --- /dev/null +++ b/JavaScriptCore/create_regex_tables @@ -0,0 +1,112 @@ +# Copyright (C) 2010 Apple Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +types = { + "wordchar": { "UseTable" : True, "data": ['_', ('0','9'), ('A', 'Z'), ('a','z')]}, + "nonwordchar": { "UseTable" : True, "Inverse": "wordchar", "data": ['`', (0, ord('0') - 1), (ord('9') + 1, ord('A') - 1), (ord('Z') + 1, ord('_') - 1), (ord('z') + 1, 0xffff)]}, + "newline": { "UseTable" : False, "data": ['\n', '\r', 0x2028, 0x2029]}, + "spaces": { "UseTable" : True, "data": [' ', ('\t', '\r'), 0xa0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000, (0x2000, 0x200a)]}, + "nonspaces": { "UseTable" : True, "Inverse": "spaces", "data": [(0, ord('\t') - 1), (ord('\r') + 1, ord(' ') - 1), (ord(' ') + 1, 0x009f), (0x00a1, 0x167f), (0x1681, 0x180d), (0x180f, 0x1fff), (0x200b, 0x2027), (0x202a, 0x202e), (0x2030, 0x205e), (0x2060, 0x2fff), (0x3001, 0xffff)]}, + "digits": { "UseTable" : False, "data": [('0', '9')]}, + "nondigits": { "UseTable" : False, "Inverse": "digits", "data": [(0, ord('0') - 1), (ord('9') + 1, 0xffff)] } +} +entriesPerLine = 50 +arrays = ""; +functions = ""; + +for name, classes in types.items(): + ranges = []; + size = 0; + for _class in classes["data"]: + if type(_class) == str: + ranges.append((ord(_class), ord(_class))) + elif type(_class) == int: + ranges.append((_class, _class)) + else: + (min, max) = _class; + if type(min) == str: + min = ord(min) + if type(max) == str: + max = ord(max) + if max > 0x7f and min <= 0x7f: + ranges.append((min, 0x7f)) + min = 0x80 + ranges.append((min,max)) + ranges.sort(); + + if classes["UseTable"] and (not "Inverse" in classes): + array = ("static const char _%sData[65536] = {\n" % name); + i = 0 + for (min,max) in ranges: + while i < min: + i = i + 1 + array += ('0,') + if (i % entriesPerLine == 0) and (i != 0): + array += ('\n') + while i <= max: + i = i + 1 + if (i == 65536): + array += ("1") + else: + array += ('1,') + if (i % entriesPerLine == 0) and (i != 0): + array += ('\n') + while i < 0xffff: + array += ("0,") + i = i + 1; + if (i % entriesPerLine == 0) and (i != 0): + array += ('\n') + if i == 0xffff: + array += ("0") + array += ("\n};\n\n"); + arrays += array + + # Generate createFunction: + function = ""; + function += ("CharacterClass* %sCreate()\n" % name) + function += ("{\n") + if classes["UseTable"]: + if "Inverse" in classes: + function += (" CharacterClass* characterClass = new CharacterClass(CharacterClassTable::create(_%sData, true));\n" % (classes["Inverse"])) + else: + function += (" CharacterClass* characterClass = new CharacterClass(CharacterClassTable::create(_%sData, false));\n" % (name)) + else: + function += (" CharacterClass* characterClass = new CharacterClass(0);\n") + for (min, max) in ranges: + if (min == max): + if (min > 127): + function += (" characterClass->m_matchesUnicode.append(0x%04x);\n" % min) + else: + function += (" characterClass->m_matches.append(0x%02x);\n" % min) + continue + if (min > 127) or (max > 127): + function += (" characterClass->m_rangesUnicode.append(CharacterRange(0x%04x, 0x%04x));\n" % (min, max)) + else: + function += (" characterClass->m_ranges.append(CharacterRange(0x%02x, 0x%02x));\n" % (min, max)) + function += (" return characterClass;\n") + function += ("}\n\n") + functions += function + +print(arrays) +print(functions) + diff --git a/JavaScriptCore/interpreter/Interpreter.cpp b/JavaScriptCore/interpreter/Interpreter.cpp index 6dbbcf9..40f6458 100644 --- a/JavaScriptCore/interpreter/Interpreter.cpp +++ b/JavaScriptCore/interpreter/Interpreter.cpp @@ -522,8 +522,9 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceId"), jsNumber(callFrame, codeBlock->ownerExecutable()->sourceID()), ReadOnly | DontDelete); exception->putWithAttributes(callFrame, Identifier(callFrame, "sourceURL"), jsOwnedString(callFrame, codeBlock->ownerExecutable()->sourceURL()), ReadOnly | DontDelete); } - - if (exception->isWatchdogException()) { + + ComplType exceptionType = exception->exceptionType(); + if (exceptionType == Interrupted || exceptionType == Terminated) { while (unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) { // Don't need handler checks or anything, we just want to unroll all the JS callframes possible. } @@ -579,8 +580,8 @@ JSValue Interpreter::execute(ProgramExecutable* program, CallFrame* callFrame, S { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + if (m_reentryDepth >= MaxSmallThreadReentryDepth) { + if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) { *exception = createStackOverflowError(callFrame); return jsNull(); } @@ -640,8 +641,8 @@ JSValue Interpreter::execute(FunctionExecutable* functionExecutable, CallFrame* { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + if (m_reentryDepth >= MaxSmallThreadReentryDepth) { + if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) { *exception = createStackOverflowError(callFrame); return jsNull(); } @@ -702,8 +703,8 @@ CallFrameClosure Interpreter::prepareForRepeatCall(FunctionExecutable* FunctionE { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + if (m_reentryDepth >= MaxSmallThreadReentryDepth) { + if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) { *exception = createStackOverflowError(callFrame); return CallFrameClosure(); } @@ -778,8 +779,8 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSObjec { ASSERT(!scopeChain->globalData->exception); - if (m_reentryDepth >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || m_reentryDepth >= MaxMainThreadReentryDepth) { + if (m_reentryDepth >= MaxSmallThreadReentryDepth) { + if (m_reentryDepth >= callFrame->globalData().maxReentryDepth) { *exception = createStackOverflowError(callFrame); return jsNull(); } @@ -1030,8 +1031,20 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* // Cache hit: Specialize instruction and ref Structures. if (slot.slotBase() == baseValue) { - vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_self) : getOpcode(op_get_by_id_self); - vPC[5] = slot.cachedOffset(); + switch (slot.cachedPropertyType()) { + case PropertySlot::Getter: + vPC[0] = getOpcode(op_get_by_id_getter_self); + vPC[5] = slot.cachedOffset(); + break; + case PropertySlot::Custom: + vPC[0] = getOpcode(op_get_by_id_custom_self); + vPC[5] = slot.customGetter(); + break; + default: + vPC[0] = getOpcode(op_get_by_id_self); + vPC[5] = slot.cachedOffset(); + break; + } codeBlock->refStructures(vPC); return; @@ -1056,10 +1069,22 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* } ASSERT(!baseObject->structure()->isUncacheableDictionary()); - - vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_proto) : getOpcode(op_get_by_id_proto); + + switch (slot.cachedPropertyType()) { + case PropertySlot::Getter: + vPC[0] = getOpcode(op_get_by_id_getter_proto); + vPC[6] = offset; + break; + case PropertySlot::Custom: + vPC[0] = getOpcode(op_get_by_id_custom_proto); + vPC[6] = slot.customGetter(); + break; + default: + vPC[0] = getOpcode(op_get_by_id_proto); + vPC[6] = offset; + break; + } vPC[5] = baseObject->structure(); - vPC[6] = offset; codeBlock->refStructures(vPC); return; @@ -1072,11 +1097,24 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* return; } - vPC[0] = slot.isGetter() ? getOpcode(op_get_by_id_getter_chain) : getOpcode(op_get_by_id_chain); + + switch (slot.cachedPropertyType()) { + case PropertySlot::Getter: + vPC[0] = getOpcode(op_get_by_id_getter_chain); + vPC[7] = offset; + break; + case PropertySlot::Custom: + vPC[0] = getOpcode(op_get_by_id_custom_chain); + vPC[7] = slot.customGetter(); + break; + default: + vPC[0] = getOpcode(op_get_by_id_chain); + vPC[7] = offset; + break; + } vPC[4] = structure; vPC[5] = structure->prototypeChain(callFrame); vPC[6] = count; - vPC[7] = offset; codeBlock->refStructures(vPC); } @@ -1137,7 +1175,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #define CHECK_FOR_TIMEOUT() \ if (!--tickCount) { \ - if (globalData->timeoutChecker.didTimeOut(callFrame)) { \ + if (globalData->terminator.shouldTerminate() || globalData->timeoutChecker.didTimeOut(callFrame)) { \ exceptionValue = jsNull(); \ goto vm_throw; \ } \ @@ -1199,20 +1237,6 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi vPC += OPCODE_LENGTH(op_new_array); NEXT_INSTRUCTION(); } - DEFINE_OPCODE(op_new_regexp) { - /* new_regexp dst(r) regExp(re) - - Constructs a new RegExp instance using the original - constructor from regexp regExp, and puts the result in - register dst. - */ - 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 += OPCODE_LENGTH(op_new_regexp); - NEXT_INSTRUCTION(); - } DEFINE_OPCODE(op_mov) { /* mov dst(r) src(r) @@ -1483,7 +1507,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi */ int dst = vPC[1].u.operand; JSValue src = callFrame->r(vPC[2].u.operand).jsValue(); - if (src.isInt32() && src.asInt32()) + if (src.isInt32() && (src.asInt32() & 0x7fffffff)) // non-zero and no overflow callFrame->r(dst) = jsNumber(callFrame, -src.asInt32()); else { JSValue result = jsNumber(callFrame, -src.toNumber(callFrame)); @@ -2207,6 +2231,48 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #if HAVE(COMPUTED_GOTO) skip_id_getter_proto: #endif +#if HAVE(COMPUTED_GOTO) + goto *(&&skip_id_custom_proto); +#endif + DEFINE_OPCODE(op_get_by_id_custom_proto) { + /* op_get_by_id_custom_proto dst(r) base(r) property(id) structure(sID) prototypeStructure(sID) offset(n) nop(n) + + Cached property access: Attempts to use a cached named property getter + from the value base's prototype. If the cache misses, op_get_by_id_custom_proto + reverts to op_get_by_id. + */ + int base = vPC[2].u.operand; + JSValue baseValue = callFrame->r(base).jsValue(); + + if (LIKELY(baseValue.isCell())) { + JSCell* baseCell = asCell(baseValue); + Structure* structure = vPC[4].u.structure; + + if (LIKELY(baseCell->structure() == structure)) { + ASSERT(structure->prototypeForLookup(callFrame).isObject()); + JSObject* protoObject = asObject(structure->prototypeForLookup(callFrame)); + Structure* prototypeStructure = vPC[5].u.structure; + + if (LIKELY(protoObject->structure() == prototypeStructure)) { + int dst = vPC[1].u.operand; + int property = vPC[3].u.operand; + Identifier& ident = callFrame->codeBlock()->identifier(property); + + PropertySlot::GetValueFunc getter = vPC[6].u.getterFunc; + JSValue result = getter(callFrame, protoObject, ident); + CHECK_FOR_EXCEPTION(); + callFrame->r(dst) = result; + vPC += OPCODE_LENGTH(op_get_by_id_custom_proto); + NEXT_INSTRUCTION(); + } + } + } + uncacheGetByID(callFrame->codeBlock(), vPC); + NEXT_INSTRUCTION(); + } +#if HAVE(COMPUTED_GOTO) + skip_id_custom_proto: +#endif DEFINE_OPCODE(op_get_by_id_self_list) { // Polymorphic self access caching currently only supported when JITting. ASSERT_NOT_REACHED(); @@ -2235,6 +2301,20 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi vPC += OPCODE_LENGTH(op_get_by_id_proto_list); NEXT_INSTRUCTION(); } + DEFINE_OPCODE(op_get_by_id_custom_self_list) { + // 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 += OPCODE_LENGTH(op_get_by_id_custom_self_list); + NEXT_INSTRUCTION(); + } + DEFINE_OPCODE(op_get_by_id_custom_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 += OPCODE_LENGTH(op_get_by_id_proto_list); + NEXT_INSTRUCTION(); + } DEFINE_OPCODE(op_get_by_id_chain) { /* op_get_by_id_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n) @@ -2324,6 +2404,43 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #if HAVE(COMPUTED_GOTO) skip_id_getter_self: #endif +#if HAVE(COMPUTED_GOTO) + goto *(&&skip_id_custom_self); +#endif + DEFINE_OPCODE(op_get_by_id_custom_self) { + /* op_get_by_id_custom_self dst(r) base(r) property(id) structure(sID) offset(n) nop(n) nop(n) + + Cached property access: Attempts to use a cached named property getter + from the value base. If the cache misses, op_get_by_id_custom_self reverts to + op_get_by_id. + */ + int base = vPC[2].u.operand; + JSValue baseValue = callFrame->r(base).jsValue(); + + if (LIKELY(baseValue.isCell())) { + JSCell* baseCell = asCell(baseValue); + Structure* structure = vPC[4].u.structure; + + if (LIKELY(baseCell->structure() == structure)) { + ASSERT(baseCell->isObject()); + int dst = vPC[1].u.operand; + int property = vPC[3].u.operand; + Identifier& ident = callFrame->codeBlock()->identifier(property); + + PropertySlot::GetValueFunc getter = vPC[5].u.getterFunc; + JSValue result = getter(callFrame, baseValue, ident); + CHECK_FOR_EXCEPTION(); + callFrame->r(dst) = result; + vPC += OPCODE_LENGTH(op_get_by_id_custom_self); + NEXT_INSTRUCTION(); + } + } + uncacheGetByID(callFrame->codeBlock(), vPC); + NEXT_INSTRUCTION(); + } +#if HAVE(COMPUTED_GOTO) +skip_id_custom_self: +#endif DEFINE_OPCODE(op_get_by_id_generic) { /* op_get_by_id_generic dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) @@ -2379,7 +2496,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi JSObject* getter = getterSetter->getter(); CallData callData; CallType callType = getter->getCallData(callData); - JSValue result = call(callFrame, getter, callType, callData, asObject(baseCell), ArgList()); + JSValue result = call(callFrame, getter, callType, callData, baseValue, ArgList()); CHECK_FOR_EXCEPTION(); callFrame->r(dst) = result; } else @@ -2399,6 +2516,58 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi #if HAVE(COMPUTED_GOTO) skip_id_getter_chain: #endif +#if HAVE(COMPUTED_GOTO) + goto *(&&skip_id_custom_chain); +#endif + DEFINE_OPCODE(op_get_by_id_custom_chain) { + /* op_get_by_id_custom_chain dst(r) base(r) property(id) structure(sID) structureChain(chain) count(n) offset(n) + + Cached property access: Attempts to use a cached named property getter on the + value base's prototype chain. If the cache misses, op_get_by_id_custom_chain + reverts to op_get_by_id. + */ + int base = vPC[2].u.operand; + JSValue baseValue = callFrame->r(base).jsValue(); + + if (LIKELY(baseValue.isCell())) { + JSCell* baseCell = asCell(baseValue); + Structure* structure = vPC[4].u.structure; + + if (LIKELY(baseCell->structure() == structure)) { + RefPtr<Structure>* it = vPC[5].u.structureChain->head(); + size_t count = vPC[6].u.operand; + RefPtr<Structure>* end = it + count; + + while (true) { + JSObject* baseObject = asObject(baseCell->structure()->prototypeForLookup(callFrame)); + + if (UNLIKELY(baseObject->structure() != (*it).get())) + break; + + if (++it == end) { + int dst = vPC[1].u.operand; + int property = vPC[3].u.operand; + Identifier& ident = callFrame->codeBlock()->identifier(property); + + PropertySlot::GetValueFunc getter = vPC[7].u.getterFunc; + JSValue result = getter(callFrame, baseObject, ident); + CHECK_FOR_EXCEPTION(); + callFrame->r(dst) = result; + vPC += OPCODE_LENGTH(op_get_by_id_custom_chain); + NEXT_INSTRUCTION(); + } + + // Update baseCell, so that next time around the loop we'll pick up the prototype's prototype. + baseCell = baseObject; + } + } + } + uncacheGetByID(callFrame->codeBlock(), vPC); + NEXT_INSTRUCTION(); + } +#if HAVE(COMPUTED_GOTO) + skip_id_custom_chain: +#endif DEFINE_OPCODE(op_get_array_length) { /* op_get_array_length dst(r) base(r) property(id) nop(sID) nop(n) nop(n) nop(n) @@ -3085,7 +3254,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi if (value->length() != 1) vPC += defaultOffset; else - vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->data()[0], defaultOffset); + vPC += callFrame->codeBlock()->characterSwitchJumpTable(tableIndex).offsetForValue(value->characters()[0], defaultOffset); } NEXT_INSTRUCTION(); } diff --git a/JavaScriptCore/interpreter/Interpreter.h b/JavaScriptCore/interpreter/Interpreter.h index e17b055..cf8b342 100644 --- a/JavaScriptCore/interpreter/Interpreter.h +++ b/JavaScriptCore/interpreter/Interpreter.h @@ -64,7 +64,7 @@ namespace JSC { WillExecuteStatement }; - enum { MaxMainThreadReentryDepth = 256, MaxSecondaryThreadReentryDepth = 32 }; + enum { MaxLargeThreadReentryDepth = 256, MaxSmallThreadReentryDepth = 32 }; class Interpreter : public FastAllocBase { friend class JIT; diff --git a/JavaScriptCore/jit/ExecutableAllocator.h b/JavaScriptCore/jit/ExecutableAllocator.h index 1fb8ff7..8f46dee 100644 --- a/JavaScriptCore/jit/ExecutableAllocator.h +++ b/JavaScriptCore/jit/ExecutableAllocator.h @@ -43,6 +43,10 @@ #include <e32std.h> #endif +#if CPU(MIPS) && OS(LINUX) +#include <sys/cachectl.h> +#endif + #if OS(WINCE) // From pkfuncs.h (private header file from the Platform Builder) #define CACHE_SYNC_ALL 0x07F @@ -190,6 +194,32 @@ public: static void cacheFlush(void*, size_t) { } +#elif CPU(MIPS) + static void cacheFlush(void* code, size_t size) + { +#if COMPILER(GCC) && (GCC_VERSION >= 40300) +#if WTF_MIPS_ISA_REV(2) && (GCC_VERSION < 40403) + int lineSize; + asm("rdhwr %0, $1" : "=r" (lineSize)); + // + // Modify "start" and "end" to avoid GCC 4.3.0-4.4.2 bug in + // mips_expand_synci_loop that may execute synci one more time. + // "start" points to the fisrt byte of the cache line. + // "end" points to the last byte of the line before the last cache line. + // Because size is always a multiple of 4, this is safe to set + // "end" to the last byte. + // + intptr_t start = reinterpret_cast<intptr_t>(code) & (-lineSize); + intptr_t end = ((reinterpret_cast<intptr_t>(code) + size - 1) & (-lineSize)) - 1; + __builtin___clear_cache(reinterpret_cast<char*>(start), reinterpret_cast<char*>(end)); +#else + intptr_t end = reinterpret_cast<intptr_t>(code) + size; + __builtin___clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end)); +#endif +#else + _flush_cache(reinterpret_cast<char*>(code), size, BCACHE); +#endif + } #elif CPU(ARM_THUMB2) && OS(IPHONE_OS) static void cacheFlush(void* code, size_t size) { diff --git a/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp index dd1db4e..4d3c847 100644 --- a/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp +++ b/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp @@ -27,10 +27,10 @@ #include "ExecutableAllocator.h" -#include <errno.h> - #if ENABLE(ASSEMBLER) && OS(DARWIN) && CPU(X86_64) +#include <errno.h> + #include "TCSpinLock.h" #include <mach/mach_init.h> #include <mach/vm_map.h> diff --git a/JavaScriptCore/jit/JIT.cpp b/JavaScriptCore/jit/JIT.cpp index 78c5153..ec23d8c 100644 --- a/JavaScriptCore/jit/JIT.cpp +++ b/JavaScriptCore/jit/JIT.cpp @@ -275,7 +275,6 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_new_func) DEFINE_OP(op_new_func_exp) DEFINE_OP(op_new_object) - DEFINE_OP(op_new_regexp) DEFINE_OP(op_next_pname) DEFINE_OP(op_not) DEFINE_OP(op_nstricteq) @@ -327,6 +326,11 @@ void JIT::privateCompileMainPass() case op_get_by_id_getter_proto_list: case op_get_by_id_getter_self: case op_get_by_id_getter_self_list: + case op_get_by_id_custom_chain: + case op_get_by_id_custom_proto: + case op_get_by_id_custom_proto_list: + case op_get_by_id_custom_self: + case op_get_by_id_custom_self_list: case op_get_string_length: case op_put_by_id_generic: case op_put_by_id_replace: diff --git a/JavaScriptCore/jit/JIT.h b/JavaScriptCore/jit/JIT.h index bfbb1ee..e757112 100644 --- a/JavaScriptCore/jit/JIT.h +++ b/JavaScriptCore/jit/JIT.h @@ -26,8 +26,6 @@ #ifndef JIT_h #define JIT_h -#include <wtf/Platform.h> - #if ENABLE(JIT) // We've run into some problems where changing the size of the class JIT leads to @@ -268,6 +266,28 @@ namespace JSC { static const FPRegisterID fpRegT0 = ARMRegisters::d0; static const FPRegisterID fpRegT1 = ARMRegisters::d1; static const FPRegisterID fpRegT2 = ARMRegisters::d2; +#elif CPU(MIPS) + static const RegisterID returnValueRegister = MIPSRegisters::v0; + static const RegisterID cachedResultRegister = MIPSRegisters::v0; + static const RegisterID firstArgumentRegister = MIPSRegisters::a0; + + // regT0 must be v0 for returning a 32-bit value. + static const RegisterID regT0 = MIPSRegisters::v0; + + // regT1 must be v1 for returning a pair of 32-bit value. + static const RegisterID regT1 = MIPSRegisters::v1; + + static const RegisterID regT2 = MIPSRegisters::t4; + + // regT3 must be saved in the callee, so use an S register. + static const RegisterID regT3 = MIPSRegisters::s2; + + static const RegisterID callFrameRegister = MIPSRegisters::s0; + static const RegisterID timeoutCheckRegister = MIPSRegisters::s1; + + static const FPRegisterID fpRegT0 = MIPSRegisters::f4; + static const FPRegisterID fpRegT1 = MIPSRegisters::f6; + static const FPRegisterID fpRegT2 = MIPSRegisters::f8; #else #error "JIT not supported on this platform." #endif @@ -283,32 +303,32 @@ namespace JSC { return JIT(globalData, codeBlock).privateCompile(); } - static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress) + static void compileGetByIdProto(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress) { JIT jit(globalData, codeBlock); - jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, cachedOffset, returnAddress, callFrame); + jit.privateCompileGetByIdProto(stubInfo, structure, prototypeStructure, ident, slot, cachedOffset, returnAddress, callFrame); } - static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset) + static void compileGetByIdSelfList(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset) { JIT jit(globalData, codeBlock); - jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, cachedOffset); + jit.privateCompileGetByIdSelfList(stubInfo, polymorphicStructures, currentIndex, structure, ident, slot, cachedOffset); } - static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset) + static void compileGetByIdProtoList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset) { JIT jit(globalData, codeBlock); - jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, cachedOffset, callFrame); + jit.privateCompileGetByIdProtoList(stubInfo, prototypeStructureList, currentIndex, structure, prototypeStructure, ident, slot, cachedOffset, callFrame); } - static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset) + static void compileGetByIdChainList(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructureList, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset) { JIT jit(globalData, codeBlock); - jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, cachedOffset, callFrame); + jit.privateCompileGetByIdChainList(stubInfo, prototypeStructureList, currentIndex, structure, chain, count, ident, slot, cachedOffset, callFrame); } - static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress) + static void compileGetByIdChain(JSGlobalData* globalData, CallFrame* callFrame, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress) { JIT jit(globalData, codeBlock); - jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, cachedOffset, returnAddress, callFrame); + jit.privateCompileGetByIdChain(stubInfo, structure, chain, count, ident, slot, cachedOffset, returnAddress, callFrame); } static void compilePutByIdTransition(JSGlobalData* globalData, CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* oldStructure, Structure* newStructure, size_t cachedOffset, StructureChain* chain, ReturnAddressPtr returnAddress) @@ -354,11 +374,11 @@ namespace JSC { void privateCompileLinkPass(); void privateCompileSlowCases(); JITCode privateCompile(); - void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame); - void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, size_t cachedOffset); - void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame); - void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame); - void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame); + void privateCompileGetByIdProto(StructureStubInfo*, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame); + void privateCompileGetByIdSelfList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, const Identifier&, const PropertySlot&, size_t cachedOffset); + void privateCompileGetByIdProtoList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, Structure* prototypeStructure, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame); + void privateCompileGetByIdChainList(StructureStubInfo*, PolymorphicAccessStructureList*, int, Structure*, StructureChain* chain, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, CallFrame* callFrame); + void privateCompileGetByIdChain(StructureStubInfo*, Structure*, StructureChain*, size_t count, const Identifier&, const PropertySlot&, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame); void privateCompilePutByIdTransition(StructureStubInfo*, Structure*, Structure*, size_t cachedOffset, StructureChain*, ReturnAddressPtr returnAddress); void privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executablePool, JSGlobalData* data, TrampolineStructure *trampolines); @@ -686,6 +706,48 @@ namespace JSC { // sequencePutById static const int sequencePutByIdInstructionSpace = 28; static const int sequencePutByIdConstantSpace = 3; +#elif CPU(MIPS) +#if WTF_MIPS_ISA(1) + static const int patchOffsetPutByIdStructure = 16; + static const int patchOffsetPutByIdExternalLoad = 48; + static const int patchLengthPutByIdExternalLoad = 20; + static const int patchOffsetPutByIdPropertyMapOffset = 68; + static const int patchOffsetGetByIdStructure = 16; + static const int patchOffsetGetByIdBranchToSlowCase = 48; + static const int patchOffsetGetByIdExternalLoad = 48; + static const int patchLengthGetByIdExternalLoad = 20; + static const int patchOffsetGetByIdPropertyMapOffset = 68; + static const int patchOffsetGetByIdPutResult = 88; +#if ENABLE(OPCODE_SAMPLING) + #error "OPCODE_SAMPLING is not yet supported" +#else + static const int patchOffsetGetByIdSlowCaseCall = 40; +#endif + static const int patchOffsetOpCallCompareToJump = 32; + static const int patchOffsetMethodCheckProtoObj = 32; + static const int patchOffsetMethodCheckProtoStruct = 56; + static const int patchOffsetMethodCheckPutFunction = 88; +#else // WTF_MIPS_ISA(1) + static const int patchOffsetPutByIdStructure = 12; + static const int patchOffsetPutByIdExternalLoad = 44; + static const int patchLengthPutByIdExternalLoad = 16; + static const int patchOffsetPutByIdPropertyMapOffset = 60; + static const int patchOffsetGetByIdStructure = 12; + static const int patchOffsetGetByIdBranchToSlowCase = 44; + static const int patchOffsetGetByIdExternalLoad = 44; + static const int patchLengthGetByIdExternalLoad = 16; + static const int patchOffsetGetByIdPropertyMapOffset = 60; + static const int patchOffsetGetByIdPutResult = 76; +#if ENABLE(OPCODE_SAMPLING) + #error "OPCODE_SAMPLING is not yet supported" +#else + static const int patchOffsetGetByIdSlowCaseCall = 40; +#endif + static const int patchOffsetOpCallCompareToJump = 32; + static const int patchOffsetMethodCheckProtoObj = 32; + static const int patchOffsetMethodCheckProtoStruct = 52; + static const int patchOffsetMethodCheckPutFunction = 84; +#endif #endif #endif // USE(JSVALUE32_64) @@ -759,7 +821,6 @@ namespace JSC { void emit_op_new_func(Instruction*); 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*); diff --git a/JavaScriptCore/jit/JITArithmetic.cpp b/JavaScriptCore/jit/JITArithmetic.cpp index 2f2ffe3..2e1ff40 100644 --- a/JavaScriptCore/jit/JITArithmetic.cpp +++ b/JavaScriptCore/jit/JITArithmetic.cpp @@ -56,8 +56,7 @@ void JIT::emit_op_negate(Instruction* currentInstruction) emitLoad(src, regT1, regT0); Jump srcNotInt = branch32(NotEqual, regT1, Imm32(JSValue::Int32Tag)); - addSlowCase(branch32(Equal, regT0, Imm32(0))); - + addSlowCase(branchTest32(Zero, regT0, Imm32(0x7fffffff))); neg32(regT0); emitStoreInt32(dst, regT0, (dst == src)); @@ -78,7 +77,7 @@ void JIT::emitSlow_op_negate(Instruction* currentInstruction, Vector<SlowCaseEnt { unsigned dst = currentInstruction[1].u.operand; - linkSlowCase(iter); // 0 check + linkSlowCase(iter); // 0x7fffffff check linkSlowCase(iter); // double check JITStubCall stubCall(this, cti_op_negate); diff --git a/JavaScriptCore/jit/JITCall.cpp b/JavaScriptCore/jit/JITCall.cpp index 179aad7..da603bd 100644 --- a/JavaScriptCore/jit/JITCall.cpp +++ b/JavaScriptCore/jit/JITCall.cpp @@ -159,7 +159,7 @@ void JIT::emit_op_construct_verify(Instruction* currentInstruction) emitLoad(dst, regT1, regT0); addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addSlowCase(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType))); + addSlowCase(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType))); } void JIT::emitSlow_op_construct_verify(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) diff --git a/JavaScriptCore/jit/JITCode.h b/JavaScriptCore/jit/JITCode.h index 69cf167..5d889b5 100644 --- a/JavaScriptCore/jit/JITCode.h +++ b/JavaScriptCore/jit/JITCode.h @@ -26,8 +26,6 @@ #ifndef JITCode_h #define JITCode_h -#include <wtf/Platform.h> - #if ENABLE(JIT) #include "CallFrame.h" diff --git a/JavaScriptCore/jit/JITInlineMethods.h b/JavaScriptCore/jit/JITInlineMethods.h index 5af7565..96a2e5b 100644 --- a/JavaScriptCore/jit/JITInlineMethods.h +++ b/JavaScriptCore/jit/JITInlineMethods.h @@ -26,7 +26,6 @@ #ifndef JITInlineMethods_h #define JITInlineMethods_h -#include <wtf/Platform.h> #if ENABLE(JIT) @@ -161,6 +160,23 @@ ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address) loadPtr(address, linkRegister); } +#elif CPU(MIPS) + +ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg) +{ + move(returnAddressRegister, reg); +} + +ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(RegisterID reg) +{ + move(reg, returnAddressRegister); +} + +ALWAYS_INLINE void JIT::restoreReturnAddressBeforeReturn(Address address) +{ + loadPtr(address, returnAddressRegister); +} + #else // CPU(X86) || CPU(X86_64) ALWAYS_INLINE void JIT::preserveReturnAddressAfterCall(RegisterID reg) diff --git a/JavaScriptCore/jit/JITOpcodes.cpp b/JavaScriptCore/jit/JITOpcodes.cpp index c470495..0dd6a40 100644 --- a/JavaScriptCore/jit/JITOpcodes.cpp +++ b/JavaScriptCore/jit/JITOpcodes.cpp @@ -1,5 +1,6 @@ /* * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -282,6 +283,33 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable // r2 - callee // stack: this(JSValue) and a pointer to ArgList +#if OS(WINCE) + // Setup arg4: + push(stackPointerRegister); + + // Setup arg3: + // regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this' + load32(Address(regT1, -(int32_t)sizeof(void*) * 2), ARMRegisters::r3); + push(ARMRegisters::r3); + load32(Address(regT1, -(int32_t)sizeof(void*)), regT3); + storePtr(regT3, Address(stackPointerRegister)); + + // Setup arg2: + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT2); + + // Setup arg1: + move(callFrameRegister, regT1); + + // Setup arg0: + move(stackPointerRegister, regT0); + + call(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data))); + + load32(Address(stackPointerRegister, 0), regT0); + load32(Address(stackPointerRegister, 4), regT1); + + addPtr(Imm32(sizeof(ArgList) + 8), stackPointerRegister); +#else // OS(WINCE) move(stackPointerRegister, regT3); subPtr(Imm32(8), stackPointerRegister); move(stackPointerRegister, regT0); @@ -290,7 +318,7 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable // Setup arg4: storePtr(regT3, Address(stackPointerRegister, 8)); - // Setup arg3 + // 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)); @@ -310,6 +338,8 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable load32(Address(stackPointerRegister, 20), regT1); addPtr(Imm32(sizeof(ArgList) + 16 + 8), stackPointerRegister); +#endif // OS(WINCE) + #endif // Check for an exception @@ -486,7 +516,7 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction) // Check that baseVal 'ImplementsDefaultHasInstance'. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance))); + addSlowCase(branchTest8(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. @@ -839,7 +869,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); + addJump(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); @@ -866,7 +896,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); + addJump(branchTest8(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); @@ -1143,13 +1173,6 @@ void JIT::emit_op_new_func_exp(Instruction* currentInstruction) stubCall.call(currentInstruction[1].u.operand); } -void JIT::emit_op_new_regexp(Instruction* currentInstruction) -{ - JITStubCall stubCall(this, cti_op_new_regexp); - stubCall.addArgument(ImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand))); - stubCall.call(currentInstruction[1].u.operand); -} - void JIT::emit_op_throw(Instruction* currentInstruction) { unsigned exception = currentInstruction[1].u.operand; @@ -1179,7 +1202,7 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction) 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))); + isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); } // We could inline the case where you have a valid cache, but @@ -1458,7 +1481,7 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction) addSlowCase(branch32(NotEqual, regT1, Imm32(JSValue::CellTag))); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addSlowCase(branchTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); + addSlowCase(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); map(m_bytecodeIndex + OPCODE_LENGTH(op_convert_this), thisRegister, regT1, regT0); } @@ -1764,7 +1787,30 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable // push pointer to arguments storePtr(regT1, Address(stackPointerRegister, OBJECT_OFFSETOF(ArgList, m_args))); - // Setup arg3: regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this' + // regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this' + +#if OS(WINCE) + // Setup arg3: + loadPtr(Address(regT1, -(int32_t)sizeof(Register)), ARMRegisters::r3); + + // Setup arg2: + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, regT2); + + // Setup arg1: + move(callFrameRegister, regT1); + + // Setup arg0: + move(stackPointerRegister, regT0); + subPtr(Imm32(sizeof(Register)), stackPointerRegister); + storePtr(regT0, Address(stackPointerRegister)); + + call(Address(regT2, OBJECT_OFFSETOF(JSFunction, m_data))); + + loadPtr(Address(regT0), regT0); + + addPtr(Imm32(sizeof(Register) + sizeof(ArgList)), stackPointerRegister); +#else // OS(WINCE) + // Setup arg3: loadPtr(Address(regT1, -(int32_t)sizeof(Register)), regT2); // Setup arg2: @@ -1779,6 +1825,57 @@ void JIT::privateCompileCTIMachineTrampolines(RefPtr<ExecutablePool>* executable call(Address(regT1, OBJECT_OFFSETOF(JSFunction, m_data))); addPtr(Imm32(sizeof(ArgList)), stackPointerRegister); +#endif // OS(WINCE) + +#elif CPU(MIPS) + emitGetFromCallFrameHeader32(RegisterFile::ArgumentCount, regT0); + + // Allocate stack space for our arglist + COMPILE_ASSERT(!(sizeof(ArgList) & 0x7), ArgList_should_by_8byte_aligned); + subPtr(Imm32(sizeof(ArgList) + 24), stackPointerRegister); + + // Set up arguments + subPtr(Imm32(1), regT0); // Don't include 'this' in argcount + + // Push argcount to 24 + offset($sp) + storePtr(regT0, Address(stackPointerRegister, 24 + 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 to 24 + offset($sp) + storePtr(regT1, Address(stackPointerRegister, 24 + OBJECT_OFFSETOF(ArgList, m_args))); + + // Setup arg3: regT1 currently points to the first argument, regT1-sizeof(Register) points to 'this' + loadPtr(Address(regT1, -(int32_t)sizeof(Register)), MIPSRegisters::a3); + + // Setup arg2: + emitGetFromCallFrameHeaderPtr(RegisterFile::Callee, MIPSRegisters::a2); + + // Setup arg1: + move(callFrameRegister, MIPSRegisters::a1); + + // Setup arg4: ArgList is passed by reference. At 16($sp), store ($sp + 24) + addPtr(Imm32(24), stackPointerRegister, regT2); + storePtr(regT2, Address(stackPointerRegister, 16)); + + // Setup arg0 as 20($sp) to hold the returned structure. + ASSERT(sizeof(JSValue) == 4); + addPtr(Imm32(20), stackPointerRegister, MIPSRegisters::a0); + + // Call + call(Address(MIPSRegisters::a2, OBJECT_OFFSETOF(JSFunction, m_data))); + + // Get returned value from 0($v0) which is the same as 20($sp) + loadPtr(Address(returnValueRegister, 0), returnValueRegister); + + // Restore stack space + addPtr(Imm32(sizeof(ArgList) + 24), stackPointerRegister); #elif ENABLE(JIT_OPTIMIZE_NATIVE_CALL) #error "JIT_OPTIMIZE_NATIVE_CALL not yet supported on this platform." @@ -1938,7 +2035,7 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction) // Check that baseVal 'ImplementsDefaultHasInstance'. loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT0); - addSlowCase(branchTest32(Zero, Address(regT0, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(ImplementsDefaultHasInstance))); + addSlowCase(branchTest8(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. @@ -2099,7 +2196,7 @@ void JIT::emit_op_construct_verify(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(regT0); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addSlowCase(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo) + OBJECT_OFFSETOF(TypeInfo, m_type)), Imm32(ObjectType))); + addSlowCase(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); } @@ -2208,7 +2305,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); + addJump(branchTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null @@ -2229,7 +2326,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); + addJump(branchTest8(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined)), target); Jump wasNotImmediate = jump(); // Now handle the immediate cases - undefined & null @@ -2342,13 +2439,6 @@ void JIT::emit_op_bitxor(Instruction* currentInstruction) emitPutVirtualRegister(currentInstruction[1].u.operand); } -void JIT::emit_op_new_regexp(Instruction* currentInstruction) -{ - JITStubCall stubCall(this, cti_op_new_regexp); - stubCall.addArgument(ImmPtr(m_codeBlock->regexp(currentInstruction[2].u.operand))); - stubCall.call(currentInstruction[1].u.operand); -} - void JIT::emit_op_bitor(Instruction* currentInstruction) { emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1); @@ -2385,7 +2475,7 @@ void JIT::emit_op_get_pnames(Instruction* currentInstruction) 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))); + isNotObject.append(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(ObjectType))); } // We could inline the case where you have a valid cache, but @@ -2536,7 +2626,7 @@ void JIT::emit_op_to_jsnumber(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(regT0, srcVReg); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - addSlowCase(branch32(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(NumberType))); + addSlowCase(branch8(NotEqual, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_type)), Imm32(NumberType))); wasImmediate.link(this); @@ -2647,7 +2737,7 @@ void JIT::emit_op_eq_null(Instruction* currentInstruction) Jump isImmediate = emitJumpIfNotJSCell(regT0); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - setTest32(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0); + setTest8(NonZero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0); Jump wasNotImmediate = jump(); @@ -2672,7 +2762,7 @@ void JIT::emit_op_neq_null(Instruction* currentInstruction) Jump isImmediate = emitJumpIfNotJSCell(regT0); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT2); - setTest32(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0); + setTest8(Zero, Address(regT2, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(MasqueradesAsUndefined), regT0); Jump wasNotImmediate = jump(); @@ -2732,7 +2822,7 @@ void JIT::emit_op_convert_this(Instruction* currentInstruction) emitJumpSlowCaseIfNotJSCell(regT0); loadPtr(Address(regT0, OBJECT_OFFSETOF(JSCell, m_structure)), regT1); - addSlowCase(branchTest32(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); + addSlowCase(branchTest8(NonZero, Address(regT1, OBJECT_OFFSETOF(Structure, m_typeInfo.m_flags)), Imm32(NeedsThisConversion))); } diff --git a/JavaScriptCore/jit/JITPropertyAccess.cpp b/JavaScriptCore/jit/JITPropertyAccess.cpp index 151bb03..3399f03 100644 --- a/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -32,6 +32,7 @@ #if ENABLE(JIT) #include "CodeBlock.h" +#include "GetterSetter.h" #include "JITInlineMethods.h" #include "JITStubCall.h" #include "JSArray.h" @@ -695,7 +696,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail)); } -void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame) +void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame) { // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is // referencing the prototype object - let's speculatively load it's table nice and early!) @@ -713,11 +714,28 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); #endif - // Checks out okay! - getDirectOffset - compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); - + bool needsStubLink = false; + + // Checks out okay! + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(ImmPtr(protoObject)); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); Jump success = jump(); - LinkBuffer patchBuffer(this, m_codeBlock->executablePool()); // Use the patch information to link the failure cases back to the original slow case routine. @@ -728,6 +746,12 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str // On success return back to the hot patch code, at a point it will perform the store to dest for us. patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult)); + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } // Track the stub we have created so that it will be deleted later. CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum(); stubInfo->stubRoutine = entryLabel; @@ -741,14 +765,43 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_proto_list)); } -void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset) +void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset) { Jump failureCase = checkStructure(regT0, structure); - compileGetDirectOffset(regT0, regT0, structure, cachedOffset); + bool needsStubLink = false; + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + if (!structure->isUsingInlineStorage()) { + move(regT0, regT1); + compileGetDirectOffset(regT1, regT1, structure, cachedOffset); + } else + compileGetDirectOffset(regT0, regT1, structure, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(regT0, regT0, structure, cachedOffset); Jump success = jump(); LinkBuffer patchBuffer(this, m_codeBlock->executablePool()); + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } + // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine; if (!lastProtoBegin) @@ -770,7 +823,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic repatchBuffer.relink(jumpLocation, entryLabel); } -void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame) +void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame) { // The prototype object definitely exists (if this stub exists the CodeBlock is referencing a Structure that is // referencing the prototype object - let's speculatively load it's table nice and early!) @@ -788,13 +841,38 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); #endif - // Checks out okay! - getDirectOffset - compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); + // Checks out okay! + bool needsStubLink = false; + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(ImmPtr(protoObject)); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); Jump success = jump(); LinkBuffer patchBuffer(this, m_codeBlock->executablePool()); + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } + // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine; patchBuffer.link(failureCases1, lastProtoBegin); @@ -815,10 +893,9 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi repatchBuffer.relink(jumpLocation, entryLabel); } -void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame) +void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame) { ASSERT(count); - JumpList bucketsOfFail; // Check eax is an object of the right Structure. @@ -842,11 +919,36 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi #endif } ASSERT(protoObject); - - compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); + + bool needsStubLink = false; + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(ImmPtr(protoObject)); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); Jump success = jump(); LinkBuffer patchBuffer(this, m_codeBlock->executablePool()); + + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine; @@ -869,10 +971,10 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi repatchBuffer.relink(jumpLocation, entryLabel); } -void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame) +void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame) { ASSERT(count); - + JumpList bucketsOfFail; // Check eax is an object of the right Structure. @@ -896,11 +998,36 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str } ASSERT(protoObject); - compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); + bool needsStubLink = false; + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + compileGetDirectOffset(protoObject, regT1, regT1, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(ImmPtr(protoObject)); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(protoObject, regT1, regT0, cachedOffset); Jump success = jump(); LinkBuffer patchBuffer(this, m_codeBlock->executablePool()); + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } + // Use the patch information to link the failure cases back to the original slow case routine. patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall)); diff --git a/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/JavaScriptCore/jit/JITPropertyAccess32_64.cpp index f9e323d..ec33026 100644 --- a/JavaScriptCore/jit/JITPropertyAccess32_64.cpp +++ b/JavaScriptCore/jit/JITPropertyAccess32_64.cpp @@ -718,7 +718,7 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_array_fail)); } -void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame) +void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame) { // regT0 holds a JSCell* @@ -736,9 +736,26 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str #else Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); #endif - - // Checks out okay! - getDirectOffset - compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset); + bool needsStubLink = false; + // Checks out okay! + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(ImmPtr(protoObject)); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset); Jump success = jump(); @@ -751,7 +768,14 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str // On success return back to the hot patch code, at a point it will perform the store to dest for us. patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult)); - + + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } + // Track the stub we have created so that it will be deleted later. CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum(); stubInfo->stubRoutine = entryLabel; @@ -766,16 +790,43 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str } -void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, size_t cachedOffset) +void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* polymorphicStructures, int currentIndex, Structure* structure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset) { // regT0 holds a JSCell* - Jump failureCase = checkStructure(regT0, structure); - compileGetDirectOffset(regT0, regT1, regT0, structure, cachedOffset); + bool needsStubLink = false; + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + if (!structure->isUsingInlineStorage()) { + move(regT0, regT1); + compileGetDirectOffset(regT1, regT2, regT1, structure, cachedOffset); + } else + compileGetDirectOffset(regT0, regT2, regT1, structure, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(regT0, regT1, regT0, structure, cachedOffset); + Jump success = jump(); LinkBuffer patchBuffer(this, m_codeBlock->executablePool()); - + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel lastProtoBegin = polymorphicStructures->list[currentIndex - 1].stubRoutine; if (!lastProtoBegin) @@ -785,7 +836,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic // On success return back to the hot patch code, at a point it will perform the store to dest for us. patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(patchOffsetGetByIdPutResult)); - + CodeLocationLabel entryLabel = patchBuffer.finalizeCodeAddendum(); structure->ref(); @@ -797,7 +848,7 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic repatchBuffer.relink(jumpLocation, entryLabel); } -void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, size_t cachedOffset, CallFrame* callFrame) +void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, Structure* prototypeStructure, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame) { // regT0 holds a JSCell* @@ -817,12 +868,35 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi Jump failureCases2 = branchPtr(NotEqual, AbsoluteAddress(prototypeStructureAddress), ImmPtr(prototypeStructure)); #endif - compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset); + bool needsStubLink = false; + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(ImmPtr(protoObject)); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset); Jump success = jump(); LinkBuffer patchBuffer(this, m_codeBlock->executablePool()); - + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine; patchBuffer.link(failureCases1, lastProtoBegin); @@ -843,10 +917,9 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi repatchBuffer.relink(jumpLocation, entryLabel); } -void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, CallFrame* callFrame) +void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, PolymorphicAccessStructureList* prototypeStructures, int currentIndex, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, CallFrame* callFrame) { // regT0 holds a JSCell* - ASSERT(count); JumpList bucketsOfFail; @@ -872,11 +945,35 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi } ASSERT(protoObject); - compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset); + bool needsStubLink = false; + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(ImmPtr(protoObject)); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset); + Jump success = jump(); LinkBuffer patchBuffer(this, m_codeBlock->executablePool()); - + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel lastProtoBegin = prototypeStructures->list[currentIndex - 1].stubRoutine; @@ -898,10 +995,9 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi repatchBuffer.relink(jumpLocation, entryLabel); } -void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame) +void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* structure, StructureChain* chain, size_t count, const Identifier& ident, const PropertySlot& slot, size_t cachedOffset, ReturnAddressPtr returnAddress, CallFrame* callFrame) { // regT0 holds a JSCell* - ASSERT(count); JumpList bucketsOfFail; @@ -927,11 +1023,34 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str } ASSERT(protoObject); - compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset); + bool needsStubLink = false; + if (slot.cachedPropertyType() == PropertySlot::Getter) { + needsStubLink = true; + compileGetDirectOffset(protoObject, regT2, regT2, regT1, cachedOffset); + JITStubCall stubCall(this, cti_op_get_by_id_getter_stub); + stubCall.addArgument(regT1); + stubCall.addArgument(regT0); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else if (slot.cachedPropertyType() == PropertySlot::Custom) { + needsStubLink = true; + JITStubCall stubCall(this, cti_op_get_by_id_custom_stub); + stubCall.addArgument(ImmPtr(protoObject)); + stubCall.addArgument(ImmPtr(FunctionPtr(slot.customGetter()).executableAddress())); + stubCall.addArgument(ImmPtr(const_cast<Identifier*>(&ident))); + stubCall.addArgument(ImmPtr(stubInfo->callReturnLocation.executableAddress())); + stubCall.call(); + } else + compileGetDirectOffset(protoObject, regT2, regT1, regT0, cachedOffset); Jump success = jump(); LinkBuffer patchBuffer(this, m_codeBlock->executablePool()); - + if (needsStubLink) { + for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { + if (iter->to) + patchBuffer.link(iter->from, FunctionPtr(iter->to)); + } + } // Use the patch information to link the failure cases back to the original slow case routine. patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall)); diff --git a/JavaScriptCore/jit/JITStubs.cpp b/JavaScriptCore/jit/JITStubs.cpp index bf430a6..c32f2ce 100644 --- a/JavaScriptCore/jit/JITStubs.cpp +++ b/JavaScriptCore/jit/JITStubs.cpp @@ -38,6 +38,7 @@ #include "Collector.h" #include "Debugger.h" #include "ExceptionHelpers.h" +#include "GetterSetter.h" #include "GlobalEvalFunction.h" #include "JIT.h" #include "JSActivation.h" @@ -238,99 +239,20 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7." #endif -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" -SYMBOL_STRING(ctiTrampoline) ":" "\n" - "sub sp, sp, #0x3c" "\n" - "str lr, [sp, #0x20]" "\n" - "str r4, [sp, #0x24]" "\n" - "str r5, [sp, #0x28]" "\n" - "str r6, [sp, #0x2c]" "\n" - "str r1, [sp, #0x30]" "\n" - "str r2, [sp, #0x34]" "\n" - "str r3, [sp, #0x38]" "\n" - "cpy r5, r2" "\n" - "mov r6, #512" "\n" - "blx r0" "\n" - "ldr r6, [sp, #0x2c]" "\n" - "ldr r5, [sp, #0x28]" "\n" - "ldr r4, [sp, #0x24]" "\n" - "ldr lr, [sp, #0x20]" "\n" - "add sp, sp, #0x3c" "\n" - "bx lr" "\n" -); - -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" -SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" - "cpy r0, sp" "\n" - "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" - "ldr r6, [sp, #0x2c]" "\n" - "ldr r5, [sp, #0x28]" "\n" - "ldr r4, [sp, #0x24]" "\n" - "ldr lr, [sp, #0x20]" "\n" - "add sp, sp, #0x3c" "\n" - "bx lr" "\n" -); - -asm volatile ( -".text" "\n" -".align 2" "\n" -".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" -".thumb" "\n" -".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n" -SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" - "ldr r6, [sp, #0x2c]" "\n" - "ldr r5, [sp, #0x28]" "\n" - "ldr r4, [sp, #0x24]" "\n" - "ldr lr, [sp, #0x20]" "\n" - "add sp, sp, #0x3c" "\n" - "bx lr" "\n" -); +#define THUNK_RETURN_ADDRESS_OFFSET 0x3C +#define PRESERVED_RETURN_ADDRESS_OFFSET 0x40 +#define PRESERVED_R4_OFFSET 0x44 +#define PRESERVED_R5_OFFSET 0x48 +#define PRESERVED_R6_OFFSET 0x4C +#define REGISTER_FILE_OFFSET 0x50 +#define CALLFRAME_OFFSET 0x54 +#define EXCEPTION_OFFSET 0x58 +#define ENABLE_PROFILER_REFERENCE_OFFSET 0x64 #elif COMPILER(GCC) && CPU(ARM_TRADITIONAL) -asm volatile ( -".globl " SYMBOL_STRING(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" -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" -SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" - "add sp, sp, #68" "\n" - "ldmia sp!, {r4-r8, lr}" "\n" - "add sp, sp, #12" "\n" - "mov pc, lr" "\n" -); +#define THUNK_RETURN_ADDRESS_OFFSET 64 +#define PRESERVEDR4_OFFSET 68 #elif COMPILER(MSVC) && CPU(X86) @@ -543,102 +465,115 @@ SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" #error "JIT_STUB_ARGUMENT_VA_LIST not supported on ARMv7." #endif -asm volatile ( +#define THUNK_RETURN_ADDRESS_OFFSET 0x1C +#define PRESERVED_RETURN_ADDRESS_OFFSET 0x20 +#define PRESERVED_R4_OFFSET 0x24 +#define PRESERVED_R5_OFFSET 0x28 +#define PRESERVED_R6_OFFSET 0x2C +#define REGISTER_FILE_OFFSET 0x30 +#define CALLFRAME_OFFSET 0x34 +#define EXCEPTION_OFFSET 0x38 +#define ENABLE_PROFILER_REFERENCE_OFFSET 0x40 + +#elif COMPILER(GCC) && CPU(ARM_TRADITIONAL) + +#define THUNK_RETURN_ADDRESS_OFFSET 32 +#define PRESERVEDR4_OFFSET 36 + +#elif CPU(MIPS) + +#if USE(JIT_STUB_ARGUMENT_VA_LIST) +#error "JIT_STUB_ARGUMENT_VA_LIST not supported on MIPS." +#endif + +asm volatile( ".text" "\n" ".align 2" "\n" +".set noreorder" "\n" +".set nomacro" "\n" +".set nomips16" "\n" ".globl " SYMBOL_STRING(ctiTrampoline) "\n" -HIDE_SYMBOL(ctiTrampoline) "\n" -".thumb" "\n" -".thumb_func " THUMB_FUNC_PARAM(ctiTrampoline) "\n" +".ent " SYMBOL_STRING(ctiTrampoline) "\n" SYMBOL_STRING(ctiTrampoline) ":" "\n" - "sub sp, sp, #0x40" "\n" - "str lr, [sp, #0x20]" "\n" - "str r4, [sp, #0x24]" "\n" - "str r5, [sp, #0x28]" "\n" - "str r6, [sp, #0x2c]" "\n" - "str r1, [sp, #0x30]" "\n" - "str r2, [sp, #0x34]" "\n" - "str r3, [sp, #0x38]" "\n" - "cpy r5, r2" "\n" - "mov r6, #512" "\n" - "blx r0" "\n" - "ldr r6, [sp, #0x2c]" "\n" - "ldr r5, [sp, #0x28]" "\n" - "ldr r4, [sp, #0x24]" "\n" - "ldr lr, [sp, #0x20]" "\n" - "add sp, sp, #0x40" "\n" - "bx lr" "\n" + "addiu $29,$29,-72" "\n" + "sw $31,44($29)" "\n" + "sw $18,40($29)" "\n" + "sw $17,36($29)" "\n" + "sw $16,32($29)" "\n" +#if WTF_MIPS_PIC + "sw $28,28($29)" "\n" +#endif + "move $16,$6 # set callFrameRegister" "\n" + "li $17,512 # set timeoutCheckRegister" "\n" + "move $25,$4 # move executableAddress to t9" "\n" + "sw $5,52($29) # store registerFile to current stack" "\n" + "sw $6,56($29) # store callFrame to curent stack" "\n" + "sw $7,60($29) # store exception to current stack" "\n" + "lw $8,88($29) # load enableProfilerReference from previous stack" "\n" + "lw $9,92($29) # load globalData from previous stack" "\n" + "sw $8,64($29) # store enableProfilerReference to current stack" "\n" + "jalr $25" "\n" + "sw $9,68($29) # store globalData to current stack" "\n" + "lw $16,32($29)" "\n" + "lw $17,36($29)" "\n" + "lw $18,40($29)" "\n" + "lw $31,44($29)" "\n" + "jr $31" "\n" + "addiu $29,$29,72" "\n" +".set reorder" "\n" +".set macro" "\n" +".end " SYMBOL_STRING(ctiTrampoline) "\n" ); -asm volatile ( +asm volatile( ".text" "\n" ".align 2" "\n" +".set noreorder" "\n" +".set nomacro" "\n" +".set nomips16" "\n" ".globl " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" -HIDE_SYMBOL(ctiVMThrowTrampoline) "\n" -".thumb" "\n" -".thumb_func " THUMB_FUNC_PARAM(ctiVMThrowTrampoline) "\n" +".ent " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" - "cpy r0, sp" "\n" - "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" - "ldr r6, [sp, #0x2c]" "\n" - "ldr r5, [sp, #0x28]" "\n" - "ldr r4, [sp, #0x24]" "\n" - "ldr lr, [sp, #0x20]" "\n" - "add sp, sp, #0x40" "\n" - "bx lr" "\n" +#if WTF_MIPS_PIC + "lw $28,28($29)" "\n" +".set macro" "\n" + "la $25," SYMBOL_STRING(cti_vm_throw) "\n" +".set nomacro" "\n" + "bal " SYMBOL_STRING(cti_vm_throw) "\n" + "move $4,$29" "\n" +#else + "jal " SYMBOL_STRING(cti_vm_throw) "\n" + "move $4,$29" "\n" +#endif + "lw $16,32($29)" "\n" + "lw $17,36($29)" "\n" + "lw $18,40($29)" "\n" + "lw $31,44($29)" "\n" + "jr $31" "\n" + "addiu $29,$29,72" "\n" +".set reorder" "\n" +".set macro" "\n" +".end " SYMBOL_STRING(ctiVMThrowTrampoline) "\n" ); -asm volatile ( +asm volatile( ".text" "\n" ".align 2" "\n" +".set noreorder" "\n" +".set nomacro" "\n" +".set nomips16" "\n" ".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" -HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" -".thumb" "\n" -".thumb_func " THUMB_FUNC_PARAM(ctiOpThrowNotCaught) "\n" -SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" - "ldr r6, [sp, #0x2c]" "\n" - "ldr r5, [sp, #0x28]" "\n" - "ldr r4, [sp, #0x24]" "\n" - "ldr lr, [sp, #0x20]" "\n" - "add sp, sp, #0x40" "\n" - "bx lr" "\n" -); - -#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" - "sub sp, sp, #36" "\n" - "mov r4, r2" "\n" - "mov r5, #512" "\n" - "mov lr, pc" "\n" - "mov pc, r0" "\n" - "add sp, sp, #36" "\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_RELOCATION(cti_vm_throw) "\n" - -// Both has the same return sequence -".globl " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" -HIDE_SYMBOL(ctiOpThrowNotCaught) "\n" +".ent " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" - "add sp, sp, #36" "\n" - "ldmia sp!, {r4-r8, lr}" "\n" - "add sp, sp, #12" "\n" - "mov pc, lr" "\n" + "lw $16,32($29)" "\n" + "lw $17,36($29)" "\n" + "lw $18,40($29)" "\n" + "lw $31,44($29)" "\n" + "jr $31" "\n" + "addiu $29,$29,72" "\n" +".set reorder" "\n" +".set macro" "\n" +".end " SYMBOL_STRING(ctiOpThrowNotCaught) "\n" ); #elif COMPILER(RVCT) && CPU(ARM_TRADITIONAL) @@ -749,6 +684,108 @@ extern "C" { #endif // USE(JSVALUE32_64) +#if COMPILER(GCC) && CPU(ARM_THUMB2) + +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" +SYMBOL_STRING(ctiTrampoline) ":" "\n" + "sub sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n" + "str lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n" + "str r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n" + "str r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n" + "str r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n" + "str r1, [sp, #" STRINGIZE_VALUE_OF(REGISTER_FILE_OFFSET) "]" "\n" + "str r2, [sp, #" STRINGIZE_VALUE_OF(CALLFRAME_OFFSET) "]" "\n" + "str r3, [sp, #" STRINGIZE_VALUE_OF(EXCEPTION_OFFSET) "]" "\n" + "cpy r5, r2" "\n" + "mov r6, #512" "\n" + "blx r0" "\n" + "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n" + "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n" + "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n" + "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n" + "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n" + "bx lr" "\n" +); + +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" +SYMBOL_STRING(ctiVMThrowTrampoline) ":" "\n" + "cpy r0, sp" "\n" + "bl " SYMBOL_STRING_RELOCATION(cti_vm_throw) "\n" + "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n" + "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n" + "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n" + "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n" + "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n" + "bx lr" "\n" +); + +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" +SYMBOL_STRING(ctiOpThrowNotCaught) ":" "\n" + "ldr r6, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R6_OFFSET) "]" "\n" + "ldr r5, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R5_OFFSET) "]" "\n" + "ldr r4, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_R4_OFFSET) "]" "\n" + "ldr lr, [sp, #" STRINGIZE_VALUE_OF(PRESERVED_RETURN_ADDRESS_OFFSET) "]" "\n" + "add sp, sp, #" STRINGIZE_VALUE_OF(ENABLE_PROFILER_REFERENCE_OFFSET) "\n" + "bx lr" "\n" +); + +#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, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n" + "mov r4, r2" "\n" + "mov r5, #512" "\n" + // r0 contains the code + "mov lr, pc" "\n" + "mov pc, r0" "\n" + "add sp, sp, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\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, #" STRINGIZE_VALUE_OF(PRESERVEDR4_OFFSET) "\n" + "ldmia sp!, {r4-r8, lr}" "\n" + "add sp, sp, #12" "\n" + "mov pc, lr" "\n" +); + +#endif + #if ENABLE(OPCODE_SAMPLING) #define CTI_SAMPLER stackFrame.globalData->interpreter->sampler() #else @@ -763,18 +800,38 @@ JITThunks::JITThunks(JSGlobalData* globalData) // 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. - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == 0x20); - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == 0x24); - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == 0x28); - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == 0x2c); - - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == 0x30); - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == 0x34); - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == 0x38); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == PRESERVED_RETURN_ADDRESS_OFFSET); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVED_R4_OFFSET); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR5) == PRESERVED_R5_OFFSET); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR6) == PRESERVED_R6_OFFSET); + + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == REGISTER_FILE_OFFSET); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == CALLFRAME_OFFSET); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == EXCEPTION_OFFSET); // The fifth argument is the first item already on the stack. - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 0x40); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == ENABLE_PROFILER_REFERENCE_OFFSET); + + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET); + +#elif CPU(ARM_TRADITIONAL) + + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == THUNK_RETURN_ADDRESS_OFFSET); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedR4) == PRESERVEDR4_OFFSET); + + +#elif CPU(MIPS) + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedGP) == 28); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS0) == 32); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS1) == 36); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedS2) == 40); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, preservedReturnAddress) == 44); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 48); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, registerFile) == 52); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, callFrame) == 56); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, exception) == 60); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, enabledProfilerReference) == 64); + ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, globalData) == 68); - ASSERT(OBJECT_OFFSETOF(struct JITStackFrame, thunkReturnAddress) == 0x1C); #endif } @@ -856,11 +913,10 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co } // Uncacheable: give up. - if (!slot.isCacheableValue()) { + if (!slot.isCacheable()) { ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_generic)); return; } - ASSERT(!slot.isGetter()); JSCell* baseCell = asCell(baseValue); Structure* structure = baseCell->structure(); @@ -875,8 +931,10 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co if (slot.slotBase() == baseValue) { // set this up, so derefStructures can do it's job. stubInfo->initGetByIdSelf(structure); - - JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); + if (slot.cachedPropertyType() != PropertySlot::Value) + ctiPatchCallByReturnAddress(codeBlock, returnAddress, FunctionPtr(cti_op_get_by_id_self_fail)); + else + JIT::patchGetByIdSelf(codeBlock, stubInfo, structure, slot.cachedOffset(), returnAddress); return; } @@ -902,7 +960,7 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co ASSERT(!structure->isDictionary()); ASSERT(!slotBaseObject->structure()->isDictionary()); - JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), offset, returnAddress); + JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), propertyName, slot, offset, returnAddress); return; } @@ -915,7 +973,7 @@ NEVER_INLINE void JITThunks::tryCacheGetByID(CallFrame* callFrame, CodeBlock* co StructureChain* prototypeChain = structure->prototypeChain(callFrame); stubInfo->initGetByIdChain(structure, prototypeChain); - JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, offset, returnAddress); + JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, prototypeChain, count, propertyName, slot, offset, returnAddress); } #endif // ENABLE(JIT_OPTIMIZE_PROPERTY_ACCESS) @@ -1025,22 +1083,73 @@ static NEVER_INLINE void throwStackOverflowError(CallFrame* callFrame, JSGlobalD ".thumb" "\n" \ ".thumb_func " THUMB_FUNC_PARAM(cti_##op) "\n" \ SYMBOL_STRING(cti_##op) ":" "\n" \ - "str lr, [sp, #0x1c]" "\n" \ + "str lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ "bl " SYMBOL_STRING(JITStubThunked_##op) "\n" \ - "ldr lr, [sp, #0x1c]" "\n" \ + "ldr lr, [sp, #" STRINGIZE_VALUE_OF(THUNK_RETURN_ADDRESS_OFFSET) "]" "\n" \ "bx lr" "\n" \ ); \ rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) \ -#elif CPU(ARM_TRADITIONAL) && COMPILER(GCC) +#elif CPU(MIPS) +#if WTF_MIPS_PIC +#define DEFINE_STUB_FUNCTION(rtype, op) \ + extern "C" { \ + rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ + }; \ + asm volatile( \ + ".text" "\n" \ + ".align 2" "\n" \ + ".set noreorder" "\n" \ + ".set nomacro" "\n" \ + ".set nomips16" "\n" \ + ".globl " SYMBOL_STRING(cti_##op) "\n" \ + ".ent " SYMBOL_STRING(cti_##op) "\n" \ + SYMBOL_STRING(cti_##op) ":" "\n" \ + "lw $28,28($29)" "\n" \ + "sw $31,48($29)" "\n" \ + ".set macro" "\n" \ + "la $25," SYMBOL_STRING(JITStubThunked_##op) "\n" \ + ".set nomacro" "\n" \ + "bal " SYMBOL_STRING(JITStubThunked_##op) "\n" \ + "nop" "\n" \ + "lw $31,48($29)" "\n" \ + "jr $31" "\n" \ + "nop" "\n" \ + ".set reorder" "\n" \ + ".set macro" "\n" \ + ".end " SYMBOL_STRING(cti_##op) "\n" \ + ); \ + rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) + +#else // WTF_MIPS_PIC +#define DEFINE_STUB_FUNCTION(rtype, op) \ + extern "C" { \ + rtype JITStubThunked_##op(STUB_ARGS_DECLARATION); \ + }; \ + asm volatile( \ + ".text" "\n" \ + ".align 2" "\n" \ + ".set noreorder" "\n" \ + ".set nomacro" "\n" \ + ".set nomips16" "\n" \ + ".globl " SYMBOL_STRING(cti_##op) "\n" \ + ".ent " SYMBOL_STRING(cti_##op) "\n" \ + SYMBOL_STRING(cti_##op) ":" "\n" \ + "sw $31,48($29)" "\n" \ + "jal " SYMBOL_STRING(JITStubThunked_##op) "\n" \ + "nop" "\n" \ + "lw $31,48($29)" "\n" \ + "jr $31" "\n" \ + "nop" "\n" \ + ".set reorder" "\n" \ + ".set macro" "\n" \ + ".end " SYMBOL_STRING(cti_##op) "\n" \ + ); \ + rtype JITStubThunked_##op(STUB_ARGS_DECLARATION) -#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); +#elif CPU(ARM_TRADITIONAL) && COMPILER(GCC) #define DEFINE_STUB_FUNCTION(rtype, op) \ extern "C" { \ @@ -1148,15 +1257,18 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_pre_inc) DEFINE_STUB_FUNCTION(int, timeout_check) { STUB_INIT_STACK_FRAME(stackFrame); - + JSGlobalData* globalData = stackFrame.globalData; TimeoutChecker& timeoutChecker = globalData->timeoutChecker; - if (timeoutChecker.didTimeOut(stackFrame.callFrame)) { + if (globalData->terminator.shouldTerminate()) { + globalData->exception = createTerminatedExecutionException(globalData); + VM_THROW_EXCEPTION_AT_END(); + } else if (timeoutChecker.didTimeOut(stackFrame.callFrame)) { globalData->exception = createInterruptedExecutionException(globalData); VM_THROW_EXCEPTION_AT_END(); } - + return timeoutChecker.ticksUntilNextCheck(); } @@ -1375,7 +1487,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail) CHECK_FOR_EXCEPTION(); if (baseValue.isCell() - && slot.isCacheableValue() + && slot.isCacheable() && !asCell(baseValue)->structure()->isUncacheableDictionary() && slot.slotBase() == baseValue) { @@ -1397,7 +1509,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_self_fail) stubInfo->u.getByIdSelfList.listSize++; } - JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset()); + JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), ident, slot, slot.cachedOffset()); if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_generic)); @@ -1435,6 +1547,37 @@ static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(Str return prototypeStructureList; } +DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_getter_stub) +{ + STUB_INIT_STACK_FRAME(stackFrame); + CallFrame* callFrame = stackFrame.callFrame; + GetterSetter* getterSetter = asGetterSetter(stackFrame.args[0].jsObject()); + if (!getterSetter->getter()) + return JSValue::encode(jsUndefined()); + JSObject* getter = asObject(getterSetter->getter()); + CallData callData; + CallType callType = getter->getCallData(callData); + JSValue result = call(callFrame, getter, callType, callData, stackFrame.args[1].jsObject(), ArgList()); + if (callFrame->hadException()) + returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[2].returnAddress(), STUB_RETURN_ADDRESS); + + return JSValue::encode(result); +} + +DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_custom_stub) +{ + STUB_INIT_STACK_FRAME(stackFrame); + CallFrame* callFrame = stackFrame.callFrame; + JSObject* slotBase = stackFrame.args[0].jsObject(); + PropertySlot::GetValueFunc getter = reinterpret_cast<PropertySlot::GetValueFunc>(stackFrame.args[1].asPointer); + const Identifier& ident = stackFrame.args[2].identifier(); + JSValue result = getter(callFrame, slotBase, ident); + if (callFrame->hadException()) + returnToThrowTrampoline(&callFrame->globalData(), stackFrame.args[3].returnAddress(), STUB_RETURN_ADDRESS); + + return JSValue::encode(result); +} + DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) { STUB_INIT_STACK_FRAME(stackFrame); @@ -1448,7 +1591,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) CHECK_FOR_EXCEPTION(); - if (!baseValue.isCell() || !slot.isCacheableValue() || asCell(baseValue)->structure()->isDictionary()) { + 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); } @@ -1476,7 +1619,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) int listIndex; PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); - JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), offset); + JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), propertyName, slot, offset); if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full)); @@ -1486,7 +1629,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_proto_list) PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex); StructureChain* protoChain = structure->prototypeChain(callFrame); - JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, offset); + JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, protoChain, count, propertyName, slot, offset); if (listIndex == (POLYMORPHIC_LIST_CACHE_SIZE - 1)) ctiPatchCallByReturnAddress(codeBlock, STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_id_proto_list_full)); @@ -2518,10 +2661,9 @@ DEFINE_STUB_FUNCTION(int, op_eq) #endif // USE(JSVALUE32_64) } -#if USE(JSVALUE32_64) - DEFINE_STUB_FUNCTION(int, op_eq_strings) { +#if USE(JSVALUE32_64) STUB_INIT_STACK_FRAME(stackFrame); JSString* string1 = stackFrame.args[0].jsString(); @@ -2530,9 +2672,12 @@ DEFINE_STUB_FUNCTION(int, op_eq_strings) ASSERT(string1->isString()); ASSERT(string2->isString()); return string1->value(stackFrame.callFrame) == string2->value(stackFrame.callFrame); -} - +#else + UNUSED_PARAM(args); + ASSERT_NOT_REACHED(); + return 0; #endif +} DEFINE_STUB_FUNCTION(EncodedJSValue, op_lshift) { @@ -2713,13 +2858,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitxor) return JSValue::encode(result); } -DEFINE_STUB_FUNCTION(JSObject*, op_new_regexp) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - return new (stackFrame.globalData) RegExpObject(stackFrame.callFrame->lexicalGlobalObject()->regExpStructure(), stackFrame.args[0].regExp()); -} - DEFINE_STUB_FUNCTION(EncodedJSValue, op_bitor) { STUB_INIT_STACK_FRAME(stackFrame); @@ -3025,7 +3163,7 @@ DEFINE_STUB_FUNCTION(void*, op_switch_char) if (scrutinee.isString()) { UString::Rep* value = asString(scrutinee)->value(callFrame).rep(); if (value->length() == 1) - result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->data()[0]).executableAddress(); + result = codeBlock->characterSwitchJumpTable(tableIndex).ctiForValue(value->characters()[0]).executableAddress(); } return result; diff --git a/JavaScriptCore/jit/JITStubs.h b/JavaScriptCore/jit/JITStubs.h index 17fd0d9..f419c8c 100644 --- a/JavaScriptCore/jit/JITStubs.h +++ b/JavaScriptCore/jit/JITStubs.h @@ -29,8 +29,6 @@ #ifndef JITStubs_h #define JITStubs_h -#include <wtf/Platform.h> - #include "MacroAssemblerCodeRef.h" #include "Register.h" @@ -108,10 +106,10 @@ namespace JSC { ReturnAddressPtr* returnAddressSlot() { return reinterpret_cast<ReturnAddressPtr*>(this) - 1; } }; #elif CPU(X86) -#if COMPILER(MSVC) +#if COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC)) #pragma pack(push) #pragma pack(4) -#endif // COMPILER(MSVC) +#endif // COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC)) struct JITStackFrame { void* reserved; // Unused JITStubArg args[6]; @@ -135,9 +133,9 @@ 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; } }; -#if COMPILER(MSVC) +#if COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC)) #pragma pack(pop) -#endif // COMPILER(MSVC) +#endif // COMPILER(MSVC) || (OS(WINDOWS) && COMPILER(GCC)) #elif CPU(ARM_THUMB2) struct JITStackFrame { void* reserved; // Unused @@ -191,6 +189,30 @@ namespace JSC { // When JIT code makes a call, it pushes its return address just below the rest of the stack. ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; } }; +#elif CPU(MIPS) + struct JITStackFrame { + void* reserved; // Unused + JITStubArg args[6]; + + void* preservedGP; // store GP when using PIC code + void* preservedS0; + void* preservedS1; + void* preservedS2; + void* preservedReturnAddress; + + ReturnAddressPtr thunkReturnAddress; + + // These arguments passed in a1..a3 (a0 contained the entry code pointed, which is not preserved) + RegisterFile* registerFile; + CallFrame* callFrame; + JSValue* exception; + + // These arguments passed on the stack. + Profiler** enabledProfilerReference; + JSGlobalData* globalData; + + ReturnAddressPtr* returnAddressSlot() { return &thunkReturnAddress; } + }; #else #error "JITStackFrame not defined for this platform." #endif @@ -276,6 +298,8 @@ extern "C" { EncodedJSValue JIT_STUB cti_op_get_by_id_array_fail(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_get_by_id_generic(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_get_by_id_method_check(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_getter_stub(STUB_ARGS_DECLARATION); + EncodedJSValue JIT_STUB cti_op_get_by_id_custom_stub(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_get_by_id_proto_fail(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_get_by_id_proto_list_full(STUB_ARGS_DECLARATION); @@ -326,7 +350,6 @@ extern "C" { JSObject* JIT_STUB cti_op_new_func(STUB_ARGS_DECLARATION); JSObject* JIT_STUB cti_op_new_func_exp(STUB_ARGS_DECLARATION); JSObject* JIT_STUB cti_op_new_object(STUB_ARGS_DECLARATION); - JSObject* JIT_STUB cti_op_new_regexp(STUB_ARGS_DECLARATION); JSObject* JIT_STUB cti_op_push_activation(STUB_ARGS_DECLARATION); JSObject* JIT_STUB cti_op_push_new_scope(STUB_ARGS_DECLARATION); JSObject* JIT_STUB cti_op_push_scope(STUB_ARGS_DECLARATION); @@ -334,9 +357,7 @@ extern "C" { JSPropertyNameIterator* JIT_STUB cti_op_get_pnames(STUB_ARGS_DECLARATION); VoidPtrPair JIT_STUB cti_op_call_arityCheck(STUB_ARGS_DECLARATION); int JIT_STUB cti_op_eq(STUB_ARGS_DECLARATION); -#if USE(JSVALUE32_64) int JIT_STUB cti_op_eq_strings(STUB_ARGS_DECLARATION); -#endif int JIT_STUB cti_op_jless(STUB_ARGS_DECLARATION); int JIT_STUB cti_op_jlesseq(STUB_ARGS_DECLARATION); int JIT_STUB cti_op_jtrue(STUB_ARGS_DECLARATION); diff --git a/JavaScriptCore/jsc.cpp b/JavaScriptCore/jsc.cpp index 252fb96..ae47d55 100644 --- a/JavaScriptCore/jsc.cpp +++ b/JavaScriptCore/jsc.cpp @@ -79,7 +79,7 @@ static JSValue JSC_HOST_CALL functionRun(ExecState*, JSObject*, JSValue, const A static JSValue JSC_HOST_CALL functionLoad(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL functionCheckSyntax(ExecState*, JSObject*, JSValue, const ArgList&); static JSValue JSC_HOST_CALL functionReadline(ExecState*, JSObject*, JSValue, const ArgList&); -static NO_RETURN JSValue JSC_HOST_CALL functionQuit(ExecState*, JSObject*, JSValue, const ArgList&); +static NO_RETURN_WITH_VALUE JSValue JSC_HOST_CALL functionQuit(ExecState*, JSObject*, JSValue, const ArgList&); #if ENABLE(SAMPLING_FLAGS) static JSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*, JSObject*, JSValue, const ArgList&); @@ -177,7 +177,7 @@ JSValue JSC_HOST_CALL functionPrint(ExecState* exec, JSObject*, JSValue, const A if (i) putchar(' '); - printf("%s", args.at(i).toString(exec).UTF8String().c_str()); + printf("%s", args.at(i).toString(exec).UTF8String().data()); } putchar('\n'); @@ -187,7 +187,7 @@ JSValue JSC_HOST_CALL functionPrint(ExecState* exec, JSObject*, JSValue, const A JSValue JSC_HOST_CALL functionDebug(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - fprintf(stderr, "--> %s\n", args.at(0).toString(exec).UTF8String().c_str()); + fprintf(stderr, "--> %s\n", args.at(0).toString(exec).UTF8String().data()); return jsUndefined(); } @@ -346,7 +346,7 @@ int main(int argc, char** argv) // We can't use destructors in the following code because it uses Windows // Structured Exception Handling int res = 0; - JSGlobalData* globalData = JSGlobalData::create().releaseRef(); + JSGlobalData* globalData = JSGlobalData::create(ThreadStackTypeLarge).releaseRef(); TRY res = jscmain(argc, argv, globalData); EXCEPT(res = 3) @@ -445,7 +445,7 @@ static void runInteractive(GlobalObject* globalObject) if (completion.complType() == Throw) printf("Exception: %s\n", completion.value().toString(globalObject->globalExec()).ascii()); else - printf("%s\n", completion.value().toString(globalObject->globalExec()).UTF8String().c_str()); + printf("%s\n", completion.value().toString(globalObject->globalExec()).UTF8String().data()); globalObject->globalExec()->clearException(); } @@ -535,9 +535,9 @@ int jscmain(int argc, char** argv, JSGlobalData* globalData) static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer) { - FILE* f = fopen(fileName.UTF8String().c_str(), "r"); + FILE* f = fopen(fileName.UTF8String().data(), "r"); if (!f) { - fprintf(stderr, "Could not open file: %s\n", fileName.UTF8String().c_str()); + fprintf(stderr, "Could not open file: %s\n", fileName.UTF8String().data()); return false; } diff --git a/JavaScriptCore/jsc.pro b/JavaScriptCore/jsc.pro index 9bcf08b..420a3f1 100644 --- a/JavaScriptCore/jsc.pro +++ b/JavaScriptCore/jsc.pro @@ -8,13 +8,13 @@ CONFIG += building-libs win32-*: CONFIG += console win32-msvc*: CONFIG += exceptions_off stl_off +isEmpty(OUTPUT_DIR): OUTPUT_DIR= .. include($$PWD/../WebKit.pri) CONFIG += link_pkgconfig QMAKE_RPATHDIR += $$OUTPUT_DIR/lib -isEmpty(OUTPUT_DIR):OUTPUT_DIR=$$PWD/.. CONFIG(debug, debug|release) { OBJECTS_DIR = obj/debug } else { # Release @@ -22,9 +22,7 @@ CONFIG(debug, debug|release) { } OBJECTS_DIR_WTR = $$OBJECTS_DIR$${QMAKE_DIR_SEP} include($$PWD/JavaScriptCore.pri) - -*-g++*:QMAKE_CXXFLAGS_RELEASE -= -O2 -*-g++*:QMAKE_CXXFLAGS_RELEASE += -O3 +addJavaScriptCoreLib(.) symbian { TARGET.CAPABILITY = ReadUserData WriteUserData NetworkServices diff --git a/JavaScriptCore/make-generated-sources.sh b/JavaScriptCore/make-generated-sources.sh index 943a7cc..a6b0f63 100755 --- a/JavaScriptCore/make-generated-sources.sh +++ b/JavaScriptCore/make-generated-sources.sh @@ -3,6 +3,7 @@ export SRCROOT=$PWD export WebCore=$PWD export CREATE_HASH_TABLE="$SRCROOT/create_hash_table" +export CREATE_REGEXP_TABLES="$SRCROOT/create_regex_tables" mkdir -p DerivedSources/JavaScriptCore cd DerivedSources/JavaScriptCore diff --git a/JavaScriptCore/os-win32/stdint.h b/JavaScriptCore/os-win32/stdint.h index 1d8787e..b5dff56 100644 --- a/JavaScriptCore/os-win32/stdint.h +++ b/JavaScriptCore/os-win32/stdint.h @@ -61,7 +61,7 @@ CASSERT(sizeof(int16_t) == 2, int16_t_is_two_bytes) CASSERT(sizeof(uint16_t) == 2, uint16_t_is_two_bytes) CASSERT(sizeof(int32_t) == 4, int32_t_is_four_bytes) CASSERT(sizeof(uint32_t) == 4, uint32_t_is_four_bytes) -CASSERT(sizeof(int64_t) == 8, int64_t_is_four_bytes) -CASSERT(sizeof(uint64_t) == 8, uint64_t_is_four_bytes) +CASSERT(sizeof(int64_t) == 8, int64_t_is_eight_bytes) +CASSERT(sizeof(uint64_t) == 8, uint64_t_is_eight_bytes) #endif diff --git a/JavaScriptCore/parser/Grammar.y b/JavaScriptCore/parser/Grammar.y index a017cff..4d6e7d1 100644 --- a/JavaScriptCore/parser/Grammar.y +++ b/JavaScriptCore/parser/Grammar.y @@ -1147,7 +1147,7 @@ ThrowStatement: ; TryStatement: - TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->emptyIdentifier, false, 0, $4.m_node), + TRY Block FINALLY Block { $$ = createNodeDeclarationInfo<StatementNode*>(new (GLOBAL_DATA) TryNode(GLOBAL_DATA, $2.m_node, GLOBAL_DATA->propertyNames->nullIdentifier, false, 0, $4.m_node), mergeDeclarationLists($2.m_varDeclarations, $4.m_varDeclarations), mergeDeclarationLists($2.m_funcDeclarations, $4.m_funcDeclarations), $2.m_features | $4.m_features, @@ -1188,10 +1188,10 @@ FunctionDeclaration: ; FunctionExpr: - FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->emptyIdentifier, $5, GLOBAL_DATA->lexer->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); setStatementLocation($5, @4, @6); } + FUNCTION '(' ')' OPENBRACE FunctionBody CLOSEBRACE { $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $5, GLOBAL_DATA->lexer->sourceCode($4, $6, @4.first_line)), ClosureFeature, 0); setStatementLocation($5, @4, @6); } | FUNCTION '(' FormalParameterList ')' OPENBRACE FunctionBody CLOSEBRACE { - $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->emptyIdentifier, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0); + $$ = createNodeInfo(new (GLOBAL_DATA) FuncExprNode(GLOBAL_DATA, GLOBAL_DATA->propertyNames->nullIdentifier, $6, GLOBAL_DATA->lexer->sourceCode($5, $7, @5.first_line), $3.m_node.head), $3.m_features | ClosureFeature, 0); if ($3.m_features & ArgumentsFeature) $6->setUsesArguments(); setStatementLocation($6, @5, @7); @@ -1981,18 +1981,15 @@ static PropertyNode* makeGetterOrSetterPropertyNode(JSGlobalData* globalData, co type = PropertyNode::Setter; else return 0; - return new (globalData) PropertyNode(globalData, name, new (globalData) FuncExprNode(globalData, globalData->propertyNames->emptyIdentifier, body, source, params), type); + return new (globalData) PropertyNode(globalData, name, new (globalData) FuncExprNode(globalData, globalData->propertyNames->nullIdentifier, body, source, params), type); } static ExpressionNode* makeNegateNode(JSGlobalData* globalData, ExpressionNode* n) { if (n->isNumber()) { - NumberNode* number = static_cast<NumberNode*>(n); - - if (number->value() > 0.0) { - number->setValue(-number->value()); - return number; - } + NumberNode* numberNode = static_cast<NumberNode*>(n); + numberNode->setValue(-numberNode->value()); + return numberNode; } return new (globalData) NegateNode(globalData, n); diff --git a/JavaScriptCore/parser/NodeConstructors.h b/JavaScriptCore/parser/NodeConstructors.h index fa8dd4b..dd3b981 100644 --- a/JavaScriptCore/parser/NodeConstructors.h +++ b/JavaScriptCore/parser/NodeConstructors.h @@ -741,7 +741,7 @@ namespace JSC { inline ContinueNode::ContinueNode(JSGlobalData* globalData) : StatementNode(globalData) - , m_ident(globalData->propertyNames->emptyIdentifier) + , m_ident(globalData->propertyNames->nullIdentifier) { } @@ -753,7 +753,7 @@ namespace JSC { inline BreakNode::BreakNode(JSGlobalData* globalData) : StatementNode(globalData) - , m_ident(globalData->propertyNames->emptyIdentifier) + , m_ident(globalData->propertyNames->nullIdentifier) { } @@ -877,7 +877,7 @@ namespace JSC { inline ForInNode::ForInNode(JSGlobalData* globalData, ExpressionNode* l, ExpressionNode* expr, StatementNode* statement) : StatementNode(globalData) - , m_ident(globalData->propertyNames->emptyIdentifier) + , m_ident(globalData->propertyNames->nullIdentifier) , m_init(0) , m_lexpr(l) , m_expr(expr) diff --git a/JavaScriptCore/parser/Nodes.h b/JavaScriptCore/parser/Nodes.h index c216ea8..7852165 100644 --- a/JavaScriptCore/parser/Nodes.h +++ b/JavaScriptCore/parser/Nodes.h @@ -1385,12 +1385,6 @@ namespace JSC { using ParserArenaRefCounted::operator new; - void adoptData(std::auto_ptr<ScopeNodeData> data) - { - ASSERT(!data->m_arena.contains(this)); - ASSERT(!m_data); - m_data.adopt(data); - } ScopeNodeData* data() const { return m_data.get(); } void destroyData() { m_data.clear(); } diff --git a/JavaScriptCore/parser/Parser.cpp b/JavaScriptCore/parser/Parser.cpp index 56c96b4..48627df 100644 --- a/JavaScriptCore/parser/Parser.cpp +++ b/JavaScriptCore/parser/Parser.cpp @@ -27,9 +27,6 @@ #include "Lexer.h" #include <wtf/HashSet.h> #include <wtf/Vector.h> -#include <memory> - -using std::auto_ptr; #ifndef yyparse extern int jscyyparse(void*); diff --git a/JavaScriptCore/pcre/pcre_exec.cpp b/JavaScriptCore/pcre/pcre_exec.cpp index 8ca2eb4..50973d0 100644 --- a/JavaScriptCore/pcre/pcre_exec.cpp +++ b/JavaScriptCore/pcre/pcre_exec.cpp @@ -198,7 +198,7 @@ static void pchars(const UChar* p, int length, bool isSubject, const MatchData& length = md.endSubject - p; while (length-- > 0) { int c; - if (isprint(c = *(p++))) + if (isASCIIPrintable(c = *(p++))) printf("%c", c); else if (c < 256) printf("\\x%02x", c); diff --git a/JavaScriptCore/profiler/CallIdentifier.h b/JavaScriptCore/profiler/CallIdentifier.h index ba48c55..f2d04fc 100644 --- a/JavaScriptCore/profiler/CallIdentifier.h +++ b/JavaScriptCore/profiler/CallIdentifier.h @@ -44,7 +44,7 @@ namespace JSC { CallIdentifier(const UString& name, const UString& url, int lineNumber) : m_name(name) - , m_url(url) + , m_url(!url.isNull() ? url : "") , m_lineNumber(lineNumber) { } @@ -71,7 +71,7 @@ namespace JSC { #ifndef NDEBUG operator const char*() const { return c_str(); } - const char* c_str() const { return m_name.UTF8String().c_str(); } + const char* c_str() const { return m_name.UTF8String().data(); } #endif }; diff --git a/JavaScriptCore/profiler/Profile.cpp b/JavaScriptCore/profiler/Profile.cpp index c90f9b0..126e6f6 100644 --- a/JavaScriptCore/profiler/Profile.cpp +++ b/JavaScriptCore/profiler/Profile.cpp @@ -127,7 +127,7 @@ void Profile::debugPrintDataSampleStyle() const std::sort(sortedFunctions.begin(), sortedFunctions.end(), functionNameCountPairComparator); for (NameCountPairVector::iterator it = sortedFunctions.begin(); it != sortedFunctions.end(); ++it) - printf(" %-12d%s\n", (*it).second, UString((*it).first).UTF8String().c_str()); + printf(" %-12d%s\n", (*it).second, UString((*it).first).UTF8String().data()); printf("\nSort by top of stack, same collapsed (when >= 5):\n"); } diff --git a/JavaScriptCore/profiler/ProfileGenerator.cpp b/JavaScriptCore/profiler/ProfileGenerator.cpp index f367033..bdfa27b 100644 --- a/JavaScriptCore/profiler/ProfileGenerator.cpp +++ b/JavaScriptCore/profiler/ProfileGenerator.cpp @@ -77,7 +77,7 @@ void ProfileGenerator::willExecute(const CallIdentifier& callIdentifier) if (JAVASCRIPTCORE_PROFILE_WILL_EXECUTE_ENABLED()) { CString name = callIdentifier.m_name.UTF8String(); CString url = callIdentifier.m_url.UTF8String(); - JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(m_profileGroup, const_cast<char*>(name.c_str()), const_cast<char*>(url.c_str()), callIdentifier.m_lineNumber); + JAVASCRIPTCORE_PROFILE_WILL_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.m_lineNumber); } if (!m_originatingGlobalExec) @@ -92,7 +92,7 @@ void ProfileGenerator::didExecute(const CallIdentifier& callIdentifier) if (JAVASCRIPTCORE_PROFILE_DID_EXECUTE_ENABLED()) { CString name = callIdentifier.m_name.UTF8String(); CString url = callIdentifier.m_url.UTF8String(); - JAVASCRIPTCORE_PROFILE_DID_EXECUTE(m_profileGroup, const_cast<char*>(name.c_str()), const_cast<char*>(url.c_str()), callIdentifier.m_lineNumber); + JAVASCRIPTCORE_PROFILE_DID_EXECUTE(m_profileGroup, const_cast<char*>(name.data()), const_cast<char*>(url.data()), callIdentifier.m_lineNumber); } if (!m_originatingGlobalExec) diff --git a/JavaScriptCore/profiler/ProfileNode.cpp b/JavaScriptCore/profiler/ProfileNode.cpp index fb126b3..f60c72e 100644 --- a/JavaScriptCore/profiler/ProfileNode.cpp +++ b/JavaScriptCore/profiler/ProfileNode.cpp @@ -32,6 +32,7 @@ #include "Profiler.h" #include <stdio.h> #include <wtf/DateMath.h> +#include <wtf/text/StringHash.h> #if OS(WINDOWS) #include <windows.h> @@ -293,11 +294,11 @@ void ProfileNode::debugPrintData(int indentLevel) const printf(" "); printf("Function Name %s %d SelfTime %.3fms/%.3f%% TotalTime %.3fms/%.3f%% VSelf %.3fms VTotal %.3fms Visible %s Next Sibling %s\n", - functionName().UTF8String().c_str(), + functionName().UTF8String().data(), m_numberOfCalls, m_actualSelfTime, selfPercent(), m_actualTotalTime, totalPercent(), m_visibleSelfTime, m_visibleTotalTime, (m_visible ? "True" : "False"), - m_nextSibling ? m_nextSibling->functionName().UTF8String().c_str() : ""); + m_nextSibling ? m_nextSibling->functionName().UTF8String().data() : ""); ++indentLevel; @@ -312,7 +313,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC printf(" "); // Print function names - const char* name = functionName().UTF8String().c_str(); + const char* name = functionName().UTF8String().data(); double sampleCount = m_actualTotalTime * 1000; if (indentLevel) { for (int i = 0; i < indentLevel; ++i) @@ -338,7 +339,7 @@ double ProfileNode::debugPrintDataSampleStyle(int indentLevel, FunctionCallHashC while (indentLevel--) printf(" "); - printf("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().UTF8String().c_str()); + printf("%.0f %s\n", sampleCount - sumOfChildrensCount, functionName().UTF8String().data()); } return m_actualTotalTime; diff --git a/JavaScriptCore/qt/api/QtScript.pro b/JavaScriptCore/qt/api/QtScript.pro index c87eaf4..88629c7 100644 --- a/JavaScriptCore/qt/api/QtScript.pro +++ b/JavaScriptCore/qt/api/QtScript.pro @@ -13,14 +13,20 @@ CONFIG(debug, debug|release) { OBJECTS_DIR = obj/release } +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../.. include($$PWD/../../../WebKit.pri) + include($$PWD/../../JavaScriptCore.pri) +addJavaScriptCoreLib(../..) INCLUDEPATH += $$PWD/../../API SOURCES += $$PWD/qscriptengine.cpp \ $$PWD/qscriptengine_p.cpp \ $$PWD/qscriptvalue.cpp \ + $$PWD/qscriptstring.cpp \ + $$PWD/qscriptprogram.cpp \ + $$PWD/qscriptsyntaxcheckresult.cpp \ HEADERS += $$PWD/qtscriptglobal.h \ $$PWD/qscriptengine.h \ @@ -28,9 +34,13 @@ HEADERS += $$PWD/qtscriptglobal.h \ $$PWD/qscriptvalue.h \ $$PWD/qscriptvalue_p.h \ $$PWD/qscriptconverter_p.h \ + $$PWD/qscriptstring.h \ + $$PWD/qscriptstring_p.h \ + $$PWD/qscriptprogram.h \ + $$PWD/qscriptprogram_p.h \ + $$PWD/qscriptsyntaxcheckresult.h \ !static: DEFINES += QT_MAKEDLL DESTDIR = $$OUTPUT_DIR/lib - diff --git a/JavaScriptCore/qt/api/qscriptconverter_p.h b/JavaScriptCore/qt/api/qscriptconverter_p.h index c3ca41f..cd86e20 100644 --- a/JavaScriptCore/qt/api/qscriptconverter_p.h +++ b/JavaScriptCore/qt/api/qscriptconverter_p.h @@ -21,7 +21,11 @@ #define qscriptconverter_p_h #include <JavaScriptCore/JavaScript.h> +#include <QtCore/qnumeric.h> #include <QtCore/qstring.h> +#include <QtCore/qvarlengtharray.h> + +extern char *qdtoa(double d, int mode, int ndigits, int *decpt, int *sign, char **rve, char **digits_str); /* \internal @@ -33,6 +37,19 @@ */ class QScriptConverter { public: + static quint32 toArrayIndex(const JSStringRef jsstring) + { + // FIXME this function should be exported by JSC C API. + QString qstring = toString(jsstring); + + bool ok; + quint32 idx = qstring.toUInt(&ok); + if (!ok || toString(idx) != qstring) + idx = 0xffffffff; + + return idx; + } + static QString toString(const JSStringRef str) { return QString(reinterpret_cast<const QChar*>(JSStringGetCharactersPtr(str)), JSStringGetLength(str)); @@ -45,6 +62,71 @@ public: { return JSStringCreateWithUTF8CString(str); } + static QString toString(double value) + { + // FIXME this should be easier. The ideal fix is to create + // a new function in JSC C API which could cover the functionality. + + if (qIsNaN(value)) + return QString::fromLatin1("NaN"); + if (qIsInf(value)) + return QString::fromLatin1(value < 0 ? "-Infinity" : "Infinity"); + if (!value) + return QString::fromLatin1("0"); + + QVarLengthArray<char, 25> buf; + int decpt; + int sign; + char* result = 0; + char* endresult; + (void)qdtoa(value, 0, 0, &decpt, &sign, &endresult, &result); + + if (!result) + return QString(); + + int resultLen = endresult - result; + if (decpt <= 0 && decpt > -6) { + buf.resize(-decpt + 2 + sign); + qMemSet(buf.data(), '0', -decpt + 2 + sign); + if (sign) // fix the sign. + buf[0] = '-'; + buf[sign + 1] = '.'; + buf.append(result, resultLen); + } else { + if (sign) + buf.append('-'); + int length = buf.size() - sign + resultLen; + if (decpt <= 21 && decpt > 0) { + if (length <= decpt) { + const char* zeros = "0000000000000000000000000"; + buf.append(result, resultLen); + buf.append(zeros, decpt - length); + } else { + buf.append(result, decpt); + buf.append('.'); + buf.append(result + decpt, resultLen - decpt); + } + } else if (result[0] >= '0' && result[0] <= '9') { + if (length > 1) { + buf.append(result, 1); + buf.append('.'); + buf.append(result + 1, resultLen - 1); + } else + buf.append(result, resultLen); + buf.append('e'); + buf.append(decpt >= 0 ? '+' : '-'); + int e = qAbs(decpt - 1); + if (e >= 100) + buf.append('0' + e / 100); + if (e >= 10) + buf.append('0' + (e % 100) / 10); + buf.append('0' + e % 10); + } + } + free(result); + buf.append(0); + return QString::fromLatin1(buf.constData()); + } }; #endif // qscriptconverter_p_h diff --git a/JavaScriptCore/qt/api/qscriptengine.cpp b/JavaScriptCore/qt/api/qscriptengine.cpp index fbeb902..d49c578 100644 --- a/JavaScriptCore/qt/api/qscriptengine.cpp +++ b/JavaScriptCore/qt/api/qscriptengine.cpp @@ -22,6 +22,8 @@ #include "qscriptengine.h" #include "qscriptengine_p.h" +#include "qscriptprogram_p.h" +#include "qscriptsyntaxcheckresult_p.h" #include "qscriptvalue_p.h" /*! @@ -42,6 +44,23 @@ QScriptEngine::~QScriptEngine() } /*! + Checks the syntax of the given \a program. Returns a + QScriptSyntaxCheckResult object that contains the result of the check. +*/ +QScriptSyntaxCheckResult QScriptEngine::checkSyntax(const QString &program) +{ + // FIXME This is not optimal. + // The JSC C API needs a context to perform a syntax check, it means that a QScriptEnginePrivate + // had to be created. This function is static so we have to create QScriptEnginePrivate for each + // call. We can't remove the "static" for compatibility reason, at least up to Qt5. + // QScriptSyntaxCheckResultPrivate takes ownership of newly created engine. The engine will be + // kept as long as it is needed for lazy evaluation of properties of + // the QScriptSyntaxCheckResultPrivate. + QScriptEnginePrivate* engine = new QScriptEnginePrivate(/* q_ptr */ 0); + return QScriptSyntaxCheckResultPrivate::get(engine->checkSyntax(program)); +} + +/*! Evaluates \a program, using \a lineNumber as the base line number, and returns the result of the evaluation. @@ -71,6 +90,11 @@ QScriptValue QScriptEngine::evaluate(const QString& program, const QString& file return QScriptValuePrivate::get(d_ptr->evaluate(program, fileName, lineNumber)); } +QScriptValue QScriptEngine::evaluate(const QScriptProgram& program) +{ + return QScriptValuePrivate::get(d_ptr->evaluate(QScriptProgramPrivate::get(program))); +} + /*! Runs the garbage collector. @@ -81,6 +105,8 @@ QScriptValue QScriptEngine::evaluate(const QString& program, const QString& file when the QScriptEngine decides that it's wise to do so (i.e. when a certain number of new objects have been created). However, you can call this function to explicitly request that garbage collection should be performed as soon as possible. + + \sa reportAdditionalMemoryCost() */ void QScriptEngine::collectGarbage() { @@ -88,6 +114,43 @@ void QScriptEngine::collectGarbage() } /*! + Reports an additional memory cost of the given \a size, measured in + bytes, to the garbage collector. + + This function can be called to indicate that a JavaScript object has + memory associated with it that isn't managed by Qt Script itself. + Reporting the additional cost makes it more likely that the garbage + collector will be triggered. + + Note that if the additional memory is shared with objects outside + the scripting environment, the cost should not be reported, since + collecting the JavaScript object would not cause the memory to be + freed anyway. + + Negative \a size values are ignored, i.e. this function can't be + used to report that the additional memory has been deallocated. + + \sa collectGarbage() +*/ +void QScriptEngine::reportAdditionalMemoryCost(int cost) +{ + d_ptr->reportAdditionalMemoryCost(cost); +} + +/*! + Returns a handle that represents the given string, \a str. + + QScriptString can be used to quickly look up properties, and + compare property names, of script objects. + + \sa QScriptValue::property() +*/ +QScriptString QScriptEngine::toStringHandle(const QString& str) +{ + return QScriptStringPrivate::get(d_ptr->toStringHandle(str)); +} + +/*! Returns a QScriptValue of the primitive type Null. \sa undefinedValue() @@ -106,3 +169,18 @@ QScriptValue QScriptEngine::undefinedValue() { return QScriptValue(this, QScriptValue::UndefinedValue); } + +/*! + Returns this engine's Global Object. + + By default, the Global Object contains the built-in objects that are + part of \l{ECMA-262}, such as Math, Date and String. Additionally, + you can set properties of the Global Object to make your own + extensions available to all script code. Non-local variables in + script code will be created as properties of the Global Object, as + well as local variables in global code. +*/ +QScriptValue QScriptEngine::globalObject() const +{ + return QScriptValuePrivate::get(d_ptr->globalObject()); +} diff --git a/JavaScriptCore/qt/api/qscriptengine.h b/JavaScriptCore/qt/api/qscriptengine.h index b8bd5e6..e10888d 100644 --- a/JavaScriptCore/qt/api/qscriptengine.h +++ b/JavaScriptCore/qt/api/qscriptengine.h @@ -20,6 +20,9 @@ #ifndef qscriptengine_h #define qscriptengine_h +#include "qscriptprogram.h" +#include "qscriptstring.h" +#include "qscriptsyntaxcheckresult.h" #include <QtCore/qobject.h> #include <QtCore/qshareddata.h> #include <QtCore/qstring.h> @@ -35,11 +38,18 @@ public: QScriptEngine(); ~QScriptEngine(); + static QScriptSyntaxCheckResult checkSyntax(const QString& program); QScriptValue evaluate(const QString& program, const QString& fileName = QString(), int lineNumber = 1); + QScriptValue evaluate(const QScriptProgram& program); + void collectGarbage(); + void reportAdditionalMemoryCost(int cost); + + QScriptString toStringHandle(const QString& str); QScriptValue nullValue(); QScriptValue undefinedValue(); + QScriptValue globalObject() const; private: friend class QScriptEnginePrivate; diff --git a/JavaScriptCore/qt/api/qscriptengine_p.cpp b/JavaScriptCore/qt/api/qscriptengine_p.cpp index de8a355..38185ab 100644 --- a/JavaScriptCore/qt/api/qscriptengine_p.cpp +++ b/JavaScriptCore/qt/api/qscriptengine_p.cpp @@ -21,6 +21,7 @@ #include "qscriptengine_p.h" +#include "qscriptprogram_p.h" #include "qscriptvalue_p.h" /*! @@ -38,6 +39,19 @@ QScriptEnginePrivate::~QScriptEnginePrivate() JSGlobalContextRelease(m_context); } +QScriptSyntaxCheckResultPrivate* QScriptEnginePrivate::checkSyntax(const QString& program) +{ + JSValueRef exception; + JSStringRef source = QScriptConverter::toString(program); + bool syntaxIsCorrect = JSCheckScriptSyntax(m_context, source, /* url */ 0, /* starting line */ 1, &exception); + JSStringRelease(source); + if (syntaxIsCorrect) { + return new QScriptSyntaxCheckResultPrivate(this); + } + JSValueProtect(m_context, exception); + return new QScriptSyntaxCheckResultPrivate(this, const_cast<JSObjectRef>(exception)); +} + /*! Evaluates program and returns the result of the evaluation. \internal @@ -46,9 +60,25 @@ QScriptValuePrivate* QScriptEnginePrivate::evaluate(const QString& program, cons { JSStringRef script = QScriptConverter::toString(program); JSStringRef file = QScriptConverter::toString(fileName); - JSValueRef exception; - JSValueRef result = JSEvaluateScript(m_context, script, /* Global Object */ 0, file, lineNumber, &exception); - if (!result) - return new QScriptValuePrivate(this, exception); // returns an exception - return new QScriptValuePrivate(this, result); + QScriptValuePrivate* result = new QScriptValuePrivate(this, evaluate(script, file, lineNumber)); + JSStringRelease(script); + JSStringRelease(file); + return result; +} + +/*! + Evaluates program and returns the result of the evaluation. + \internal +*/ +QScriptValuePrivate* QScriptEnginePrivate::evaluate(const QScriptProgramPrivate* program) +{ + if (program->isNull()) + return new QScriptValuePrivate; + return new QScriptValuePrivate(this, evaluate(program->program(), program->file(), program->line())); +} + +QScriptValuePrivate* QScriptEnginePrivate::globalObject() const +{ + JSObjectRef globalObject = JSContextGetGlobalObject(context()); + return new QScriptValuePrivate(this, globalObject, globalObject); } diff --git a/JavaScriptCore/qt/api/qscriptengine_p.h b/JavaScriptCore/qt/api/qscriptengine_p.h index 8e27c42..2bda68e 100644 --- a/JavaScriptCore/qt/api/qscriptengine_p.h +++ b/JavaScriptCore/qt/api/qscriptengine_p.h @@ -22,12 +22,16 @@ #include "qscriptconverter_p.h" #include "qscriptengine.h" +#include "qscriptstring_p.h" +#include "qscriptsyntaxcheckresult_p.h" #include "qscriptvalue.h" #include <JavaScriptCore/JavaScript.h> +#include <JSBasePrivate.h> #include <QtCore/qshareddata.h> #include <QtCore/qstring.h> class QScriptEngine; +class QScriptSyntaxCheckResultPrivate; class QScriptEnginePrivate : public QSharedData { public: @@ -37,8 +41,13 @@ public: QScriptEnginePrivate(const QScriptEngine*); ~QScriptEnginePrivate(); + QScriptSyntaxCheckResultPrivate* checkSyntax(const QString& program); QScriptValuePrivate* evaluate(const QString& program, const QString& fileName, int lineNumber); + QScriptValuePrivate* evaluate(const QScriptProgramPrivate* program); + inline JSValueRef evaluate(JSStringRef program, JSStringRef fileName, int lineNumber); + inline void collectGarbage(); + inline void reportAdditionalMemoryCost(int cost); inline JSValueRef makeJSValue(double number) const; inline JSValueRef makeJSValue(int number) const; @@ -47,17 +56,42 @@ public: inline JSValueRef makeJSValue(bool number) const; inline JSValueRef makeJSValue(QScriptValue::SpecialValue value) const; + QScriptValuePrivate* globalObject() const; + + inline QScriptStringPrivate* toStringHandle(const QString& str) const; + inline JSGlobalContextRef context() const; private: QScriptEngine* q_ptr; JSGlobalContextRef m_context; }; + +/*! + Evaluates given JavaScript program and returns result of the evaluation. + \attention this function doesn't take ownership of the parameters. + \internal +*/ +JSValueRef QScriptEnginePrivate::evaluate(JSStringRef program, JSStringRef fileName, int lineNumber) +{ + JSValueRef exception; + JSValueRef result = JSEvaluateScript(m_context, program, /* Global Object */ 0, fileName, lineNumber, &exception); + if (!result) + return exception; // returns an exception + return result; +} + void QScriptEnginePrivate::collectGarbage() { JSGarbageCollect(m_context); } +void QScriptEnginePrivate::reportAdditionalMemoryCost(int cost) +{ + if (cost > 0) + JSReportExtraMemoryCost(m_context, cost); +} + JSValueRef QScriptEnginePrivate::makeJSValue(double number) const { return JSValueMakeNumber(m_context, number); @@ -75,7 +109,10 @@ JSValueRef QScriptEnginePrivate::makeJSValue(uint number) const JSValueRef QScriptEnginePrivate::makeJSValue(const QString& string) const { - return JSValueMakeString(m_context, QScriptConverter::toString(string)); + JSStringRef tmp = QScriptConverter::toString(string); + JSValueRef result = JSValueMakeString(m_context, tmp); + JSStringRelease(tmp); + return result; } JSValueRef QScriptEnginePrivate::makeJSValue(bool value) const @@ -90,6 +127,11 @@ JSValueRef QScriptEnginePrivate::makeJSValue(QScriptValue::SpecialValue value) c return JSValueMakeUndefined(m_context); } +QScriptStringPrivate* QScriptEnginePrivate::toStringHandle(const QString& str) const +{ + return new QScriptStringPrivate(str); +} + JSGlobalContextRef QScriptEnginePrivate::context() const { return m_context; diff --git a/JavaScriptCore/qt/api/qscriptprogram.cpp b/JavaScriptCore/qt/api/qscriptprogram.cpp new file mode 100644 index 0000000..d7d4948 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptprogram.cpp @@ -0,0 +1,136 @@ +/* + Copyright (C) 2010 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 "qscriptprogram.h" + +#include "qscriptprogram_p.h" + +/*! + \internal + + \class QScriptProgram + + \brief The QScriptProgram class encapsulates a Qt Script program. + + \ingroup script + + QScriptProgram retains the compiled representation of the script if + possible. Thus, QScriptProgram can be used to evaluate the same + script multiple times more efficiently. + + \code + QScriptEngine engine; + QScriptProgram program("1 + 2"); + QScriptValue result = engine.evaluate(program); + \endcode +*/ + +/*! + Constructs a null QScriptProgram. +*/ +QScriptProgram::QScriptProgram() + : d_ptr(new QScriptProgramPrivate) +{} + +/*! + Constructs a new QScriptProgram with the given \a sourceCode, \a + fileName and \a firstLineNumber. +*/ +QScriptProgram::QScriptProgram(const QString& sourceCode, + const QString fileName, + int firstLineNumber) + : d_ptr(new QScriptProgramPrivate(sourceCode, fileName, firstLineNumber)) +{} + +/*! + Destroys this QScriptProgram. +*/ +QScriptProgram::~QScriptProgram() +{} + +/*! + Constructs a new QScriptProgram that is a copy of \a other. +*/ +QScriptProgram::QScriptProgram(const QScriptProgram& other) +{ + d_ptr = other.d_ptr; +} + +/*! + Assigns the \a other value to this QScriptProgram. +*/ +QScriptProgram& QScriptProgram::operator=(const QScriptProgram& other) +{ + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if this QScriptProgram is null; otherwise + returns false. +*/ +bool QScriptProgram::isNull() const +{ + return d_ptr->isNull(); +} + +/*! + Returns the source code of this program. +*/ +QString QScriptProgram::sourceCode() const +{ + return d_ptr->sourceCode(); +} + +/*! + Returns the filename associated with this program. +*/ +QString QScriptProgram::fileName() const +{ + return d_ptr->fileName(); +} + +/*! + Returns the line number associated with this program. +*/ +int QScriptProgram::firstLineNumber() const +{ + return d_ptr->firstLineNumber(); +} + +/*! + Returns true if this QScriptProgram is equal to \a other; + otherwise returns false. +*/ +bool QScriptProgram::operator==(const QScriptProgram& other) const +{ + return d_ptr == other.d_ptr || *d_ptr == *other.d_ptr; +} + +/*! + Returns true if this QScriptProgram is not equal to \a other; + otherwise returns false. +*/ +bool QScriptProgram::operator!=(const QScriptProgram& other) const +{ + return d_ptr != other.d_ptr && *d_ptr != *other.d_ptr; +} + diff --git a/JavaScriptCore/qt/api/qscriptprogram.h b/JavaScriptCore/qt/api/qscriptprogram.h new file mode 100644 index 0000000..93c8a3c --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptprogram.h @@ -0,0 +1,53 @@ +/* + Copyright (C) 2010 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. +*/ + +#ifndef qscriptprogram_h +#define qscriptprogram_h + +#include "qtscriptglobal.h" +#include <QtCore/qshareddata.h> +#include <QtCore/qstring.h> + +class QScriptProgramPrivate; +class Q_JAVASCRIPT_EXPORT QScriptProgram { +public: + QScriptProgram(); + QScriptProgram(const QString& sourceCode, + const QString fileName = QString(), + int firstLineNumber = 1); + QScriptProgram(const QScriptProgram& other); + ~QScriptProgram(); + + QScriptProgram& operator=(const QScriptProgram& other); + + bool isNull() const; + + QString sourceCode() const; + QString fileName() const; + int firstLineNumber() const; + + bool operator==(const QScriptProgram& other) const; + bool operator!=(const QScriptProgram& other) const; + +private: + QExplicitlySharedDataPointer<QScriptProgramPrivate> d_ptr; + Q_DECLARE_PRIVATE(QScriptProgram) +}; + +#endif // qscriptprogram_h diff --git a/JavaScriptCore/qt/api/qscriptprogram_p.h b/JavaScriptCore/qt/api/qscriptprogram_p.h new file mode 100644 index 0000000..6e80e85 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptprogram_p.h @@ -0,0 +1,129 @@ +/* + Copyright (C) 2010 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. +*/ + +#ifndef qscriptprogram_p_h +#define qscriptprogram_p_h + +#include "qscriptconverter_p.h" +#include "qscriptprogram.h" +#include <JavaScriptCore/JavaScript.h> +#include <QtCore/qshareddata.h> +#include <QtCore/qstring.h> + +/* + FIXME The QScriptProgramPrivate potentially could be much faster. In current implementation we + gain CPU time only by avoiding QString -> JSStringRef conversion. In the ideal world we should + have a function inside the JSC C API that could provide us "parse once, execute multiple times" + functionality. +*/ + +class QScriptProgramPrivate : public QSharedData { +public: + inline static QScriptProgramPrivate* get(const QScriptProgram& program); + inline QScriptProgramPrivate(); + inline QScriptProgramPrivate(const QString& sourceCode, + const QString fileName, + int firstLineNumber); + + inline ~QScriptProgramPrivate(); + + inline bool isNull() const; + + inline QString sourceCode() const; + inline QString fileName() const; + inline int firstLineNumber() const; + + inline bool operator==(const QScriptProgramPrivate& other) const; + inline bool operator!=(const QScriptProgramPrivate& other) const; + + inline JSStringRef program() const; + inline JSStringRef file() const; + inline int line() const; +private: + JSStringRef m_program; + JSStringRef m_fileName; + int m_line; +}; + +QScriptProgramPrivate* QScriptProgramPrivate::get(const QScriptProgram& program) +{ + return const_cast<QScriptProgramPrivate*>(program.d_ptr.constData()); +} + +QScriptProgramPrivate::QScriptProgramPrivate() + : m_program(0) + , m_fileName(0) + , m_line(-1) +{} + +QScriptProgramPrivate::QScriptProgramPrivate(const QString& sourceCode, + const QString fileName, + int firstLineNumber) + : m_program(QScriptConverter::toString(sourceCode)) + , m_fileName(QScriptConverter::toString(fileName)) + , m_line(firstLineNumber) +{} + +QScriptProgramPrivate::~QScriptProgramPrivate() +{ + if (!isNull()) { + JSStringRelease(m_program); + JSStringRelease(m_fileName); + } +} + +bool QScriptProgramPrivate::isNull() const +{ + return !m_program; +} + +QString QScriptProgramPrivate::sourceCode() const +{ + return QScriptConverter::toString(m_program); +} + +QString QScriptProgramPrivate::fileName() const +{ + return QScriptConverter::toString(m_fileName); +} + +int QScriptProgramPrivate::firstLineNumber() const +{ + return m_line; +} + +bool QScriptProgramPrivate::operator==(const QScriptProgramPrivate& other) const +{ + return m_line == other.m_line + && JSStringIsEqual(m_fileName, other.m_fileName) + && JSStringIsEqual(m_program, other.m_program); +} + +bool QScriptProgramPrivate::operator!=(const QScriptProgramPrivate& other) const +{ + return m_line != other.m_line + || !JSStringIsEqual(m_fileName, other.m_fileName) + || !JSStringIsEqual(m_program, other.m_program); +} + +JSStringRef QScriptProgramPrivate::program() const { return m_program; } +JSStringRef QScriptProgramPrivate::file() const {return m_fileName; } +int QScriptProgramPrivate::line() const { return m_line; } + +#endif // qscriptprogram_p_h diff --git a/JavaScriptCore/qt/api/qscriptstring.cpp b/JavaScriptCore/qt/api/qscriptstring.cpp new file mode 100644 index 0000000..83c03c5 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptstring.cpp @@ -0,0 +1,131 @@ +/* + 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 "qscriptstring.h" + +#include "qscriptstring_p.h" +#include <QtCore/qhash.h> + +/*! + Constructs an invalid QScriptString. +*/ +QScriptString::QScriptString() + : d_ptr(new QScriptStringPrivate()) +{ +} +/*! + Constructs an QScriptString from internal representation + \internal +*/ +QScriptString::QScriptString(QScriptStringPrivate* d) + : d_ptr(d) +{ +} + +/*! + Constructs a new QScriptString that is a copy of \a other. +*/ +QScriptString::QScriptString(const QScriptString& other) +{ + d_ptr = other.d_ptr; +} + +/*! + Destroys this QScriptString. +*/ +QScriptString::~QScriptString() +{ +} + +/*! + Assigns the \a other value to this QScriptString. +*/ +QScriptString& QScriptString::operator=(const QScriptString& other) +{ + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns true if this QScriptString is valid; otherwise + returns false. +*/ +bool QScriptString::isValid() const +{ + return d_ptr->isValid(); +} + +/*! + Returns true if this QScriptString is equal to \a other; + otherwise returns false. +*/ +bool QScriptString::operator==(const QScriptString& other) const +{ + return d_ptr == other.d_ptr || *d_ptr == *(other.d_ptr); +} + +/*! + Returns true if this QScriptString is not equal to \a other; + otherwise returns false. +*/ +bool QScriptString::operator!=(const QScriptString& other) const +{ + return d_ptr != other.d_ptr || *d_ptr != *(other.d_ptr); +} + +/*! + Attempts to convert this QScriptString to a QtScript array index, + and returns the result. + + If a conversion error occurs, *\a{ok} is set to false; otherwise + *\a{ok} is set to true. +*/ +quint32 QScriptString::toArrayIndex(bool* ok) const +{ + return d_ptr->toArrayIndex(ok); +} + +/*! + Returns the string that this QScriptString represents, or a + null string if this QScriptString is not valid. + + \sa isValid() +*/ +QString QScriptString::toString() const +{ + return d_ptr->toString(); +} + +/*! + Returns the string that this QScriptString represents, or a + null string if this QScriptString is not valid. + + \sa toString() +*/ +QScriptString::operator QString() const +{ + return d_ptr->toString(); +} + +uint qHash(const QScriptString& key) +{ + return qHash(QScriptStringPrivate::get(key)->id()); +} diff --git a/JavaScriptCore/qt/api/qscriptstring.h b/JavaScriptCore/qt/api/qscriptstring.h new file mode 100644 index 0000000..16593bc --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptstring.h @@ -0,0 +1,58 @@ +/* + Copyright (C) 2010 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. +*/ + +#ifndef qscriptstring_h +#define qscriptstring_h + +#include "qtscriptglobal.h" +#include <QtCore/qshareddata.h> +#include <QtCore/qstring.h> + +class QScriptStringPrivate; +typedef QExplicitlySharedDataPointer<QScriptStringPrivate> QScriptStringPtr; + +class Q_JAVASCRIPT_EXPORT QScriptString { +public: + QScriptString(); + QScriptString(const QScriptString& other); + ~QScriptString(); + + QScriptString& operator=(const QScriptString& other); + + bool isValid() const; + + bool operator==(const QScriptString& other) const; + bool operator!=(const QScriptString& other) const; + + quint32 toArrayIndex(bool* ok = 0) const; + + QString toString() const; + operator QString() const; + +private: + QScriptString(QScriptStringPrivate* d); + + QScriptStringPtr d_ptr; + + friend class QScriptStringPrivate; +}; + +uint qHash(const QScriptString& key); + +#endif // qscriptstring_h diff --git a/JavaScriptCore/qt/api/qscriptstring_p.h b/JavaScriptCore/qt/api/qscriptstring_p.h new file mode 100644 index 0000000..f4fd117 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptstring_p.h @@ -0,0 +1,112 @@ +/* + Copyright (C) 2010 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. +*/ + +#ifndef qscriptstring_p_h +#define qscriptstring_p_h + +#include "qscriptconverter_p.h" +#include "qscriptstring.h" +#include <JavaScriptCore/JavaScript.h> +#include <QtCore/qnumeric.h> +#include <QtCore/qshareddata.h> + +class QScriptStringPrivate : public QSharedData { +public: + inline QScriptStringPrivate(); + inline QScriptStringPrivate(const QString& qtstring); + inline ~QScriptStringPrivate(); + + static inline QScriptString get(QScriptStringPrivate* d); + static inline QScriptStringPtr get(const QScriptString& p); + + inline bool isValid() const; + + inline bool operator==(const QScriptStringPrivate& other) const; + inline bool operator!=(const QScriptStringPrivate& other) const; + + inline quint32 toArrayIndex(bool* ok = 0) const; + + inline QString toString() const; + + inline quint64 id() const; + +private: + JSStringRef m_string; +}; + + +QScriptStringPrivate::QScriptStringPrivate() + : m_string(0) +{} + +QScriptStringPrivate::QScriptStringPrivate(const QString& qtstring) + : m_string(JSStringRetain(QScriptConverter::toString(qtstring))) +{} + +QScriptStringPrivate::~QScriptStringPrivate() +{ + if (isValid()) + JSStringRelease(m_string); +} + +QScriptString QScriptStringPrivate::get(QScriptStringPrivate* d) +{ + Q_ASSERT(d); + return QScriptString(d); +} + +QScriptStringPtr QScriptStringPrivate::get(const QScriptString& p) +{ + return p.d_ptr; +} + +bool QScriptStringPrivate::isValid() const +{ + return m_string; +} + +bool QScriptStringPrivate::operator==(const QScriptStringPrivate& other) const +{ + return isValid() && other.isValid() && JSStringIsEqual(m_string, other.m_string); +} + +bool QScriptStringPrivate::operator!=(const QScriptStringPrivate& other) const +{ + return isValid() && other.isValid() && !JSStringIsEqual(m_string, other.m_string); +} + +quint32 QScriptStringPrivate::toArrayIndex(bool* ok) const +{ + quint32 idx = QScriptConverter::toArrayIndex(m_string); + if (ok) + *ok = (idx != 0xffffffff); + return idx; +} + +QString QScriptStringPrivate::toString() const +{ + return QScriptConverter::toString(m_string); +} + +quint64 QScriptStringPrivate::id() const +{ + return reinterpret_cast<quint32>(m_string); +} + +#endif // qscriptstring_p_h diff --git a/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.cpp b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.cpp new file mode 100644 index 0000000..5cf02ef --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.cpp @@ -0,0 +1,148 @@ +/* + Copyright (C) 2010 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 "qscriptsyntaxcheckresult.h" +#include "qscriptsyntaxcheckresult_p.h" + +/*! + \class QScriptSyntaxCheckResult + + \brief The QScriptSyntaxCheckResult class provides the result of a script syntax check. + + \ingroup script + \mainclass + + QScriptSyntaxCheckResult is returned by QScriptEngine::checkSyntax() to + provide information about the syntactical (in)correctness of a script. +*/ + +/*! + \enum QScriptSyntaxCheckResult::State + + This enum specifies the state of a syntax check. + + \value Error The program contains a syntax error. + \value Intermediate The program is incomplete. + \value Valid The program is a syntactically correct Qt Script program. +*/ + +/*! + Constructs a new QScriptSyntaxCheckResult from the \a other result. +*/ +QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult& other) + : d_ptr(other.d_ptr) +{} + +/*! + Constructs a new QScriptSyntaxCheckResult from an internal representation. + \internal +*/ +QScriptSyntaxCheckResult::QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate* d) + : d_ptr(d) +{} + +/*! + Destroys this QScriptSyntaxCheckResult. +*/ +QScriptSyntaxCheckResult::~QScriptSyntaxCheckResult() +{} + +/*! + Assigns the \a other result to this QScriptSyntaxCheckResult, and returns a + reference to this QScriptSyntaxCheckResult. +*/ +QScriptSyntaxCheckResult& QScriptSyntaxCheckResult::operator=(const QScriptSyntaxCheckResult& other) +{ + d_ptr = other.d_ptr; + return *this; +} + +/*! + Returns the state of this QScriptSyntaxCheckResult. +*/ +QScriptSyntaxCheckResult::State QScriptSyntaxCheckResult::state() const +{ + return d_ptr->state(); +} + +/*! + Returns the error line number of this QScriptSyntaxCheckResult, or -1 if + there is no error. + + \sa state(), errorMessage() +*/ +int QScriptSyntaxCheckResult::errorLineNumber() const +{ + return d_ptr->errorLineNumber(); +} + +/*! + Returns the error column number of this QScriptSyntaxCheckResult, or -1 if + there is no error. + + \sa state(), errorLineNumber() +*/ +int QScriptSyntaxCheckResult::errorColumnNumber() const +{ + return d_ptr->errorColumnNumber(); +} + +/*! + Returns the error message of this QScriptSyntaxCheckResult, or an empty + string if there is no error. + + \sa state(), errorLineNumber() +*/ +QString QScriptSyntaxCheckResult::errorMessage() const +{ + return d_ptr->errorMessage(); +} + +QScriptSyntaxCheckResultPrivate::~QScriptSyntaxCheckResultPrivate() +{ + if (m_exception) + JSValueUnprotect(m_engine->context(), m_exception); +} + +QString QScriptSyntaxCheckResultPrivate::errorMessage() const +{ + if (!m_exception) + return QString(); + + JSStringRef tmp = JSValueToStringCopy(m_engine->context(), m_exception, /* exception */ 0); + QString message = QScriptConverter::toString(tmp); + JSStringRelease(tmp); + return message; +} + +int QScriptSyntaxCheckResultPrivate::errorLineNumber() const +{ + if (!m_exception) + return -1; + // m_exception is an instance of the Exception so it has "line" attribute. + JSStringRef lineAttrName = QScriptConverter::toString("line"); + JSValueRef line = JSObjectGetProperty(m_engine->context(), + m_exception, + lineAttrName, + /* exceptions */0); + JSStringRelease(lineAttrName); + return JSValueToNumber(m_engine->context(), line, /* exceptions */0); +} diff --git a/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.h b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.h new file mode 100644 index 0000000..aa57744 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2010 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. +*/ + +#ifndef qscriptsyntaxcheckresult_h +#define qscriptsyntaxcheckresult_h + +#include "qtscriptglobal.h" +#include <QtCore/qshareddata.h> + +class QScriptSyntaxCheckResultPrivate; +class Q_JAVASCRIPT_EXPORT QScriptSyntaxCheckResult { +public: + enum State { + Error, + Intermediate, + Valid + }; + + QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult& other); + ~QScriptSyntaxCheckResult(); + QScriptSyntaxCheckResult& operator=(const QScriptSyntaxCheckResult& other); + + State state() const; + int errorLineNumber() const; + int errorColumnNumber() const; + QString errorMessage() const; + +private: + QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate* d); + QExplicitlySharedDataPointer<QScriptSyntaxCheckResultPrivate> d_ptr; + + friend class QScriptSyntaxCheckResultPrivate; +}; +#endif // qscriptsyntaxcheckresult_h diff --git a/JavaScriptCore/qt/api/qscriptsyntaxcheckresult_p.h b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult_p.h new file mode 100644 index 0000000..6e1a131 --- /dev/null +++ b/JavaScriptCore/qt/api/qscriptsyntaxcheckresult_p.h @@ -0,0 +1,73 @@ +/* + Copyright (C) 2010 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. +*/ + +#ifndef qscriptsyntaxcheckresult_p_h +#define qscriptsyntaxcheckresult_p_h + +#include "qscriptconverter_p.h" +#include "qscriptengine_p.h" +#include "qscriptsyntaxcheckresult.h" +#include <JavaScriptCore/JavaScript.h> +#include <QtCore/qshareddata.h> + +class QScriptSyntaxCheckResultPrivate : public QSharedData { +public: + static inline QScriptSyntaxCheckResult get(QScriptSyntaxCheckResultPrivate* p); + inline QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine); + inline QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine, JSObjectRef value); + ~QScriptSyntaxCheckResultPrivate(); + + inline QScriptSyntaxCheckResult::State state() const; + int errorLineNumber() const; + inline int errorColumnNumber() const; + QString errorMessage() const; +private: + JSObjectRef m_exception; + QScriptEnginePtr m_engine; +}; + +QScriptSyntaxCheckResult QScriptSyntaxCheckResultPrivate::get(QScriptSyntaxCheckResultPrivate* p) +{ + return QScriptSyntaxCheckResult(p); +} + +QScriptSyntaxCheckResultPrivate::QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine) + : m_exception(0) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) +{} + +QScriptSyntaxCheckResultPrivate::QScriptSyntaxCheckResultPrivate(const QScriptEnginePrivate* engine, JSObjectRef value) + : m_exception(value) + , m_engine(const_cast<QScriptEnginePrivate*>(engine)) +{} + +QScriptSyntaxCheckResult::State QScriptSyntaxCheckResultPrivate::state() const +{ + // FIXME This function doesn't return QScriptSyntaxCheckResult::Intermediate + return m_exception ? QScriptSyntaxCheckResult::Error : QScriptSyntaxCheckResult::Valid; +} + +int QScriptSyntaxCheckResultPrivate::errorColumnNumber() const +{ + // FIXME JSC C API doesn't expose the error column number. + return m_exception ? 1 : -1; +} + + +#endif // qscriptsyntaxcheckresult_p_h diff --git a/JavaScriptCore/qt/api/qscriptvalue_p.h b/JavaScriptCore/qt/api/qscriptvalue_p.h index 8db43a7..830b38e 100644 --- a/JavaScriptCore/qt/api/qscriptvalue_p.h +++ b/JavaScriptCore/qt/api/qscriptvalue_p.h @@ -38,10 +38,10 @@ class QScriptValue; Implementation of QScriptValue. The implementation is based on a state machine. The states names are included in - QScriptValuePrivate::States. Each method should check for the current state and then perform a + QScriptValuePrivate::State. Each method should check for the current state and then perform a correct action. - States: + State: Invalid -> QSVP is invalid, no assumptions should be made about class members (apart from m_value). CString -> QSVP is created from QString or const char* and no JSC engine has been associated yet. Current value is kept in m_string, @@ -53,7 +53,7 @@ class QScriptValue; is kept in m_number (cast of QScriptValue::SpecialValue) JSValue -> QSVP is associated with engine, but there is no information about real type, the state have really short live cycle. Normally it is created as a function call result. - JSNative -> QSVP is associated with engine, and it is sure that it isn't a JavaScript object. + JSPrimitive -> QSVP is associated with engine, and it is sure that it isn't a JavaScript object. JSObject -> QSVP is associated with engine, and it is sure that it is a JavaScript object. Each state keep all necessary information to invoke all methods, if not it should be changed to @@ -117,14 +117,14 @@ public: private: // Please, update class documentation when you change the enum. - enum States { + enum State { Invalid = 0, CString = 0x1000, CNumber, CBool, CSpecial, JSValue = 0x2000, // JS values are equal or higher then this value. - JSNative, + JSPrimitive, JSObject } m_state; QScriptEnginePtr m_engine; @@ -136,6 +136,7 @@ private: inline void setValue(JSValueRef); inline bool inherits(const char*); + inline State refinedJSValue(); inline bool isJSBased() const; inline bool isNumberBased() const; @@ -209,7 +210,7 @@ QScriptValuePrivate::QScriptValuePrivate(QScriptValue::SpecialValue value) } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, bool value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -224,7 +225,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, bool value } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, int value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -239,7 +240,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, int value) } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, uint value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -254,7 +255,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, uint value } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, qsreal value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -269,7 +270,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, qsreal val } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, const QString& value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -284,7 +285,7 @@ QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, const QStr } QScriptValuePrivate::QScriptValuePrivate(const QScriptEngine* engine, QScriptValue::SpecialValue value) - : m_state(JSNative) + : m_state(JSPrimitive) { if (!engine) { // slower path reinitialization @@ -325,10 +326,10 @@ bool QScriptValuePrivate::isBool() case CBool: return true; case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsBoolean(context(), value()); default: return false; @@ -341,10 +342,10 @@ bool QScriptValuePrivate::isNumber() case CNumber: return true; case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsNumber(context(), value()); default: return false; @@ -357,10 +358,10 @@ bool QScriptValuePrivate::isNull() case CSpecial: return m_number == static_cast<int>(QScriptValue::NullValue); case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsNull(context(), value()); default: return false; @@ -373,10 +374,10 @@ bool QScriptValuePrivate::isString() case CString: return true; case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsString(context(), value()); default: return false; @@ -389,10 +390,10 @@ bool QScriptValuePrivate::isUndefined() case CSpecial: return m_number == static_cast<int>(QScriptValue::UndefinedValue); case JSValue: - if (isObject()) + if (refinedJSValue() != JSPrimitive) return false; // Fall-through. - case JSNative: + case JSPrimitive: return JSValueIsUndefined(context(), value()); default: return false; @@ -403,7 +404,7 @@ bool QScriptValuePrivate::isError() { switch (m_state) { case JSValue: - if (!isObject()) + if (refinedJSValue() != JSObject) return false; // Fall-through. case JSObject: @@ -416,14 +417,11 @@ bool QScriptValuePrivate::isError() bool QScriptValuePrivate::isObject() { switch (m_state) { - case JSObject: - return true; case JSValue: - m_object = JSValueToObject(context(), value(), /* exception */ 0); - if (!m_object) - return false; - m_state = JSObject; + return refinedJSValue() == JSObject; + case JSObject: return true; + default: return false; } @@ -433,10 +431,8 @@ bool QScriptValuePrivate::isFunction() { switch (m_state) { case JSValue: - m_object = JSValueToObject(context(), value(), /* exception */ 0); - if (!m_object) + if (refinedJSValue() != JSObject) return false; - m_state = JSObject; // Fall-through. case JSObject: return JSObjectIsFunction(context(), object()); @@ -455,11 +451,11 @@ QString QScriptValuePrivate::toString() const case CString: return m_string; case CNumber: - return QString::number(m_number); + return QScriptConverter::toString(m_number); case CSpecial: return m_number == QScriptValue::NullValue ? QString::fromLatin1("null") : QString::fromLatin1("undefined"); case JSValue: - case JSNative: + case JSPrimitive: case JSObject: return QScriptConverter::toString(JSValueToStringCopy(context(), value(), /* exception */ 0)); } @@ -472,7 +468,7 @@ qsreal QScriptValuePrivate::toNumber() const { switch (m_state) { case JSValue: - case JSNative: + case JSPrimitive: case JSObject: return JSValueToNumber(context(), value(), /* exception */ 0); case CNumber: @@ -504,7 +500,7 @@ bool QScriptValuePrivate::toBool() const { switch (m_state) { case JSValue: - case JSNative: + case JSPrimitive: return JSValueToBoolean(context(), value()); case JSObject: return true; @@ -631,7 +627,7 @@ bool QScriptValuePrivate::assignEngine(QScriptEnginePrivate* engine) return false; } m_engine = engine; - m_state = JSNative; + m_state = JSPrimitive; setValue(value); return true; } @@ -640,12 +636,8 @@ QScriptValuePrivate* QScriptValuePrivate::call(const QScriptValuePrivate*, const { switch (m_state) { case JSValue: - m_object = JSValueToObject(context(), value(), /* exception */ 0); - if (!object()) { - m_state = JSValue; + if (refinedJSValue() != JSObject) return new QScriptValuePrivate; - } - m_state = JSObject; // Fall-through. case JSObject: { @@ -719,12 +711,32 @@ bool QScriptValuePrivate::inherits(const char* name) { Q_ASSERT(isJSBased()); JSObjectRef globalObject = JSContextGetGlobalObject(context()); - JSValueRef error = JSObjectGetProperty(context(), globalObject, QScriptConverter::toString(name), 0); + JSStringRef errorAttrName = QScriptConverter::toString(name); + JSValueRef error = JSObjectGetProperty(context(), globalObject, errorAttrName, /* exception */ 0); + JSStringRelease(errorAttrName); return JSValueIsInstanceOfConstructor(context(), value(), JSValueToObject(context(), error, /* exception */ 0), /* exception */ 0); } /*! \internal + Refines the state of this QScriptValuePrivate. Returns the new state. +*/ +QScriptValuePrivate::State QScriptValuePrivate::refinedJSValue() +{ + Q_ASSERT(m_state == JSValue); + if (!JSValueIsObject(context(), value())) { + m_state = JSPrimitive; + } else { + m_state = JSObject; + // We are sure that value is an JSObject, so we can const_cast safely without + // calling JSC C API (JSValueToObject(context(), value(), /* exceptions */ 0)). + m_object = const_cast<JSObjectRef>(m_value); + } + return m_state; +} + +/*! + \internal Returns true if QSV have an engine associated. */ bool QScriptValuePrivate::isJSBased() const { return m_state >= JSValue; } diff --git a/JavaScriptCore/qt/tests/qscriptengine/qscriptengine.pro b/JavaScriptCore/qt/tests/qscriptengine/qscriptengine.pro index 0dc0902..d521dd8 100644 --- a/JavaScriptCore/qt/tests/qscriptengine/qscriptengine.pro +++ b/JavaScriptCore/qt/tests/qscriptengine/qscriptengine.pro @@ -1,6 +1,7 @@ TEMPLATE = app TARGET = tst_qscriptengine QT += testlib +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. include(../tests.pri) SOURCES += tst_qscriptengine.cpp diff --git a/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp b/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp index b36e364..1ec9ad3 100644 --- a/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp +++ b/JavaScriptCore/qt/tests/qscriptengine/tst_qscriptengine.cpp @@ -18,6 +18,8 @@ */ #include "qscriptengine.h" +#include "qscriptprogram.h" +#include "qscriptsyntaxcheckresult.h" #include "qscriptvalue.h" #include <QtTest/qtest.h> @@ -33,10 +35,15 @@ public slots: void cleanup() {} private slots: + void globalObject(); void evaluate(); void collectGarbage(); + void reportAdditionalMemoryCost(); void nullValue(); void undefinedValue(); + void evaluateProgram(); + void checkSyntax_data(); + void checkSyntax(); }; /* Evaluating a script that throw an unhandled exception should return an invalid value. */ @@ -47,6 +54,17 @@ void tst_QScriptEngine::evaluate() QVERIFY2(engine.evaluate("ping").isValid(), "Script throwing an unhandled exception should return an exception value"); } +void tst_QScriptEngine::globalObject() +{ + QScriptEngine engine; + QScriptValue global = engine.globalObject(); + QScriptValue self = engine.evaluate("this"); + QVERIFY(global.isObject()); + QVERIFY(engine.globalObject().equals(engine.evaluate("this"))); + QEXPECT_FAIL("", "strictlyEquals is broken - bug 36600 in bugs.webkit.org", Continue); + QVERIFY(engine.globalObject().strictlyEquals(self)); +} + /* Test garbage collection, at least try to not crash. */ void tst_QScriptEngine::collectGarbage() { @@ -57,6 +75,26 @@ void tst_QScriptEngine::collectGarbage() QCOMPARE(foo.call().toString(), QString::fromAscii("pong")); } +void tst_QScriptEngine::reportAdditionalMemoryCost() +{ + // There isn't any easy way to test the responsiveness of the GC; + // just try to call the function a few times with various sizes. + QScriptEngine eng; + for (int i = 0; i < 100; ++i) { + eng.reportAdditionalMemoryCost(0); + eng.reportAdditionalMemoryCost(10); + eng.reportAdditionalMemoryCost(1000); + eng.reportAdditionalMemoryCost(10000); + eng.reportAdditionalMemoryCost(100000); + eng.reportAdditionalMemoryCost(1000000); + eng.reportAdditionalMemoryCost(10000000); + eng.reportAdditionalMemoryCost(-1); + eng.reportAdditionalMemoryCost(-1000); + QScriptValue obj = eng.evaluate("new Object"); + eng.collectGarbage(); + } +} + void tst_QScriptEngine::nullValue() { QScriptEngine engine; @@ -73,5 +111,198 @@ void tst_QScriptEngine::undefinedValue() QVERIFY(value.isUndefined()); } +void tst_QScriptEngine::evaluateProgram() +{ + QScriptEngine eng; + { + QString code("1 + 2"); + QString fileName("hello.js"); + int lineNumber = 123; + QScriptProgram program(code, fileName, lineNumber); + QVERIFY(!program.isNull()); + QCOMPARE(program.sourceCode(), code); + QCOMPARE(program.fileName(), fileName); + QCOMPARE(program.firstLineNumber(), lineNumber); + + QScriptValue expected = eng.evaluate(code); + for (int x = 0; x < 10; ++x) { + QScriptValue ret = eng.evaluate(program); + QVERIFY(ret.equals(expected)); + } + + // operator= + QScriptProgram sameProgram = program; + QVERIFY(sameProgram == program); + QVERIFY(eng.evaluate(sameProgram).equals(expected)); + + // copy constructor + QScriptProgram sameProgram2(program); + QVERIFY(sameProgram2 == program); + QVERIFY(eng.evaluate(sameProgram2).equals(expected)); + + QScriptProgram differentProgram("2 + 3"); + QVERIFY(differentProgram != program); + QVERIFY(!eng.evaluate(differentProgram).equals(expected)); + } + + // Program that accesses variable in the scope + { + QScriptProgram program("a"); + QVERIFY(!program.isNull()); + { + QScriptValue ret = eng.evaluate(program); + QVERIFY(ret.isError()); + QCOMPARE(ret.toString(), QString::fromLatin1("ReferenceError: Can't find variable: a")); + } + { + QScriptValue ret = eng.evaluate(program); + QVERIFY(ret.isError()); + } + eng.evaluate("a = 456"); + { + QScriptValue ret = eng.evaluate(program); + QVERIFY(!ret.isError()); + QCOMPARE(ret.toNumber(), 456.0); + } + } + + // Program that creates closure + { + QScriptProgram program("(function() { var count = 0; return function() { return count++; }; })"); + QVERIFY(!program.isNull()); + QScriptValue createCounter = eng.evaluate(program); + QVERIFY(createCounter.isFunction()); + QScriptValue counter = createCounter.call(); + QVERIFY(counter.isFunction()); + { + QScriptValue ret = counter.call(); + QVERIFY(ret.isNumber()); + } + QScriptValue counter2 = createCounter.call(); + QVERIFY(counter2.isFunction()); + QVERIFY(!counter2.equals(counter)); + { + QScriptValue ret = counter2.call(); + QVERIFY(ret.isNumber()); + } + } + + // Same program run in different engines + { + QString code("1 + 2"); + QScriptProgram program(code); + QVERIFY(!program.isNull()); + double expected = eng.evaluate(program).toNumber(); + for (int x = 0; x < 2; ++x) { + QScriptEngine eng2; + for (int y = 0; y < 2; ++y) { + double ret = eng2.evaluate(program).toNumber(); + QCOMPARE(ret, expected); + } + } + } + + // No program + { + QScriptProgram program; + QVERIFY(program.isNull()); + QScriptValue ret = eng.evaluate(program); + QVERIFY(!ret.isValid()); + } +} + +void tst_QScriptEngine::checkSyntax_data() +{ + QTest::addColumn<QString>("code"); + QTest::addColumn<int>("expectedState"); + QTest::addColumn<int>("errorLineNumber"); + QTest::addColumn<int>("errorColumnNumber"); + QTest::addColumn<QString>("errorMessage"); + + QTest::newRow("0") + << QString("0") << int(QScriptSyntaxCheckResult::Valid) + << -1 << -1 << ""; + QTest::newRow("if (") + << QString("if (\n") << int(QScriptSyntaxCheckResult::Intermediate) + << 1 << 4 << ""; + QTest::newRow("if else") + << QString("\nif else") << int(QScriptSyntaxCheckResult::Error) + << 2 << 4 << "SyntaxError: Parse error"; + QTest::newRow("{if}") + << QString("{\n{\nif\n}\n") << int(QScriptSyntaxCheckResult::Error) + << 4 << 1 << "SyntaxError: Parse error"; + QTest::newRow("foo[") + << QString("foo[") << int(QScriptSyntaxCheckResult::Error) + << 1 << 4 << "SyntaxError: Parse error"; + QTest::newRow("foo['bar']") + << QString("foo['bar']") << int(QScriptSyntaxCheckResult::Valid) + << -1 << -1 << ""; + + QTest::newRow("/*") + << QString("/*") << int(QScriptSyntaxCheckResult::Intermediate) + << 1 << 1 << "Unclosed comment at end of file"; + QTest::newRow("/*\nMy comment") + << QString("/*\nMy comment") << int(QScriptSyntaxCheckResult::Intermediate) + << 1 << 1 << "Unclosed comment at end of file"; + QTest::newRow("/*\nMy comment */\nfoo = 10") + << QString("/*\nMy comment */\nfoo = 10") << int(QScriptSyntaxCheckResult::Valid) + << -1 << -1 << ""; + QTest::newRow("foo = 10 /*") + << QString("foo = 10 /*") << int(QScriptSyntaxCheckResult::Intermediate) + << -1 << -1 << ""; + QTest::newRow("foo = 10; /*") + << QString("foo = 10; /*") << int(QScriptSyntaxCheckResult::Intermediate) + << 1 << 11 << "Expected `end of file'"; + QTest::newRow("foo = 10 /* My comment */") + << QString("foo = 10 /* My comment */") << int(QScriptSyntaxCheckResult::Valid) + << -1 << -1 << ""; + + QTest::newRow("/=/") + << QString("/=/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << ""; + QTest::newRow("/=/g") + << QString("/=/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << ""; + QTest::newRow("/a/") + << QString("/a/") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << ""; + QTest::newRow("/a/g") + << QString("/a/g") << int(QScriptSyntaxCheckResult::Valid) << -1 << -1 << ""; +} + +void tst_QScriptEngine::checkSyntax() +{ + QFETCH(QString, code); + QFETCH(int, expectedState); + QFETCH(int, errorLineNumber); + QFETCH(int, errorColumnNumber); + QFETCH(QString, errorMessage); + + QScriptSyntaxCheckResult result = QScriptEngine::checkSyntax(code); + + // assignment + { + QScriptSyntaxCheckResult copy = result; + QCOMPARE(copy.state(), result.state()); + QCOMPARE(copy.errorLineNumber(), result.errorLineNumber()); + QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber()); + QCOMPARE(copy.errorMessage(), result.errorMessage()); + } + { + QScriptSyntaxCheckResult copy(result); + QCOMPARE(copy.state(), result.state()); + QCOMPARE(copy.errorLineNumber(), result.errorLineNumber()); + QCOMPARE(copy.errorColumnNumber(), result.errorColumnNumber()); + QCOMPARE(copy.errorMessage(), result.errorMessage()); + } + + if (expectedState == QScriptSyntaxCheckResult::Intermediate) + QEXPECT_FAIL("", "QScriptSyntaxCheckResult::state() doesn't return the Intermediate state", Abort); + QCOMPARE(result.state(), QScriptSyntaxCheckResult::State(expectedState)); + QCOMPARE(result.errorLineNumber(), errorLineNumber); + if (expectedState != QScriptSyntaxCheckResult::Valid && errorColumnNumber != 1) + QEXPECT_FAIL("", "QScriptSyntaxCheckResult::errorColumnNumber() doesn't return correct value", Continue); + QCOMPARE(result.errorColumnNumber(), errorColumnNumber); + QCOMPARE(result.errorMessage(), errorMessage); +} + + QTEST_MAIN(tst_QScriptEngine) #include "tst_qscriptengine.moc" diff --git a/JavaScriptCore/qt/tests/qscriptstring/qscriptstring.pro b/JavaScriptCore/qt/tests/qscriptstring/qscriptstring.pro new file mode 100644 index 0000000..5ad9b7c --- /dev/null +++ b/JavaScriptCore/qt/tests/qscriptstring/qscriptstring.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +TARGET = tst_qscriptstring +QT += testlib +include(../tests.pri) + +SOURCES += tst_qscriptstring.cpp + diff --git a/JavaScriptCore/qt/tests/qscriptstring/tst_qscriptstring.cpp b/JavaScriptCore/qt/tests/qscriptstring/tst_qscriptstring.cpp new file mode 100644 index 0000000..ff31835 --- /dev/null +++ b/JavaScriptCore/qt/tests/qscriptstring/tst_qscriptstring.cpp @@ -0,0 +1,175 @@ +/* + Copyright (C) 2010 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. +*/ + +#ifndef tst_qscriptstring_h +#define tst_qscriptstring_h + +#include "qscriptengine.h" +#include "qscriptstring.h" +#include <QtCore/qhash.h> +#include <QtTest/QtTest> + +class tst_QScriptString : public QObject { + Q_OBJECT + +public: + tst_QScriptString(); + virtual ~tst_QScriptString(); + +private slots: + void test(); + void hash(); + void toArrayIndex_data(); + void toArrayIndex(); +}; + +tst_QScriptString::tst_QScriptString() +{ +} + +tst_QScriptString::~tst_QScriptString() +{ +} + +void tst_QScriptString::test() +{ + QScriptEngine eng; + { + QScriptString str; + QVERIFY(!str.isValid()); + QVERIFY(str == str); + QVERIFY(!(str != str)); + QVERIFY(str.toString().isNull()); + + QScriptString str1(str); + QVERIFY(!str1.isValid()); + + QScriptString str2 = str; + QVERIFY(!str2.isValid()); + + QCOMPARE(str.toArrayIndex(), quint32(0xffffffff)); + } + for (int x = 0; x < 2; ++x) { + QString ciao = QString::fromLatin1("ciao"); + QScriptString str = eng.toStringHandle(ciao); + QVERIFY(str.isValid()); + QVERIFY(str == str); + QVERIFY(!(str != str)); + QCOMPARE(str.toString(), ciao); + + QScriptString str1(str); + QCOMPARE(str, str1); + + QScriptString str2 = str; + QCOMPARE(str, str2); + + QScriptString str3 = eng.toStringHandle(ciao); + QVERIFY(str3.isValid()); + QCOMPARE(str, str3); + + eng.collectGarbage(); + + QVERIFY(str.isValid()); + QCOMPARE(str.toString(), ciao); + QVERIFY(str1.isValid()); + QCOMPARE(str1.toString(), ciao); + QVERIFY(str2.isValid()); + QCOMPARE(str2.toString(), ciao); + QVERIFY(str3.isValid()); + QCOMPARE(str3.toString(), ciao); + } + { + QScriptEngine* eng2 = new QScriptEngine; + QString one = QString::fromLatin1("one"); + QString two = QString::fromLatin1("two"); + QScriptString oneInterned = eng2->toStringHandle(one); + QCOMPARE(oneInterned.toString(), one); + QScriptString twoInterned = eng2->toStringHandle(two); + QCOMPARE(twoInterned.toString(), two); + QVERIFY(oneInterned != twoInterned); + QVERIFY(!(oneInterned == twoInterned)); + + delete eng2; + } +} + +void tst_QScriptString::hash() +{ + QScriptEngine engine; + QHash<QScriptString, int> stringToInt; + QScriptString foo = engine.toStringHandle("foo"); + + QScriptString bar = engine.toStringHandle("bar"); + QVERIFY(!stringToInt.contains(foo)); + for (int i = 0; i < 1000000; ++i) + stringToInt.insert(foo, 123); + QCOMPARE(stringToInt.value(foo), 123); + QVERIFY(!stringToInt.contains(bar)); + stringToInt.insert(bar, 456); + QCOMPARE(stringToInt.value(bar), 456); + QCOMPARE(stringToInt.value(foo), 123); +} + +void tst_QScriptString::toArrayIndex_data() +{ + QTest::addColumn<QString>("input"); + QTest::addColumn<bool>("expectSuccess"); + QTest::addColumn<quint32>("expectedIndex"); + QTest::newRow("foo") << QString::fromLatin1("foo") << false << quint32(0xffffffff); + QTest::newRow("empty") << QString::fromLatin1("") << false << quint32(0xffffffff); + QTest::newRow("0") << QString::fromLatin1("0") << true << quint32(0); + QTest::newRow("00") << QString::fromLatin1("00") << false << quint32(0xffffffff); + QTest::newRow("1") << QString::fromLatin1("1") << true << quint32(1); + QTest::newRow("123") << QString::fromLatin1("123") << true << quint32(123); + QTest::newRow("-1") << QString::fromLatin1("-1") << false << quint32(0xffffffff); + QTest::newRow("0a") << QString::fromLatin1("0a") << false << quint32(0xffffffff); + QTest::newRow("0x1") << QString::fromLatin1("0x1") << false << quint32(0xffffffff); + QTest::newRow("01") << QString::fromLatin1("01") << false << quint32(0xffffffff); + QTest::newRow("101a") << QString::fromLatin1("101a") << false << quint32(0xffffffff); + QTest::newRow("4294967294") << QString::fromLatin1("4294967294") << true << quint32(0xfffffffe); + QTest::newRow("4294967295") << QString::fromLatin1("4294967295") << false << quint32(0xffffffff); + QTest::newRow("11111111111") << QString::fromLatin1("11111111111") << false << quint32(0xffffffff); + QTest::newRow("0.0") << QString::fromLatin1("0.0") << false << quint32(0xffffffff); + QTest::newRow("1.0") << QString::fromLatin1("1.0") << false << quint32(0xffffffff); + QTest::newRow("1.5") << QString::fromLatin1("1.5") << false << quint32(0xffffffff); + QTest::newRow("1.") << QString::fromLatin1("1.") << false << quint32(0xffffffff); + QTest::newRow(".1") << QString::fromLatin1(".1") << false << quint32(0xffffffff); + QTest::newRow("1e0") << QString::fromLatin1("1e0") << false << quint32(0xffffffff); +} + +void tst_QScriptString::toArrayIndex() +{ + QFETCH(QString, input); + QFETCH(bool, expectSuccess); + QFETCH(quint32, expectedIndex); + QScriptEngine engine; + for (int x = 0; x < 2; ++x) { + bool isArrayIndex; + bool* ptr = (!x) ? &isArrayIndex : (bool*)0; + quint32 result = engine.toStringHandle(input).toArrayIndex(ptr); + if (!x) + QCOMPARE(isArrayIndex, expectSuccess); + QCOMPARE(result, expectedIndex); + } +} + +QTEST_MAIN(tst_QScriptString) +#include "tst_qscriptstring.moc" + +#endif // tst_qscriptstring_h diff --git a/JavaScriptCore/qt/tests/qscriptvalue/qscriptvalue.pro b/JavaScriptCore/qt/tests/qscriptvalue/qscriptvalue.pro index b12337f..35cc17d 100644 --- a/JavaScriptCore/qt/tests/qscriptvalue/qscriptvalue.pro +++ b/JavaScriptCore/qt/tests/qscriptvalue/qscriptvalue.pro @@ -1,6 +1,7 @@ TEMPLATE = app TARGET = tst_qscriptvalue QT += testlib +isEmpty(OUTPUT_DIR): OUTPUT_DIR = ../../../.. include(../tests.pri) SOURCES += \ diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp index b44c5ca..82f0901 100644 --- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp +++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.cpp @@ -274,7 +274,7 @@ void tst_QScriptValue::ctor() QVERIFY(QScriptValue(0, QString("ciao")).isString()); } -void tst_QScriptValue::toString_data() +void tst_QScriptValue::toStringSimple_data() { QTest::addColumn<QString>("code"); QTest::addColumn<QString>("result"); @@ -289,7 +289,7 @@ void tst_QScriptValue::toString_data() } /* Test conversion to string from different JSC types */ -void tst_QScriptValue::toString() +void tst_QScriptValue::toStringSimple() { QFETCH(QString, code); QFETCH(QString, result); diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h index 1b3c657..28154a9 100644 --- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h +++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue.h @@ -36,8 +36,8 @@ public: virtual ~tst_QScriptValue(); private slots: - void toString_data(); - void toString(); + void toStringSimple_data(); + void toStringSimple(); void copyConstructor_data(); void copyConstructor(); void assignOperator_data(); @@ -76,6 +76,9 @@ private slots: void isValid_data(); void isValid(); + void toString_data(); + void toString(); + void toNumber_data(); void toNumber(); @@ -146,6 +149,10 @@ private: void isValid_makeData(const char* expr); void isValid_test(const char* expr, const QScriptValue& value); + void toString_initData(); + void toString_makeData(const char*); + void toString_test(const char*, const QScriptValue&); + void toNumber_initData(); void toNumber_makeData(const char*); void toNumber_test(const char*, const QScriptValue&); diff --git a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp index 006b343..970c960 100644 --- a/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp +++ b/JavaScriptCore/qt/tests/qscriptvalue/tst_qscriptvalue_generated.cpp @@ -130,6 +130,35 @@ void tst_QScriptValue::initScriptValues() DEFINE_TEST_VALUE(engine->evaluate("new Object()")); DEFINE_TEST_VALUE(engine->evaluate("new Array()")); DEFINE_TEST_VALUE(engine->evaluate("new Error()")); + DEFINE_TEST_VALUE(engine->evaluate("a = new Object(); a.foo = 22; a.foo")); + DEFINE_TEST_VALUE(engine->evaluate("Undefined")); + DEFINE_TEST_VALUE(engine->evaluate("Null")); + DEFINE_TEST_VALUE(engine->evaluate("True")); + DEFINE_TEST_VALUE(engine->evaluate("False")); + DEFINE_TEST_VALUE(engine->evaluate("undefined")); + DEFINE_TEST_VALUE(engine->evaluate("null")); + DEFINE_TEST_VALUE(engine->evaluate("true")); + DEFINE_TEST_VALUE(engine->evaluate("false")); + DEFINE_TEST_VALUE(engine->evaluate("122")); + DEFINE_TEST_VALUE(engine->evaluate("124")); + DEFINE_TEST_VALUE(engine->evaluate("0")); + DEFINE_TEST_VALUE(engine->evaluate("0.0")); + DEFINE_TEST_VALUE(engine->evaluate("123.0")); + DEFINE_TEST_VALUE(engine->evaluate("6.37e-8")); + DEFINE_TEST_VALUE(engine->evaluate("-6.37e-8")); + DEFINE_TEST_VALUE(engine->evaluate("0x43211234")); + DEFINE_TEST_VALUE(engine->evaluate("0x10000")); + DEFINE_TEST_VALUE(engine->evaluate("0x10001")); + DEFINE_TEST_VALUE(engine->evaluate("NaN")); + DEFINE_TEST_VALUE(engine->evaluate("Infinity")); + DEFINE_TEST_VALUE(engine->evaluate("-Infinity")); + DEFINE_TEST_VALUE(engine->evaluate("'ciao'")); + DEFINE_TEST_VALUE(engine->evaluate("''")); + DEFINE_TEST_VALUE(engine->evaluate("'0'")); + DEFINE_TEST_VALUE(engine->evaluate("'123'")); + DEFINE_TEST_VALUE(engine->evaluate("'12.4'")); + DEFINE_TEST_VALUE(engine->nullValue()); + DEFINE_TEST_VALUE(engine->undefinedValue()); } @@ -244,7 +273,36 @@ void tst_QScriptValue::isValid_makeData(const char* expr) << "engine->evaluate(\"/foo/\")" << "engine->evaluate(\"new Object()\")" << "engine->evaluate(\"new Array()\")" - << "engine->evaluate(\"new Error()\")"; + << "engine->evaluate(\"new Error()\")" + << "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")" + << "engine->evaluate(\"Undefined\")" + << "engine->evaluate(\"Null\")" + << "engine->evaluate(\"True\")" + << "engine->evaluate(\"False\")" + << "engine->evaluate(\"undefined\")" + << "engine->evaluate(\"null\")" + << "engine->evaluate(\"true\")" + << "engine->evaluate(\"false\")" + << "engine->evaluate(\"122\")" + << "engine->evaluate(\"124\")" + << "engine->evaluate(\"0\")" + << "engine->evaluate(\"0.0\")" + << "engine->evaluate(\"123.0\")" + << "engine->evaluate(\"6.37e-8\")" + << "engine->evaluate(\"-6.37e-8\")" + << "engine->evaluate(\"0x43211234\")" + << "engine->evaluate(\"0x10000\")" + << "engine->evaluate(\"0x10001\")" + << "engine->evaluate(\"NaN\")" + << "engine->evaluate(\"Infinity\")" + << "engine->evaluate(\"-Infinity\")" + << "engine->evaluate(\"'ciao'\")" + << "engine->evaluate(\"''\")" + << "engine->evaluate(\"'0'\")" + << "engine->evaluate(\"'123'\")" + << "engine->evaluate(\"'12.4'\")" + << "engine->nullValue()" + << "engine->undefinedValue()"; } newRow(expr) << isValid.contains(expr); } @@ -253,6 +311,7 @@ void tst_QScriptValue::isValid_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.isValid(), expected); + QCOMPARE(value.isValid(), expected); } DEFINE_TEST_FUNCTION(isValid) @@ -273,7 +332,9 @@ void tst_QScriptValue::isBool_makeData(const char* expr) << "QScriptValue(0, true)" << "QScriptValue(0, false)" << "QScriptValue(engine, true)" - << "QScriptValue(engine, false)"; + << "QScriptValue(engine, false)" + << "engine->evaluate(\"true\")" + << "engine->evaluate(\"false\")"; } newRow(expr) << isBool.contains(expr); } @@ -282,6 +343,7 @@ void tst_QScriptValue::isBool_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.isBool(), expected); + QCOMPARE(value.isBool(), expected); } DEFINE_TEST_FUNCTION(isBool) @@ -302,7 +364,9 @@ void tst_QScriptValue::isBoolean_makeData(const char* expr) << "QScriptValue(0, true)" << "QScriptValue(0, false)" << "QScriptValue(engine, true)" - << "QScriptValue(engine, false)"; + << "QScriptValue(engine, false)" + << "engine->evaluate(\"true\")" + << "engine->evaluate(\"false\")"; } newRow(expr) << isBoolean.contains(expr); } @@ -311,10 +375,12 @@ void tst_QScriptValue::isBoolean_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.isBoolean(), expected); + QCOMPARE(value.isBoolean(), expected); } DEFINE_TEST_FUNCTION(isBoolean) + void tst_QScriptValue::isNumber_initData() { QTest::addColumn<bool>("expected"); @@ -366,7 +432,21 @@ void tst_QScriptValue::isNumber_makeData(const char* expr) << "QScriptValue(engine, qSNaN())" << "QScriptValue(engine, qQNaN())" << "QScriptValue(engine, qInf())" - << "QScriptValue(engine, -qInf())"; + << "QScriptValue(engine, -qInf())" + << "engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")" + << "engine->evaluate(\"122\")" + << "engine->evaluate(\"124\")" + << "engine->evaluate(\"0\")" + << "engine->evaluate(\"0.0\")" + << "engine->evaluate(\"123.0\")" + << "engine->evaluate(\"6.37e-8\")" + << "engine->evaluate(\"-6.37e-8\")" + << "engine->evaluate(\"0x43211234\")" + << "engine->evaluate(\"0x10000\")" + << "engine->evaluate(\"0x10001\")" + << "engine->evaluate(\"NaN\")" + << "engine->evaluate(\"Infinity\")" + << "engine->evaluate(\"-Infinity\")"; } newRow(expr) << isNumber.contains(expr); } @@ -375,6 +455,7 @@ void tst_QScriptValue::isNumber_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.isNumber(), expected); + QCOMPARE(value.isNumber(), expected); } DEFINE_TEST_FUNCTION(isNumber) @@ -407,6 +488,7 @@ void tst_QScriptValue::isFunction_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.isFunction(), expected); + QCOMPARE(value.isFunction(), expected); } DEFINE_TEST_FUNCTION(isFunction) @@ -424,7 +506,9 @@ void tst_QScriptValue::isNull_makeData(const char* expr) if (isNull.isEmpty()) { isNull << "QScriptValue(QScriptValue::NullValue)" << "QScriptValue(0, QScriptValue::NullValue)" - << "QScriptValue(engine, QScriptValue::NullValue)"; + << "QScriptValue(engine, QScriptValue::NullValue)" + << "engine->evaluate(\"null\")" + << "engine->nullValue()"; } newRow(expr) << isNull.contains(expr); } @@ -433,6 +517,7 @@ void tst_QScriptValue::isNull_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.isNull(), expected); + QCOMPARE(value.isNull(), expected); } DEFINE_TEST_FUNCTION(isNull) @@ -477,7 +562,12 @@ void tst_QScriptValue::isString_makeData(const char* expr) << "QScriptValue(engine, QString())" << "QScriptValue(engine, QString(\"0\"))" << "QScriptValue(engine, QString(\"123\"))" - << "QScriptValue(engine, QString(\"1.23\"))"; + << "QScriptValue(engine, QString(\"1.23\"))" + << "engine->evaluate(\"'ciao'\")" + << "engine->evaluate(\"''\")" + << "engine->evaluate(\"'0'\")" + << "engine->evaluate(\"'123'\")" + << "engine->evaluate(\"'12.4'\")"; } newRow(expr) << isString.contains(expr); } @@ -486,6 +576,7 @@ void tst_QScriptValue::isString_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.isString(), expected); + QCOMPARE(value.isString(), expected); } DEFINE_TEST_FUNCTION(isString) @@ -504,7 +595,9 @@ void tst_QScriptValue::isUndefined_makeData(const char* expr) isUndefined << "QScriptValue(QScriptValue::UndefinedValue)" << "QScriptValue(0, QScriptValue::UndefinedValue)" << "QScriptValue(engine, QScriptValue::UndefinedValue)" - << "engine->evaluate(\"{}\")"; + << "engine->evaluate(\"{}\")" + << "engine->evaluate(\"undefined\")" + << "engine->undefinedValue()"; } newRow(expr) << isUndefined.contains(expr); } @@ -513,10 +606,15 @@ void tst_QScriptValue::isUndefined_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.isUndefined(), expected); + QCOMPARE(value.isUndefined(), expected); } DEFINE_TEST_FUNCTION(isUndefined) + + + + void tst_QScriptValue::isObject_initData() { QTest::addColumn<bool>("expected"); @@ -543,7 +641,11 @@ void tst_QScriptValue::isObject_makeData(const char* expr) << "engine->evaluate(\"/foo/\")" << "engine->evaluate(\"new Object()\")" << "engine->evaluate(\"new Array()\")" - << "engine->evaluate(\"new Error()\")"; + << "engine->evaluate(\"new Error()\")" + << "engine->evaluate(\"Undefined\")" + << "engine->evaluate(\"Null\")" + << "engine->evaluate(\"True\")" + << "engine->evaluate(\"False\")"; } newRow(expr) << isObject.contains(expr); } @@ -552,10 +654,168 @@ void tst_QScriptValue::isObject_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.isObject(), expected); + QCOMPARE(value.isObject(), expected); } DEFINE_TEST_FUNCTION(isObject) + +void tst_QScriptValue::toString_initData() +{ + QTest::addColumn<QString>("expected"); + initScriptValues(); +} + +void tst_QScriptValue::toString_makeData(const char* expr) +{ + static QHash<QString, QString> toString; + if (toString.isEmpty()) { + toString.insert("QScriptValue()", ""); + toString.insert("QScriptValue(QScriptValue::UndefinedValue)", "undefined"); + toString.insert("QScriptValue(QScriptValue::NullValue)", "null"); + toString.insert("QScriptValue(true)", "true"); + toString.insert("QScriptValue(false)", "false"); + toString.insert("QScriptValue(int(122))", "122"); + toString.insert("QScriptValue(uint(124))", "124"); + toString.insert("QScriptValue(0)", "0"); + toString.insert("QScriptValue(0.0)", "0"); + toString.insert("QScriptValue(123.0)", "123"); + toString.insert("QScriptValue(6.37e-8)", "6.37e-8"); + toString.insert("QScriptValue(-6.37e-8)", "-6.37e-8"); + toString.insert("QScriptValue(0x43211234)", "1126240820"); + toString.insert("QScriptValue(0x10000)", "65536"); + toString.insert("QScriptValue(0x10001)", "65537"); + toString.insert("QScriptValue(qSNaN())", "NaN"); + toString.insert("QScriptValue(qQNaN())", "NaN"); + toString.insert("QScriptValue(qInf())", "Infinity"); + toString.insert("QScriptValue(-qInf())", "-Infinity"); + toString.insert("QScriptValue(\"NaN\")", "NaN"); + toString.insert("QScriptValue(\"Infinity\")", "Infinity"); + toString.insert("QScriptValue(\"-Infinity\")", "-Infinity"); + toString.insert("QScriptValue(\"ciao\")", "ciao"); + toString.insert("QScriptValue(QString::fromLatin1(\"ciao\"))", "ciao"); + toString.insert("QScriptValue(QString(\"\"))", ""); + toString.insert("QScriptValue(QString())", ""); + toString.insert("QScriptValue(QString(\"0\"))", "0"); + toString.insert("QScriptValue(QString(\"123\"))", "123"); + toString.insert("QScriptValue(QString(\"12.4\"))", "12.4"); + toString.insert("QScriptValue(0, QScriptValue::UndefinedValue)", "undefined"); + toString.insert("QScriptValue(0, QScriptValue::NullValue)", "null"); + toString.insert("QScriptValue(0, true)", "true"); + toString.insert("QScriptValue(0, false)", "false"); + toString.insert("QScriptValue(0, int(122))", "122"); + toString.insert("QScriptValue(0, uint(124))", "124"); + toString.insert("QScriptValue(0, 0)", "0"); + toString.insert("QScriptValue(0, 0.0)", "0"); + toString.insert("QScriptValue(0, 123.0)", "123"); + toString.insert("QScriptValue(0, 6.37e-8)", "6.37e-8"); + toString.insert("QScriptValue(0, -6.37e-8)", "-6.37e-8"); + toString.insert("QScriptValue(0, 0x43211234)", "1126240820"); + toString.insert("QScriptValue(0, 0x10000)", "65536"); + toString.insert("QScriptValue(0, 0x10001)", "65537"); + toString.insert("QScriptValue(0, qSNaN())", "NaN"); + toString.insert("QScriptValue(0, qQNaN())", "NaN"); + toString.insert("QScriptValue(0, qInf())", "Infinity"); + toString.insert("QScriptValue(0, -qInf())", "-Infinity"); + toString.insert("QScriptValue(0, \"NaN\")", "NaN"); + toString.insert("QScriptValue(0, \"Infinity\")", "Infinity"); + toString.insert("QScriptValue(0, \"-Infinity\")", "-Infinity"); + toString.insert("QScriptValue(0, \"ciao\")", "ciao"); + toString.insert("QScriptValue(0, QString::fromLatin1(\"ciao\"))", "ciao"); + toString.insert("QScriptValue(0, QString(\"\"))", ""); + toString.insert("QScriptValue(0, QString())", ""); + toString.insert("QScriptValue(0, QString(\"0\"))", "0"); + toString.insert("QScriptValue(0, QString(\"123\"))", "123"); + toString.insert("QScriptValue(0, QString(\"12.3\"))", "12.3"); + toString.insert("QScriptValue(engine, QScriptValue::UndefinedValue)", "undefined"); + toString.insert("QScriptValue(engine, QScriptValue::NullValue)", "null"); + toString.insert("QScriptValue(engine, true)", "true"); + toString.insert("QScriptValue(engine, false)", "false"); + toString.insert("QScriptValue(engine, int(122))", "122"); + toString.insert("QScriptValue(engine, uint(124))", "124"); + toString.insert("QScriptValue(engine, 0)", "0"); + toString.insert("QScriptValue(engine, 0.0)", "0"); + toString.insert("QScriptValue(engine, 123.0)", "123"); + toString.insert("QScriptValue(engine, 6.37e-8)", "6.37e-8"); + toString.insert("QScriptValue(engine, -6.37e-8)", "-6.37e-8"); + toString.insert("QScriptValue(engine, 0x43211234)", "1126240820"); + toString.insert("QScriptValue(engine, 0x10000)", "65536"); + toString.insert("QScriptValue(engine, 0x10001)", "65537"); + toString.insert("QScriptValue(engine, qSNaN())", "NaN"); + toString.insert("QScriptValue(engine, qQNaN())", "NaN"); + toString.insert("QScriptValue(engine, qInf())", "Infinity"); + toString.insert("QScriptValue(engine, -qInf())", "-Infinity"); + toString.insert("QScriptValue(engine, \"NaN\")", "NaN"); + toString.insert("QScriptValue(engine, \"Infinity\")", "Infinity"); + toString.insert("QScriptValue(engine, \"-Infinity\")", "-Infinity"); + toString.insert("QScriptValue(engine, \"ciao\")", "ciao"); + toString.insert("QScriptValue(engine, QString::fromLatin1(\"ciao\"))", "ciao"); + toString.insert("QScriptValue(engine, QString(\"\"))", ""); + toString.insert("QScriptValue(engine, QString())", ""); + toString.insert("QScriptValue(engine, QString(\"0\"))", "0"); + toString.insert("QScriptValue(engine, QString(\"123\"))", "123"); + toString.insert("QScriptValue(engine, QString(\"1.23\"))", "1.23"); + toString.insert("engine->evaluate(\"[]\")", ""); + toString.insert("engine->evaluate(\"{}\")", "undefined"); + toString.insert("engine->evaluate(\"Object.prototype\")", "[object Object]"); + toString.insert("engine->evaluate(\"Date.prototype\")", "Invalid Date"); + toString.insert("engine->evaluate(\"Array.prototype\")", ""); + toString.insert("engine->evaluate(\"Function.prototype\")", "function () {\n [native code]\n}"); + toString.insert("engine->evaluate(\"Error.prototype\")", "Error: Unknown error"); + toString.insert("engine->evaluate(\"Object\")", "function Object() {\n [native code]\n}"); + toString.insert("engine->evaluate(\"Array\")", "function Array() {\n [native code]\n}"); + toString.insert("engine->evaluate(\"Number\")", "function Number() {\n [native code]\n}"); + toString.insert("engine->evaluate(\"Function\")", "function Function() {\n [native code]\n}"); + toString.insert("engine->evaluate(\"(function() { return 1; })\")", "function () { return 1; }"); + toString.insert("engine->evaluate(\"(function() { return 'ciao'; })\")", "function () { return 'ciao'; }"); + toString.insert("engine->evaluate(\"(function() { throw new Error('foo'); })\")", "function () { throw new Error('foo'); }"); + toString.insert("engine->evaluate(\"/foo/\")", "/foo/"); + toString.insert("engine->evaluate(\"new Object()\")", "[object Object]"); + toString.insert("engine->evaluate(\"new Array()\")", ""); + toString.insert("engine->evaluate(\"new Error()\")", "Error: Unknown error"); + toString.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", "22"); + toString.insert("engine->evaluate(\"Undefined\")", "ReferenceError: Can't find variable: Undefined"); + toString.insert("engine->evaluate(\"Null\")", "ReferenceError: Can't find variable: Null"); + toString.insert("engine->evaluate(\"True\")", "ReferenceError: Can't find variable: True"); + toString.insert("engine->evaluate(\"False\")", "ReferenceError: Can't find variable: False"); + toString.insert("engine->evaluate(\"undefined\")", "undefined"); + toString.insert("engine->evaluate(\"null\")", "null"); + toString.insert("engine->evaluate(\"true\")", "true"); + toString.insert("engine->evaluate(\"false\")", "false"); + toString.insert("engine->evaluate(\"122\")", "122"); + toString.insert("engine->evaluate(\"124\")", "124"); + toString.insert("engine->evaluate(\"0\")", "0"); + toString.insert("engine->evaluate(\"0.0\")", "0"); + toString.insert("engine->evaluate(\"123.0\")", "123"); + toString.insert("engine->evaluate(\"6.37e-8\")", "6.37e-8"); + toString.insert("engine->evaluate(\"-6.37e-8\")", "-6.37e-8"); + toString.insert("engine->evaluate(\"0x43211234\")", "1126240820"); + toString.insert("engine->evaluate(\"0x10000\")", "65536"); + toString.insert("engine->evaluate(\"0x10001\")", "65537"); + toString.insert("engine->evaluate(\"NaN\")", "NaN"); + toString.insert("engine->evaluate(\"Infinity\")", "Infinity"); + toString.insert("engine->evaluate(\"-Infinity\")", "-Infinity"); + toString.insert("engine->evaluate(\"'ciao'\")", "ciao"); + toString.insert("engine->evaluate(\"''\")", ""); + toString.insert("engine->evaluate(\"'0'\")", "0"); + toString.insert("engine->evaluate(\"'123'\")", "123"); + toString.insert("engine->evaluate(\"'12.4'\")", "12.4"); + toString.insert("engine->nullValue()", "null"); + toString.insert("engine->undefinedValue()", "undefined"); + } + newRow(expr) << toString.value(expr); +} + +void tst_QScriptValue::toString_test(const char*, const QScriptValue& value) +{ + QFETCH(QString, expected); + QCOMPARE(value.toString(), expected); + QCOMPARE(value.toString(), expected); +} + +DEFINE_TEST_FUNCTION(toString) + + void tst_QScriptValue::toNumber_initData() { QTest::addColumn<qsreal>("expected"); @@ -669,6 +929,35 @@ void tst_QScriptValue::toNumber_makeData(const char* expr) toNumber.insert("engine->evaluate(\"new Object()\")", qQNaN()); toNumber.insert("engine->evaluate(\"new Array()\")", 0); toNumber.insert("engine->evaluate(\"new Error()\")", qQNaN()); + toNumber.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22); + toNumber.insert("engine->evaluate(\"Undefined\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Null\")", qQNaN()); + toNumber.insert("engine->evaluate(\"True\")", qQNaN()); + toNumber.insert("engine->evaluate(\"False\")", qQNaN()); + toNumber.insert("engine->evaluate(\"undefined\")", qQNaN()); + toNumber.insert("engine->evaluate(\"null\")", 0); + toNumber.insert("engine->evaluate(\"true\")", 1); + toNumber.insert("engine->evaluate(\"false\")", 0); + toNumber.insert("engine->evaluate(\"122\")", 122); + toNumber.insert("engine->evaluate(\"124\")", 124); + toNumber.insert("engine->evaluate(\"0\")", 0); + toNumber.insert("engine->evaluate(\"0.0\")", 0); + toNumber.insert("engine->evaluate(\"123.0\")", 123); + toNumber.insert("engine->evaluate(\"6.37e-8\")", 6.369999999999999e-08); + toNumber.insert("engine->evaluate(\"-6.37e-8\")", -6.369999999999999e-08); + toNumber.insert("engine->evaluate(\"0x43211234\")", 1126240820); + toNumber.insert("engine->evaluate(\"0x10000\")", 65536); + toNumber.insert("engine->evaluate(\"0x10001\")", 65537); + toNumber.insert("engine->evaluate(\"NaN\")", qQNaN()); + toNumber.insert("engine->evaluate(\"Infinity\")", qInf()); + toNumber.insert("engine->evaluate(\"-Infinity\")", qInf()); + toNumber.insert("engine->evaluate(\"'ciao'\")", qQNaN()); + toNumber.insert("engine->evaluate(\"''\")", 0); + toNumber.insert("engine->evaluate(\"'0'\")", 0); + toNumber.insert("engine->evaluate(\"'123'\")", 123); + toNumber.insert("engine->evaluate(\"'12.4'\")", 12.4); + toNumber.insert("engine->nullValue()", 0); + toNumber.insert("engine->undefinedValue()", qQNaN()); } newRow(expr) << toNumber.value(expr); } @@ -682,9 +971,11 @@ void tst_QScriptValue::toNumber_test(const char*, const QScriptValue& value) } if (qIsInf(expected)) { QVERIFY(qIsInf(value.toNumber())); + QVERIFY(qIsInf(value.toNumber())); return; } QCOMPARE(value.toNumber(), expected); + QCOMPARE(value.toNumber(), expected); } DEFINE_TEST_FUNCTION(toNumber) @@ -803,6 +1094,35 @@ void tst_QScriptValue::toBool_makeData(const char* expr) toBool.insert("engine->evaluate(\"new Object()\")", true); toBool.insert("engine->evaluate(\"new Array()\")", true); toBool.insert("engine->evaluate(\"new Error()\")", true); + toBool.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", true); + toBool.insert("engine->evaluate(\"Undefined\")", true); + toBool.insert("engine->evaluate(\"Null\")", true); + toBool.insert("engine->evaluate(\"True\")", true); + toBool.insert("engine->evaluate(\"False\")", true); + toBool.insert("engine->evaluate(\"undefined\")", false); + toBool.insert("engine->evaluate(\"null\")", false); + toBool.insert("engine->evaluate(\"true\")", true); + toBool.insert("engine->evaluate(\"false\")", false); + toBool.insert("engine->evaluate(\"122\")", true); + toBool.insert("engine->evaluate(\"124\")", true); + toBool.insert("engine->evaluate(\"0\")", false); + toBool.insert("engine->evaluate(\"0.0\")", false); + toBool.insert("engine->evaluate(\"123.0\")", true); + toBool.insert("engine->evaluate(\"6.37e-8\")", true); + toBool.insert("engine->evaluate(\"-6.37e-8\")", true); + toBool.insert("engine->evaluate(\"0x43211234\")", true); + toBool.insert("engine->evaluate(\"0x10000\")", true); + toBool.insert("engine->evaluate(\"0x10001\")", true); + toBool.insert("engine->evaluate(\"NaN\")", false); + toBool.insert("engine->evaluate(\"Infinity\")", true); + toBool.insert("engine->evaluate(\"-Infinity\")", true); + toBool.insert("engine->evaluate(\"'ciao'\")", true); + toBool.insert("engine->evaluate(\"''\")", false); + toBool.insert("engine->evaluate(\"'0'\")", true); + toBool.insert("engine->evaluate(\"'123'\")", true); + toBool.insert("engine->evaluate(\"'12.4'\")", true); + toBool.insert("engine->nullValue()", false); + toBool.insert("engine->undefinedValue()", false); } newRow(expr) << toBool.value(expr); } @@ -811,6 +1131,7 @@ void tst_QScriptValue::toBool_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.toBool(), expected); + QCOMPARE(value.toBool(), expected); } DEFINE_TEST_FUNCTION(toBool) @@ -929,6 +1250,35 @@ void tst_QScriptValue::toBoolean_makeData(const char* expr) toBoolean.insert("engine->evaluate(\"new Object()\")", true); toBoolean.insert("engine->evaluate(\"new Array()\")", true); toBoolean.insert("engine->evaluate(\"new Error()\")", true); + toBoolean.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", true); + toBoolean.insert("engine->evaluate(\"Undefined\")", true); + toBoolean.insert("engine->evaluate(\"Null\")", true); + toBoolean.insert("engine->evaluate(\"True\")", true); + toBoolean.insert("engine->evaluate(\"False\")", true); + toBoolean.insert("engine->evaluate(\"undefined\")", false); + toBoolean.insert("engine->evaluate(\"null\")", false); + toBoolean.insert("engine->evaluate(\"true\")", true); + toBoolean.insert("engine->evaluate(\"false\")", false); + toBoolean.insert("engine->evaluate(\"122\")", true); + toBoolean.insert("engine->evaluate(\"124\")", true); + toBoolean.insert("engine->evaluate(\"0\")", false); + toBoolean.insert("engine->evaluate(\"0.0\")", false); + toBoolean.insert("engine->evaluate(\"123.0\")", true); + toBoolean.insert("engine->evaluate(\"6.37e-8\")", true); + toBoolean.insert("engine->evaluate(\"-6.37e-8\")", true); + toBoolean.insert("engine->evaluate(\"0x43211234\")", true); + toBoolean.insert("engine->evaluate(\"0x10000\")", true); + toBoolean.insert("engine->evaluate(\"0x10001\")", true); + toBoolean.insert("engine->evaluate(\"NaN\")", false); + toBoolean.insert("engine->evaluate(\"Infinity\")", true); + toBoolean.insert("engine->evaluate(\"-Infinity\")", true); + toBoolean.insert("engine->evaluate(\"'ciao'\")", true); + toBoolean.insert("engine->evaluate(\"''\")", false); + toBoolean.insert("engine->evaluate(\"'0'\")", true); + toBoolean.insert("engine->evaluate(\"'123'\")", true); + toBoolean.insert("engine->evaluate(\"'12.4'\")", true); + toBoolean.insert("engine->nullValue()", false); + toBoolean.insert("engine->undefinedValue()", false); } newRow(expr) << toBoolean.value(expr); } @@ -937,6 +1287,7 @@ void tst_QScriptValue::toBoolean_test(const char*, const QScriptValue& value) { QFETCH(bool, expected); QCOMPARE(value.toBoolean(), expected); + QCOMPARE(value.toBoolean(), expected); } DEFINE_TEST_FUNCTION(toBoolean) @@ -1055,6 +1406,35 @@ void tst_QScriptValue::toInteger_makeData(const char* expr) toInteger.insert("engine->evaluate(\"new Object()\")", 0); toInteger.insert("engine->evaluate(\"new Array()\")", 0); toInteger.insert("engine->evaluate(\"new Error()\")", 0); + toInteger.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22); + toInteger.insert("engine->evaluate(\"Undefined\")", 0); + toInteger.insert("engine->evaluate(\"Null\")", 0); + toInteger.insert("engine->evaluate(\"True\")", 0); + toInteger.insert("engine->evaluate(\"False\")", 0); + toInteger.insert("engine->evaluate(\"undefined\")", 0); + toInteger.insert("engine->evaluate(\"null\")", 0); + toInteger.insert("engine->evaluate(\"true\")", 1); + toInteger.insert("engine->evaluate(\"false\")", 0); + toInteger.insert("engine->evaluate(\"122\")", 122); + toInteger.insert("engine->evaluate(\"124\")", 124); + toInteger.insert("engine->evaluate(\"0\")", 0); + toInteger.insert("engine->evaluate(\"0.0\")", 0); + toInteger.insert("engine->evaluate(\"123.0\")", 123); + toInteger.insert("engine->evaluate(\"6.37e-8\")", 0); + toInteger.insert("engine->evaluate(\"-6.37e-8\")", 0); + toInteger.insert("engine->evaluate(\"0x43211234\")", 1126240820); + toInteger.insert("engine->evaluate(\"0x10000\")", 65536); + toInteger.insert("engine->evaluate(\"0x10001\")", 65537); + toInteger.insert("engine->evaluate(\"NaN\")", 0); + toInteger.insert("engine->evaluate(\"Infinity\")", qInf()); + toInteger.insert("engine->evaluate(\"-Infinity\")", qInf()); + toInteger.insert("engine->evaluate(\"'ciao'\")", 0); + toInteger.insert("engine->evaluate(\"''\")", 0); + toInteger.insert("engine->evaluate(\"'0'\")", 0); + toInteger.insert("engine->evaluate(\"'123'\")", 123); + toInteger.insert("engine->evaluate(\"'12.4'\")", 12); + toInteger.insert("engine->nullValue()", 0); + toInteger.insert("engine->undefinedValue()", 0); } newRow(expr) << toInteger.value(expr); } @@ -1064,9 +1444,11 @@ void tst_QScriptValue::toInteger_test(const char*, const QScriptValue& value) QFETCH(qsreal, expected); if (qIsInf(expected)) { QVERIFY(qIsInf(value.toInteger())); + QVERIFY(qIsInf(value.toInteger())); return; } QCOMPARE(value.toInteger(), expected); + QCOMPARE(value.toInteger(), expected); } DEFINE_TEST_FUNCTION(toInteger) @@ -1185,6 +1567,35 @@ void tst_QScriptValue::toInt32_makeData(const char* expr) toInt32.insert("engine->evaluate(\"new Object()\")", 0); toInt32.insert("engine->evaluate(\"new Array()\")", 0); toInt32.insert("engine->evaluate(\"new Error()\")", 0); + toInt32.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22); + toInt32.insert("engine->evaluate(\"Undefined\")", 0); + toInt32.insert("engine->evaluate(\"Null\")", 0); + toInt32.insert("engine->evaluate(\"True\")", 0); + toInt32.insert("engine->evaluate(\"False\")", 0); + toInt32.insert("engine->evaluate(\"undefined\")", 0); + toInt32.insert("engine->evaluate(\"null\")", 0); + toInt32.insert("engine->evaluate(\"true\")", 1); + toInt32.insert("engine->evaluate(\"false\")", 0); + toInt32.insert("engine->evaluate(\"122\")", 122); + toInt32.insert("engine->evaluate(\"124\")", 124); + toInt32.insert("engine->evaluate(\"0\")", 0); + toInt32.insert("engine->evaluate(\"0.0\")", 0); + toInt32.insert("engine->evaluate(\"123.0\")", 123); + toInt32.insert("engine->evaluate(\"6.37e-8\")", 0); + toInt32.insert("engine->evaluate(\"-6.37e-8\")", 0); + toInt32.insert("engine->evaluate(\"0x43211234\")", 1126240820); + toInt32.insert("engine->evaluate(\"0x10000\")", 65536); + toInt32.insert("engine->evaluate(\"0x10001\")", 65537); + toInt32.insert("engine->evaluate(\"NaN\")", 0); + toInt32.insert("engine->evaluate(\"Infinity\")", 0); + toInt32.insert("engine->evaluate(\"-Infinity\")", 0); + toInt32.insert("engine->evaluate(\"'ciao'\")", 0); + toInt32.insert("engine->evaluate(\"''\")", 0); + toInt32.insert("engine->evaluate(\"'0'\")", 0); + toInt32.insert("engine->evaluate(\"'123'\")", 123); + toInt32.insert("engine->evaluate(\"'12.4'\")", 12); + toInt32.insert("engine->nullValue()", 0); + toInt32.insert("engine->undefinedValue()", 0); } newRow(expr) << toInt32.value(expr); } @@ -1193,6 +1604,7 @@ void tst_QScriptValue::toInt32_test(const char*, const QScriptValue& value) { QFETCH(qint32, expected); QCOMPARE(value.toInt32(), expected); + QCOMPARE(value.toInt32(), expected); } DEFINE_TEST_FUNCTION(toInt32) @@ -1311,6 +1723,35 @@ void tst_QScriptValue::toUInt32_makeData(const char* expr) toUInt32.insert("engine->evaluate(\"new Object()\")", 0); toUInt32.insert("engine->evaluate(\"new Array()\")", 0); toUInt32.insert("engine->evaluate(\"new Error()\")", 0); + toUInt32.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22); + toUInt32.insert("engine->evaluate(\"Undefined\")", 0); + toUInt32.insert("engine->evaluate(\"Null\")", 0); + toUInt32.insert("engine->evaluate(\"True\")", 0); + toUInt32.insert("engine->evaluate(\"False\")", 0); + toUInt32.insert("engine->evaluate(\"undefined\")", 0); + toUInt32.insert("engine->evaluate(\"null\")", 0); + toUInt32.insert("engine->evaluate(\"true\")", 1); + toUInt32.insert("engine->evaluate(\"false\")", 0); + toUInt32.insert("engine->evaluate(\"122\")", 122); + toUInt32.insert("engine->evaluate(\"124\")", 124); + toUInt32.insert("engine->evaluate(\"0\")", 0); + toUInt32.insert("engine->evaluate(\"0.0\")", 0); + toUInt32.insert("engine->evaluate(\"123.0\")", 123); + toUInt32.insert("engine->evaluate(\"6.37e-8\")", 0); + toUInt32.insert("engine->evaluate(\"-6.37e-8\")", 0); + toUInt32.insert("engine->evaluate(\"0x43211234\")", 1126240820); + toUInt32.insert("engine->evaluate(\"0x10000\")", 65536); + toUInt32.insert("engine->evaluate(\"0x10001\")", 65537); + toUInt32.insert("engine->evaluate(\"NaN\")", 0); + toUInt32.insert("engine->evaluate(\"Infinity\")", 0); + toUInt32.insert("engine->evaluate(\"-Infinity\")", 0); + toUInt32.insert("engine->evaluate(\"'ciao'\")", 0); + toUInt32.insert("engine->evaluate(\"''\")", 0); + toUInt32.insert("engine->evaluate(\"'0'\")", 0); + toUInt32.insert("engine->evaluate(\"'123'\")", 123); + toUInt32.insert("engine->evaluate(\"'12.4'\")", 12); + toUInt32.insert("engine->nullValue()", 0); + toUInt32.insert("engine->undefinedValue()", 0); } newRow(expr) << toUInt32.value(expr); } @@ -1319,6 +1760,7 @@ void tst_QScriptValue::toUInt32_test(const char*, const QScriptValue& value) { QFETCH(quint32, expected); QCOMPARE(value.toUInt32(), expected); + QCOMPARE(value.toUInt32(), expected); } DEFINE_TEST_FUNCTION(toUInt32) @@ -1437,6 +1879,35 @@ void tst_QScriptValue::toUInt16_makeData(const char* expr) toUInt16.insert("engine->evaluate(\"new Object()\")", 0); toUInt16.insert("engine->evaluate(\"new Array()\")", 0); toUInt16.insert("engine->evaluate(\"new Error()\")", 0); + toUInt16.insert("engine->evaluate(\"a = new Object(); a.foo = 22; a.foo\")", 22); + toUInt16.insert("engine->evaluate(\"Undefined\")", 0); + toUInt16.insert("engine->evaluate(\"Null\")", 0); + toUInt16.insert("engine->evaluate(\"True\")", 0); + toUInt16.insert("engine->evaluate(\"False\")", 0); + toUInt16.insert("engine->evaluate(\"undefined\")", 0); + toUInt16.insert("engine->evaluate(\"null\")", 0); + toUInt16.insert("engine->evaluate(\"true\")", 1); + toUInt16.insert("engine->evaluate(\"false\")", 0); + toUInt16.insert("engine->evaluate(\"122\")", 122); + toUInt16.insert("engine->evaluate(\"124\")", 124); + toUInt16.insert("engine->evaluate(\"0\")", 0); + toUInt16.insert("engine->evaluate(\"0.0\")", 0); + toUInt16.insert("engine->evaluate(\"123.0\")", 123); + toUInt16.insert("engine->evaluate(\"6.37e-8\")", 0); + toUInt16.insert("engine->evaluate(\"-6.37e-8\")", 0); + toUInt16.insert("engine->evaluate(\"0x43211234\")", 4660); + toUInt16.insert("engine->evaluate(\"0x10000\")", 0); + toUInt16.insert("engine->evaluate(\"0x10001\")", 1); + toUInt16.insert("engine->evaluate(\"NaN\")", 0); + toUInt16.insert("engine->evaluate(\"Infinity\")", 0); + toUInt16.insert("engine->evaluate(\"-Infinity\")", 0); + toUInt16.insert("engine->evaluate(\"'ciao'\")", 0); + toUInt16.insert("engine->evaluate(\"''\")", 0); + toUInt16.insert("engine->evaluate(\"'0'\")", 0); + toUInt16.insert("engine->evaluate(\"'123'\")", 123); + toUInt16.insert("engine->evaluate(\"'12.4'\")", 12); + toUInt16.insert("engine->nullValue()", 0); + toUInt16.insert("engine->undefinedValue()", 0); } newRow(expr) << toUInt16.value(expr); } @@ -1445,6 +1916,7 @@ void tst_QScriptValue::toUInt16_test(const char*, const QScriptValue& value) { QFETCH(quint16, expected); QCOMPARE(value.toUInt16(), expected); + QCOMPARE(value.toUInt16(), expected); } DEFINE_TEST_FUNCTION(toUInt16) diff --git a/JavaScriptCore/qt/tests/tests.pri b/JavaScriptCore/qt/tests/tests.pri index 1ce238f..5af3383 100644 --- a/JavaScriptCore/qt/tests/tests.pri +++ b/JavaScriptCore/qt/tests/tests.pri @@ -1,12 +1,3 @@ -isEmpty(OUTPUT_DIR) { - CONFIG(debug, debug|release) { - OUTPUT_DIR=$$PWD/WebKitBuild/Debug - } else { # Release - OUTPUT_DIR=$$PWD/WebKitBuild/Release - } -} - - QMAKE_RPATHDIR = $$OUTPUT_DIR/lib $$QMAKE_RPATHDIR QMAKE_LIBDIR = $$OUTPUT_DIR/lib $$QMAKE_LIBDIR mac:!static:contains(QT_CONFIG, qt_framework):!CONFIG(webkit_no_framework) { diff --git a/JavaScriptCore/qt/tests/tests.pro b/JavaScriptCore/qt/tests/tests.pro index 6e5edb1..7c3f590 100644 --- a/JavaScriptCore/qt/tests/tests.pro +++ b/JavaScriptCore/qt/tests/tests.pro @@ -1,3 +1,4 @@ TEMPLATE = subdirs SUBDIRS = qscriptengine \ - qscriptvalue + qscriptvalue \ + qscriptstring diff --git a/JavaScriptCore/runtime/ArrayPrototype.cpp b/JavaScriptCore/runtime/ArrayPrototype.cpp index 6d79581..bd14e64 100644 --- a/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -24,13 +24,13 @@ #include "config.h" #include "ArrayPrototype.h" -#include "CodeBlock.h" #include "CachedCall.h" +#include "CodeBlock.h" #include "Interpreter.h" #include "JIT.h" #include "JSStringBuilder.h" -#include "ObjectPrototype.h" #include "Lookup.h" +#include "ObjectPrototype.h" #include "Operations.h" #include <algorithm> #include <wtf/Assertions.h> @@ -156,9 +156,9 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue JSArray* thisObj = asArray(thisValue); HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements; - if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth) - return throwError(exec, RangeError, "Maximum call stack size exceeded."); + if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) { + if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth) + return throwError(exec, RangeError, "Maximum call stack size exceeded."); } bool alreadyVisited = !arrayVisitedElements.add(thisObj).second; @@ -201,7 +201,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec, JSObject*, JSValue if (i) buffer.append(','); if (RefPtr<UString::Rep> rep = strBuffer[i]) - buffer.append(rep->data(), rep->length()); + buffer.append(rep->characters(), rep->length()); } ASSERT(buffer.size() == totalSize); return jsString(exec, UString::adopt(buffer)); @@ -214,9 +214,9 @@ JSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec, JSObject*, J JSObject* thisObj = asArray(thisValue); HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements; - if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth) - return throwError(exec, RangeError, "Maximum call stack size exceeded."); + if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) { + if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth) + return throwError(exec, RangeError, "Maximum call stack size exceeded."); } bool alreadyVisited = !arrayVisitedElements.add(thisObj).second; @@ -252,9 +252,9 @@ JSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec, JSObject*, JSValue thi JSObject* thisObj = thisValue.toThisObject(exec); HashSet<JSObject*>& arrayVisitedElements = exec->globalData().arrayVisitedElements; - if (arrayVisitedElements.size() >= MaxSecondaryThreadReentryDepth) { - if (!isMainThread() || arrayVisitedElements.size() >= MaxMainThreadReentryDepth) - return throwError(exec, RangeError, "Maximum call stack size exceeded."); + if (arrayVisitedElements.size() >= MaxSmallThreadReentryDepth) { + if (arrayVisitedElements.size() >= exec->globalData().maxReentryDepth) + return throwError(exec, RangeError, "Maximum call stack size exceeded."); } bool alreadyVisited = !arrayVisitedElements.add(thisObj).second; @@ -506,14 +506,19 @@ JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue t // 15.4.4.12 JSArray* resObj = constructEmptyArray(exec); JSValue result = resObj; - unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + + // FIXME: Firefox returns an empty array. if (!args.size()) return jsUndefined(); - int begin = args.at(0).toUInt32(exec); - if (begin < 0) - begin = std::max<int>(begin + length, 0); - else - begin = std::min<int>(begin, length); + + unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); + double relativeBegin = args.at(0).toInteger(exec); + unsigned begin; + if (relativeBegin < 0) { + relativeBegin += length; + begin = (relativeBegin < 0) ? 0 : static_cast<unsigned>(relativeBegin); + } else + begin = std::min<unsigned>(static_cast<unsigned>(relativeBegin), length); unsigned deleteCount; if (args.size() > 1) @@ -539,7 +544,7 @@ JSValue JSC_HOST_CALL arrayProtoFuncSplice(ExecState* exec, JSObject*, JSValue t for (unsigned k = length; k > length - deleteCount + additionalArgs; --k) thisObj->deleteProperty(exec, k - 1); } else { - for (unsigned k = length - deleteCount; (int)k > begin; --k) { + for (unsigned k = length - deleteCount; k > begin; --k) { if (JSValue obj = getProperty(exec, thisObj, k + deleteCount - 1)) thisObj->put(exec, k + additionalArgs - 1, obj); else diff --git a/JavaScriptCore/runtime/Collector.cpp b/JavaScriptCore/runtime/Collector.cpp index 2873e0b..9b72755 100644 --- a/JavaScriptCore/runtime/Collector.cpp +++ b/JavaScriptCore/runtime/Collector.cpp @@ -53,11 +53,6 @@ #include <mach/thread_act.h> #include <mach/vm_map.h> -#elif OS(SYMBIAN) -#include <e32std.h> -#include <e32cmn.h> -#include <unistd.h> - #elif OS(WINDOWS) #include <windows.h> @@ -109,11 +104,6 @@ const size_t ALLOCATIONS_PER_COLLECTION = 3600; // a PIC branch in Mach-O binaries, see <rdar://problem/5971391>. #define MIN_ARRAY_SIZE (static_cast<size_t>(14)) -#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 OS(DARWIN) @@ -145,30 +135,12 @@ Heap::Heap(JSGlobalData* globalData) , m_registeredThreads(0) , m_currentThreadRegistrar(0) #endif +#if OS(SYMBIAN) + , m_blockallocator(JSCCOLLECTOR_VIRTUALMEM_RESERVATION, BLOCK_SIZE) +#endif , m_globalData(globalData) { ASSERT(globalData); - -#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. - // UserHeap::ChunkHeap allows allocation of continuous memory and specification - // of alignment value for (symbian) cells within that heap. - // - // Clarification and mapping of terminology: - // RHeap (created by UserHeap::ChunkHeap below) is continuos memory chunk, - // which can dynamically grow up to 8 MB, - // that holds all CollectorBlocks of this session (static). - // Each symbian cell within RHeap maps to a 64kb aligned CollectorBlock. - // JSCell objects are maintained as usual within CollectorBlocks. - if (!userChunk) { - userChunk = UserHeap::ChunkHeap(0, 0, MAX_NUM_BLOCKS * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE); - if (!userChunk) - CRASH(); - } -#endif // OS(SYMBIAN) - memset(&m_heap, 0, sizeof(CollectorHeap)); allocateBlock(); } @@ -211,7 +183,9 @@ void Heap::destroy() t = next; } #endif - +#if OS(SYMBIAN) + m_blockallocator.destroy(); +#endif m_globalData = 0; } @@ -221,15 +195,13 @@ NEVER_INLINE CollectorBlock* Heap::allocateBlock() vm_address_t address = 0; 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 OS(SYMBIAN) - // Allocate a 64 kb aligned CollectorBlock - unsigned char* mask = reinterpret_cast<unsigned char*>(userChunk->Alloc(BLOCK_SIZE)); - if (!mask) + void* address = m_blockallocator.alloc(); + if (!address) CRASH(); - uintptr_t address = reinterpret_cast<uintptr_t>(mask); #elif OS(WINCE) void* address = VirtualAlloc(NULL, BLOCK_SIZE, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); #elif OS(WINDOWS) -#if COMPILER(MINGW) +#if COMPILER(MINGW) && !COMPILER(MINGW64) void* address = __mingw_aligned_malloc(BLOCK_SIZE, BLOCK_SIZE); #else void* address = _aligned_malloc(BLOCK_SIZE, BLOCK_SIZE); @@ -316,11 +288,11 @@ NEVER_INLINE void Heap::freeBlockPtr(CollectorBlock* block) #if OS(DARWIN) vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(block), BLOCK_SIZE); #elif OS(SYMBIAN) - userChunk->Free(reinterpret_cast<TAny*>(block)); + m_blockallocator.free(reinterpret_cast<void*>(block)); #elif OS(WINCE) VirtualFree(block, 0, MEM_RELEASE); #elif OS(WINDOWS) -#if COMPILER(MINGW) +#if COMPILER(MINGW) && !COMPILER(MINGW64) __mingw_aligned_free(block); #else _aligned_free(block); @@ -574,10 +546,6 @@ static inline void* currentThreadStackBase() MOV pTib, EAX } return static_cast<void*>(pTib->StackBase); -#elif OS(WINDOWS) && CPU(X86_64) && COMPILER(MSVC) - // FIXME: why only for MSVC? - PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); - return reinterpret_cast<void*>(pTib->StackBase); #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 @@ -586,6 +554,9 @@ static inline void* currentThreadStackBase() : "=r" (pTib) ); return static_cast<void*>(pTib->StackBase); +#elif OS(WINDOWS) && CPU(X86_64) + PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); + return reinterpret_cast<void*>(pTib->StackBase); #elif OS(QNX) return currentThreadStackBaseQNX(); #elif OS(SOLARIS) @@ -667,7 +638,7 @@ void Heap::makeUsableFromMultipleThreads() void Heap::registerThread() { - ASSERT(!m_globalData->mainThreadOnly || isMainThread()); + ASSERT(!m_globalData->exclusiveThread || m_globalData->exclusiveThread == currentThread()); if (!m_currentThreadRegistrar || pthread_getspecific(m_currentThreadRegistrar)) return; @@ -1009,15 +980,15 @@ void Heap::protect(JSValue k) m_protectedValues.add(k.asCell()); } -void Heap::unprotect(JSValue k) +bool Heap::unprotect(JSValue k) { ASSERT(k); ASSERT(JSLock::currentThreadIsHoldingLock() || !m_globalData->isSharedInstance); if (!k.isCell()) - return; + return false; - m_protectedValues.remove(k.asCell()); + return m_protectedValues.remove(k.asCell()); } void Heap::markProtectedObjects(MarkStack& markStack) diff --git a/JavaScriptCore/runtime/Collector.h b/JavaScriptCore/runtime/Collector.h index 82aa8a1..3db3d7e 100644 --- a/JavaScriptCore/runtime/Collector.h +++ b/JavaScriptCore/runtime/Collector.h @@ -35,6 +35,10 @@ #include <pthread.h> #endif +#if OS(SYMBIAN) +#include <wtf/symbian/BlockAllocatorSymbian.h> +#endif + #define ASSERT_CLASS_FITS_IN_CELL(class) COMPILE_ASSERT(sizeof(class) <= CELL_SIZE, class_fits_in_cell) namespace JSC { @@ -91,7 +95,9 @@ namespace JSC { Statistics statistics() const; void protect(JSValue); - void unprotect(JSValue); + // Returns true if the value is no longer protected by any protect pointers + // (though it may still be alive due to heap/stack references). + bool unprotect(JSValue); static Heap* heap(JSValue); // 0 for immediate values static Heap* heap(JSCell*); @@ -168,6 +174,11 @@ namespace JSC { pthread_key_t m_currentThreadRegistrar; #endif +#if OS(SYMBIAN) + // Allocates collector blocks with correct alignment + WTF::AlignedBlockAllocator m_blockallocator; +#endif + JSGlobalData* m_globalData; }; diff --git a/JavaScriptCore/runtime/CommonIdentifiers.cpp b/JavaScriptCore/runtime/CommonIdentifiers.cpp index ed5e304..3837817 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.cpp +++ b/JavaScriptCore/runtime/CommonIdentifiers.cpp @@ -28,7 +28,8 @@ static const char* const nullCString = 0; #define INITIALIZE_PROPERTY_NAME(name) , name(globalData, #name) CommonIdentifiers::CommonIdentifiers(JSGlobalData* globalData) - : emptyIdentifier(globalData, "") + : nullIdentifier(globalData, nullCString) + , emptyIdentifier(globalData, "") , underscoreProto(globalData, "__proto__") , thisIdentifier(globalData, "this") JSC_COMMON_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_PROPERTY_NAME) diff --git a/JavaScriptCore/runtime/CommonIdentifiers.h b/JavaScriptCore/runtime/CommonIdentifiers.h index 0a3d774..de24f4a 100644 --- a/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/JavaScriptCore/runtime/CommonIdentifiers.h @@ -90,6 +90,7 @@ namespace JSC { friend class JSGlobalData; public: + const Identifier nullIdentifier; const Identifier emptyIdentifier; const Identifier underscoreProto; const Identifier thisIdentifier; diff --git a/JavaScriptCore/runtime/Completion.cpp b/JavaScriptCore/runtime/Completion.cpp index 2f88df9..9af5171 100644 --- a/JavaScriptCore/runtime/Completion.cpp +++ b/JavaScriptCore/runtime/Completion.cpp @@ -29,6 +29,7 @@ #include "Interpreter.h" #include "Parser.h" #include "Debugger.h" +#include "WTFThreadData.h" #include <stdio.h> namespace JSC { @@ -36,7 +37,7 @@ namespace JSC { Completion checkSyntax(ExecState* exec, const SourceCode& source) { JSLock lock(exec); - ASSERT(exec->globalData().identifierTable == currentIdentifierTable()); + ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); JSObject* error = program->checkSyntax(exec); @@ -49,7 +50,7 @@ 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()); + ASSERT(exec->globalData().identifierTable == wtfThreadData().currentIdentifierTable()); RefPtr<ProgramExecutable> program = ProgramExecutable::create(exec, source); JSObject* error = program->compile(exec, scopeChain.node()); @@ -62,9 +63,10 @@ Completion evaluate(ExecState* exec, ScopeChain& scopeChain, const SourceCode& s 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); + ComplType exceptionType = Throw; + if (exception.isObject()) + exceptionType = asObject(exception)->exceptionType(); + return Completion(exceptionType, exception); } return Completion(Normal, result); } diff --git a/JavaScriptCore/runtime/Completion.h b/JavaScriptCore/runtime/Completion.h index 41c9a64..63b315e 100644 --- a/JavaScriptCore/runtime/Completion.h +++ b/JavaScriptCore/runtime/Completion.h @@ -31,7 +31,7 @@ namespace JSC { class ScopeChain; class SourceCode; - enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted }; + enum ComplType { Normal, Break, Continue, ReturnValue, Throw, Interrupted, Terminated }; /* * Completion objects are used to convey the return status and value diff --git a/JavaScriptCore/runtime/DateConversion.cpp b/JavaScriptCore/runtime/DateConversion.cpp index f129407..70dbaa0 100644 --- a/JavaScriptCore/runtime/DateConversion.cpp +++ b/JavaScriptCore/runtime/DateConversion.cpp @@ -56,7 +56,7 @@ double parseDate(ExecState* exec, const UString &date) { if (date == exec->globalData().cachedDateString) return exec->globalData().cachedDateStringValue; - double value = parseDateFromNullTerminatedCharacters(exec, date.UTF8String().c_str()); + double value = parseDateFromNullTerminatedCharacters(exec, date.UTF8String().data()); exec->globalData().cachedDateString = date; exec->globalData().cachedDateStringValue = value; return value; diff --git a/JavaScriptCore/runtime/DatePrototype.cpp b/JavaScriptCore/runtime/DatePrototype.cpp index 25b0ac4..d331409 100644 --- a/JavaScriptCore/runtime/DatePrototype.cpp +++ b/JavaScriptCore/runtime/DatePrototype.cpp @@ -24,11 +24,12 @@ #include "DatePrototype.h" #include "DateConversion.h" +#include "DateInstance.h" #include "Error.h" #include "JSString.h" #include "JSStringBuilder.h" +#include "Lookup.h" #include "ObjectPrototype.h" -#include "DateInstance.h" #if !PLATFORM(MAC) && HAVE(LANGINFO_H) #include <langinfo.h> diff --git a/JavaScriptCore/runtime/ExceptionHelpers.cpp b/JavaScriptCore/runtime/ExceptionHelpers.cpp index b9c6319..aee6f31 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.cpp +++ b/JavaScriptCore/runtime/ExceptionHelpers.cpp @@ -46,7 +46,7 @@ public: { } - virtual bool isWatchdogException() const { return true; } + virtual ComplType exceptionType() const { return Interrupted; } virtual UString toString(ExecState*) const { return "JavaScript execution exceeded timeout."; } }; @@ -56,6 +56,23 @@ JSValue createInterruptedExecutionException(JSGlobalData* globalData) return new (globalData) InterruptedExecutionError(globalData); } +class TerminatedExecutionError : public JSObject { +public: + TerminatedExecutionError(JSGlobalData* globalData) + : JSObject(globalData->terminatedExecutionErrorStructure) + { + } + + virtual ComplType exceptionType() const { return Terminated; } + + virtual UString toString(ExecState*) const { return "JavaScript execution terminated."; } +}; + +JSValue createTerminatedExecutionException(JSGlobalData* globalData) +{ + return new (globalData) TerminatedExecutionError(globalData); +} + static JSValue createError(ExecState* exec, ErrorType e, const char* msg) { return Error::create(exec, e, msg, -1, -1, UString()); diff --git a/JavaScriptCore/runtime/ExceptionHelpers.h b/JavaScriptCore/runtime/ExceptionHelpers.h index b6e7373..b152439 100644 --- a/JavaScriptCore/runtime/ExceptionHelpers.h +++ b/JavaScriptCore/runtime/ExceptionHelpers.h @@ -43,6 +43,7 @@ namespace JSC { struct Instruction; JSValue createInterruptedExecutionException(JSGlobalData*); + JSValue createTerminatedExecutionException(JSGlobalData*); JSValue createStackOverflowError(ExecState*); JSValue createTypeError(ExecState*, const char* message); JSValue createUndefinedVariableError(ExecState*, const Identifier&, unsigned bytecodeOffset, CodeBlock*); diff --git a/JavaScriptCore/runtime/FunctionPrototype.cpp b/JavaScriptCore/runtime/FunctionPrototype.cpp index 3475f08..a77b5b2 100644 --- a/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -39,7 +39,7 @@ static JSValue JSC_HOST_CALL functionProtoFuncApply(ExecState*, JSObject*, JSVal static JSValue JSC_HOST_CALL functionProtoFuncCall(ExecState*, JSObject*, JSValue, const ArgList&); FunctionPrototype::FunctionPrototype(ExecState* exec, NonNullPassRefPtr<Structure> structure) - : InternalFunction(&exec->globalData(), structure, exec->propertyNames().emptyIdentifier) + : InternalFunction(&exec->globalData(), structure, exec->propertyNames().nullIdentifier) { putDirectWithoutTransition(exec->propertyNames().length, jsNumber(exec, 0), DontDelete | ReadOnly | DontEnum); } diff --git a/JavaScriptCore/runtime/GetterSetter.h b/JavaScriptCore/runtime/GetterSetter.h index 4e47361..27ffbe7 100644 --- a/JavaScriptCore/runtime/GetterSetter.h +++ b/JavaScriptCore/runtime/GetterSetter.h @@ -34,6 +34,7 @@ namespace JSC { // This is an internal value object which stores getter and setter functions // for a property. class GetterSetter : public JSCell { + friend class JIT; public: GetterSetter(ExecState* exec) : JSCell(exec->globalData().getterSetterStructure.get()) diff --git a/JavaScriptCore/runtime/Identifier.cpp b/JavaScriptCore/runtime/Identifier.cpp index 46fcd0b..f2642a9 100644 --- a/JavaScriptCore/runtime/Identifier.cpp +++ b/JavaScriptCore/runtime/Identifier.cpp @@ -22,50 +22,38 @@ #include "Identifier.h" #include "CallFrame.h" +#include "NumericStrings.h" #include <new> // for placement new #include <string.h> // for strlen #include <wtf/Assertions.h> #include <wtf/FastMalloc.h> #include <wtf/HashSet.h> +#include <wtf/WTFThreadData.h> +#include <wtf/text/StringHash.h> using WTF::ThreadSpecific; namespace JSC { -typedef HashMap<const char*, RefPtr<UString::Rep>, PtrHash<const char*> > LiteralIdentifierTable; - -class IdentifierTable : public FastAllocBase { -public: - ~IdentifierTable() - { - HashSet<UString::Rep*>::iterator end = m_table.end(); - for (HashSet<UString::Rep*>::iterator iter = m_table.begin(); iter != end; ++iter) - (*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)->setIsIdentifier(true); - return result; - } - - template<typename U, typename V> - 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)->setIsIdentifier(true); - return result; - } - - void remove(UString::Rep* r) { m_table.remove(r); } - - LiteralIdentifierTable& literalTable() { return m_literalTable; } - -private: - HashSet<UString::Rep*> m_table; - LiteralIdentifierTable m_literalTable; -}; +IdentifierTable::~IdentifierTable() +{ + HashSet<StringImpl*>::iterator end = m_table.end(); + for (HashSet<StringImpl*>::iterator iter = m_table.begin(); iter != end; ++iter) + (*iter)->setIsIdentifier(false); +} +std::pair<HashSet<StringImpl*>::iterator, bool> IdentifierTable::add(StringImpl* value) +{ + std::pair<HashSet<StringImpl*>::iterator, bool> result = m_table.add(value); + (*result.first)->setIsIdentifier(true); + return result; +} +template<typename U, typename V> +std::pair<HashSet<StringImpl*>::iterator, bool> IdentifierTable::add(U value) +{ + std::pair<HashSet<StringImpl*>::iterator, bool> result = m_table.add<U, V>(value); + (*result.first)->setIsIdentifier(true); + return result; +} IdentifierTable* createIdentifierTable() { @@ -80,7 +68,7 @@ void deleteIdentifierTable(IdentifierTable* table) bool Identifier::equal(const UString::Rep* r, const char* s) { int length = r->length(); - const UChar* d = r->data(); + const UChar* d = r->characters(); for (int i = 0; i != length; ++i) if (d[i] != (unsigned char)s[i]) return false; @@ -91,14 +79,14 @@ bool Identifier::equal(const UString::Rep* r, const UChar* s, unsigned length) { if (r->length() != length) return false; - const UChar* d = r->data(); + const UChar* d = r->characters(); for (unsigned i = 0; i != length; ++i) if (d[i] != s[i]) return false; return true; } -struct CStringTranslator { +struct IdentifierCStringTranslator { static unsigned hash(const char* c) { return UString::Rep::computeHash(c); @@ -123,12 +111,10 @@ struct CStringTranslator { PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c) { - ASSERT(c); - - if (!c[0]) { - UString::Rep::empty().hash(); - return &UString::Rep::empty(); - } + if (!c) + return UString::null().rep(); + if (!c[0]) + return UString::Rep::empty(); if (!c[1]) return add(globalData, globalData->smallStrings.singleCharacterStringRep(static_cast<unsigned char>(c[0]))); @@ -139,7 +125,7 @@ PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const char* c if (iter != literalIdentifierTable.end()) return iter->second; - pair<HashSet<UString::Rep*>::iterator, bool> addResult = identifierTable.add<const char*, CStringTranslator>(c); + pair<HashSet<UString::Rep*>::iterator, bool> addResult = identifierTable.add<const char*, IdentifierCStringTranslator>(c); // If the string is newly-translated, then we need to adopt it. // The boolean in the pair tells us if that is so. @@ -160,7 +146,7 @@ struct UCharBuffer { unsigned int length; }; -struct UCharBufferTranslator { +struct IdentifierUCharBufferTranslator { static unsigned hash(const UCharBuffer& buf) { return UString::Rep::computeHash(buf.s, buf.length); @@ -189,12 +175,10 @@ PassRefPtr<UString::Rep> Identifier::add(JSGlobalData* globalData, const UChar* if (c <= 0xFF) return add(globalData, globalData->smallStrings.singleCharacterStringRep(c)); } - if (!length) { - UString::Rep::empty().hash(); - return &UString::Rep::empty(); - } + if (!length) + return UString::Rep::empty(); UCharBuffer buf = {s, length}; - pair<HashSet<UString::Rep*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, UCharBufferTranslator>(buf); + pair<HashSet<UString::Rep*>::iterator, bool> addResult = globalData->identifierTable->add<UCharBuffer, IdentifierUCharBufferTranslator>(buf); // If the string is newly-translated, then we need to adopt it. // The boolean in the pair tells us if that is so. @@ -209,21 +193,18 @@ PassRefPtr<UString::Rep> Identifier::add(ExecState* exec, const UChar* s, int le PassRefPtr<UString::Rep> Identifier::addSlowCase(JSGlobalData* globalData, UString::Rep* r) { ASSERT(!r->isIdentifier()); + // The empty & null strings are static singletons, and static strings are handled + // in ::add() in the header, so we should never get here with a zero length string. + ASSERT(r->length()); + if (r->length() == 1) { - UChar c = r->data()[0]; + UChar c = r->characters()[0]; if (c <= 0xFF) r = globalData->smallStrings.singleCharacterStringRep(c); - if (r->isIdentifier()) { -#ifndef NDEBUG - checkSameIdentifierTable(globalData, r); -#endif + if (r->isIdentifier()) return r; - } - } - if (!r->length()) { - UString::Rep::empty().hash(); - return &UString::Rep::empty(); } + return *globalData->identifierTable->add(r).first; } @@ -232,58 +213,41 @@ PassRefPtr<UString::Rep> Identifier::addSlowCase(ExecState* exec, UString::Rep* return addSlowCase(&exec->globalData(), r); } -void Identifier::remove(UString::Rep* r) +Identifier Identifier::from(ExecState* exec, unsigned value) { - currentIdentifierTable()->remove(r); + return Identifier(exec, exec->globalData().numericStrings.add(value)); } -#ifndef NDEBUG - -void Identifier::checkSameIdentifierTable(ExecState* exec, UString::Rep*) +Identifier Identifier::from(ExecState* exec, int value) { - ASSERT_UNUSED(exec, exec->globalData().identifierTable == currentIdentifierTable()); + return Identifier(exec, exec->globalData().numericStrings.add(value)); } -void Identifier::checkSameIdentifierTable(JSGlobalData* globalData, UString::Rep*) +Identifier Identifier::from(ExecState* exec, double value) { - ASSERT_UNUSED(globalData, globalData->identifierTable == currentIdentifierTable()); + return Identifier(exec, exec->globalData().numericStrings.add(value)); } -#else - -void Identifier::checkSameIdentifierTable(ExecState*, UString::Rep*) -{ -} +#ifndef NDEBUG -void Identifier::checkSameIdentifierTable(JSGlobalData*, UString::Rep*) +void Identifier::checkCurrentIdentifierTable(JSGlobalData* globalData) { + // Check the identifier table accessible through the threadspecific matches the + // globalData's identifier table. + ASSERT_UNUSED(globalData, globalData->identifierTable == wtfThreadData().currentIdentifierTable()); } -#endif - -ThreadSpecific<ThreadIdentifierTableData>* g_identifierTableSpecific = 0; - -#if ENABLE(JSC_MULTIPLE_THREADS) - -pthread_once_t createIdentifierTableSpecificOnce = PTHREAD_ONCE_INIT; -static void createIdentifierTableSpecificCallback() +void Identifier::checkCurrentIdentifierTable(ExecState* exec) { - ASSERT(!g_identifierTableSpecific); - g_identifierTableSpecific = new ThreadSpecific<ThreadIdentifierTableData>(); -} -void createIdentifierTableSpecific() -{ - pthread_once(&createIdentifierTableSpecificOnce, createIdentifierTableSpecificCallback); - ASSERT(g_identifierTableSpecific); + checkCurrentIdentifierTable(&exec->globalData()); } -#else +#else -void createIdentifierTableSpecific() -{ - ASSERT(!g_identifierTableSpecific); - g_identifierTableSpecific = new ThreadSpecific<ThreadIdentifierTableData>(); -} +// These only exists so that our exports are the same for debug and release builds. +// This would be an ASSERT_NOT_REACHED(), but we're in NDEBUG only code here! +void Identifier::checkCurrentIdentifierTable(JSGlobalData*) { CRASH(); } +void Identifier::checkCurrentIdentifierTable(ExecState*) { CRASH(); } #endif diff --git a/JavaScriptCore/runtime/Identifier.h b/JavaScriptCore/runtime/Identifier.h index 73e2af8..2f16bbf 100644 --- a/JavaScriptCore/runtime/Identifier.h +++ b/JavaScriptCore/runtime/Identifier.h @@ -54,9 +54,9 @@ namespace JSC { const char* ascii() const { return _ustring.ascii(); } - static Identifier from(ExecState* exec, unsigned y) { return Identifier(exec, UString::from(y)); } - static Identifier from(ExecState* exec, int y) { return Identifier(exec, UString::from(y)); } - static Identifier from(ExecState* exec, double y) { return Identifier(exec, UString::from(y)); } + static Identifier from(ExecState* exec, unsigned y); + static Identifier from(ExecState* exec, int y); + static Identifier from(ExecState* exec, double y); bool isNull() const { return _ustring.isNull(); } bool isEmpty() const { return _ustring.isEmpty(); } @@ -73,11 +73,9 @@ namespace JSC { friend bool operator==(const Identifier&, const char*); friend bool operator!=(const Identifier&, const char*); - static void remove(UString::Rep*); - static bool equal(const UString::Rep*, const char*); static bool equal(const UString::Rep*, const UChar*, unsigned length); - static bool equal(const UString::Rep* a, const UString::Rep* b) { return JSC::equal(a, b); } + static bool equal(const UString::Rep* a, const UString::Rep* b) { return ::equal(a, b); } static PassRefPtr<UString::Rep> add(ExecState*, const char*); // Only to be used with string literals. static PassRefPtr<UString::Rep> add(JSGlobalData*, const char*); // Only to be used with string literals. @@ -93,30 +91,28 @@ namespace JSC { static PassRefPtr<UString::Rep> add(ExecState* exec, UString::Rep* r) { - if (r->isIdentifier()) { #ifndef NDEBUG - checkSameIdentifierTable(exec, r); + checkCurrentIdentifierTable(exec); #endif + if (r->isIdentifier()) return r; - } return addSlowCase(exec, r); } static PassRefPtr<UString::Rep> add(JSGlobalData* globalData, UString::Rep* r) { - if (r->isIdentifier()) { #ifndef NDEBUG - checkSameIdentifierTable(globalData, r); + checkCurrentIdentifierTable(globalData); #endif + if (r->isIdentifier()) return r; - } return addSlowCase(globalData, r); } static PassRefPtr<UString::Rep> addSlowCase(ExecState*, UString::Rep* r); static PassRefPtr<UString::Rep> addSlowCase(JSGlobalData*, UString::Rep* r); - static void checkSameIdentifierTable(ExecState*, UString::Rep*); - static void checkSameIdentifierTable(JSGlobalData*, UString::Rep*); + static void checkCurrentIdentifierTable(ExecState*); + static void checkCurrentIdentifierTable(JSGlobalData*); }; inline bool operator==(const Identifier& a, const Identifier& b) @@ -142,67 +138,6 @@ 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/JavaScriptCore/runtime/InitializeThreading.cpp b/JavaScriptCore/runtime/InitializeThreading.cpp index 2605a9a..51d43ee 100644 --- a/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/JavaScriptCore/runtime/InitializeThreading.cpp @@ -36,6 +36,7 @@ #include "UString.h" #include <wtf/DateMath.h> #include <wtf/Threading.h> +#include <wtf/WTFThreadData.h> using namespace WTF; @@ -48,6 +49,7 @@ static pthread_once_t initializeThreadingKeyOnce = PTHREAD_ONCE_INIT; static void initializeThreadingOnce() { WTF::initializeThreading(); + wtfThreadData(); initializeUString(); JSGlobalData::storeVPtrs(); #if ENABLE(JSC_MULTIPLE_THREADS) diff --git a/JavaScriptCore/runtime/InternalFunction.cpp b/JavaScriptCore/runtime/InternalFunction.cpp index c48d628..717b5ff 100644 --- a/JavaScriptCore/runtime/InternalFunction.cpp +++ b/JavaScriptCore/runtime/InternalFunction.cpp @@ -40,7 +40,7 @@ const ClassInfo* InternalFunction::classInfo() const InternalFunction::InternalFunction(JSGlobalData* globalData, NonNullPassRefPtr<Structure> structure, const Identifier& name) : JSObject(structure) { - putDirect(globalData->propertyNames->name, jsString(globalData, name.ustring()), DontDelete | ReadOnly | DontEnum); + putDirect(globalData->propertyNames->name, jsString(globalData, name.isNull() ? "" : name.ustring()), DontDelete | ReadOnly | DontEnum); } const UString& InternalFunction::name(ExecState* exec) diff --git a/JavaScriptCore/runtime/JSAPIValueWrapper.h b/JavaScriptCore/runtime/JSAPIValueWrapper.h index b5016c2..10ded4c 100644 --- a/JavaScriptCore/runtime/JSAPIValueWrapper.h +++ b/JavaScriptCore/runtime/JSAPIValueWrapper.h @@ -23,8 +23,6 @@ #ifndef JSAPIValueWrapper_h #define JSAPIValueWrapper_h -#include <wtf/Platform.h> - #include "JSCell.h" #include "CallFrame.h" diff --git a/JavaScriptCore/runtime/JSActivation.cpp b/JavaScriptCore/runtime/JSActivation.cpp index 22fdaaf..85e8bba 100644 --- a/JavaScriptCore/runtime/JSActivation.cpp +++ b/JavaScriptCore/runtime/JSActivation.cpp @@ -139,9 +139,9 @@ bool JSActivation::isDynamicScope() const return d()->functionExecutable->usesEval(); } -JSValue JSActivation::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue JSActivation::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&) { - JSActivation* activation = asActivation(slot.slotBase()); + JSActivation* activation = asActivation(slotBase); if (activation->d()->functionExecutable->usesArguments()) { PropertySlot slot; diff --git a/JavaScriptCore/runtime/JSActivation.h b/JavaScriptCore/runtime/JSActivation.h index 761bee4..91c960c 100644 --- a/JavaScriptCore/runtime/JSActivation.h +++ b/JavaScriptCore/runtime/JSActivation.h @@ -89,7 +89,7 @@ namespace JSC { RefPtr<FunctionExecutable> functionExecutable; }; - static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&); NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); JSActivationData* d() const { return static_cast<JSActivationData*>(JSVariableObject::d); } diff --git a/JavaScriptCore/runtime/JSArray.cpp b/JavaScriptCore/runtime/JSArray.cpp index 2be7371..d3ef44c 100644 --- a/JavaScriptCore/runtime/JSArray.cpp +++ b/JavaScriptCore/runtime/JSArray.cpp @@ -151,7 +151,7 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, unsigned initialLength) m_vectorLength = initialCapacity; m_storage->m_numValuesInVector = 0; m_storage->m_sparseValueMap = 0; - m_storage->lazyCreationData = 0; + m_storage->subclassData = 0; m_storage->reportedMapCapacity = 0; JSValue* vector = m_storage->m_vector; @@ -173,7 +173,7 @@ JSArray::JSArray(NonNullPassRefPtr<Structure> structure, const ArgList& list) m_vectorLength = initialCapacity; m_storage->m_numValuesInVector = initialCapacity; m_storage->m_sparseValueMap = 0; - m_storage->lazyCreationData = 0; + m_storage->subclassData = 0; m_storage->reportedMapCapacity = 0; size_t i = 0; @@ -1022,14 +1022,14 @@ unsigned JSArray::compactForSorting() return numDefined; } -void* JSArray::lazyCreationData() +void* JSArray::subclassData() const { - return m_storage->lazyCreationData; + return m_storage->subclassData; } -void JSArray::setLazyCreationData(void* d) +void JSArray::setSubclassData(void* d) { - m_storage->lazyCreationData = d; + m_storage->subclassData = d; } #if CHECK_ARRAY_CONSISTENCY diff --git a/JavaScriptCore/runtime/JSArray.h b/JavaScriptCore/runtime/JSArray.h index ad6ee88..f65f2bc 100644 --- a/JavaScriptCore/runtime/JSArray.h +++ b/JavaScriptCore/runtime/JSArray.h @@ -31,7 +31,7 @@ namespace JSC { unsigned m_length; unsigned m_numValuesInVector; SparseArrayValueMap* m_sparseValueMap; - void* lazyCreationData; // A JSArray subclass can use this to fill the vector lazily. + void* subclassData; // A JSArray subclass can use this to fill the vector lazily. size_t reportedMapCapacity; JSValue m_vector[1]; }; @@ -101,8 +101,8 @@ namespace JSC { virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, EnumerationMode mode = ExcludeDontEnumProperties); virtual void markChildren(MarkStack&); - void* lazyCreationData(); - void setLazyCreationData(void*); + void* subclassData() const; + void setSubclassData(void*); private: virtual const ClassInfo* classInfo() const { return &info; } diff --git a/JavaScriptCore/runtime/JSCell.cpp b/JavaScriptCore/runtime/JSCell.cpp index 869fbfc..0cc1ab1 100644 --- a/JavaScriptCore/runtime/JSCell.cpp +++ b/JavaScriptCore/runtime/JSCell.cpp @@ -163,16 +163,6 @@ JSObject* JSCell::toThisObject(ExecState* exec) const return toObject(exec); } -UString JSCell::toThisString(ExecState* exec) const -{ - return toThisObject(exec)->toString(exec); -} - -JSString* JSCell::toThisJSString(ExecState* exec) -{ - return jsString(exec, toThisString(exec)); -} - const ClassInfo* JSCell::classInfo() const { return 0; diff --git a/JavaScriptCore/runtime/JSCell.h b/JavaScriptCore/runtime/JSCell.h index 3c8c829..772708f 100644 --- a/JavaScriptCore/runtime/JSCell.h +++ b/JavaScriptCore/runtime/JSCell.h @@ -107,8 +107,6 @@ namespace JSC { 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; } @@ -301,11 +299,6 @@ namespace JSC { return asCell()->structure()->typeInfo().needsThisConversion(); } - inline UString JSValue::toThisString(ExecState* exec) const - { - return isCell() ? asCell()->toThisString(exec) : toString(exec); - } - inline JSValue JSValue::getJSNumber() { if (isInt32() || isDouble()) diff --git a/JavaScriptCore/runtime/JSFunction.cpp b/JavaScriptCore/runtime/JSFunction.cpp index d213b4a..cba6795 100644 --- a/JavaScriptCore/runtime/JSFunction.cpp +++ b/JavaScriptCore/runtime/JSFunction.cpp @@ -122,23 +122,23 @@ JSValue JSFunction::call(ExecState* exec, JSValue thisValue, const ArgList& args return exec->interpreter()->execute(jsExecutable(), exec, this, thisValue.toThisObject(exec), args, scopeChain().node(), exec->exceptionSlot()); } -JSValue JSFunction::argumentsGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&) { - JSFunction* thisObj = asFunction(slot.slotBase()); + JSFunction* thisObj = asFunction(slotBase); ASSERT(!thisObj->isHostFunction()); return exec->interpreter()->retrieveArguments(exec, thisObj); } -JSValue JSFunction::callerGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identifier&) { - JSFunction* thisObj = asFunction(slot.slotBase()); + JSFunction* thisObj = asFunction(slotBase); ASSERT(!thisObj->isHostFunction()); return exec->interpreter()->retrieveCaller(exec, thisObj); } -JSValue JSFunction::lengthGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue JSFunction::lengthGetter(ExecState* exec, JSValue slotBase, const Identifier&) { - JSFunction* thisObj = asFunction(slot.slotBase()); + JSFunction* thisObj = asFunction(slotBase); ASSERT(!thisObj->isHostFunction()); return jsNumber(exec, thisObj->jsExecutable()->parameterCount()); } @@ -162,17 +162,17 @@ bool JSFunction::getOwnPropertySlot(ExecState* exec, const Identifier& propertyN } if (propertyName == exec->propertyNames().arguments) { - slot.setCustom(this, argumentsGetter); + slot.setCacheableCustom(this, argumentsGetter); return true; } if (propertyName == exec->propertyNames().length) { - slot.setCustom(this, lengthGetter); + slot.setCacheableCustom(this, lengthGetter); return true; } if (propertyName == exec->propertyNames().caller) { - slot.setCustom(this, callerGetter); + slot.setCacheableCustom(this, callerGetter); return true; } diff --git a/JavaScriptCore/runtime/JSFunction.h b/JavaScriptCore/runtime/JSFunction.h index 8cd4b51..afa24a8 100644 --- a/JavaScriptCore/runtime/JSFunction.h +++ b/JavaScriptCore/runtime/JSFunction.h @@ -90,9 +90,9 @@ namespace JSC { virtual const ClassInfo* classInfo() const { return &info; } - static JSValue argumentsGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue callerGetter(ExecState*, const Identifier&, const PropertySlot&); - static JSValue lengthGetter(ExecState*, const Identifier&, const PropertySlot&); + static JSValue argumentsGetter(ExecState*, JSValue, const Identifier&); + static JSValue callerGetter(ExecState*, JSValue, const Identifier&); + static JSValue lengthGetter(ExecState*, JSValue, const Identifier&); RefPtr<ExecutableBase> m_executable; ScopeChain& scopeChain() diff --git a/JavaScriptCore/runtime/JSGlobalData.cpp b/JavaScriptCore/runtime/JSGlobalData.cpp index 45abc86..2948d1c 100644 --- a/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/JavaScriptCore/runtime/JSGlobalData.cpp @@ -49,6 +49,7 @@ #include "Lookup.h" #include "Nodes.h" #include "Parser.h" +#include <wtf/WTFThreadData.h> #if ENABLE(JSC_MULTIPLE_THREADS) #include <wtf/Threading.h> @@ -102,7 +103,7 @@ void JSGlobalData::storeVPtrs() jsFunction->~JSCell(); } -JSGlobalData::JSGlobalData(bool isShared) +JSGlobalData::JSGlobalData(bool isShared, ThreadStackType threadStackType) : isSharedInstance(isShared) , clientData(0) , arrayTable(fastNew<HashTable>(JSC::arrayTable)) @@ -115,6 +116,7 @@ JSGlobalData::JSGlobalData(bool isShared) , stringTable(fastNew<HashTable>(JSC::stringTable)) , activationStructure(JSActivation::createStructure(jsNull())) , interruptedExecutionErrorStructure(JSObject::createStructure(jsNull())) + , terminatedExecutionErrorStructure(JSObject::createStructure(jsNull())) , staticScopeStructure(JSStaticScopeObject::createStructure(jsNull())) , stringStructure(JSString::createStructure(jsNull())) , notAnObjectErrorStubStructure(JSNotAnObjectErrorStub::createStructure(jsNull())) @@ -144,8 +146,9 @@ JSGlobalData::JSGlobalData(bool isShared) , markStack(jsArrayVPtr) , cachedUTCOffset(NaN) , weakRandom(static_cast<int>(currentTime())) + , maxReentryDepth(threadStackType == ThreadStackTypeSmall ? MaxSmallThreadReentryDepth : MaxLargeThreadReentryDepth) #ifndef NDEBUG - , mainThreadOnly(false) + , exclusiveThread(0) #endif { #if PLATFORM(MAC) @@ -194,23 +197,22 @@ JSGlobalData::~JSGlobalData() delete clientData; } -PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault() +PassRefPtr<JSGlobalData> JSGlobalData::createNonDefault(ThreadStackType type) { - return adoptRef(new JSGlobalData(false)); + return adoptRef(new JSGlobalData(false, type)); } -PassRefPtr<JSGlobalData> JSGlobalData::create() +PassRefPtr<JSGlobalData> JSGlobalData::create(ThreadStackType type) { - JSGlobalData* globalData = new JSGlobalData(false); - setDefaultIdentifierTable(globalData->identifierTable); - setCurrentIdentifierTable(globalData->identifierTable); + JSGlobalData* globalData = new JSGlobalData(false, type); + wtfThreadData().initializeIdentifierTable(globalData->identifierTable); return adoptRef(globalData); } -PassRefPtr<JSGlobalData> JSGlobalData::createLeaked() +PassRefPtr<JSGlobalData> JSGlobalData::createLeaked(ThreadStackType type) { Structure::startIgnoringLeaks(); - RefPtr<JSGlobalData> data = create(); + RefPtr<JSGlobalData> data = create(type); Structure::stopIgnoringLeaks(); return data.release(); } @@ -224,7 +226,7 @@ JSGlobalData& JSGlobalData::sharedInstance() { JSGlobalData*& instance = sharedInstanceInternal(); if (!instance) { - instance = new JSGlobalData(true); + instance = new JSGlobalData(true, ThreadStackTypeSmall); #if ENABLE(JSC_MULTIPLE_THREADS) instance->makeUsableFromMultipleThreads(); #endif diff --git a/JavaScriptCore/runtime/JSGlobalData.h b/JavaScriptCore/runtime/JSGlobalData.h index 0f1f3c6..a90bf2c 100644 --- a/JavaScriptCore/runtime/JSGlobalData.h +++ b/JavaScriptCore/runtime/JSGlobalData.h @@ -37,6 +37,7 @@ #include "MarkStack.h" #include "NumericStrings.h" #include "SmallStrings.h" +#include "Terminator.h" #include "TimeoutChecker.h" #include "WeakRandom.h" #include <wtf/Forward.h> @@ -83,6 +84,11 @@ namespace JSC { double increment; }; + enum ThreadStackType { + ThreadStackTypeLarge, + ThreadStackTypeSmall + }; + class JSGlobalData : public RefCounted<JSGlobalData> { public: struct ClientData { @@ -92,9 +98,9 @@ namespace JSC { static bool sharedInstanceExists(); static JSGlobalData& sharedInstance(); - static PassRefPtr<JSGlobalData> create(); - static PassRefPtr<JSGlobalData> createLeaked(); - static PassRefPtr<JSGlobalData> createNonDefault(); + static PassRefPtr<JSGlobalData> create(ThreadStackType); + static PassRefPtr<JSGlobalData> createLeaked(ThreadStackType); + static PassRefPtr<JSGlobalData> createNonDefault(ThreadStackType); ~JSGlobalData(); #if ENABLE(JSC_MULTIPLE_THREADS) @@ -116,6 +122,7 @@ namespace JSC { RefPtr<Structure> activationStructure; RefPtr<Structure> interruptedExecutionErrorStructure; + RefPtr<Structure> terminatedExecutionErrorStructure; RefPtr<Structure> staticScopeStructure; RefPtr<Structure> stringStructure; RefPtr<Structure> notAnObjectErrorStubStructure; @@ -153,6 +160,7 @@ namespace JSC { JITThunks jitStubs; #endif TimeoutChecker timeoutChecker; + Terminator terminator; Heap heap; JSValue exception; @@ -184,8 +192,9 @@ namespace JSC { WeakRandom weakRandom; + int maxReentryDepth; #ifndef NDEBUG - bool mainThreadOnly; + ThreadIdentifier exclusiveThread; #endif void resetDateCache(); @@ -194,7 +203,7 @@ namespace JSC { void stopSampling(); void dumpSampleData(ExecState* exec); private: - JSGlobalData(bool isShared); + JSGlobalData(bool isShared, ThreadStackType); static JSGlobalData*& sharedInstanceInternal(); void createNativeThunk(); }; diff --git a/JavaScriptCore/runtime/JSGlobalObject.cpp b/JavaScriptCore/runtime/JSGlobalObject.cpp index 4bf0a69..86690bd 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -319,9 +319,9 @@ void JSGlobalObject::reset(JSValue prototype) // Set global values. GlobalPropertyInfo staticGlobals[] = { GlobalPropertyInfo(Identifier(exec, "Math"), new (exec) MathObject(exec, MathObject::createStructure(d()->objectPrototype)), DontEnum | DontDelete), - GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(exec), DontEnum | DontDelete), - GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(exec, Inf), DontEnum | DontDelete), - GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete), + GlobalPropertyInfo(Identifier(exec, "NaN"), jsNaN(exec), DontEnum | DontDelete | ReadOnly), + GlobalPropertyInfo(Identifier(exec, "Infinity"), jsNumber(exec, Inf), DontEnum | DontDelete | ReadOnly), + GlobalPropertyInfo(Identifier(exec, "undefined"), jsUndefined(), DontEnum | DontDelete | ReadOnly), GlobalPropertyInfo(Identifier(exec, "JSON"), new (exec) JSONObject(JSONObject::createStructure(d()->objectPrototype)), DontEnum | DontDelete) }; diff --git a/JavaScriptCore/runtime/JSGlobalObject.h b/JavaScriptCore/runtime/JSGlobalObject.h index bbb6d5e..df942cf 100644 --- a/JavaScriptCore/runtime/JSGlobalObject.h +++ b/JavaScriptCore/runtime/JSGlobalObject.h @@ -25,6 +25,7 @@ #include "JSArray.h" #include "JSGlobalData.h" #include "JSVariableObject.h" +#include "JSWeakObjectMapRefInternal.h" #include "NativeFunctionWrapper.h" #include "NumberPrototype.h" #include "StringPrototype.h" @@ -56,6 +57,7 @@ namespace JSC { class JSGlobalObject : public JSVariableObject { protected: using JSVariableObject::JSVariableObjectData; + typedef HashSet<RefPtr<OpaqueJSWeakObjectMap> > WeakMapSet; struct JSGlobalObjectData : public JSVariableObjectData { // We use an explicit destructor function pointer instead of a @@ -153,6 +155,7 @@ namespace JSC { RefPtr<JSGlobalData> globalData; HashSet<GlobalCodeBlock*> codeBlocks; + WeakMapSet weakMaps; }; public: @@ -270,6 +273,16 @@ namespace JSC { return Structure::create(prototype, TypeInfo(ObjectType, StructureFlags), AnonymousSlotCount); } + void registerWeakMap(OpaqueJSWeakObjectMap* map) + { + d()->weakMaps.add(map); + } + + void deregisterWeakMap(OpaqueJSWeakObjectMap* map) + { + d()->weakMaps.remove(map); + } + protected: static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesMarkChildren | OverridesGetPropertyNames | JSVariableObject::StructureFlags; diff --git a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 0e1fbee..5b6369a 100644 --- a/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -35,6 +35,7 @@ #include "LiteralParser.h" #include "Nodes.h" #include "Parser.h" +#include "StringBuilder.h" #include "StringExtras.h" #include "dtoa.h" #include <stdio.h> @@ -54,12 +55,12 @@ static JSValue encode(ExecState* exec, const ArgList& args, const char* doNotEsc { UString str = args.at(0).toString(exec); CString cstr = str.UTF8String(true); - if (!cstr.c_str()) + if (!cstr.data()) return throwError(exec, URIError, "String contained an illegal UTF-16 sequence."); JSStringBuilder builder; - const char* p = cstr.c_str(); - for (size_t k = 0; k < cstr.size(); k++, p++) { + const char* p = cstr.data(); + for (size_t k = 0; k < cstr.length(); k++, p++) { char c = *p; if (c && strchr(doNotEscape, c)) builder.append(c); @@ -429,8 +430,7 @@ JSValue JSC_HOST_CALL globalFuncUnescape(ExecState* exec, JSObject*, JSValue, co #ifndef NDEBUG JSValue JSC_HOST_CALL globalFuncJSCPrint(ExecState* exec, JSObject*, JSValue, const ArgList& args) { - CStringBuffer string; - args.at(0).toString(exec).getCString(string); + CString string = args.at(0).toString(exec).UTF8String(); puts(string.data()); return jsUndefined(); } diff --git a/JavaScriptCore/runtime/JSImmediate.h b/JavaScriptCore/runtime/JSImmediate.h index 4ed35fc..0f54f60 100644 --- a/JavaScriptCore/runtime/JSImmediate.h +++ b/JavaScriptCore/runtime/JSImmediate.h @@ -22,8 +22,6 @@ #ifndef JSImmediate_h #define JSImmediate_h -#include <wtf/Platform.h> - #if !USE(JSVALUE32_64) #include <wtf/Assertions.h> diff --git a/JavaScriptCore/runtime/JSNumberCell.cpp b/JavaScriptCore/runtime/JSNumberCell.cpp index f1009b9..a61c751 100644 --- a/JavaScriptCore/runtime/JSNumberCell.cpp +++ b/JavaScriptCore/runtime/JSNumberCell.cpp @@ -57,11 +57,6 @@ UString JSNumberCell::toString(ExecState*) const return UString::from(m_value); } -UString JSNumberCell::toThisString(ExecState*) const -{ - return UString::from(m_value); -} - JSObject* JSNumberCell::toObject(ExecState* exec) const { return constructNumber(exec, const_cast<JSNumberCell*>(this)); diff --git a/JavaScriptCore/runtime/JSNumberCell.h b/JavaScriptCore/runtime/JSNumberCell.h index bcb506b..cdd2d8c 100644 --- a/JavaScriptCore/runtime/JSNumberCell.h +++ b/JavaScriptCore/runtime/JSNumberCell.h @@ -62,7 +62,6 @@ namespace JSC { virtual UString toString(ExecState*) const; virtual JSObject* toObject(ExecState*) const; - virtual UString toThisString(ExecState*) const; virtual JSObject* toThisObject(ExecState*) const; virtual JSValue getJSNumber(); diff --git a/JavaScriptCore/runtime/JSONObject.cpp b/JavaScriptCore/runtime/JSONObject.cpp index d69a8da..f6c6b5f 100644 --- a/JavaScriptCore/runtime/JSONObject.cpp +++ b/JavaScriptCore/runtime/JSONObject.cpp @@ -31,6 +31,7 @@ #include "ExceptionHelpers.h" #include "JSArray.h" #include "LiteralParser.h" +#include "Lookup.h" #include "PropertyNameArray.h" #include "StringBuilder.h" #include <wtf/MathExtras.h> @@ -868,4 +869,12 @@ JSValue JSC_HOST_CALL JSONProtoFuncStringify(ExecState* exec, JSObject*, JSValue return Stringifier(exec, replacer, space).stringify(value); } +UString JSONStringify(ExecState* exec, JSValue value, unsigned indent) +{ + JSValue result = Stringifier(exec, jsNull(), jsNumber(exec, indent)).stringify(value); + if (result.isUndefinedOrNull()) + return UString(); + return result.getString(exec); +} + } // namespace JSC diff --git a/JavaScriptCore/runtime/JSONObject.h b/JavaScriptCore/runtime/JSONObject.h index 905e4bc..7a9e0a4 100644 --- a/JavaScriptCore/runtime/JSONObject.h +++ b/JavaScriptCore/runtime/JSONObject.h @@ -57,6 +57,8 @@ namespace JSC { static const ClassInfo info; }; + UString JSONStringify(ExecState* exec, JSValue value, unsigned indent); + } // namespace JSC #endif // JSONObject_h diff --git a/JavaScriptCore/runtime/JSObject.h b/JavaScriptCore/runtime/JSObject.h index 2b31a65..64a1118 100644 --- a/JavaScriptCore/runtime/JSObject.h +++ b/JavaScriptCore/runtime/JSObject.h @@ -26,6 +26,7 @@ #include "ArgList.h" #include "ClassInfo.h" #include "CommonIdentifiers.h" +#include "Completion.h" #include "CallFrame.h" #include "JSCell.h" #include "JSNumberCell.h" @@ -35,6 +36,7 @@ #include "ScopeChain.h" #include "Structure.h" #include "JSGlobalData.h" +#include "JSString.h" #include <wtf/StdLibExtras.h> namespace JSC { @@ -194,9 +196,10 @@ namespace JSC { virtual bool isGlobalObject() const { return false; } virtual bool isVariableObject() const { return false; } virtual bool isActivationObject() const { return false; } - virtual bool isWatchdogException() const { return false; } virtual bool isNotAnObjectErrorStub() const { return false; } + virtual ComplType exceptionType() const { return Throw; } + void allocatePropertyStorage(size_t oldSize, size_t newSize); void allocatePropertyStorageInline(size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return m_structure->isUsingInlineStorage(); } @@ -436,12 +439,20 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue JSCell* currentSpecificFunction; size_t offset = m_structure->get(propertyName, currentAttributes, currentSpecificFunction); if (offset != WTF::notFound) { + // If there is currently a specific function, and there now either isn't, + // or the new value is different, then despecify. if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) m_structure->despecifyDictionaryFunction(propertyName); if (checkReadOnly && currentAttributes & ReadOnly) return; putDirectOffset(offset, value); - if (!specificFunction && !currentSpecificFunction) + // At this point, the objects structure only has a specific value set if previously there + // had been one set, and if the new value being specified is the same (otherwise we would + // have despecified, above). So, if currentSpecificFunction is not set, or if the new + // value is different (or there is no new value), then the slot now has no value - and + // as such it is cachable. + // If there was previously a value, and the new value is the same, then we cannot cache. + if (!currentSpecificFunction || (specificFunction != currentSpecificFunction)) slot.setExistingProperty(this, offset); return; } @@ -468,7 +479,8 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue ASSERT(offset < structure->propertyStorageCapacity()); setStructure(structure.release()); putDirectOffset(offset, value); - // See comment on setNewProperty call below. + // This is a new property; transitions with specific values are not currently cachable, + // so leave the slot in an uncachable state. if (!specificFunction) slot.setNewProperty(this, offset); return; @@ -481,14 +493,28 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue if (checkReadOnly && currentAttributes & ReadOnly) return; - if (currentSpecificFunction && (specificFunction != currentSpecificFunction)) { + // There are three possibilities here: + // (1) There is an existing specific value set, and we're overwriting with *the same value*. + // * Do nothing - no need to despecify, but that means we can't cache (a cached + // put could write a different value). Leave the slot in an uncachable state. + // (2) There is a specific value currently set, but we're writing a different value. + // * First, we have to despecify. Having done so, this is now a regular slot + // with no specific value, so go ahead & cache like normal. + // (3) Normal case, there is no specific value set. + // * Go ahead & cache like normal. + if (currentSpecificFunction) { + // case (1) Do the put, then return leaving the slot uncachable. + if (specificFunction == currentSpecificFunction) { + putDirectOffset(offset, value); + return; + } + // case (2) Despecify, fall through to (3). setStructure(Structure::despecifyFunctionTransition(m_structure, propertyName)); - putDirectOffset(offset, value); - // Function transitions are not currently cachable, so leave the slot in an uncachable state. - return; } - putDirectOffset(offset, value); + + // case (3) set the slot, do the put, return. slot.setExistingProperty(this, offset); + putDirectOffset(offset, value); return; } @@ -510,7 +536,8 @@ inline void JSObject::putDirectInternal(const Identifier& propertyName, JSValue ASSERT(offset < structure->propertyStorageCapacity()); setStructure(structure.release()); putDirectOffset(offset, value); - // Function transitions are not currently cachable, so leave the slot in an uncachable state. + // This is a new property; transitions with specific values are not currently cachable, + // so leave the slot in an uncachable state. if (!specificFunction) slot.setNewProperty(this, offset); } @@ -685,6 +712,18 @@ ALWAYS_INLINE void JSObject::markChildrenDirect(MarkStack& markStack) markStack.appendValues(reinterpret_cast<JSValue*>(storage), storageSize); } +// --- JSValue inlines ---------------------------- + +ALWAYS_INLINE UString JSValue::toThisString(ExecState* exec) const +{ + return isString() ? static_cast<JSString*>(asCell())->value(exec) : toThisObject(exec)->toString(exec); +} + +inline JSString* JSValue::toThisJSString(ExecState* exec) const +{ + return isString() ? static_cast<JSString*>(asCell()) : jsString(exec, toThisObject(exec)->toString(exec)); +} + } // namespace JSC #endif // JSObject_h diff --git a/JavaScriptCore/runtime/JSPropertyNameIterator.h b/JavaScriptCore/runtime/JSPropertyNameIterator.h index 3f533a0..01700ac 100644 --- a/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -67,8 +67,13 @@ namespace JSC { 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 setCachedStructure(Structure* structure) + { + ASSERT(!m_cachedStructure); + ASSERT(structure); + m_cachedStructure = structure; + } + Structure* cachedStructure() { return m_cachedStructure.get(); } void setCachedPrototypeChain(NonNullPassRefPtr<StructureChain> cachedPrototypeChain) { m_cachedPrototypeChain = cachedPrototypeChain; } StructureChain* cachedPrototypeChain() { return m_cachedPrototypeChain.get(); } @@ -76,7 +81,7 @@ namespace JSC { private: JSPropertyNameIterator(ExecState*, PropertyNameArrayData* propertyNameArrayData, size_t numCacheableSlot); - Structure* m_cachedStructure; + RefPtr<Structure> m_cachedStructure; RefPtr<StructureChain> m_cachedPrototypeChain; uint32_t m_numCacheableSlots; uint32_t m_jsStringsSize; diff --git a/JavaScriptCore/runtime/JSString.cpp b/JavaScriptCore/runtime/JSString.cpp index a72457e..fbc7d72 100644 --- a/JavaScriptCore/runtime/JSString.cpp +++ b/JavaScriptCore/runtime/JSString.cpp @@ -51,7 +51,7 @@ void JSString::resolveRope(ExecState* exec) const m_value = newImpl; else { for (unsigned i = 0; i < m_fiberCount; ++i) { - m_other.m_fibers[i]->deref(); + RopeImpl::deref(m_other.m_fibers[i]); m_other.m_fibers[i] = 0; } m_fiberCount = 0; @@ -62,15 +62,15 @@ void JSString::resolveRope(ExecState* exec) const } UChar* position = buffer + m_length; - // Start with the current Rope. - Vector<Rope::Fiber, 32> workQueue; - Rope::Fiber currentFiber; + // Start with the current RopeImpl. + Vector<RopeImpl::Fiber, 32> workQueue; + RopeImpl::Fiber currentFiber; for (unsigned i = 0; i < (m_fiberCount - 1); ++i) workQueue.append(m_other.m_fibers[i]); currentFiber = m_other.m_fibers[m_fiberCount - 1]; while (true) { - if (currentFiber->isRope()) { - Rope* rope = static_cast<URopeImpl*>(currentFiber); + if (RopeImpl::isRope(currentFiber)) { + RopeImpl* rope = static_cast<RopeImpl*>(currentFiber); // 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 fiberCountMinusOne = rope->fiberCount() - 1; @@ -81,14 +81,14 @@ void JSString::resolveRope(ExecState* exec) const UStringImpl* string = static_cast<UStringImpl*>(currentFiber); unsigned length = string->length(); position -= length; - UStringImpl::copyChars(position, string->data(), length); + UStringImpl::copyChars(position, string->characters(), 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_fiberCount; ++i) { - m_other.m_fibers[i]->deref(); + RopeImpl::deref(m_other.m_fibers[i]); m_other.m_fibers[i] = 0; } m_fiberCount = 0; @@ -104,6 +104,18 @@ void JSString::resolveRope(ExecState* exec) const } } +JSString* JSString::getIndexSlowCase(ExecState* exec, unsigned i) +{ + ASSERT(isRope()); + resolveRope(exec); + // Return a safe no-value result, this should never be used, since the excetion will be thrown. + if (exec->exception()) + return jsString(exec, ""); + ASSERT(!isRope()); + ASSERT(i < m_value.size()); + return jsSingleCharacterSubstring(exec, m_value, i); +} + JSValue JSString::toPrimitive(ExecState*, PreferredPrimitiveType) const { return const_cast<JSString*>(this); @@ -131,16 +143,6 @@ UString JSString::toString(ExecState* exec) const return value(exec); } -UString JSString::toThisString(ExecState* exec) const -{ - return value(exec); -} - -JSString* JSString::toThisJSString(ExecState*) -{ - return this; -} - inline StringObject* StringObject::create(ExecState* exec, JSString* string) { return new (exec) StringObject(exec->lexicalGlobalObject()->stringObjectStructure(), string); @@ -187,7 +189,7 @@ bool JSString::getStringPropertyDescriptor(ExecState* exec, const Identifier& pr bool isStrictUInt32; unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); if (isStrictUInt32 && i < m_length) { - descriptor.setDescriptor(jsSingleCharacterSubstring(exec, value(exec), i), DontDelete | ReadOnly); + descriptor.setDescriptor(getIndex(exec, i), DontDelete | ReadOnly); return true; } diff --git a/JavaScriptCore/runtime/JSString.h b/JavaScriptCore/runtime/JSString.h index 0162282..b1dccfa 100644 --- a/JavaScriptCore/runtime/JSString.h +++ b/JavaScriptCore/runtime/JSString.h @@ -29,6 +29,7 @@ #include "JSNumberCell.h" #include "PropertyDescriptor.h" #include "PropertySlot.h" +#include "RopeImpl.h" namespace JSC { @@ -41,7 +42,6 @@ namespace JSC { JSString* jsSingleCharacterString(JSGlobalData*, UChar); JSString* jsSingleCharacterString(ExecState*, UChar); - JSString* jsSingleCharacterSubstring(JSGlobalData*, const UString&, unsigned offset); JSString* jsSingleCharacterSubstring(ExecState*, const UString&, unsigned offset); JSString* jsSubstring(JSGlobalData*, const UString&, unsigned offset, unsigned length); JSString* jsSubstring(ExecState*, const UString&, unsigned offset, unsigned length); @@ -67,19 +67,17 @@ namespace JSC { friend class JIT; friend class JSGlobalData; - typedef URopeImpl Rope; - class RopeBuilder { public: RopeBuilder(unsigned fiberCount) : m_index(0) - , m_rope(Rope::tryCreateUninitialized(fiberCount)) + , m_rope(RopeImpl::tryCreateUninitialized(fiberCount)) { } bool isOutOfMemory() { return !m_rope; } - void append(Rope::Fiber& fiber) + void append(RopeImpl::Fiber& fiber) { ASSERT(m_rope); m_rope->initializeFiber(m_index, fiber); @@ -98,7 +96,7 @@ namespace JSC { append(jsString->string()); } - PassRefPtr<Rope> release() + PassRefPtr<RopeImpl> release() { ASSERT(m_index == m_rope->fiberCount()); return m_rope.release(); @@ -108,7 +106,7 @@ namespace JSC { private: unsigned m_index; - RefPtr<Rope> m_rope; + RefPtr<RopeImpl> m_rope; }; ALWAYS_INLINE JSString(JSGlobalData* globalData, const UString& value) @@ -117,6 +115,7 @@ namespace JSC { , m_value(value) , m_fiberCount(0) { + ASSERT(!m_value.isNull()); Heap::heap(this)->reportExtraMemoryCost(value.cost()); } @@ -127,6 +126,7 @@ namespace JSC { , m_value(value) , m_fiberCount(0) { + ASSERT(!m_value.isNull()); } JSString(JSGlobalData* globalData, PassRefPtr<UString::Rep> value, HasOtherOwnerType) : JSCell(globalData->stringStructure.get()) @@ -134,8 +134,9 @@ namespace JSC { , m_value(value) , m_fiberCount(0) { + ASSERT(!m_value.isNull()); } - JSString(JSGlobalData* globalData, PassRefPtr<Rope> rope) + JSString(JSGlobalData* globalData, PassRefPtr<RopeImpl> rope) : JSCell(globalData->stringStructure.get()) , m_length(rope->length()) , m_fiberCount(1) @@ -203,6 +204,7 @@ namespace JSC { , m_value(value) , m_fiberCount(0) { + ASSERT(!m_value.isNull()); // nasty hack because we can't union non-POD types m_other.m_finalizerCallback = finalizer; m_other.m_finalizerContext = context; @@ -213,7 +215,7 @@ namespace JSC { { ASSERT(vptr() == JSGlobalData::jsStringVPtr); for (unsigned i = 0; i < m_fiberCount; ++i) - m_other.m_fibers[i]->deref(); + RopeImpl::deref(m_other.m_fibers[i]); if (!m_fiberCount && m_other.m_finalizerCallback) m_other.m_finalizerCallback(this, m_other.m_finalizerContext); @@ -240,6 +242,7 @@ namespace JSC { bool canGetIndex(unsigned i) { return i < m_length; } JSString* getIndex(ExecState*, unsigned); + JSString* getIndexSlowCase(ExecState*, unsigned); static PassRefPtr<Structure> createStructure(JSValue proto) { return Structure::create(proto, TypeInfo(StringType, OverridesGetOwnPropertySlot | NeedsThisConversion), AnonymousSlotCount); } @@ -264,7 +267,7 @@ namespace JSC { { if (jsString->isRope()) { for (unsigned i = 0; i < jsString->m_fiberCount; ++i) { - Rope::Fiber fiber = jsString->m_other.m_fibers[i]; + RopeImpl::Fiber fiber = jsString->m_other.m_fibers[i]; fiber->ref(); m_other.m_fibers[index++] = fiber; } @@ -297,8 +300,6 @@ namespace JSC { virtual UString toString(ExecState*) const; virtual JSObject* toThisObject(ExecState*) const; - virtual UString toThisString(ExecState*) const; - virtual JSString* toThisJSString(ExecState*); // Actually getPropertySlot, not getOwnPropertySlot (see JSCell). virtual bool getOwnPropertySlot(ExecState*, const Identifier& propertyName, PropertySlot&); @@ -307,7 +308,7 @@ namespace JSC { static const unsigned s_maxInternalRopeLength = 3; - // A string is represented either by a UString or a Rope. + // A string is represented either by a UString or a RopeImpl. unsigned m_length; mutable UString m_value; mutable unsigned m_fiberCount; @@ -315,7 +316,7 @@ namespace JSC { struct JSStringFinalizerStruct { JSStringFinalizerStruct() : m_finalizerCallback(0) {} union { - mutable Rope::Fiber m_fibers[s_maxInternalRopeLength]; + mutable RopeImpl::Fiber m_fibers[s_maxInternalRopeLength]; struct { JSStringFinalizerCallback m_finalizerCallback; void* m_finalizerContext; @@ -365,8 +366,9 @@ namespace JSC { return fixupVPtr(globalData, new (globalData) JSString(globalData, UString(&c, 1))); } - inline JSString* jsSingleCharacterSubstring(JSGlobalData* globalData, const UString& s, unsigned offset) + inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) { + JSGlobalData* globalData = &exec->globalData(); ASSERT(offset < static_cast<unsigned>(s.size())); UChar c = s.data()[offset]; if (c <= 0xFF) @@ -391,7 +393,10 @@ namespace JSC { inline JSString* JSString::getIndex(ExecState* exec, unsigned i) { ASSERT(canGetIndex(i)); - return jsSingleCharacterSubstring(&exec->globalData(), value(exec), i); + if (isRope()) + return getIndexSlowCase(exec, i); + ASSERT(i < m_value.size()); + return jsSingleCharacterSubstring(exec, value(exec), i); } inline JSString* jsString(JSGlobalData* globalData, const UString& s) @@ -445,7 +450,6 @@ namespace JSC { inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); } inline JSString* jsString(ExecState* exec, const UString& s) { return jsString(&exec->globalData(), s); } inline JSString* jsSingleCharacterString(ExecState* exec, UChar c) { return jsSingleCharacterString(&exec->globalData(), c); } - inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) { return jsSingleCharacterSubstring(&exec->globalData(), s, offset); } inline JSString* jsSubstring(ExecState* exec, const UString& s, unsigned offset, unsigned length) { return jsSubstring(&exec->globalData(), s, offset, length); } inline JSString* jsNontrivialString(ExecState* exec, const UString& s) { return jsNontrivialString(&exec->globalData(), s); } inline JSString* jsNontrivialString(ExecState* exec, const char* s) { return jsNontrivialString(&exec->globalData(), s); } @@ -461,7 +465,7 @@ namespace JSC { bool isStrictUInt32; unsigned i = propertyName.toStrictUInt32(&isStrictUInt32); if (isStrictUInt32 && i < m_length) { - slot.setValue(jsSingleCharacterSubstring(exec, value(exec), i)); + slot.setValue(getIndex(exec, i)); return true; } @@ -471,7 +475,7 @@ namespace JSC { ALWAYS_INLINE bool JSString::getStringPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { if (propertyName < m_length) { - slot.setValue(jsSingleCharacterSubstring(exec, value(exec), propertyName)); + slot.setValue(getIndex(exec, propertyName)); return true; } @@ -482,11 +486,6 @@ namespace JSC { // --- JSValue inlines ---------------------------- - inline JSString* JSValue::toThisJSString(ExecState* exec) - { - return isCell() ? asCell()->toThisJSString(exec) : jsString(exec, toString(exec)); - } - inline UString JSValue::toString(ExecState* exec) const { if (isString()) diff --git a/JavaScriptCore/runtime/JSStringBuilder.h b/JavaScriptCore/runtime/JSStringBuilder.h index 2b11736..8f208a1 100644 --- a/JavaScriptCore/runtime/JSStringBuilder.h +++ b/JavaScriptCore/runtime/JSStringBuilder.h @@ -28,31 +28,59 @@ #include "ExceptionHelpers.h" #include "JSString.h" -#include "StringBuilder.h" +#include "Vector.h" namespace JSC { -class JSStringBuilder : public StringBuilder { +class JSStringBuilder { public: + JSStringBuilder() + : m_okay(true) + { + } + + void append(const UChar u) + { + m_okay &= buffer.tryAppend(&u, 1); + } + + void append(const char* str) + { + append(str, strlen(str)); + } + + void append(const char* str, size_t len) + { + m_okay &= buffer.tryReserveCapacity(buffer.size() + len); + for (size_t i = 0; i < len; i++) { + UChar u = static_cast<unsigned char>(str[i]); + m_okay &= buffer.tryAppend(&u, 1); + } + } + + void append(const UChar* str, size_t len) + { + m_okay &= buffer.tryAppend(str, len); + } + + void append(const UString& str) + { + m_okay &= buffer.tryAppend(str.data(), str.size()); + } + JSValue build(ExecState* exec) { + if (!m_okay) + return throwOutOfMemoryError(exec); buffer.shrinkToFit(); if (!buffer.data()) return throwOutOfMemoryError(exec); return jsString(exec, UString::adopt(buffer)); } -private: - // Make attempts to call this compile error - if you only wanted a UString, - // Why didn't you just use a StringBuilder?! (This may change, maybe at some - // point in the future we'll need to start building a string not knowing whether - // we'll want a UString or a JSValue - but until we have this requirement, - // block this). - UString build() - { - ASSERT_NOT_REACHED(); - return StringBuilder::build(); - } +protected: + Vector<UChar, 64> buffer; + bool m_okay; }; template<typename StringType1, typename StringType2> diff --git a/JavaScriptCore/runtime/JSTypeInfo.h b/JavaScriptCore/runtime/JSTypeInfo.h index 7c89600..e225bc7 100644 --- a/JavaScriptCore/runtime/JSTypeInfo.h +++ b/JavaScriptCore/runtime/JSTypeInfo.h @@ -50,6 +50,8 @@ namespace JSC { TypeInfo(JSType type, unsigned flags = 0) : m_type(type) { + ASSERT(flags <= 0xFF); + ASSERT(type <= 0xFF); // ImplementsDefaultHasInstance means (ImplementsHasInstance & !OverridesHasInstance) if ((flags & (ImplementsHasInstance | OverridesHasInstance)) == ImplementsHasInstance) m_flags = flags | ImplementsDefaultHasInstance; @@ -57,7 +59,7 @@ namespace JSC { m_flags = flags; } - JSType type() const { return m_type; } + JSType type() const { return (JSType)m_type; } bool masqueradesAsUndefined() const { return m_flags & MasqueradesAsUndefined; } bool implementsHasInstance() const { return m_flags & ImplementsHasInstance; } @@ -69,8 +71,8 @@ namespace JSC { unsigned flags() const { return m_flags; } private: - JSType m_type; - unsigned m_flags; + unsigned char m_type; + unsigned char m_flags; }; } diff --git a/JavaScriptCore/runtime/JSValue.h b/JavaScriptCore/runtime/JSValue.h index 6da921f..b37adc0 100644 --- a/JavaScriptCore/runtime/JSValue.h +++ b/JavaScriptCore/runtime/JSValue.h @@ -188,7 +188,7 @@ namespace JSC { bool needsThisConversion() const; JSObject* toThisObject(ExecState*) const; UString toThisString(ExecState*) const; - JSString* toThisJSString(ExecState*); + JSString* toThisJSString(ExecState*) const; static bool equal(ExecState* exec, JSValue v1, JSValue v2); static bool equalSlowCase(ExecState* exec, JSValue v1, JSValue v2); diff --git a/JavaScriptCore/runtime/JSZombie.h b/JavaScriptCore/runtime/JSZombie.h index 8b33ea6..711f673 100644 --- a/JavaScriptCore/runtime/JSZombie.h +++ b/JavaScriptCore/runtime/JSZombie.h @@ -60,8 +60,6 @@ public: 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; } diff --git a/JavaScriptCore/runtime/Lookup.h b/JavaScriptCore/runtime/Lookup.h index e673c09..995aeee 100644 --- a/JavaScriptCore/runtime/Lookup.h +++ b/JavaScriptCore/runtime/Lookup.h @@ -181,7 +181,7 @@ namespace JSC { if (entry->attributes() & Function) setUpStaticFunctionSlot(exec, entry, thisObj, propertyName, slot); else - slot.setCustom(thisObj, entry->propertyGetter()); + slot.setCacheableCustom(thisObj, entry->propertyGetter()); return true; } @@ -258,7 +258,7 @@ namespace JSC { ASSERT(!(entry->attributes() & Function)); - slot.setCustom(thisObj, entry->propertyGetter()); + slot.setCacheableCustom(thisObj, entry->propertyGetter()); return true; } diff --git a/JavaScriptCore/runtime/MathObject.cpp b/JavaScriptCore/runtime/MathObject.cpp index 8f22fba..16d32a0 100644 --- a/JavaScriptCore/runtime/MathObject.cpp +++ b/JavaScriptCore/runtime/MathObject.cpp @@ -21,6 +21,7 @@ #include "config.h" #include "MathObject.h" +#include "Lookup.h" #include "ObjectPrototype.h" #include "Operations.h" #include <time.h> @@ -216,8 +217,6 @@ JSValue JSC_HOST_CALL mathProtoFuncRandom(ExecState* exec, JSObject*, JSValue, c JSValue JSC_HOST_CALL mathProtoFuncRound(ExecState* exec, JSObject*, JSValue, const ArgList& args) { double arg = args.at(0).toNumber(exec); - if (signbit(arg) && arg >= -0.5) - return jsNumber(exec, -0.0); double integer = ceil(arg); return jsNumber(exec, integer - (integer - arg > 0.5)); } diff --git a/JavaScriptCore/runtime/NumberConstructor.cpp b/JavaScriptCore/runtime/NumberConstructor.cpp index cc6c51d..0b7e821 100644 --- a/JavaScriptCore/runtime/NumberConstructor.cpp +++ b/JavaScriptCore/runtime/NumberConstructor.cpp @@ -22,6 +22,7 @@ #include "config.h" #include "NumberConstructor.h" +#include "Lookup.h" #include "NumberObject.h" #include "NumberPrototype.h" @@ -29,11 +30,11 @@ namespace JSC { ASSERT_CLASS_FITS_IN_CELL(NumberConstructor); -static JSValue numberConstructorNaNValue(ExecState*, const Identifier&, const PropertySlot&); -static JSValue numberConstructorNegInfinity(ExecState*, const Identifier&, const PropertySlot&); -static JSValue numberConstructorPosInfinity(ExecState*, const Identifier&, const PropertySlot&); -static JSValue numberConstructorMaxValue(ExecState*, const Identifier&, const PropertySlot&); -static JSValue numberConstructorMinValue(ExecState*, const Identifier&, const PropertySlot&); +static JSValue numberConstructorNaNValue(ExecState*, JSValue, const Identifier&); +static JSValue numberConstructorNegInfinity(ExecState*, JSValue, const Identifier&); +static JSValue numberConstructorPosInfinity(ExecState*, JSValue, const Identifier&); +static JSValue numberConstructorMaxValue(ExecState*, JSValue, const Identifier&); +static JSValue numberConstructorMinValue(ExecState*, JSValue, const Identifier&); } // namespace JSC @@ -73,27 +74,27 @@ bool NumberConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifi return getStaticValueDescriptor<NumberConstructor, InternalFunction>(exec, ExecState::numberTable(exec), this, propertyName, descriptor); } -static JSValue numberConstructorNaNValue(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorNaNValue(ExecState* exec, JSValue, const Identifier&) { return jsNaN(exec); } -static JSValue numberConstructorNegInfinity(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorNegInfinity(ExecState* exec, JSValue, const Identifier&) { return jsNumber(exec, -Inf); } -static JSValue numberConstructorPosInfinity(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorPosInfinity(ExecState* exec, JSValue, const Identifier&) { return jsNumber(exec, Inf); } -static JSValue numberConstructorMaxValue(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorMaxValue(ExecState* exec, JSValue, const Identifier&) { return jsNumber(exec, 1.7976931348623157E+308); } -static JSValue numberConstructorMinValue(ExecState* exec, const Identifier&, const PropertySlot&) +static JSValue numberConstructorMinValue(ExecState* exec, JSValue, const Identifier&) { return jsNumber(exec, 5E-324); } diff --git a/JavaScriptCore/runtime/NumericStrings.h b/JavaScriptCore/runtime/NumericStrings.h index c0696a4..89235af 100644 --- a/JavaScriptCore/runtime/NumericStrings.h +++ b/JavaScriptCore/runtime/NumericStrings.h @@ -45,6 +45,8 @@ namespace JSC { UString add(int i) { + if (static_cast<unsigned>(i) < cacheSize) + return lookupSmallString(static_cast<unsigned>(i)); CacheEntry<int>& entry = lookup(i); if (i == entry.key && !entry.value.isNull()) return entry.value; @@ -53,6 +55,17 @@ namespace JSC { return entry.value; } + UString add(unsigned i) + { + if (i < cacheSize) + return lookupSmallString(static_cast<unsigned>(i)); + CacheEntry<unsigned>& entry = lookup(i); + if (i == entry.key && !entry.value.isNull()) + return entry.value; + entry.key = i; + entry.value = UString::from(i); + return entry.value; + } private: static const size_t cacheSize = 64; @@ -64,9 +77,19 @@ namespace JSC { CacheEntry<double>& lookup(double d) { return doubleCache[WTF::FloatHash<double>::hash(d) & (cacheSize - 1)]; } CacheEntry<int>& lookup(int i) { return intCache[WTF::IntHash<int>::hash(i) & (cacheSize - 1)]; } + CacheEntry<unsigned>& lookup(unsigned i) { return unsignedCache[WTF::IntHash<unsigned>::hash(i) & (cacheSize - 1)]; } + const UString& lookupSmallString(unsigned i) + { + ASSERT(i < cacheSize); + if (smallIntCache[i].isNull()) + smallIntCache[i] = UString::from(i); + return smallIntCache[i]; + } CacheEntry<double> doubleCache[cacheSize]; CacheEntry<int> intCache[cacheSize]; + CacheEntry<unsigned> unsignedCache[cacheSize]; + UString smallIntCache[cacheSize]; }; } // namespace JSC diff --git a/JavaScriptCore/runtime/PropertyNameArray.cpp b/JavaScriptCore/runtime/PropertyNameArray.cpp index 4937b7c..6b24669 100644 --- a/JavaScriptCore/runtime/PropertyNameArray.cpp +++ b/JavaScriptCore/runtime/PropertyNameArray.cpp @@ -30,7 +30,7 @@ static const size_t setThreshold = 20; void PropertyNameArray::add(UString::Rep* identifier) { - ASSERT(identifier == &UString::Rep::empty() || identifier->isIdentifier()); + ASSERT(identifier == UString::null().rep() || identifier == UString::Rep::empty() || identifier->isIdentifier()); size_t size = m_data->propertyNameVector().size(); if (size < setThreshold) { diff --git a/JavaScriptCore/runtime/PropertySlot.cpp b/JavaScriptCore/runtime/PropertySlot.cpp index 8b6ceb9..2306a11 100644 --- a/JavaScriptCore/runtime/PropertySlot.cpp +++ b/JavaScriptCore/runtime/PropertySlot.cpp @@ -26,19 +26,19 @@ namespace JSC { -JSValue PropertySlot::functionGetter(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue PropertySlot::functionGetter(ExecState* exec) const { // Prevent getter functions from observing execution if an exception is pending. if (exec->hadException()) return exec->exception(); CallData callData; - CallType callType = slot.m_data.getterFunc->getCallData(callData); + CallType callType = m_data.getterFunc->getCallData(callData); if (callType == CallTypeHost) - return callData.native.function(exec, slot.m_data.getterFunc, slot.thisValue(), exec->emptyList()); + return callData.native.function(exec, m_data.getterFunc, thisValue(), exec->emptyList()); ASSERT(callType == CallTypeJS); // FIXME: Can this be done more efficiently using the callData? - return asFunction(slot.m_data.getterFunc)->call(exec, slot.thisValue(), exec->emptyList()); + return asFunction(m_data.getterFunc)->call(exec, thisValue(), exec->emptyList()); } } // namespace JSC diff --git a/JavaScriptCore/runtime/PropertySlot.h b/JavaScriptCore/runtime/PropertySlot.h index a364e42..de9ddc9 100644 --- a/JavaScriptCore/runtime/PropertySlot.h +++ b/JavaScriptCore/runtime/PropertySlot.h @@ -34,10 +34,20 @@ namespace JSC { #define JSC_VALUE_SLOT_MARKER 0 #define JSC_REGISTER_SLOT_MARKER reinterpret_cast<GetValueFunc>(1) +#define INDEX_GETTER_MARKER reinterpret_cast<GetValueFunc>(2) +#define GETTER_FUNCTION_MARKER reinterpret_cast<GetValueFunc>(3) class PropertySlot { public: + enum CachedPropertyType { + Uncacheable, + Getter, + Custom, + Value + }; + PropertySlot() + : m_cachedPropertyType(Uncacheable) { clearBase(); clearOffset(); @@ -46,12 +56,14 @@ namespace JSC { explicit PropertySlot(const JSValue base) : m_slotBase(base) + , m_cachedPropertyType(Uncacheable) { clearOffset(); clearValue(); } - typedef JSValue (*GetValueFunc)(ExecState*, const Identifier&, const PropertySlot&); + typedef JSValue (*GetValueFunc)(ExecState*, JSValue slotBase, const Identifier&); + typedef JSValue (*GetIndexValueFunc)(ExecState*, JSValue slotBase, unsigned); JSValue getValue(ExecState* exec, const Identifier& propertyName) const { @@ -59,7 +71,11 @@ namespace JSC { return *m_data.valueSlot; if (m_getValue == JSC_REGISTER_SLOT_MARKER) return (*m_data.registerSlot).jsValue(); - return m_getValue(exec, propertyName, *this); + if (m_getValue == INDEX_GETTER_MARKER) + return m_getIndexValue(exec, slotBase(), index()); + if (m_getValue == GETTER_FUNCTION_MARKER) + return functionGetter(exec); + return m_getValue(exec, slotBase(), propertyName); } JSValue getValue(ExecState* exec, unsigned propertyName) const @@ -68,12 +84,16 @@ namespace JSC { return *m_data.valueSlot; if (m_getValue == JSC_REGISTER_SLOT_MARKER) return (*m_data.registerSlot).jsValue(); - return m_getValue(exec, Identifier::from(exec, propertyName), *this); + if (m_getValue == INDEX_GETTER_MARKER) + return m_getIndexValue(exec, m_slotBase, m_data.index); + if (m_getValue == GETTER_FUNCTION_MARKER) + return functionGetter(exec); + return m_getValue(exec, slotBase(), Identifier::from(exec, propertyName)); } - bool isGetter() const { return m_isGetter; } - bool isCacheable() const { return m_isCacheable; } - bool isCacheableValue() const { return m_isCacheable && !m_isGetter; } + CachedPropertyType cachedPropertyType() const { return m_cachedPropertyType; } + bool isCacheable() const { return m_cachedPropertyType != Uncacheable; } + bool isCacheableValue() const { return m_cachedPropertyType == Value; } size_t cachedOffset() const { ASSERT(isCacheable()); @@ -104,8 +124,7 @@ namespace JSC { m_slotBase = slotBase; m_data.valueSlot = valueSlot; m_offset = offset; - m_isCacheable = true; - m_isGetter = false; + m_cachedPropertyType = Value; } void setValue(JSValue value) @@ -132,14 +151,26 @@ namespace JSC { ASSERT(slotBase); ASSERT(getValue); m_getValue = getValue; + m_getIndexValue = 0; m_slotBase = slotBase; } - - void setCustomIndex(JSValue slotBase, unsigned index, GetValueFunc getValue) + + void setCacheableCustom(JSValue slotBase, GetValueFunc getValue) { ASSERT(slotBase); ASSERT(getValue); m_getValue = getValue; + m_getIndexValue = 0; + m_slotBase = slotBase; + m_cachedPropertyType = Custom; + } + + void setCustomIndex(JSValue slotBase, unsigned index, GetIndexValueFunc getIndexValue) + { + ASSERT(slotBase); + ASSERT(getIndexValue); + m_getValue = INDEX_GETTER_MARKER; + m_getIndexValue = getIndexValue; m_slotBase = slotBase; m_data.index = index; } @@ -148,21 +179,19 @@ namespace JSC { { ASSERT(getterFunc); m_thisValue = m_slotBase; - m_getValue = functionGetter; + m_getValue = GETTER_FUNCTION_MARKER; m_data.getterFunc = getterFunc; - m_isGetter = true; } void setCacheableGetterSlot(JSValue slotBase, JSObject* getterFunc, unsigned offset) { ASSERT(getterFunc); - m_getValue = functionGetter; + m_getValue = GETTER_FUNCTION_MARKER; m_thisValue = m_slotBase; m_slotBase = slotBase; m_data.getterFunc = getterFunc; m_offset = offset; - m_isCacheable = true; - m_isGetter = true; + m_cachedPropertyType = Getter; } void setUndefined() @@ -201,17 +230,23 @@ namespace JSC { // Clear offset even in release builds, in case this PropertySlot has been used before. // (For other data members, we don't need to clear anything because reuse would meaningfully overwrite them.) m_offset = 0; - m_isCacheable = false; - m_isGetter = false; + m_cachedPropertyType = Uncacheable; } unsigned index() const { return m_data.index; } JSValue thisValue() const { return m_thisValue; } + + GetValueFunc customGetter() const + { + ASSERT(m_cachedPropertyType == Custom); + return m_getValue; + } private: - static JSValue functionGetter(ExecState*, const Identifier&, const PropertySlot&); + JSValue functionGetter(ExecState*) const; GetValueFunc m_getValue; + GetIndexValueFunc m_getIndexValue; JSValue m_slotBase; union { @@ -225,8 +260,7 @@ namespace JSC { JSValue m_thisValue; size_t m_offset; - bool m_isCacheable : 1; - bool m_isGetter : 1; + CachedPropertyType m_cachedPropertyType; }; } // namespace JSC diff --git a/JavaScriptCore/runtime/RegExp.cpp b/JavaScriptCore/runtime/RegExp.cpp index 85d41ee..f097943 100644 --- a/JavaScriptCore/runtime/RegExp.cpp +++ b/JavaScriptCore/runtime/RegExp.cpp @@ -40,20 +40,12 @@ #else -#if ENABLE(WREC) -#include "JIT.h" -#include "WRECGenerator.h" -#endif #include <pcre/pcre.h> #endif namespace JSC { -#if ENABLE(WREC) -using namespace WREC; -#endif - inline RegExp::RegExp(JSGlobalData* globalData, const UString& pattern) : m_pattern(pattern) , m_flagBits(0) @@ -164,18 +156,9 @@ int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector) #else -void RegExp::compile(JSGlobalData* globalData) +void RegExp::compile(JSGlobalData*) { m_regExp = 0; -#if ENABLE(WREC) - m_wrecFunction = Generator::compileRegExp(globalData, m_pattern, &m_numSubpatterns, &m_constructionError, m_executablePool, ignoreCase(), multiline()); - if (m_wrecFunction || m_constructionError) - return; - // Fall through to non-WREC case. -#else - UNUSED_PARAM(globalData); -#endif - JSRegExpIgnoreCaseOption ignoreCaseOption = ignoreCase() ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase; JSRegExpMultilineOption multilineOption = multiline() ? JSRegExpMultiline : JSRegExpSingleLine; m_regExp = jsRegExpCompile(reinterpret_cast<const UChar*>(m_pattern.data()), m_pattern.size(), ignoreCaseOption, multilineOption, &m_numSubpatterns, &m_constructionError); @@ -191,36 +174,6 @@ int RegExp::match(const UString& s, int startOffset, Vector<int, 32>* ovector) if (static_cast<unsigned>(startOffset) > s.size() || s.isNull()) return -1; -#if ENABLE(WREC) - if (m_wrecFunction) { - int offsetVectorSize = (m_numSubpatterns + 1) * 2; - int* offsetVector; - Vector<int, 32> nonReturnedOvector; - if (ovector) { - ovector->resize(offsetVectorSize); - offsetVector = ovector->data(); - } else { - nonReturnedOvector.resize(offsetVectorSize); - offsetVector = nonReturnedOvector.data(); - } - ASSERT(offsetVector); - for (int j = 0; j < offsetVectorSize; ++j) - offsetVector[j] = -1; - - int result = m_wrecFunction(s.data(), startOffset, s.size(), offsetVector); - - if (result < 0) { -#ifndef NDEBUG - // TODO: define up a symbol, rather than magic -1 - if (result != -1) - fprintf(stderr, "jsRegExpExecute failed with result %d\n", result); -#endif - if (ovector) - ovector->clear(); - } - return result; - } else -#endif if (m_regExp) { // Set up the offset vector for the result. // First 2/3 used for result, the last third used by PCRE. diff --git a/JavaScriptCore/runtime/RegExp.h b/JavaScriptCore/runtime/RegExp.h index 61ab0bc..695b688 100644 --- a/JavaScriptCore/runtime/RegExp.h +++ b/JavaScriptCore/runtime/RegExp.h @@ -23,7 +23,6 @@ #define RegExp_h #include "UString.h" -#include "WREC.h" #include "ExecutableAllocator.h" #include <wtf/Forward.h> #include <wtf/RefCounted.h> @@ -74,10 +73,6 @@ namespace JSC { #elif ENABLE(YARR) OwnPtr<Yarr::BytecodePattern> m_regExpBytecode; #else -#if ENABLE(WREC) - WREC::CompiledRegExp m_wrecFunction; - RefPtr<ExecutablePool> m_executablePool; -#endif JSRegExp* m_regExp; #endif }; diff --git a/JavaScriptCore/runtime/RegExpConstructor.cpp b/JavaScriptCore/runtime/RegExpConstructor.cpp index 6f00142..3a67ae6 100644 --- a/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -27,6 +27,7 @@ #include "JSArray.h" #include "JSFunction.h" #include "JSString.h" +#include "Lookup.h" #include "ObjectPrototype.h" #include "RegExpMatchesArray.h" #include "RegExpObject.h" @@ -35,21 +36,21 @@ namespace JSC { -static JSValue regExpConstructorInput(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorLastMatch(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorLastParen(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorLeftContext(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorRightContext(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorDollar1(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorDollar2(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorDollar3(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorDollar4(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorDollar5(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorDollar6(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorDollar7(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorDollar8(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpConstructorDollar9(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpConstructorInput(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorMultiline(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorLastMatch(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorLastParen(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorLeftContext(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorRightContext(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorDollar1(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorDollar2(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorDollar3(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorDollar4(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorDollar5(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorDollar6(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorDollar7(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorDollar8(ExecState*, JSValue, const Identifier&); +static JSValue regExpConstructorDollar9(ExecState*, JSValue, const Identifier&); static void setRegExpConstructorInput(ExecState*, JSObject*, JSValue); static void setRegExpConstructorMultiline(ExecState*, JSObject*, JSValue); @@ -113,17 +114,17 @@ RegExpMatchesArray::RegExpMatchesArray(ExecState* exec, RegExpConstructorPrivate memcpy(d->lastOvector().data(), data->lastOvector().data(), offsetVectorSize * sizeof(int)); // d->multiline is not needed, and remains uninitialized - setLazyCreationData(d); + setSubclassData(d); } RegExpMatchesArray::~RegExpMatchesArray() { - delete static_cast<RegExpConstructorPrivate*>(lazyCreationData()); + delete static_cast<RegExpConstructorPrivate*>(subclassData()); } void RegExpMatchesArray::fillArrayInstance(ExecState* exec) { - RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(lazyCreationData()); + RegExpConstructorPrivate* d = static_cast<RegExpConstructorPrivate*>(subclassData()); ASSERT(d); unsigned lastNumSubpatterns = d->lastNumSubPatterns; @@ -141,7 +142,7 @@ void RegExpMatchesArray::fillArrayInstance(ExecState* exec) JSArray::put(exec, exec->propertyNames().input, jsString(exec, d->input), slot); delete d; - setLazyCreationData(0); + setSubclassData(0); } JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const @@ -195,79 +196,79 @@ bool RegExpConstructor::getOwnPropertyDescriptor(ExecState* exec, const Identifi return getStaticValueDescriptor<RegExpConstructor, InternalFunction>(exec, ExecState::regExpConstructorTable(exec), this, propertyName, descriptor); } -JSValue regExpConstructorDollar1(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar1(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 1); + return asRegExpConstructor(slotBase)->getBackref(exec, 1); } -JSValue regExpConstructorDollar2(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar2(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 2); + return asRegExpConstructor(slotBase)->getBackref(exec, 2); } -JSValue regExpConstructorDollar3(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar3(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 3); + return asRegExpConstructor(slotBase)->getBackref(exec, 3); } -JSValue regExpConstructorDollar4(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar4(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 4); + return asRegExpConstructor(slotBase)->getBackref(exec, 4); } -JSValue regExpConstructorDollar5(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar5(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 5); + return asRegExpConstructor(slotBase)->getBackref(exec, 5); } -JSValue regExpConstructorDollar6(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar6(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 6); + return asRegExpConstructor(slotBase)->getBackref(exec, 6); } -JSValue regExpConstructorDollar7(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar7(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 7); + return asRegExpConstructor(slotBase)->getBackref(exec, 7); } -JSValue regExpConstructorDollar8(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar8(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 8); + return asRegExpConstructor(slotBase)->getBackref(exec, 8); } -JSValue regExpConstructorDollar9(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorDollar9(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 9); + return asRegExpConstructor(slotBase)->getBackref(exec, 9); } -JSValue regExpConstructorInput(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorInput(ExecState* exec, JSValue slotBase, const Identifier&) { - return jsString(exec, asRegExpConstructor(slot.slotBase())->input()); + return jsString(exec, asRegExpConstructor(slotBase)->input()); } -JSValue regExpConstructorMultiline(ExecState*, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorMultiline(ExecState*, JSValue slotBase, const Identifier&) { - return jsBoolean(asRegExpConstructor(slot.slotBase())->multiline()); + return jsBoolean(asRegExpConstructor(slotBase)->multiline()); } -JSValue regExpConstructorLastMatch(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorLastMatch(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getBackref(exec, 0); + return asRegExpConstructor(slotBase)->getBackref(exec, 0); } -JSValue regExpConstructorLastParen(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorLastParen(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getLastParen(exec); + return asRegExpConstructor(slotBase)->getLastParen(exec); } -JSValue regExpConstructorLeftContext(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorLeftContext(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getLeftContext(exec); + return asRegExpConstructor(slotBase)->getLeftContext(exec); } -JSValue regExpConstructorRightContext(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpConstructorRightContext(ExecState* exec, JSValue slotBase, const Identifier&) { - return asRegExpConstructor(slot.slotBase())->getRightContext(exec); + return asRegExpConstructor(slotBase)->getRightContext(exec); } void RegExpConstructor::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) diff --git a/JavaScriptCore/runtime/RegExpMatchesArray.h b/JavaScriptCore/runtime/RegExpMatchesArray.h index 38d3cb4..b823621 100644 --- a/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -32,56 +32,56 @@ namespace JSC { private: virtual bool getOwnPropertySlot(ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { - if (lazyCreationData()) + if (subclassData()) fillArrayInstance(exec); return JSArray::getOwnPropertySlot(exec, propertyName, slot); } virtual bool getOwnPropertySlot(ExecState* exec, unsigned propertyName, PropertySlot& slot) { - if (lazyCreationData()) + if (subclassData()) fillArrayInstance(exec); return JSArray::getOwnPropertySlot(exec, propertyName, slot); } virtual bool getOwnPropertyDescriptor(ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { - if (lazyCreationData()) + if (subclassData()) fillArrayInstance(exec); return JSArray::getOwnPropertyDescriptor(exec, propertyName, descriptor); } virtual void put(ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot) { - if (lazyCreationData()) + if (subclassData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v, slot); } virtual void put(ExecState* exec, unsigned propertyName, JSValue v) { - if (lazyCreationData()) + if (subclassData()) fillArrayInstance(exec); JSArray::put(exec, propertyName, v); } virtual bool deleteProperty(ExecState* exec, const Identifier& propertyName) { - if (lazyCreationData()) + if (subclassData()) fillArrayInstance(exec); return JSArray::deleteProperty(exec, propertyName); } virtual bool deleteProperty(ExecState* exec, unsigned propertyName) { - if (lazyCreationData()) + if (subclassData()) fillArrayInstance(exec); return JSArray::deleteProperty(exec, propertyName); } virtual void getOwnPropertyNames(ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties) { - if (lazyCreationData()) + if (subclassData()) fillArrayInstance(exec); JSArray::getOwnPropertyNames(exec, arr, mode); } diff --git a/JavaScriptCore/runtime/RegExpObject.cpp b/JavaScriptCore/runtime/RegExpObject.cpp index 42bfcef..bc74924 100644 --- a/JavaScriptCore/runtime/RegExpObject.cpp +++ b/JavaScriptCore/runtime/RegExpObject.cpp @@ -25,16 +25,17 @@ #include "JSArray.h" #include "JSGlobalObject.h" #include "JSString.h" +#include "Lookup.h" #include "RegExpConstructor.h" #include "RegExpPrototype.h" namespace JSC { -static JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpObjectSource(ExecState*, const Identifier&, const PropertySlot&); -static JSValue regExpObjectLastIndex(ExecState*, const Identifier&, const PropertySlot&); +static JSValue regExpObjectGlobal(ExecState*, JSValue, const Identifier&); +static JSValue regExpObjectIgnoreCase(ExecState*, JSValue, const Identifier&); +static JSValue regExpObjectMultiline(ExecState*, JSValue, const Identifier&); +static JSValue regExpObjectSource(ExecState*, JSValue, const Identifier&); +static JSValue regExpObjectLastIndex(ExecState*, JSValue, const Identifier&); static void setRegExpObjectLastIndex(ExecState*, JSObject*, JSValue); } // namespace JSC @@ -77,29 +78,29 @@ bool RegExpObject::getOwnPropertyDescriptor(ExecState* exec, const Identifier& p return getStaticValueDescriptor<RegExpObject, JSObject>(exec, ExecState::regExpTable(exec), this, propertyName, descriptor); } -JSValue regExpObjectGlobal(ExecState*, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectGlobal(ExecState*, JSValue slotBase, const Identifier&) { - return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->global()); + return jsBoolean(asRegExpObject(slotBase)->regExp()->global()); } -JSValue regExpObjectIgnoreCase(ExecState*, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectIgnoreCase(ExecState*, JSValue slotBase, const Identifier&) { - return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->ignoreCase()); + return jsBoolean(asRegExpObject(slotBase)->regExp()->ignoreCase()); } -JSValue regExpObjectMultiline(ExecState*, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectMultiline(ExecState*, JSValue slotBase, const Identifier&) { - return jsBoolean(asRegExpObject(slot.slotBase())->regExp()->multiline()); + return jsBoolean(asRegExpObject(slotBase)->regExp()->multiline()); } -JSValue regExpObjectSource(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectSource(ExecState* exec, JSValue slotBase, const Identifier&) { - return jsString(exec, asRegExpObject(slot.slotBase())->regExp()->pattern()); + return jsString(exec, asRegExpObject(slotBase)->regExp()->pattern()); } -JSValue regExpObjectLastIndex(ExecState* exec, const Identifier&, const PropertySlot& slot) +JSValue regExpObjectLastIndex(ExecState* exec, JSValue slotBase, const Identifier&) { - return jsNumber(exec, asRegExpObject(slot.slotBase())->lastIndex()); + return jsNumber(exec, asRegExpObject(slotBase)->lastIndex()); } void RegExpObject::put(ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) diff --git a/JavaScriptCore/wrec/Quantifier.h b/JavaScriptCore/runtime/RopeImpl.cpp index 3da74cd..a3760e6 100644 --- a/JavaScriptCore/wrec/Quantifier.h +++ b/JavaScriptCore/runtime/RopeImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * 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 @@ -23,44 +23,40 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef Quantifier_h -#define Quantifier_h - -#include <wtf/Platform.h> - -#if ENABLE(WREC) - -#include <wtf/Assertions.h> -#include <limits.h> - -namespace JSC { namespace WREC { - - struct Quantifier { - enum Type { - None, - Greedy, - NonGreedy, - Error, - }; - - Quantifier(Type type = None, unsigned min = 0, unsigned max = Infinity) - : type(type) - , min(min) - , max(max) - { - ASSERT(min <= max); - } - - Type type; - - unsigned min; - unsigned max; - - static const unsigned Infinity = UINT_MAX; - }; - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) - -#endif // Quantifier_h +#include "config.h" +#include "RopeImpl.h" + +namespace JSC { + +void RopeImpl::derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue) +{ + unsigned length = fiberCount(); + for (unsigned i = 0; i < length; ++i) { + Fiber& fiber = fibers(i); + if (isRope(fiber)) { + RopeImpl* nextRope = static_cast<RopeImpl*>(fiber); + if (nextRope->hasOneRef()) + workQueue.append(nextRope); + else + nextRope->deref(); + } else + static_cast<UStringImpl*>(fiber)->deref(); + } +} + +void RopeImpl::destructNonRecursive() +{ + Vector<RopeImpl*, 32> workQueue; + + derefFibersNonRecursive(workQueue); + delete this; + + while (!workQueue.isEmpty()) { + RopeImpl* rope = workQueue.last(); + workQueue.removeLast(); + rope->derefFibersNonRecursive(workQueue); + delete rope; + } +} + +} // namespace JSC diff --git a/JavaScriptCore/runtime/RopeImpl.h b/JavaScriptCore/runtime/RopeImpl.h new file mode 100644 index 0000000..6fbc595 --- /dev/null +++ b/JavaScriptCore/runtime/RopeImpl.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef RopeImpl_h +#define RopeImpl_h + +#include "UStringImpl.h" + +namespace JSC { + +class RopeImpl : public StringImplBase { +public: + // A RopeImpl is composed from a set of smaller strings called Fibers. + // Each Fiber in a rope is either UStringImpl or another RopeImpl. + typedef StringImplBase* Fiber; + + // Creates a RopeImpl comprising of 'fiberCount' Fibers. + // The RopeImpl is constructed in an uninitialized state - initialize must be called for each Fiber in the RopeImpl. + static PassRefPtr<RopeImpl> tryCreateUninitialized(unsigned fiberCount) + { + void* allocation; + if (tryFastMalloc(sizeof(RopeImpl) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation)) + return adoptRef(new (allocation) RopeImpl(fiberCount)); + return 0; + } + + void initializeFiber(unsigned &index, Fiber fiber) + { + m_fibers[index++] = fiber; + fiber->ref(); + m_length += fiber->length(); + } + + unsigned fiberCount() { return m_fiberCount; } + Fiber& fibers(unsigned index) { return m_fibers[index]; } + + ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) destructNonRecursive(); } + + static bool isRope(Fiber fiber) + { + return !fiber->isStringImpl(); + } + + static void deref(Fiber fiber) + { + if (isRope(fiber)) + static_cast<RopeImpl*>(fiber)->deref(); + else + static_cast<UStringImpl*>(fiber)->deref(); + } + +private: + RopeImpl(unsigned fiberCount) : StringImplBase(ConstructNonStringImpl), m_fiberCount(fiberCount) {} + + void destructNonRecursive(); + void derefFibersNonRecursive(Vector<RopeImpl*, 32>& workQueue); + + bool hasOneRef() { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; } + + unsigned m_fiberCount; + Fiber m_fibers[1]; +}; + +} + +#endif diff --git a/JavaScriptCore/runtime/SmallStrings.cpp b/JavaScriptCore/runtime/SmallStrings.cpp index 78bd4e4..0f5df4a 100644 --- a/JavaScriptCore/runtime/SmallStrings.cpp +++ b/JavaScriptCore/runtime/SmallStrings.cpp @@ -43,10 +43,10 @@ class SmallStringsStorage : public Noncopyable { public: SmallStringsStorage(); - UString::Rep* rep(unsigned char character) { return &m_reps[character]; } + UString::Rep* rep(unsigned char character) { return m_reps[character].get(); } private: - UString::Rep m_reps[numCharactersToStore]; + RefPtr<UString::Rep> m_reps[numCharactersToStore]; }; SmallStringsStorage::SmallStringsStorage() @@ -55,7 +55,7 @@ SmallStringsStorage::SmallStringsStorage() RefPtr<UStringImpl> baseString = UStringImpl::createUninitialized(numCharactersToStore, characterBuffer); for (unsigned i = 0; i < numCharactersToStore; ++i) { characterBuffer[i] = i; - new (&m_reps[i]) UString::Rep(&characterBuffer[i], 1, PassRefPtr<UStringImpl>(baseString)); + m_reps[i] = UStringImpl::create(baseString, i, 1); } } diff --git a/JavaScriptCore/runtime/StringBuilder.h b/JavaScriptCore/runtime/StringBuilder.h index 27dbbd7..59b01e0 100644 --- a/JavaScriptCore/runtime/StringBuilder.h +++ b/JavaScriptCore/runtime/StringBuilder.h @@ -69,8 +69,7 @@ public: UString build() { buffer.shrinkToFit(); - if (buffer.size() && !buffer.data()) - CRASH(); + ASSERT(buffer.data() || !buffer.size()); return UString::adopt(buffer); } diff --git a/JavaScriptCore/runtime/StringPrototype.cpp b/JavaScriptCore/runtime/StringPrototype.cpp index bef4083..345378e 100644 --- a/JavaScriptCore/runtime/StringPrototype.cpp +++ b/JavaScriptCore/runtime/StringPrototype.cpp @@ -29,6 +29,7 @@ #include "JSArray.h" #include "JSFunction.h" #include "JSStringBuilder.h" +#include "Lookup.h" #include "ObjectPrototype.h" #include "Operations.h" #include "PropertyNameArray.h" diff --git a/JavaScriptCore/runtime/Structure.cpp b/JavaScriptCore/runtime/Structure.cpp index ebf8a4c..6f23c7d 100644 --- a/JavaScriptCore/runtime/Structure.cpp +++ b/JavaScriptCore/runtime/Structure.cpp @@ -265,9 +265,7 @@ Structure::~Structure() m_previous->transitionTableRemove(make_pair(m_nameInPrevious.get(), m_attributesInPrevious), m_specificValueInPrevious); } - - if (m_enumerationCache) - m_enumerationCache->setCachedStructure(0); + ASSERT(!m_enumerationCache.hasDeadObject()); if (m_propertyTable) { unsigned entryCount = m_propertyTable->keyCount + m_propertyTable->deletedSentinelCount; diff --git a/JavaScriptCore/runtime/Terminator.h b/JavaScriptCore/runtime/Terminator.h new file mode 100644 index 0000000..6b0f236 --- /dev/null +++ b/JavaScriptCore/runtime/Terminator.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 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: + * + * 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. + * 3. Neither the name of Google Inc. ("Google") 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 APPLE 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 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 Terminator_h +#define Terminator_h + +namespace JSC { + +class Terminator { +public: + Terminator() : m_shouldTerminate(false) { } + + void terminateSoon() { m_shouldTerminate = true; } + bool shouldTerminate() const { return m_shouldTerminate; } + +private: + bool m_shouldTerminate; +}; + +} // namespace JSC + +#endif // Terminator_h diff --git a/JavaScriptCore/runtime/TimeoutChecker.cpp b/JavaScriptCore/runtime/TimeoutChecker.cpp index 250fdaf..2dc1028 100644 --- a/JavaScriptCore/runtime/TimeoutChecker.cpp +++ b/JavaScriptCore/runtime/TimeoutChecker.cpp @@ -84,6 +84,13 @@ static inline unsigned getCPUTime() GetThreadTimes(GetCurrentThread(), &creationTime, &exitTime, &kernelTime.fileTime, &userTime.fileTime); return userTime.fileTimeAsLong / 10000 + kernelTime.fileTimeAsLong / 10000; +#elif OS(SYMBIAN) + RThread current; + TTimeIntervalMicroSeconds cpuTime; + + TInt err = current.GetCpuTime(cpuTime); + ASSERT_WITH_MESSAGE(err == KErrNone, "GetCpuTime failed with %d", err); + return cpuTime.Int64() / 1000; #elif PLATFORM(BREWMP) // This function returns a continuously and linearly increasing millisecond // timer from the time the device was powered on. diff --git a/JavaScriptCore/runtime/UString.cpp b/JavaScriptCore/runtime/UString.cpp index 1684ec2..ce91040 100644 --- a/JavaScriptCore/runtime/UString.cpp +++ b/JavaScriptCore/runtime/UString.cpp @@ -57,108 +57,15 @@ namespace JSC { extern const double NaN; extern const double Inf; -CString::CString(const char* c) - : m_length(strlen(c)) - , m_data(new char[m_length + 1]) -{ - memcpy(m_data, c, m_length + 1); -} - -CString::CString(const char* c, size_t length) - : m_length(length) - , m_data(new char[length + 1]) -{ - memcpy(m_data, c, m_length); - m_data[m_length] = 0; -} - -CString::CString(const CString& b) -{ - m_length = b.m_length; - if (b.m_data) { - m_data = new char[m_length + 1]; - memcpy(m_data, b.m_data, m_length + 1); - } else - m_data = 0; -} - -CString::~CString() -{ - delete [] m_data; -} - -CString CString::adopt(char* c, size_t length) -{ - CString s; - s.m_data = c; - s.m_length = length; - return s; -} - -CString& CString::append(const CString& t) -{ - char* n; - n = new char[m_length + t.m_length + 1]; - if (m_length) - memcpy(n, m_data, m_length); - if (t.m_length) - memcpy(n + m_length, t.m_data, t.m_length); - m_length += t.m_length; - n[m_length] = 0; - - delete [] m_data; - m_data = n; - - return *this; -} - -CString& CString::operator=(const char* c) -{ - if (m_data) - delete [] m_data; - m_length = strlen(c); - m_data = new char[m_length + 1]; - memcpy(m_data, c, m_length + 1); - - return *this; -} - -CString& CString::operator=(const CString& str) -{ - if (this == &str) - return *this; - - if (m_data) - delete [] m_data; - m_length = str.m_length; - if (str.m_data) { - m_data = new char[m_length + 1]; - memcpy(m_data, str.m_data, m_length + 1); - } else - m_data = 0; - - return *this; -} - -bool operator==(const CString& c1, const CString& c2) -{ - size_t len = c1.size(); - return len == c2.size() && (len == 0 || memcmp(c1.c_str(), c2.c_str(), len) == 0); -} - -// 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; -UStringImpl* UStringImpl::s_empty; - -UString::Rep* UString::s_nullRep; +// The null string is immutable, except for refCount. UString* UString::s_nullUString; void initializeUString() { - UStringImpl::s_empty = new UStringImpl(&sharedEmptyChar, 0, UStringImpl::ConstructStaticString); + // UStringImpl::empty() does not construct its static string in a threadsafe fashion, + // so ensure it has been initialized from here. + UStringImpl::empty(); - UString::s_nullRep = new UStringImpl(0, 0, UStringImpl::ConstructStaticString); UString::s_nullUString = new UString; } @@ -173,11 +80,8 @@ UString::UString(const char* c, unsigned length) } UString::UString(const UChar* c, unsigned length) + : m_rep(Rep::create(c, length)) { - if (length == 0) - m_rep = &Rep::empty(); - else - m_rep = Rep::create(c, length); } UString UString::from(int i) @@ -242,7 +146,7 @@ UString UString::from(long long i) return UString(p, static_cast<unsigned>(end - p)); } -UString UString::from(unsigned int u) +UString UString::from(unsigned u) { UChar buf[sizeof(u) * 3]; UChar* end = buf + sizeof(buf) / sizeof(UChar); @@ -297,29 +201,6 @@ UString UString::from(double d) return UString(buffer, length); } -bool UString::getCString(CStringBuffer& buffer) const -{ - unsigned length = size(); - unsigned neededSize = length + 1; - buffer.resize(neededSize); - char* buf = buffer.data(); - - UChar ored = 0; - const UChar* p = data(); - char* q = buf; - const UChar* limit = p + length; - while (p != limit) { - UChar c = p[0]; - ored |= c; - *q = static_cast<char>(c); - ++p; - ++q; - } - *q = '\0'; - - return !(ored & 0xFF00); -} - char* UString::ascii() const { static char* asciiBuffer = 0; @@ -373,11 +254,7 @@ double UString::toDouble(bool tolerateTrailingJunk, bool tolerateEmptyString) co return NaN; } - // FIXME: If tolerateTrailingJunk is true, then we want to tolerate non-8-bit junk - // after the number, so this is too strict a check. - CStringBuffer s; - if (!getCString(s)) - return NaN; + CString s = UTF8String(); const char* c = s.data(); // skip leading white space @@ -498,7 +375,7 @@ uint32_t UString::toStrictUInt32(bool* ok) const unsigned len = m_rep->length(); if (len == 0) return 0; - const UChar* p = m_rep->data(); + const UChar* p = m_rep->characters(); unsigned short c = p[0]; // If the first digit is 0, only 0 itself is OK. @@ -548,7 +425,7 @@ unsigned UString::find(const UString& f, unsigned pos) const const UChar* end = data() + size(); for (const UChar* c = data() + pos; c < end; c++) { if (*c == ch) - return static_cast<int>(c - data()); + return static_cast<unsigned>(c - data()); } return NotFound; } @@ -565,7 +442,7 @@ unsigned UString::find(const UString& f, unsigned pos) const ++fdata; for (const UChar* c = data() + pos; c <= end; c++) { if (c[0] == fchar && !memcmp(c + 1, fdata, fsizeminusone)) - return static_cast<int>(c - data()); + return static_cast<unsigned>(c - data()); } return NotFound; @@ -576,7 +453,7 @@ unsigned UString::find(UChar ch, unsigned pos) const const UChar* end = data() + size(); for (const UChar* c = data() + pos; c < end; c++) { if (*c == ch) - return static_cast<int>(c - data()); + return static_cast<unsigned>(c - data()); } return NotFound; @@ -596,7 +473,7 @@ unsigned UString::rfind(const UString& f, unsigned pos) const const UChar* fdata = f.data(); for (const UChar* c = data() + pos; c >= data(); c--) { if (*c == *fdata && !memcmp(c + 1, fdata + 1, fsizeminusone)) - return static_cast<int>(c - data()); + return static_cast<unsigned>(c - data()); } return NotFound; @@ -610,7 +487,7 @@ unsigned UString::rfind(UChar ch, unsigned pos) const pos = size() - 1; for (const UChar* c = data() + pos; c >= data(); c--) { if (*c == ch) - return static_cast<int>(c - data()); + return static_cast<unsigned>(c - data()); } return NotFound; @@ -710,20 +587,6 @@ int compare(const UString& s1, const UString& s2) return (l1 > l2) ? 1 : -1; } -bool equal(const UString::Rep* r, const UString::Rep* b) -{ - unsigned length = r->length(); - if (length != b->length()) - return false; - const UChar* d = r->data(); - const UChar* s = b->data(); - for (unsigned i = 0; i != length; ++i) { - if (d[i] != s[i]) - return false; - } - return true; -} - CString UString::UTF8String(bool strict) const { // Allocate a buffer big enough to hold all the characters. diff --git a/JavaScriptCore/runtime/UString.h b/JavaScriptCore/runtime/UString.h index 75b43b7..da1065e 100644 --- a/JavaScriptCore/runtime/UString.h +++ b/JavaScriptCore/runtime/UString.h @@ -33,6 +33,7 @@ #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> +#include <wtf/text/CString.h> #include <wtf/unicode/Unicode.h> namespace JSC { @@ -40,39 +41,6 @@ namespace JSC { using WTF::PlacementNewAdoptType; using WTF::PlacementNewAdopt; - class CString { - public: - CString() - : m_length(0) - , m_data(0) - { - } - - CString(const char*); - CString(const char*, size_t); - CString(const CString&); - - ~CString(); - - static CString adopt(char*, size_t); // buffer should be allocated with new[]. - - CString& append(const CString&); - CString& operator=(const char* c); - CString& operator=(const CString&); - CString& operator+=(const CString& c) { return append(c); } - - size_t size() const { return m_length; } - const char* c_str() const { return m_data; } - - private: - size_t m_length; - char* m_data; - }; - - bool operator==(const CString&, const CString&); - - typedef Vector<char, 32> CStringBuffer; - class UString { friend class JIT; @@ -80,7 +48,7 @@ namespace JSC { typedef UStringImpl Rep; public: - UString(); + UString() {} UString(const char*); // Constructor for null-terminated string. UString(const char*, unsigned length); UString(const UChar*, unsigned length); @@ -97,10 +65,6 @@ namespace JSC { { } - ~UString() - { - } - template<size_t inlineCapacity> static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) { @@ -109,12 +73,10 @@ namespace JSC { static UString from(int); static UString from(long long); - static UString from(unsigned int); + static UString from(unsigned); static UString from(long); static UString from(double); - bool getCString(CStringBuffer&) const; - // NOTE: This method should only be used for *debugging* purposes as it // is neither Unicode safe nor free from side effects nor thread-safe. char* ascii() const; @@ -129,14 +91,24 @@ namespace JSC { */ CString UTF8String(bool strict = false) const; - const UChar* data() const { return m_rep->data(); } + const UChar* data() const + { + if (!m_rep) + return 0; + return m_rep->characters(); + } - bool isNull() const { return m_rep == s_nullRep; } - bool isEmpty() const { return !m_rep->length(); } + unsigned size() const + { + if (!m_rep) + return 0; + return m_rep->length(); + } - bool is8Bit() const; + bool isNull() const { return !m_rep; } + bool isEmpty() const { return !m_rep || !m_rep->length(); } - unsigned size() const { return m_rep->length(); } + bool is8Bit() const; UChar operator[](unsigned pos) const; @@ -165,15 +137,18 @@ namespace JSC { UString(PassRefPtr<Rep> r) : m_rep(r) { - ASSERT(m_rep); } - size_t cost() const { return m_rep->cost(); } + size_t cost() const + { + if (!m_rep) + return 0; + return m_rep->cost(); + } private: RefPtr<Rep> m_rep; - JS_EXPORTDATA static Rep* s_nullRep; static UString* s_nullUString; friend void initializeUString(); @@ -228,11 +203,6 @@ namespace JSC { int compare(const UString&, const UString&); - inline UString::UString() - : m_rep(s_nullRep) - { - } - // Rule from ECMA 15.2 about what an array index is. // Must exactly match string form of an unsigned integer, and be less than 2^32 - 1. inline unsigned UString::toArrayIndex(bool* ok) const @@ -657,7 +627,7 @@ namespace WTF { template<> struct StrHash<JSC::UString::Rep*> { static unsigned hash(const JSC::UString::Rep* key) { return key->hash(); } - static bool equal(const JSC::UString::Rep* a, const JSC::UString::Rep* b) { return JSC::equal(a, b); } + static bool equal(const JSC::UString::Rep* a, const JSC::UString::Rep* b) { return ::equal(a, b); } static const bool safeToCompareToEmptyOrDeleted = false; }; @@ -665,22 +635,18 @@ namespace WTF { using StrHash<JSC::UString::Rep*>::hash; static unsigned hash(const RefPtr<JSC::UString::Rep>& key) { return key->hash(); } using StrHash<JSC::UString::Rep*>::equal; - static bool equal(const RefPtr<JSC::UString::Rep>& a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a.get(), b.get()); } - static bool equal(const JSC::UString::Rep* a, const RefPtr<JSC::UString::Rep>& b) { return JSC::equal(a, b.get()); } - static bool equal(const RefPtr<JSC::UString::Rep>& a, const JSC::UString::Rep* b) { return JSC::equal(a.get(), b); } + static bool equal(const RefPtr<JSC::UString::Rep>& a, const RefPtr<JSC::UString::Rep>& b) { return ::equal(a.get(), b.get()); } + static bool equal(const JSC::UString::Rep* a, const RefPtr<JSC::UString::Rep>& b) { return ::equal(a, b.get()); } + static bool equal(const RefPtr<JSC::UString::Rep>& a, const JSC::UString::Rep* b) { return ::equal(a.get(), b); } static const bool safeToCompareToEmptyOrDeleted = false; }; - template<> struct DefaultHash<JSC::UString::Rep*> { - typedef StrHash<JSC::UString::Rep*> Hash; - }; - - template<> struct DefaultHash<RefPtr<JSC::UString::Rep> > { - typedef StrHash<RefPtr<JSC::UString::Rep> > Hash; - + template <> struct VectorTraits<JSC::UString> : SimpleClassVectorTraits + { + static const bool canInitializeWithMemset = true; }; - + } // namespace WTF #endif diff --git a/JavaScriptCore/runtime/UStringImpl.cpp b/JavaScriptCore/runtime/UStringImpl.cpp deleted file mode 100644 index b7d9a40..0000000 --- a/JavaScriptCore/runtime/UStringImpl.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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 { - -PassRefPtr<UStringImpl> UStringImpl::create(const char* c) -{ - ASSERT(c); - - if (!c[0]) - return &UStringImpl::empty(); - - size_t length = strlen(c); - UChar* d; - PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d); - 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; -} - -PassRefPtr<UStringImpl> UStringImpl::create(const char* c, unsigned length) -{ - ASSERT(c); - - if (!length) - return &UStringImpl::empty(); - - UChar* d; - PassRefPtr<UStringImpl> result = UStringImpl::createUninitialized(length, d); - for (unsigned 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; -} - -PassRefPtr<UStringImpl> UStringImpl::create(const UChar* buffer, unsigned length) -{ - UChar* newBuffer; - PassRefPtr<UStringImpl> impl = createUninitialized(length, newBuffer); - copyChars(newBuffer, buffer, length); - return impl; -} - -SharedUChar* UStringImpl::baseSharedBuffer() -{ - ASSERT((bufferOwnership() == BufferShared) - || ((bufferOwnership() == BufferOwned) && !m_buffer)); - - if (bufferOwnership() != BufferShared) { - m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared; - m_bufferShared = SharedUChar::create(new OwnFastMallocPtr<UChar>(m_data)).releaseRef(); - } - - return m_bufferShared; -} - -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_bufferSubstring->deref(); - else { - ASSERT(bufferOwnership() == BufferShared); - m_bufferShared->deref(); - } - } -} - -void URopeImpl::derefFibersNonRecursive(Vector<URopeImpl*, 32>& workQueue) -{ - unsigned length = fiberCount(); - for (unsigned i = 0; i < length; ++i) { - Fiber& fiber = fibers(i); - if (fiber->isRope()) { - URopeImpl* nextRope = static_cast<URopeImpl*>(fiber); - if (nextRope->hasOneRef()) - workQueue.append(nextRope); - else - nextRope->deref(); - } else - static_cast<UStringImpl*>(fiber)->deref(); - } -} - -void URopeImpl::destructNonRecursive() -{ - Vector<URopeImpl*, 32> workQueue; - - derefFibersNonRecursive(workQueue); - delete this; - - while (!workQueue.isEmpty()) { - URopeImpl* rope = workQueue.last(); - workQueue.removeLast(); - rope->derefFibersNonRecursive(workQueue); - delete rope; - } -} - -} // namespace JSC diff --git a/JavaScriptCore/runtime/UStringImpl.h b/JavaScriptCore/runtime/UStringImpl.h index 142e01d..08f1fa5 100644 --- a/JavaScriptCore/runtime/UStringImpl.h +++ b/JavaScriptCore/runtime/UStringImpl.h @@ -1,359 +1,30 @@ /* - * Copyright (C) 2009 Apple Inc. All rights reserved. + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * 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: - * 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 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. * - * 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 UStringOrRopeImpl : public Noncopyable { -public: - bool isRope() { return (m_refCountAndFlags & s_refCountIsRope) == s_refCountIsRope; } - unsigned length() const { return m_length; } - - void ref() { m_refCountAndFlags += s_refCountIncrement; } - inline void deref(); - -protected: - enum BufferOwnership { - BufferInternal, - BufferOwned, - BufferSubstring, - BufferShared, - }; - - using Noncopyable::operator new; - void* operator new(size_t, void* inPlace) { return inPlace; } - - // For SmallStringStorage, which allocates an array and uses an in-place new. - UStringOrRopeImpl() { } - - UStringOrRopeImpl(unsigned length, BufferOwnership ownership) - : m_refCountAndFlags(s_refCountIncrement | s_refCountFlagShouldReportedCost | ownership) - , m_length(length) - { - ASSERT(!isRope()); - } - - enum StaticStringConstructType { ConstructStaticString }; - UStringOrRopeImpl(unsigned length, StaticStringConstructType) - : m_refCountAndFlags(s_refCountFlagStatic | BufferOwned) - , m_length(length) - { - ASSERT(!isRope()); - } - - enum RopeConstructType { ConstructRope }; - UStringOrRopeImpl(RopeConstructType) - : m_refCountAndFlags(s_refCountIncrement | s_refCountIsRope) - , m_length(0) - { - ASSERT(isRope()); - } - - // The bottom 5 bits hold flags, the top 27 bits hold the ref count. - // When dereferencing UStringImpls we check for the ref count AND the - // static bit both being zero - static strings are never deleted. - static const unsigned s_refCountMask = 0xFFFFFFE0; - static const unsigned s_refCountIncrement = 0x20; - static const unsigned s_refCountFlagStatic = 0x10; - static const unsigned s_refCountFlagShouldReportedCost = 0x8; - static const unsigned s_refCountFlagIsIdentifier = 0x4; - static const unsigned s_refCountMaskBufferOwnership = 0x3; - // Use an otherwise invalid permutation of flags (static & shouldReportedCost - - // static strings do not set shouldReportedCost in the constructor, and this bit - // is only ever cleared, not set) to identify objects that are ropes. - static const unsigned s_refCountIsRope = s_refCountFlagStatic | s_refCountFlagShouldReportedCost; - - unsigned m_refCountAndFlags; - unsigned m_length; -}; - -class UStringImpl : public UStringOrRopeImpl { -public: - template<size_t inlineCapacity> - static PassRefPtr<UStringImpl> adopt(Vector<UChar, inlineCapacity>& vector) - { - if (unsigned length = vector.size()) { - ASSERT(vector.data()); - return adoptRef(new UStringImpl(vector.releaseBuffer(), length)); - } - return &empty(); - } - - static PassRefPtr<UStringImpl> create(const char* c); - static PassRefPtr<UStringImpl> create(const char* c, unsigned length); - static PassRefPtr<UStringImpl> create(const UChar* buffer, unsigned length); - - static PassRefPtr<UStringImpl> create(PassRefPtr<UStringImpl> rep, unsigned offset, unsigned 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, unsigned 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(length)); - } - - 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(length)); - } - - SharedUChar* sharedBuffer(); - UChar* data() const { return m_data; } - size_t cost() - { - // For substrings, return the cost of the base string. - if (bufferOwnership() == BufferSubstring) - return m_bufferSubstring->cost(); - - if (m_refCountAndFlags & s_refCountFlagShouldReportedCost) { - m_refCountAndFlags &= ~s_refCountFlagShouldReportedCost; - return m_length; - } - return 0; - } - 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_refCountAndFlags & s_refCountFlagIsIdentifier; } - void setIsIdentifier(bool isIdentifier) - { - if (isIdentifier) - m_refCountAndFlags |= s_refCountFlagIsIdentifier; - else - m_refCountAndFlags &= ~s_refCountFlagIsIdentifier; - } - - ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) 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, unsigned length) { return WTF::stringHash(s, length); } - static unsigned computeHash(const char* s, unsigned length) { return WTF::stringHash(s, length); } - static unsigned computeHash(const char* s) { return WTF::stringHash(s); } - - 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: - // For SmallStringStorage, which allocates an array and uses an in-place new. - UStringImpl() { } - - // Used to construct normal strings with an internal buffer. - UStringImpl(unsigned length) - : UStringOrRopeImpl(length, BufferInternal) - , m_data(reinterpret_cast<UChar*>(this + 1)) - , m_buffer(0) - , m_hash(0) - { - checkConsistency(); - } - - // Used to construct normal strings with an external buffer. - UStringImpl(UChar* data, unsigned length) - : UStringOrRopeImpl(length, BufferOwned) - , m_data(data) - , m_buffer(0) - , m_hash(0) - { - 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. - UStringImpl(UChar* data, unsigned length, StaticStringConstructType) - : UStringOrRopeImpl(length, ConstructStaticString) - , m_data(data) - , m_buffer(0) - , m_hash(0) - { - checkConsistency(); - } - - // Used to create new strings that are a substring of an existing string. - UStringImpl(UChar* data, unsigned length, PassRefPtr<UStringImpl> base) - : UStringOrRopeImpl(length, BufferSubstring) - , m_data(data) - , m_bufferSubstring(base.releaseRef()) - , m_hash(0) - { - // 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_bufferSubstring->length()); - ASSERT(!m_bufferSubstring->isStatic()); - checkConsistency(); - } - - // Used to construct new strings sharing an existing shared buffer. - UStringImpl(UChar* data, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) - : UStringOrRopeImpl(length, BufferShared) - , m_data(data) - , m_bufferShared(sharedBuffer.releaseRef()) - , m_hash(0) - { - checkConsistency(); - } - - ~UStringImpl(); - - // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. - static const unsigned s_minLengthToShare = 10; - static const unsigned s_copyCharsInlineCutOff = 20; - - UStringImpl* bufferOwnerString() { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring : this; } - const UStringImpl* bufferOwnerString() const { return (bufferOwnership() == BufferSubstring) ? m_bufferSubstring : this; } - SharedUChar* baseSharedBuffer(); - unsigned bufferOwnership() const { return m_refCountAndFlags & s_refCountMaskBufferOwnership; } - bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } - - // unshared data - UChar* m_data; - union { - void* m_buffer; - UStringImpl* m_bufferSubstring; - SharedUChar* m_bufferShared; - }; - mutable unsigned m_hash; - - JS_EXPORTDATA static UStringImpl* s_empty; - - friend class JIT; - friend class SmallStringsStorage; - friend class UStringOrRopeImpl; - friend void initializeUString(); -}; - -class URopeImpl : public UStringOrRopeImpl { -public: - // A URopeImpl is composed from a set of smaller strings called Fibers. - // Each Fiber in a rope is either UStringImpl or another URopeImpl. - typedef UStringOrRopeImpl* Fiber; - - // Creates a URopeImpl comprising of 'fiberCount' Fibers. - // The URopeImpl is constructed in an uninitialized state - initialize must be called for each Fiber in the URopeImpl. - static PassRefPtr<URopeImpl> tryCreateUninitialized(unsigned fiberCount) - { - void* allocation; - if (tryFastMalloc(sizeof(URopeImpl) + (fiberCount - 1) * sizeof(Fiber)).getValue(allocation)) - return adoptRef(new (allocation) URopeImpl(fiberCount)); - return 0; - } - - void initializeFiber(unsigned &index, Fiber fiber) - { - m_fibers[index++] = fiber; - fiber->ref(); - m_length += fiber->length(); - } - - unsigned fiberCount() { return m_fiberCount; } - Fiber& fibers(unsigned index) { return m_fibers[index]; } - - ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & s_refCountMask)) destructNonRecursive(); } - -private: - URopeImpl(unsigned fiberCount) : UStringOrRopeImpl(ConstructRope), m_fiberCount(fiberCount) {} - - void destructNonRecursive(); - void derefFibersNonRecursive(Vector<URopeImpl*, 32>& workQueue); - - bool hasOneRef() { return (m_refCountAndFlags & s_refCountMask) == s_refCountIncrement; } - - unsigned m_fiberCount; - Fiber m_fibers[1]; - - friend class UStringOrRopeImpl; -}; - -inline void UStringOrRopeImpl::deref() -{ - if (isRope()) - static_cast<URopeImpl*>(this)->deref(); - else - static_cast<UStringImpl*>(this)->deref(); -} - -bool equal(const UStringImpl*, const UStringImpl*); - -} +// FIXME: Remove this redundant name! +#include <wtf/text/StringImpl.h> +namespace JSC { typedef WebCore::StringImpl UStringImpl; } #endif diff --git a/JavaScriptCore/runtime/WeakGCPtr.h b/JavaScriptCore/runtime/WeakGCPtr.h index 3ed4645..5f58374 100644 --- a/JavaScriptCore/runtime/WeakGCPtr.h +++ b/JavaScriptCore/runtime/WeakGCPtr.h @@ -65,6 +65,10 @@ public: WeakGCPtr& operator=(T*); +#if !ASSERT_DISABLED + bool hasDeadObject() const { return !!m_ptr; } +#endif + private: void assign(T* ptr) { diff --git a/JavaScriptCore/tests/perf/bench-allocate-nonretained.js b/JavaScriptCore/tests/perf/bench-allocate-nonretained.js new file mode 100644 index 0000000..d493416 --- /dev/null +++ b/JavaScriptCore/tests/perf/bench-allocate-nonretained.js @@ -0,0 +1,6 @@ +(function () { + for (var i = 0; i < 500; ++i) { + for (var j = 0; j < 100000; ++j) + var a = {}; + } +})(); diff --git a/JavaScriptCore/tests/perf/bench-allocate-retained.js b/JavaScriptCore/tests/perf/bench-allocate-retained.js new file mode 100644 index 0000000..4e6a4bd --- /dev/null +++ b/JavaScriptCore/tests/perf/bench-allocate-retained.js @@ -0,0 +1,10 @@ +(function () { + var a = new Array(100000); + for (var i = 0; i < 100000; ++i) + a[i] = {}; + + for (var i = 0; i < 500; ++i) { + for (var j = 0; j < 100000; ++j) + var b = {}; + } +})(); diff --git a/JavaScriptCore/wrec/CharacterClass.cpp b/JavaScriptCore/wrec/CharacterClass.cpp deleted file mode 100644 index e3f12f2..0000000 --- a/JavaScriptCore/wrec/CharacterClass.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (C) 2008 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 "CharacterClass.h" - -#if ENABLE(WREC) - -using namespace WTF; - -namespace JSC { namespace WREC { - -const CharacterClass& CharacterClass::newline() { - static const UChar asciiNewlines[2] = { '\n', '\r' }; - static const UChar unicodeNewlines[2] = { 0x2028, 0x2029 }; - static const CharacterClass charClass = { - asciiNewlines, 2, - 0, 0, - unicodeNewlines, 2, - 0, 0, - }; - - return charClass; -} - -const CharacterClass& CharacterClass::digits() { - static const CharacterRange asciiDigitsRange[1] = { { '0', '9' } }; - static const CharacterClass charClass = { - 0, 0, - asciiDigitsRange, 1, - 0, 0, - 0, 0, - }; - - return charClass; -} - -const CharacterClass& CharacterClass::spaces() { - static const UChar asciiSpaces[1] = { ' ' }; - static const CharacterRange asciiSpacesRange[1] = { { '\t', '\r' } }; - static const UChar unicodeSpaces[8] = { 0x00a0, 0x1680, 0x180e, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000 }; - static const CharacterRange unicodeSpacesRange[1] = { { 0x2000, 0x200a } }; - static const CharacterClass charClass = { - asciiSpaces, 1, - asciiSpacesRange, 1, - unicodeSpaces, 8, - unicodeSpacesRange, 1, - }; - - return charClass; -} - -const CharacterClass& CharacterClass::wordchar() { - static const UChar asciiWordchar[1] = { '_' }; - static const CharacterRange asciiWordcharRange[3] = { { '0', '9' }, { 'A', 'Z' }, { 'a', 'z' } }; - static const CharacterClass charClass = { - asciiWordchar, 1, - asciiWordcharRange, 3, - 0, 0, - 0, 0, - }; - - return charClass; -} - -const CharacterClass& CharacterClass::nondigits() { - static const CharacterRange asciiNondigitsRange[2] = { { 0, '0' - 1 }, { '9' + 1, 0x7f } }; - static const CharacterRange unicodeNondigitsRange[1] = { { 0x0080, 0xffff } }; - static const CharacterClass charClass = { - 0, 0, - asciiNondigitsRange, 2, - 0, 0, - unicodeNondigitsRange, 1, - }; - - return charClass; -} - -const CharacterClass& CharacterClass::nonspaces() { - static const CharacterRange asciiNonspacesRange[3] = { { 0, '\t' - 1 }, { '\r' + 1, ' ' - 1 }, { ' ' + 1, 0x7f } }; - static const CharacterRange unicodeNonspacesRange[9] = { - { 0x0080, 0x009f }, - { 0x00a1, 0x167f }, - { 0x1681, 0x180d }, - { 0x180f, 0x1fff }, - { 0x200b, 0x2027 }, - { 0x202a, 0x202e }, - { 0x2030, 0x205e }, - { 0x2060, 0x2fff }, - { 0x3001, 0xffff } - }; - static const CharacterClass charClass = { - 0, 0, - asciiNonspacesRange, 3, - 0, 0, - unicodeNonspacesRange, 9, - }; - - return charClass; -} - -const CharacterClass& CharacterClass::nonwordchar() { - static const UChar asciiNonwordchar[1] = { '`' }; - static const CharacterRange asciiNonwordcharRange[4] = { { 0, '0' - 1 }, { '9' + 1, 'A' - 1 }, { 'Z' + 1, '_' - 1 }, { 'z' + 1, 0x7f } }; - static const CharacterRange unicodeNonwordcharRange[1] = { { 0x0080, 0xffff } }; - static const CharacterClass charClass = { - asciiNonwordchar, 1, - asciiNonwordcharRange, 4, - 0, 0, - unicodeNonwordcharRange, 1, - }; - - return charClass; -} - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/CharacterClassConstructor.cpp b/JavaScriptCore/wrec/CharacterClassConstructor.cpp deleted file mode 100644 index 06f4262..0000000 --- a/JavaScriptCore/wrec/CharacterClassConstructor.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2008, 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 "CharacterClassConstructor.h" - -#if ENABLE(WREC) - -#include "pcre_internal.h" -#include <wtf/ASCIICType.h> - -using namespace WTF; - -namespace JSC { namespace WREC { - -void CharacterClassConstructor::addSorted(Vector<UChar>& matches, UChar ch) -{ - unsigned pos = 0; - unsigned range = matches.size(); - - // binary chop, find position to insert char. - while (range) { - unsigned index = range >> 1; - - int val = matches[pos+index] - ch; - if (!val) - return; - else if (val > 0) - range = index; - else { - pos += (index+1); - range -= (index+1); - } - } - - if (pos == matches.size()) - matches.append(ch); - else - matches.insert(pos, ch); -} - -void CharacterClassConstructor::addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi) -{ - unsigned end = ranges.size(); - - // Simple linear scan - I doubt there are that many ranges anyway... - // feel free to fix this with something faster (eg binary chop). - for (unsigned i = 0; i < end; ++i) { - // does the new range fall before the current position in the array - if (hi < ranges[i].begin) { - // optional optimization: concatenate appending ranges? - may not be worthwhile. - if (hi == (ranges[i].begin - 1)) { - ranges[i].begin = lo; - return; - } - CharacterRange r = {lo, hi}; - ranges.insert(i, r); - return; - } - // Okay, since we didn't hit the last case, the end of the new range is definitely at or after the begining - // If the new range start at or before the end of the last range, then the overlap (if it starts one after the - // end of the last range they concatenate, which is just as good. - if (lo <= (ranges[i].end + 1)) { - // found an intersect! we'll replace this entry in the array. - ranges[i].begin = std::min(ranges[i].begin, lo); - ranges[i].end = std::max(ranges[i].end, hi); - - // now check if the new range can subsume any subsequent ranges. - unsigned next = i+1; - // each iteration of the loop we will either remove something from the list, or break the loop. - while (next < ranges.size()) { - if (ranges[next].begin <= (ranges[i].end + 1)) { - // the next entry now overlaps / concatenates this one. - ranges[i].end = std::max(ranges[i].end, ranges[next].end); - ranges.remove(next); - } else - break; - } - - return; - } - } - - // CharacterRange comes after all existing ranges. - CharacterRange r = {lo, hi}; - ranges.append(r); -} - -void CharacterClassConstructor::put(UChar ch) -{ - // Parsing a regular expression like [a-z], we start in an initial empty state: - // ((m_charBuffer == -1) && !m_isPendingDash) - // When buffer the 'a' sice it may be (and is in this case) part of a range: - // ((m_charBuffer != -1) && !m_isPendingDash) - // Having parsed the hyphen we then record that the dash is also pending: - // ((m_charBuffer != -1) && m_isPendingDash) - // The next change will always take us back to the initial state - either because - // a complete range has been parsed (such as [a-z]), or because a flush is forced, - // due to an early end in the regexp ([a-]), or a character class escape being added - // ([a-\s]). The fourth permutation of m_charBuffer and m_isPendingDash is not permitted. - ASSERT(!((m_charBuffer == -1) && m_isPendingDash)); - - if (m_charBuffer != -1) { - if (m_isPendingDash) { - // EXAMPLE: parsing [-a-c], the 'c' reaches this case - we have buffered a previous character and seen a hyphen, so this is a range. - UChar lo = m_charBuffer; - UChar hi = ch; - // Reset back to the inital state. - m_charBuffer = -1; - m_isPendingDash = false; - - // This is an error, detected lazily. Do not proceed. - if (lo > hi) { - m_isUpsideDown = true; - return; - } - - if (lo <= 0x7f) { - char asciiLo = lo; - char asciiHi = std::min(hi, (UChar)0x7f); - addSortedRange(m_ranges, lo, asciiHi); - - if (m_isCaseInsensitive) { - if ((asciiLo <= 'Z') && (asciiHi >= 'A')) - addSortedRange(m_ranges, std::max(asciiLo, 'A')+('a'-'A'), std::min(asciiHi, 'Z')+('a'-'A')); - if ((asciiLo <= 'z') && (asciiHi >= 'a')) - addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a')); - } - } - if (hi >= 0x80) { - UChar unicodeCurr = std::max(lo, (UChar)0x80); - addSortedRange(m_rangesUnicode, unicodeCurr, hi); - - if (m_isCaseInsensitive) { - // we're going to scan along, updating the start of the range - while (unicodeCurr <= hi) { - // Spin forwards over any characters that don't have two cases. - for (; jsc_pcre_ucp_othercase(unicodeCurr) == -1; ++unicodeCurr) { - // if this was the last character in the range, we're done. - if (unicodeCurr == hi) - return; - } - // if we fall through to here, unicodeCurr <= hi & has another case. Get the other case. - UChar rangeStart = unicodeCurr; - UChar otherCurr = jsc_pcre_ucp_othercase(unicodeCurr); - - // If unicodeCurr is not yet hi, check the next char in the range. If it also has another case, - // and if it's other case value is one greater then the othercase value for the current last - // character included in the range, we can include next into the range. - while ((unicodeCurr < hi) && (jsc_pcre_ucp_othercase(unicodeCurr + 1) == (otherCurr + 1))) { - // increment unicodeCurr; it points to the end of the range. - // increment otherCurr, due to the check above other for next must be 1 greater than the currrent other value. - ++unicodeCurr; - ++otherCurr; - } - - // otherChar is the last in the range of other case chars, calculate offset to get back to the start. - addSortedRange(m_rangesUnicode, otherCurr-(unicodeCurr-rangeStart), otherCurr); - - // unicodeCurr has been added, move on to the next char. - ++unicodeCurr; - } - } - } - } else if (ch == '-') - // EXAMPLE: parsing [-a-c], the second '-' reaches this case - the hyphen is treated as potentially indicating a range. - m_isPendingDash = true; - else { - // EXAMPLE: Parsing [-a-c], the 'a' reaches this case - we repace the previously buffered char with the 'a'. - flush(); - m_charBuffer = ch; - } - } else - // EXAMPLE: Parsing [-a-c], the first hyphen reaches this case - there is no buffered character - // (the hyphen not treated as a special character in this case, same handling for any char). - m_charBuffer = ch; -} - -// When a character is added to the set we do not immediately add it to the arrays, in case it is actually defining a range. -// When we have determined the character is not used in specifing a range it is added, in a sorted fashion, to the appropriate -// array (either ascii or unicode). -// If the pattern is case insensitive we add entries for both cases. -void CharacterClassConstructor::flush() -{ - if (m_charBuffer != -1) { - if (m_charBuffer <= 0x7f) { - if (m_isCaseInsensitive && isASCIILower(m_charBuffer)) - addSorted(m_matches, toASCIIUpper(m_charBuffer)); - addSorted(m_matches, m_charBuffer); - if (m_isCaseInsensitive && isASCIIUpper(m_charBuffer)) - addSorted(m_matches, toASCIILower(m_charBuffer)); - } else { - addSorted(m_matchesUnicode, m_charBuffer); - if (m_isCaseInsensitive) { - int other = jsc_pcre_ucp_othercase(m_charBuffer); - if (other != -1) - addSorted(m_matchesUnicode, other); - } - } - m_charBuffer = -1; - } - - if (m_isPendingDash) { - addSorted(m_matches, '-'); - m_isPendingDash = false; - } -} - -void CharacterClassConstructor::append(const CharacterClass& other) -{ - // [x-\s] will add, 'x', '-', and all unicode spaces to new class (same as [x\s-]). - // Need to check the spec, really, but think this matches PCRE behaviour. - flush(); - - if (other.numMatches) { - for (size_t i = 0; i < other.numMatches; ++i) - addSorted(m_matches, other.matches[i]); - } - if (other.numRanges) { - for (size_t i = 0; i < other.numRanges; ++i) - addSortedRange(m_ranges, other.ranges[i].begin, other.ranges[i].end); - } - if (other.numMatchesUnicode) { - for (size_t i = 0; i < other.numMatchesUnicode; ++i) - addSorted(m_matchesUnicode, other.matchesUnicode[i]); - } - if (other.numRangesUnicode) { - for (size_t i = 0; i < other.numRangesUnicode; ++i) - addSortedRange(m_rangesUnicode, other.rangesUnicode[i].begin, other.rangesUnicode[i].end); - } -} - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/CharacterClassConstructor.h b/JavaScriptCore/wrec/CharacterClassConstructor.h deleted file mode 100644 index 581733d..0000000 --- a/JavaScriptCore/wrec/CharacterClassConstructor.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2008 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 CharacterClassConstructor_h -#define CharacterClassConstructor_h - -#include <wtf/Platform.h> - -#if ENABLE(WREC) - -#include "CharacterClass.h" -#include <wtf/AlwaysInline.h> -#include <wtf/Vector.h> -#include <wtf/unicode/Unicode.h> - -namespace JSC { namespace WREC { - - class CharacterClassConstructor { - public: - CharacterClassConstructor(bool isCaseInsensitive) - : m_charBuffer(-1) - , m_isPendingDash(false) - , m_isCaseInsensitive(isCaseInsensitive) - , m_isUpsideDown(false) - { - } - - void flush(); - - // We need to flush prior to an escaped hyphen to prevent it as being treated as indicating - // a range, e.g. [a\-c] we flush prior to adding the hyphen so that this is not treated as - // [a-c]. However, we do not want to flush if we have already seen a non escaped hyphen - - // e.g. [+-\-] should be treated the same as [+--], producing a range that will also match - // a comma. - void flushBeforeEscapedHyphen() - { - if (!m_isPendingDash) - flush(); - } - - void put(UChar ch); - void append(const CharacterClass& other); - - bool isUpsideDown() { return m_isUpsideDown; } - - ALWAYS_INLINE CharacterClass charClass() - { - CharacterClass newCharClass = { - m_matches.begin(), m_matches.size(), - m_ranges.begin(), m_ranges.size(), - m_matchesUnicode.begin(), m_matchesUnicode.size(), - m_rangesUnicode.begin(), m_rangesUnicode.size(), - }; - - return newCharClass; - } - - private: - void addSorted(Vector<UChar>& matches, UChar ch); - void addSortedRange(Vector<CharacterRange>& ranges, UChar lo, UChar hi); - - int m_charBuffer; - bool m_isPendingDash; - bool m_isCaseInsensitive; - bool m_isUpsideDown; - - Vector<UChar> m_matches; - Vector<CharacterRange> m_ranges; - Vector<UChar> m_matchesUnicode; - Vector<CharacterRange> m_rangesUnicode; - }; - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) - -#endif // CharacterClassConstructor_h diff --git a/JavaScriptCore/wrec/Escapes.h b/JavaScriptCore/wrec/Escapes.h deleted file mode 100644 index 16c1d6f..0000000 --- a/JavaScriptCore/wrec/Escapes.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2008 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 Escapes_h -#define Escapes_h - -#include <wtf/Platform.h> - -#if ENABLE(WREC) - -#include <wtf/Assertions.h> - -namespace JSC { namespace WREC { - - class CharacterClass; - - class Escape { - public: - enum Type { - PatternCharacter, - CharacterClass, - Backreference, - WordBoundaryAssertion, - Error, - }; - - Escape(Type type) - : m_type(type) - { - } - - Type type() const { return m_type; } - - private: - Type m_type; - - protected: - // Used by subclasses to store data. - union { - int i; - const WREC::CharacterClass* c; - } m_u; - bool m_invert; - }; - - class PatternCharacterEscape : public Escape { - public: - static const PatternCharacterEscape& cast(const Escape& escape) - { - ASSERT(escape.type() == PatternCharacter); - return static_cast<const PatternCharacterEscape&>(escape); - } - - PatternCharacterEscape(int character) - : Escape(PatternCharacter) - { - m_u.i = character; - } - - operator Escape() const { return *this; } - - int character() const { return m_u.i; } - }; - - class CharacterClassEscape : public Escape { - public: - static const CharacterClassEscape& cast(const Escape& escape) - { - ASSERT(escape.type() == CharacterClass); - return static_cast<const CharacterClassEscape&>(escape); - } - - CharacterClassEscape(const WREC::CharacterClass& characterClass, bool invert) - : Escape(CharacterClass) - { - m_u.c = &characterClass; - m_invert = invert; - } - - operator Escape() { return *this; } - - const WREC::CharacterClass& characterClass() const { return *m_u.c; } - bool invert() const { return m_invert; } - }; - - class BackreferenceEscape : public Escape { - public: - static const BackreferenceEscape& cast(const Escape& escape) - { - ASSERT(escape.type() == Backreference); - return static_cast<const BackreferenceEscape&>(escape); - } - - BackreferenceEscape(int subpatternId) - : Escape(Backreference) - { - m_u.i = subpatternId; - } - - operator Escape() const { return *this; } - - int subpatternId() const { return m_u.i; } - }; - - class WordBoundaryAssertionEscape : public Escape { - public: - static const WordBoundaryAssertionEscape& cast(const Escape& escape) - { - ASSERT(escape.type() == WordBoundaryAssertion); - return static_cast<const WordBoundaryAssertionEscape&>(escape); - } - - WordBoundaryAssertionEscape(bool invert) - : Escape(WordBoundaryAssertion) - { - m_invert = invert; - } - - operator Escape() const { return *this; } - - bool invert() const { return m_invert; } - }; - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) - -#endif // Escapes_h diff --git a/JavaScriptCore/wrec/WREC.cpp b/JavaScriptCore/wrec/WREC.cpp deleted file mode 100644 index 145a1ce..0000000 --- a/JavaScriptCore/wrec/WREC.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2008 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 "WREC.h" - -#if ENABLE(WREC) - -#include "CharacterClassConstructor.h" -#include "Interpreter.h" -#include "JSGlobalObject.h" -#include "RegisterFile.h" -#include "WRECFunctors.h" -#include "WRECParser.h" -#include "pcre_internal.h" - -using namespace WTF; - -namespace JSC { namespace WREC { - -CompiledRegExp Generator::compileRegExp(JSGlobalData* globalData, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, RefPtr<ExecutablePool>& pool, bool ignoreCase, bool multiline) -{ - if (pattern.size() > MAX_PATTERN_SIZE) { - *error_ptr = "regular expression too large"; - return 0; - } - - Parser parser(pattern, ignoreCase, multiline); - Generator& generator = parser.generator(); - MacroAssembler::JumpList failures; - MacroAssembler::Jump endOfInput; - - generator.generateEnter(); - generator.generateSaveIndex(); - - Label beginPattern(&generator); - parser.parsePattern(failures); - generator.generateReturnSuccess(); - - failures.link(&generator); - generator.generateIncrementIndex(&endOfInput); - parser.parsePattern(failures); - generator.generateReturnSuccess(); - - failures.link(&generator); - generator.generateIncrementIndex(); - generator.generateJumpIfNotEndOfInput(beginPattern); - - endOfInput.link(&generator); - generator.generateReturnFailure(); - - if (parser.error()) { - *error_ptr = parser.syntaxError(); // NULL in the case of patterns that WREC doesn't support yet. - return 0; - } - - *numSubpatterns_ptr = parser.numSubpatterns(); - pool = globalData->executableAllocator.poolForSize(generator.size()); - return reinterpret_cast<CompiledRegExp>(generator.copyCode(pool.get())); -} - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECFunctors.cpp b/JavaScriptCore/wrec/WRECFunctors.cpp deleted file mode 100644 index 5f1674e..0000000 --- a/JavaScriptCore/wrec/WRECFunctors.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2008 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 "WRECFunctors.h" - -#if ENABLE(WREC) - -#include "WRECGenerator.h" - -using namespace WTF; - -namespace JSC { namespace WREC { - -void GeneratePatternCharacterFunctor::generateAtom(Generator* generator, Generator::JumpList& failures) -{ - generator->generatePatternCharacter(failures, m_ch); -} - -void GeneratePatternCharacterFunctor::backtrack(Generator* generator) -{ - generator->generateBacktrack1(); -} - -void GenerateCharacterClassFunctor::generateAtom(Generator* generator, Generator::JumpList& failures) -{ - generator->generateCharacterClass(failures, *m_charClass, m_invert); -} - -void GenerateCharacterClassFunctor::backtrack(Generator* generator) -{ - generator->generateBacktrack1(); -} - -void GenerateBackreferenceFunctor::generateAtom(Generator* generator, Generator::JumpList& failures) -{ - generator->generateBackreference(failures, m_subpatternId); -} - -void GenerateBackreferenceFunctor::backtrack(Generator* generator) -{ - generator->generateBacktrackBackreference(m_subpatternId); -} - -void GenerateParenthesesNonGreedyFunctor::generateAtom(Generator* generator, Generator::JumpList& failures) -{ - generator->generateParenthesesNonGreedy(failures, m_start, m_success, m_fail); -} - -void GenerateParenthesesNonGreedyFunctor::backtrack(Generator*) -{ - // FIXME: do something about this. - CRASH(); -} - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECFunctors.h b/JavaScriptCore/wrec/WRECFunctors.h deleted file mode 100644 index 610ce55..0000000 --- a/JavaScriptCore/wrec/WRECFunctors.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2008 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 <wtf/Platform.h> - -#if ENABLE(WREC) - -#include "WRECGenerator.h" -#include <wtf/unicode/Unicode.h> - -namespace JSC { namespace WREC { - - struct CharacterClass; - - class GenerateAtomFunctor { - public: - virtual ~GenerateAtomFunctor() {} - - virtual void generateAtom(Generator*, Generator::JumpList&) = 0; - virtual void backtrack(Generator*) = 0; - }; - - class GeneratePatternCharacterFunctor : public GenerateAtomFunctor { - public: - GeneratePatternCharacterFunctor(const UChar ch) - : m_ch(ch) - { - } - - virtual void generateAtom(Generator*, Generator::JumpList&); - virtual void backtrack(Generator*); - - private: - const UChar m_ch; - }; - - class GenerateCharacterClassFunctor : public GenerateAtomFunctor { - public: - GenerateCharacterClassFunctor(const CharacterClass* charClass, bool invert) - : m_charClass(charClass) - , m_invert(invert) - { - } - - virtual void generateAtom(Generator*, Generator::JumpList&); - virtual void backtrack(Generator*); - - private: - const CharacterClass* m_charClass; - bool m_invert; - }; - - class GenerateBackreferenceFunctor : public GenerateAtomFunctor { - public: - GenerateBackreferenceFunctor(unsigned subpatternId) - : m_subpatternId(subpatternId) - { - } - - virtual void generateAtom(Generator*, Generator::JumpList&); - virtual void backtrack(Generator*); - - private: - unsigned m_subpatternId; - }; - - class GenerateParenthesesNonGreedyFunctor : public GenerateAtomFunctor { - public: - GenerateParenthesesNonGreedyFunctor(Generator::Label start, Generator::Jump success, Generator::Jump fail) - : m_start(start) - , m_success(success) - , m_fail(fail) - { - } - - virtual void generateAtom(Generator*, Generator::JumpList&); - virtual void backtrack(Generator*); - - private: - Generator::Label m_start; - Generator::Jump m_success; - Generator::Jump m_fail; - }; - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECGenerator.cpp b/JavaScriptCore/wrec/WRECGenerator.cpp deleted file mode 100644 index 7105984..0000000 --- a/JavaScriptCore/wrec/WRECGenerator.cpp +++ /dev/null @@ -1,653 +0,0 @@ -/* - * Copyright (C) 2008 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 "WREC.h" - -#if ENABLE(WREC) - -#include "CharacterClassConstructor.h" -#include "Interpreter.h" -#include "WRECFunctors.h" -#include "WRECParser.h" -#include "pcre_internal.h" - -using namespace WTF; - -namespace JSC { namespace WREC { - -void Generator::generateEnter() -{ -#if CPU(X86) - // On x86 edi & esi are callee preserved registers. - push(X86Registers::edi); - push(X86Registers::esi); - -#if COMPILER(MSVC) - // Move the arguments into registers. - peek(input, 3); - peek(index, 4); - peek(length, 5); - peek(output, 6); -#else - // On gcc the function is regparm(3), so the input, index, and length registers - // (eax, edx, and ecx respectively) already contain the appropriate values. - // Just load the fourth argument (output) into edi - peek(output, 3); -#endif -#endif -} - -void Generator::generateReturnSuccess() -{ - ASSERT(returnRegister != index); - ASSERT(returnRegister != output); - - // Set return value. - pop(returnRegister); // match begin - store32(returnRegister, output); - store32(index, Address(output, 4)); // match end - - // Restore callee save registers. -#if CPU(X86) - pop(X86Registers::esi); - pop(X86Registers::edi); -#endif - ret(); -} - -void Generator::generateSaveIndex() -{ - push(index); -} - -void Generator::generateIncrementIndex(Jump* failure) -{ - peek(index); - if (failure) - *failure = branch32(Equal, length, index); - add32(Imm32(1), index); - poke(index); -} - -void Generator::generateLoadCharacter(JumpList& failures) -{ - failures.append(branch32(Equal, length, index)); - load16(BaseIndex(input, index, TimesTwo), character); -} - -// For the sake of end-of-line assertions, we treat one-past-the-end as if it -// were part of the input string. -void Generator::generateJumpIfNotEndOfInput(Label target) -{ - branch32(LessThanOrEqual, index, length, target); -} - -void Generator::generateReturnFailure() -{ - pop(); - move(Imm32(-1), returnRegister); - -#if CPU(X86) - pop(X86Registers::esi); - pop(X86Registers::edi); -#endif - ret(); -} - -void Generator::generateBacktrack1() -{ - sub32(Imm32(1), index); -} - -void Generator::generateBacktrackBackreference(unsigned subpatternId) -{ - sub32(Address(output, (2 * subpatternId + 1) * sizeof(int)), index); - add32(Address(output, (2 * subpatternId) * sizeof(int)), index); -} - -void Generator::generateBackreferenceQuantifier(JumpList& failures, Quantifier::Type quantifierType, unsigned subpatternId, unsigned min, unsigned max) -{ - GenerateBackreferenceFunctor functor(subpatternId); - - load32(Address(output, (2 * subpatternId) * sizeof(int)), character); - Jump skipIfEmpty = branch32(Equal, Address(output, ((2 * subpatternId) + 1) * sizeof(int)), character); - - ASSERT(quantifierType == Quantifier::Greedy || quantifierType == Quantifier::NonGreedy); - if (quantifierType == Quantifier::Greedy) - generateGreedyQuantifier(failures, functor, min, max); - else - generateNonGreedyQuantifier(failures, functor, min, max); - - skipIfEmpty.link(this); -} - -void Generator::generateNonGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max) -{ - JumpList atomFailedList; - JumpList alternativeFailedList; - - // (0) Setup: Save, then init repeatCount. - push(repeatCount); - move(Imm32(0), repeatCount); - Jump start = jump(); - - // (4) Quantifier failed: No more atom reading possible. - Label quantifierFailed(this); - pop(repeatCount); - failures.append(jump()); - - // (3) Alternative failed: If we can, read another atom, then fall through to (2) to try again. - Label alternativeFailed(this); - pop(index); - if (max != Quantifier::Infinity) - branch32(Equal, repeatCount, Imm32(max), quantifierFailed); - - // (1) Read an atom. - if (min) - start.link(this); - Label readAtom(this); - functor.generateAtom(this, atomFailedList); - atomFailedList.linkTo(quantifierFailed, this); - add32(Imm32(1), repeatCount); - - // (2) Keep reading if we're under the minimum. - if (min > 1) - branch32(LessThan, repeatCount, Imm32(min), readAtom); - - // (3) Test the rest of the alternative. - if (!min) - start.link(this); - push(index); - m_parser.parseAlternative(alternativeFailedList); - alternativeFailedList.linkTo(alternativeFailed, this); - - pop(); - pop(repeatCount); -} - -void Generator::generateGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max) -{ - if (!max) - return; - - JumpList doneReadingAtomsList; - JumpList alternativeFailedList; - - // (0) Setup: Save, then init repeatCount. - push(repeatCount); - move(Imm32(0), repeatCount); - - // (1) Greedily read as many copies of the atom as possible, then jump to (2). - Label readAtom(this); - functor.generateAtom(this, doneReadingAtomsList); - add32(Imm32(1), repeatCount); - if (max == Quantifier::Infinity) - jump(readAtom); - else if (max == 1) - doneReadingAtomsList.append(jump()); - else { - branch32(NotEqual, repeatCount, Imm32(max), readAtom); - doneReadingAtomsList.append(jump()); - } - - // (5) Quantifier failed: No more backtracking possible. - Label quantifierFailed(this); - pop(repeatCount); - failures.append(jump()); - - // (4) Alternative failed: Backtrack, then fall through to (2) to try again. - Label alternativeFailed(this); - pop(index); - functor.backtrack(this); - sub32(Imm32(1), repeatCount); - - // (2) Verify that we have enough atoms. - doneReadingAtomsList.link(this); - branch32(LessThan, repeatCount, Imm32(min), quantifierFailed); - - // (3) Test the rest of the alternative. - push(index); - m_parser.parseAlternative(alternativeFailedList); - alternativeFailedList.linkTo(alternativeFailed, this); - - pop(); - pop(repeatCount); -} - -void Generator::generatePatternCharacterSequence(JumpList& failures, int* sequence, size_t count) -{ - for (size_t i = 0; i < count;) { - if (i < count - 1) { - if (generatePatternCharacterPair(failures, sequence[i], sequence[i + 1])) { - i += 2; - continue; - } - } - - generatePatternCharacter(failures, sequence[i]); - ++i; - } -} - -bool Generator::generatePatternCharacterPair(JumpList& failures, int ch1, int ch2) -{ - if (m_parser.ignoreCase()) { - // Non-trivial case folding requires more than one test, so we can't - // test as a pair with an adjacent character. - if (!isASCII(ch1) && Unicode::toLower(ch1) != Unicode::toUpper(ch1)) - return false; - if (!isASCII(ch2) && Unicode::toLower(ch2) != Unicode::toUpper(ch2)) - return false; - } - - // Optimistically consume 2 characters. - add32(Imm32(2), index); - failures.append(branch32(GreaterThan, index, length)); - - // Load the characters we just consumed, offset -2 characters from index. - load32(BaseIndex(input, index, TimesTwo, -2 * 2), character); - - if (m_parser.ignoreCase()) { - // Convert ASCII alphabet characters to upper case before testing for - // equality. (ASCII non-alphabet characters don't require upper-casing - // because they have no uppercase equivalents. Unicode characters don't - // require upper-casing because we only handle Unicode characters whose - // upper and lower cases are equal.) - int ch1Mask = 0; - if (isASCIIAlpha(ch1)) { - ch1 |= 32; - ch1Mask = 32; - } - - int ch2Mask = 0; - if (isASCIIAlpha(ch2)) { - ch2 |= 32; - ch2Mask = 32; - } - - int mask = ch1Mask | (ch2Mask << 16); - if (mask) - or32(Imm32(mask), character); - } - int pair = ch1 | (ch2 << 16); - - failures.append(branch32(NotEqual, character, Imm32(pair))); - return true; -} - -void Generator::generatePatternCharacter(JumpList& failures, int ch) -{ - generateLoadCharacter(failures); - - // used for unicode case insensitive - bool hasUpper = false; - Jump isUpper; - - // if case insensitive match - if (m_parser.ignoreCase()) { - UChar lower, upper; - - // check for ascii case sensitive characters - if (isASCIIAlpha(ch)) { - or32(Imm32(32), character); - ch |= 32; - } else if (!isASCII(ch) && ((lower = Unicode::toLower(ch)) != (upper = Unicode::toUpper(ch)))) { - // handle unicode case sentitive characters - branch to success on upper - isUpper = branch32(Equal, character, Imm32(upper)); - hasUpper = true; - ch = lower; - } - } - - // checks for ch, or lower case version of ch, if insensitive - failures.append(branch32(NotEqual, character, Imm32((unsigned short)ch))); - - if (m_parser.ignoreCase() && hasUpper) { - // for unicode case insensitive matches, branch here if upper matches. - isUpper.link(this); - } - - // on success consume the char - add32(Imm32(1), index); -} - -void Generator::generateCharacterClassInvertedRange(JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount) -{ - do { - // pick which range we're going to generate - int which = count >> 1; - char lo = ranges[which].begin; - char hi = ranges[which].end; - - // check if there are any ranges or matches below lo. If not, just jl to failure - - // if there is anything else to check, check that first, if it falls through jmp to failure. - if ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) { - Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo)); - - // generate code for all ranges before this one - if (which) - generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount); - - while ((*matchIndex < matchCount) && (matches[*matchIndex] < lo)) { - matchDest.append(branch32(Equal, character, Imm32((unsigned short)matches[*matchIndex]))); - ++*matchIndex; - } - failures.append(jump()); - - loOrAbove.link(this); - } else if (which) { - Jump loOrAbove = branch32(GreaterThanOrEqual, character, Imm32((unsigned short)lo)); - - generateCharacterClassInvertedRange(failures, matchDest, ranges, which, matchIndex, matches, matchCount); - failures.append(jump()); - - loOrAbove.link(this); - } else - failures.append(branch32(LessThan, character, Imm32((unsigned short)lo))); - - while ((*matchIndex < matchCount) && (matches[*matchIndex] <= hi)) - ++*matchIndex; - - matchDest.append(branch32(LessThanOrEqual, character, Imm32((unsigned short)hi))); - // fall through to here, the value is above hi. - - // shuffle along & loop around if there are any more matches to handle. - unsigned next = which + 1; - ranges += next; - count -= next; - } while (count); -} - -void Generator::generateCharacterClassInverted(JumpList& matchDest, const CharacterClass& charClass) -{ - Jump unicodeFail; - if (charClass.numMatchesUnicode || charClass.numRangesUnicode) { - Jump isAscii = branch32(LessThanOrEqual, character, Imm32(0x7f)); - - if (charClass.numMatchesUnicode) { - for (unsigned i = 0; i < charClass.numMatchesUnicode; ++i) { - UChar ch = charClass.matchesUnicode[i]; - matchDest.append(branch32(Equal, character, Imm32(ch))); - } - } - - if (charClass.numRangesUnicode) { - for (unsigned i = 0; i < charClass.numRangesUnicode; ++i) { - UChar lo = charClass.rangesUnicode[i].begin; - UChar hi = charClass.rangesUnicode[i].end; - - Jump below = branch32(LessThan, character, Imm32(lo)); - matchDest.append(branch32(LessThanOrEqual, character, Imm32(hi))); - below.link(this); - } - } - - unicodeFail = jump(); - isAscii.link(this); - } - - if (charClass.numRanges) { - unsigned matchIndex = 0; - JumpList failures; - generateCharacterClassInvertedRange(failures, matchDest, charClass.ranges, charClass.numRanges, &matchIndex, charClass.matches, charClass.numMatches); - while (matchIndex < charClass.numMatches) - matchDest.append(branch32(Equal, character, Imm32((unsigned short)charClass.matches[matchIndex++]))); - - failures.link(this); - } else if (charClass.numMatches) { - // optimization: gather 'a','A' etc back together, can mask & test once. - Vector<char> matchesAZaz; - - for (unsigned i = 0; i < charClass.numMatches; ++i) { - char ch = charClass.matches[i]; - if (m_parser.ignoreCase()) { - if (isASCIILower(ch)) { - matchesAZaz.append(ch); - continue; - } - if (isASCIIUpper(ch)) - continue; - } - matchDest.append(branch32(Equal, character, Imm32((unsigned short)ch))); - } - - if (unsigned countAZaz = matchesAZaz.size()) { - or32(Imm32(32), character); - for (unsigned i = 0; i < countAZaz; ++i) - matchDest.append(branch32(Equal, character, Imm32(matchesAZaz[i]))); - } - } - - if (charClass.numMatchesUnicode || charClass.numRangesUnicode) - unicodeFail.link(this); -} - -void Generator::generateCharacterClass(JumpList& failures, const CharacterClass& charClass, bool invert) -{ - generateLoadCharacter(failures); - - if (invert) - generateCharacterClassInverted(failures, charClass); - else { - JumpList successes; - generateCharacterClassInverted(successes, charClass); - failures.append(jump()); - successes.link(this); - } - - add32(Imm32(1), index); -} - -void Generator::generateParenthesesAssertion(JumpList& failures) -{ - JumpList disjunctionFailed; - - push(index); - m_parser.parseDisjunction(disjunctionFailed); - Jump success = jump(); - - disjunctionFailed.link(this); - pop(index); - failures.append(jump()); - - success.link(this); - pop(index); -} - -void Generator::generateParenthesesInvertedAssertion(JumpList& failures) -{ - JumpList disjunctionFailed; - - push(index); - m_parser.parseDisjunction(disjunctionFailed); - - // If the disjunction succeeded, the inverted assertion failed. - pop(index); - failures.append(jump()); - - // If the disjunction failed, the inverted assertion succeeded. - disjunctionFailed.link(this); - pop(index); -} - -void Generator::generateParenthesesNonGreedy(JumpList& failures, Label start, Jump success, Jump fail) -{ - jump(start); - success.link(this); - failures.append(fail); -} - -Generator::Jump Generator::generateParenthesesResetTrampoline(JumpList& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter) -{ - Jump skip = jump(); - newFailures.link(this); - for (unsigned i = subpatternIdBefore + 1; i <= subpatternIdAfter; ++i) { - store32(Imm32(-1), Address(output, (2 * i) * sizeof(int))); - store32(Imm32(-1), Address(output, (2 * i + 1) * sizeof(int))); - } - - Jump newFailJump = jump(); - skip.link(this); - - return newFailJump; -} - -void Generator::generateAssertionBOL(JumpList& failures) -{ - if (m_parser.multiline()) { - JumpList previousIsNewline; - - // begin of input == success - previousIsNewline.append(branch32(Equal, index, Imm32(0))); - - // now check prev char against newline characters. - load16(BaseIndex(input, index, TimesTwo, -2), character); - generateCharacterClassInverted(previousIsNewline, CharacterClass::newline()); - - failures.append(jump()); - - previousIsNewline.link(this); - } else - failures.append(branch32(NotEqual, index, Imm32(0))); -} - -void Generator::generateAssertionEOL(JumpList& failures) -{ - if (m_parser.multiline()) { - JumpList nextIsNewline; - - generateLoadCharacter(nextIsNewline); // end of input == success - generateCharacterClassInverted(nextIsNewline, CharacterClass::newline()); - failures.append(jump()); - nextIsNewline.link(this); - } else { - failures.append(branch32(NotEqual, length, index)); - } -} - -void Generator::generateAssertionWordBoundary(JumpList& failures, bool invert) -{ - JumpList wordBoundary; - JumpList notWordBoundary; - - // (1) Check if the previous value was a word char - - // (1.1) check for begin of input - Jump atBegin = branch32(Equal, index, Imm32(0)); - // (1.2) load the last char, and chck if is word character - load16(BaseIndex(input, index, TimesTwo, -2), character); - JumpList previousIsWord; - generateCharacterClassInverted(previousIsWord, CharacterClass::wordchar()); - // (1.3) if we get here, previous is not a word char - atBegin.link(this); - - // (2) Handle situation where previous was NOT a \w - - generateLoadCharacter(notWordBoundary); - generateCharacterClassInverted(wordBoundary, CharacterClass::wordchar()); - // (2.1) If we get here, neither chars are word chars - notWordBoundary.append(jump()); - - // (3) Handle situation where previous was a \w - - // (3.0) link success in first match to here - previousIsWord.link(this); - generateLoadCharacter(wordBoundary); - generateCharacterClassInverted(notWordBoundary, CharacterClass::wordchar()); - // (3.1) If we get here, this is an end of a word, within the input. - - // (4) Link everything up - - if (invert) { - // handle the fall through case - wordBoundary.append(jump()); - - // looking for non word boundaries, so link boundary fails to here. - notWordBoundary.link(this); - - failures.append(wordBoundary); - } else { - // looking for word boundaries, so link successes here. - wordBoundary.link(this); - - failures.append(notWordBoundary); - } -} - -void Generator::generateBackreference(JumpList& failures, unsigned subpatternId) -{ - push(index); - push(repeatCount); - - // get the start pos of the backref into repeatCount (multipurpose!) - load32(Address(output, (2 * subpatternId) * sizeof(int)), repeatCount); - - Jump skipIncrement = jump(); - Label topOfLoop(this); - - add32(Imm32(1), index); - add32(Imm32(1), repeatCount); - skipIncrement.link(this); - - // check if we're at the end of backref (if we are, success!) - Jump endOfBackRef = branch32(Equal, Address(output, ((2 * subpatternId) + 1) * sizeof(int)), repeatCount); - - load16(BaseIndex(input, repeatCount, MacroAssembler::TimesTwo), character); - - // check if we've run out of input (this would be a can o'fail) - Jump endOfInput = branch32(Equal, length, index); - - branch16(Equal, BaseIndex(input, index, TimesTwo), character, topOfLoop); - - endOfInput.link(this); - - // Failure - pop(repeatCount); - pop(index); - failures.append(jump()); - - // Success - endOfBackRef.link(this); - pop(repeatCount); - pop(); -} - -void Generator::terminateAlternative(JumpList& successes, JumpList& failures) -{ - successes.append(jump()); - - failures.link(this); - peek(index); -} - -void Generator::terminateDisjunction(JumpList& successes) -{ - successes.link(this); -} - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECGenerator.h b/JavaScriptCore/wrec/WRECGenerator.h deleted file mode 100644 index d707a6e..0000000 --- a/JavaScriptCore/wrec/WRECGenerator.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2008 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 WRECGenerator_h -#define WRECGenerator_h - -#include <wtf/Platform.h> - -#if ENABLE(WREC) - -#include "Quantifier.h" -#include "MacroAssembler.h" -#include <wtf/ASCIICType.h> -#include <wtf/unicode/Unicode.h> -#include "WREC.h" - -namespace JSC { - - class JSGlobalData; - - namespace WREC { - - class CharacterRange; - class GenerateAtomFunctor; - class Parser; - struct CharacterClass; - - class Generator : private MacroAssembler { - public: - using MacroAssembler::Jump; - using MacroAssembler::JumpList; - using MacroAssembler::Label; - - enum ParenthesesType { Capturing, NonCapturing, Assertion, InvertedAssertion, Error }; - - static CompiledRegExp compileRegExp(JSGlobalData*, const UString& pattern, unsigned* numSubpatterns_ptr, const char** error_ptr, RefPtr<ExecutablePool>& pool, bool ignoreCase = false, bool multiline = false); - - Generator(Parser& parser) - : m_parser(parser) - { - } - -#if CPU(X86) - static const RegisterID input = X86Registers::eax; - static const RegisterID index = X86Registers::edx; - static const RegisterID length = X86Registers::ecx; - static const RegisterID output = X86Registers::edi; - - static const RegisterID character = X86Registers::esi; - static const RegisterID repeatCount = X86Registers::ebx; // How many times the current atom repeats in the current match. - - static const RegisterID returnRegister = X86Registers::eax; -#endif -#if CPU(X86_64) - static const RegisterID input = X86Registers::edi; - static const RegisterID index = X86Registers::esi; - static const RegisterID length = X86Registers::edx; - static const RegisterID output = X86Registers::ecx; - - static const RegisterID character = X86Registers::eax; - static const RegisterID repeatCount = X86Registers::ebx; // How many times the current atom repeats in the current match. - - static const RegisterID returnRegister = X86Registers::eax; -#endif - - void generateEnter(); - void generateSaveIndex(); - void generateIncrementIndex(Jump* failure = 0); - void generateLoadCharacter(JumpList& failures); - void generateJumpIfNotEndOfInput(Label); - void generateReturnSuccess(); - void generateReturnFailure(); - - void generateGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max); - void generateNonGreedyQuantifier(JumpList& failures, GenerateAtomFunctor& functor, unsigned min, unsigned max); - void generateBacktrack1(); - void generateBacktrackBackreference(unsigned subpatternId); - void generateCharacterClass(JumpList& failures, const CharacterClass& charClass, bool invert); - void generateCharacterClassInverted(JumpList& failures, const CharacterClass& charClass); - void generateCharacterClassInvertedRange(JumpList& failures, JumpList& matchDest, const CharacterRange* ranges, unsigned count, unsigned* matchIndex, const UChar* matches, unsigned matchCount); - void generatePatternCharacter(JumpList& failures, int ch); - void generatePatternCharacterSequence(JumpList& failures, int* sequence, size_t count); - void generateAssertionWordBoundary(JumpList& failures, bool invert); - void generateAssertionBOL(JumpList& failures); - void generateAssertionEOL(JumpList& failures); - void generateBackreference(JumpList& failures, unsigned subpatternID); - void generateBackreferenceQuantifier(JumpList& failures, Quantifier::Type quantifierType, unsigned subpatternId, unsigned min, unsigned max); - void generateParenthesesAssertion(JumpList& failures); - void generateParenthesesInvertedAssertion(JumpList& failures); - Jump generateParenthesesResetTrampoline(JumpList& newFailures, unsigned subpatternIdBefore, unsigned subpatternIdAfter); - void generateParenthesesNonGreedy(JumpList& failures, Label start, Jump success, Jump fail); - - void terminateAlternative(JumpList& successes, JumpList& failures); - void terminateDisjunction(JumpList& successes); - - private: - bool generatePatternCharacterPair(JumpList& failures, int ch1, int ch2); - - Parser& m_parser; - }; - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) - -#endif // WRECGenerator_h diff --git a/JavaScriptCore/wrec/WRECParser.cpp b/JavaScriptCore/wrec/WRECParser.cpp deleted file mode 100644 index 1709bf9..0000000 --- a/JavaScriptCore/wrec/WRECParser.cpp +++ /dev/null @@ -1,643 +0,0 @@ -/* - * Copyright (C) 2008 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 "WRECParser.h" - -#if ENABLE(WREC) - -#include "CharacterClassConstructor.h" -#include "WRECFunctors.h" - -using namespace WTF; - -namespace JSC { namespace WREC { - -// These error messages match the error messages used by PCRE. -const char* Parser::QuantifierOutOfOrder = "numbers out of order in {} quantifier"; -const char* Parser::QuantifierWithoutAtom = "nothing to repeat"; -const char* Parser::ParenthesesUnmatched = "unmatched parentheses"; -const char* Parser::ParenthesesTypeInvalid = "unrecognized character after (?"; -const char* Parser::ParenthesesNotSupported = ""; // Not a user-visible syntax error -- just signals a syntax that WREC doesn't support yet. -const char* Parser::CharacterClassUnmatched = "missing terminating ] for character class"; -const char* Parser::CharacterClassOutOfOrder = "range out of order in character class"; -const char* Parser::EscapeUnterminated = "\\ at end of pattern"; - -class PatternCharacterSequence { -typedef Generator::JumpList JumpList; - -public: - PatternCharacterSequence(Generator& generator, JumpList& failures) - : m_generator(generator) - , m_failures(failures) - { - } - - size_t size() { return m_sequence.size(); } - - void append(int ch) - { - m_sequence.append(ch); - } - - void flush() - { - if (!m_sequence.size()) - return; - - m_generator.generatePatternCharacterSequence(m_failures, m_sequence.begin(), m_sequence.size()); - m_sequence.clear(); - } - - void flush(const Quantifier& quantifier) - { - if (!m_sequence.size()) - return; - - m_generator.generatePatternCharacterSequence(m_failures, m_sequence.begin(), m_sequence.size() - 1); - - switch (quantifier.type) { - case Quantifier::None: - case Quantifier::Error: - ASSERT_NOT_REACHED(); - break; - - case Quantifier::Greedy: { - GeneratePatternCharacterFunctor functor(m_sequence.last()); - m_generator.generateGreedyQuantifier(m_failures, functor, quantifier.min, quantifier.max); - break; - } - - case Quantifier::NonGreedy: { - GeneratePatternCharacterFunctor functor(m_sequence.last()); - m_generator.generateNonGreedyQuantifier(m_failures, functor, quantifier.min, quantifier.max); - break; - } - } - - m_sequence.clear(); - } - -private: - Generator& m_generator; - JumpList& m_failures; - Vector<int, 8> m_sequence; -}; - -ALWAYS_INLINE Quantifier Parser::consumeGreedyQuantifier() -{ - switch (peek()) { - case '?': - consume(); - return Quantifier(Quantifier::Greedy, 0, 1); - - case '*': - consume(); - return Quantifier(Quantifier::Greedy, 0); - - case '+': - consume(); - return Quantifier(Quantifier::Greedy, 1); - - case '{': { - SavedState state(*this); - consume(); - - // Accept: {n}, {n,}, {n,m}. - // Reject: {n,m} where n > m. - // Ignore: Anything else, such as {n, m}. - - if (!peekIsDigit()) { - state.restore(); - return Quantifier(); - } - - unsigned min = consumeNumber(); - unsigned max = min; - - if (peek() == ',') { - consume(); - max = peekIsDigit() ? consumeNumber() : Quantifier::Infinity; - } - - if (peek() != '}') { - state.restore(); - return Quantifier(); - } - consume(); - - if (min > max) { - setError(QuantifierOutOfOrder); - return Quantifier(Quantifier::Error); - } - - return Quantifier(Quantifier::Greedy, min, max); - } - - default: - return Quantifier(); // No quantifier. - } -} - -Quantifier Parser::consumeQuantifier() -{ - Quantifier q = consumeGreedyQuantifier(); - - if ((q.type == Quantifier::Greedy) && (peek() == '?')) { - consume(); - q.type = Quantifier::NonGreedy; - } - - return q; -} - -bool Parser::parseCharacterClassQuantifier(JumpList& failures, const CharacterClass& charClass, bool invert) -{ - Quantifier q = consumeQuantifier(); - - switch (q.type) { - case Quantifier::None: { - m_generator.generateCharacterClass(failures, charClass, invert); - break; - } - - case Quantifier::Greedy: { - GenerateCharacterClassFunctor functor(&charClass, invert); - m_generator.generateGreedyQuantifier(failures, functor, q.min, q.max); - break; - } - - case Quantifier::NonGreedy: { - GenerateCharacterClassFunctor functor(&charClass, invert); - m_generator.generateNonGreedyQuantifier(failures, functor, q.min, q.max); - break; - } - - case Quantifier::Error: - return false; - } - - return true; -} - -bool Parser::parseBackreferenceQuantifier(JumpList& failures, unsigned subpatternId) -{ - Quantifier q = consumeQuantifier(); - - switch (q.type) { - case Quantifier::None: { - m_generator.generateBackreference(failures, subpatternId); - break; - } - - case Quantifier::Greedy: - case Quantifier::NonGreedy: - m_generator.generateBackreferenceQuantifier(failures, q.type, subpatternId, q.min, q.max); - return true; - - case Quantifier::Error: - return false; - } - - return true; -} - -bool Parser::parseParentheses(JumpList& failures) -{ - ParenthesesType type = consumeParenthesesType(); - - // FIXME: WREC originally failed to backtrack correctly in cases such as - // "c".match(/(.*)c/). Now, most parentheses handling is disabled. For - // unsupported parentheses, we fall back on PCRE. - - switch (type) { - case Generator::Assertion: { - m_generator.generateParenthesesAssertion(failures); - - if (consume() != ')') { - setError(ParenthesesUnmatched); - return false; - } - - Quantifier quantifier = consumeQuantifier(); - if (quantifier.type != Quantifier::None && quantifier.min == 0) { - setError(ParenthesesNotSupported); - return false; - } - - return true; - } - case Generator::InvertedAssertion: { - m_generator.generateParenthesesInvertedAssertion(failures); - - if (consume() != ')') { - setError(ParenthesesUnmatched); - return false; - } - - Quantifier quantifier = consumeQuantifier(); - if (quantifier.type != Quantifier::None && quantifier.min == 0) { - setError(ParenthesesNotSupported); - return false; - } - - return true; - } - default: - setError(ParenthesesNotSupported); - return false; - } -} - -bool Parser::parseCharacterClass(JumpList& failures) -{ - bool invert = false; - if (peek() == '^') { - consume(); - invert = true; - } - - CharacterClassConstructor constructor(m_ignoreCase); - - int ch; - while ((ch = peek()) != ']') { - switch (ch) { - case EndOfPattern: - setError(CharacterClassUnmatched); - return false; - - case '\\': { - consume(); - Escape escape = consumeEscape(true); - - switch (escape.type()) { - case Escape::PatternCharacter: { - int character = PatternCharacterEscape::cast(escape).character(); - if (character == '-') - constructor.flushBeforeEscapedHyphen(); - constructor.put(character); - break; - } - case Escape::CharacterClass: { - const CharacterClassEscape& characterClassEscape = CharacterClassEscape::cast(escape); - ASSERT(!characterClassEscape.invert()); - constructor.append(characterClassEscape.characterClass()); - break; - } - case Escape::Error: - return false; - case Escape::Backreference: - case Escape::WordBoundaryAssertion: { - ASSERT_NOT_REACHED(); - break; - } - } - break; - } - - default: - consume(); - constructor.put(ch); - } - } - consume(); - - // lazily catch reversed ranges ([z-a])in character classes - if (constructor.isUpsideDown()) { - setError(CharacterClassOutOfOrder); - return false; - } - - constructor.flush(); - CharacterClass charClass = constructor.charClass(); - return parseCharacterClassQuantifier(failures, charClass, invert); -} - -bool Parser::parseNonCharacterEscape(JumpList& failures, const Escape& escape) -{ - switch (escape.type()) { - case Escape::PatternCharacter: - ASSERT_NOT_REACHED(); - return false; - - case Escape::CharacterClass: - return parseCharacterClassQuantifier(failures, CharacterClassEscape::cast(escape).characterClass(), CharacterClassEscape::cast(escape).invert()); - - case Escape::Backreference: - return parseBackreferenceQuantifier(failures, BackreferenceEscape::cast(escape).subpatternId()); - - case Escape::WordBoundaryAssertion: - m_generator.generateAssertionWordBoundary(failures, WordBoundaryAssertionEscape::cast(escape).invert()); - return true; - - case Escape::Error: - return false; - } - - ASSERT_NOT_REACHED(); - return false; -} - -Escape Parser::consumeEscape(bool inCharacterClass) -{ - switch (peek()) { - case EndOfPattern: - setError(EscapeUnterminated); - return Escape(Escape::Error); - - // Assertions - case 'b': - consume(); - if (inCharacterClass) - return PatternCharacterEscape('\b'); - return WordBoundaryAssertionEscape(false); // do not invert - case 'B': - consume(); - if (inCharacterClass) - return PatternCharacterEscape('B'); - return WordBoundaryAssertionEscape(true); // invert - - // CharacterClassEscape - case 'd': - consume(); - return CharacterClassEscape(CharacterClass::digits(), false); - case 's': - consume(); - return CharacterClassEscape(CharacterClass::spaces(), false); - case 'w': - consume(); - return CharacterClassEscape(CharacterClass::wordchar(), false); - case 'D': - consume(); - return inCharacterClass - ? CharacterClassEscape(CharacterClass::nondigits(), false) - : CharacterClassEscape(CharacterClass::digits(), true); - case 'S': - consume(); - return inCharacterClass - ? CharacterClassEscape(CharacterClass::nonspaces(), false) - : CharacterClassEscape(CharacterClass::spaces(), true); - case 'W': - consume(); - return inCharacterClass - ? CharacterClassEscape(CharacterClass::nonwordchar(), false) - : CharacterClassEscape(CharacterClass::wordchar(), true); - - // DecimalEscape - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': { - if (peekDigit() > m_numSubpatterns || inCharacterClass) { - // To match Firefox, we parse an invalid backreference in the range [1-7] - // as an octal escape. - return peekDigit() > 7 ? PatternCharacterEscape('\\') : PatternCharacterEscape(consumeOctal()); - } - - int value = 0; - do { - unsigned newValue = value * 10 + peekDigit(); - if (newValue > m_numSubpatterns) - break; - value = newValue; - consume(); - } while (peekIsDigit()); - - return BackreferenceEscape(value); - } - - // Octal escape - case '0': - consume(); - return PatternCharacterEscape(consumeOctal()); - - // ControlEscape - case 'f': - consume(); - return PatternCharacterEscape('\f'); - case 'n': - consume(); - return PatternCharacterEscape('\n'); - case 'r': - consume(); - return PatternCharacterEscape('\r'); - case 't': - consume(); - return PatternCharacterEscape('\t'); - case 'v': - consume(); - return PatternCharacterEscape('\v'); - - // ControlLetter - case 'c': { - SavedState state(*this); - consume(); - - int control = consume(); - // To match Firefox, inside a character class, we also accept numbers - // and '_' as control characters. - if ((!inCharacterClass && !isASCIIAlpha(control)) || (!isASCIIAlphanumeric(control) && control != '_')) { - state.restore(); - return PatternCharacterEscape('\\'); - } - return PatternCharacterEscape(control & 31); - } - - // HexEscape - case 'x': { - consume(); - - SavedState state(*this); - int x = consumeHex(2); - if (x == -1) { - state.restore(); - return PatternCharacterEscape('x'); - } - return PatternCharacterEscape(x); - } - - // UnicodeEscape - case 'u': { - consume(); - - SavedState state(*this); - int x = consumeHex(4); - if (x == -1) { - state.restore(); - return PatternCharacterEscape('u'); - } - return PatternCharacterEscape(x); - } - - // IdentityEscape - default: - return PatternCharacterEscape(consume()); - } -} - -void Parser::parseAlternative(JumpList& failures) -{ - PatternCharacterSequence sequence(m_generator, failures); - - while (1) { - switch (peek()) { - case EndOfPattern: - case '|': - case ')': - sequence.flush(); - return; - - case '*': - case '+': - case '?': - case '{': { - Quantifier q = consumeQuantifier(); - - if (q.type == Quantifier::None) { - sequence.append(consume()); - continue; - } - - if (q.type == Quantifier::Error) - return; - - if (!sequence.size()) { - setError(QuantifierWithoutAtom); - return; - } - - sequence.flush(q); - continue; - } - - case '^': - consume(); - - sequence.flush(); - m_generator.generateAssertionBOL(failures); - continue; - - case '$': - consume(); - - sequence.flush(); - m_generator.generateAssertionEOL(failures); - continue; - - case '.': - consume(); - - sequence.flush(); - if (!parseCharacterClassQuantifier(failures, CharacterClass::newline(), true)) - return; - continue; - - case '[': - consume(); - - sequence.flush(); - if (!parseCharacterClass(failures)) - return; - continue; - - case '(': - consume(); - - sequence.flush(); - if (!parseParentheses(failures)) - return; - continue; - - case '\\': { - consume(); - - Escape escape = consumeEscape(false); - if (escape.type() == Escape::PatternCharacter) { - sequence.append(PatternCharacterEscape::cast(escape).character()); - continue; - } - - sequence.flush(); - if (!parseNonCharacterEscape(failures, escape)) - return; - continue; - } - - default: - sequence.append(consume()); - continue; - } - } -} - -/* - TOS holds index. -*/ -void Parser::parseDisjunction(JumpList& failures) -{ - parseAlternative(failures); - if (peek() != '|') - return; - - JumpList successes; - do { - consume(); - m_generator.terminateAlternative(successes, failures); - parseAlternative(failures); - } while (peek() == '|'); - - m_generator.terminateDisjunction(successes); -} - -Generator::ParenthesesType Parser::consumeParenthesesType() -{ - if (peek() != '?') - return Generator::Capturing; - consume(); - - switch (consume()) { - case ':': - return Generator::NonCapturing; - - case '=': - return Generator::Assertion; - - case '!': - return Generator::InvertedAssertion; - - default: - setError(ParenthesesTypeInvalid); - return Generator::Error; - } -} - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) diff --git a/JavaScriptCore/wrec/WRECParser.h b/JavaScriptCore/wrec/WRECParser.h deleted file mode 100644 index a3e151b..0000000 --- a/JavaScriptCore/wrec/WRECParser.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (C) 2008 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 Parser_h -#define Parser_h - -#include <wtf/Platform.h> - -#if ENABLE(WREC) - -#include "Escapes.h" -#include "Quantifier.h" -#include "UString.h" -#include "WRECGenerator.h" -#include <wtf/ASCIICType.h> - -namespace JSC { namespace WREC { - - struct CharacterClass; - - class Parser { - typedef Generator::JumpList JumpList; - typedef Generator::ParenthesesType ParenthesesType; - - friend class SavedState; - - public: - Parser(const UString& pattern, bool ignoreCase, bool multiline) - : m_generator(*this) - , m_data(pattern.data()) - , m_size(pattern.size()) - , m_ignoreCase(ignoreCase) - , m_multiline(multiline) - { - reset(); - } - - Generator& generator() { return m_generator; } - - bool ignoreCase() const { return m_ignoreCase; } - bool multiline() const { return m_multiline; } - - void recordSubpattern() { ++m_numSubpatterns; } - unsigned numSubpatterns() const { return m_numSubpatterns; } - - const char* error() const { return m_error; } - const char* syntaxError() const { return m_error == ParenthesesNotSupported ? 0 : m_error; } - - void parsePattern(JumpList& failures) - { - reset(); - - parseDisjunction(failures); - - if (peek() != EndOfPattern) - setError(ParenthesesUnmatched); // Parsing the pattern should fully consume it. - } - - void parseDisjunction(JumpList& failures); - void parseAlternative(JumpList& failures); - bool parseTerm(JumpList& failures); - bool parseNonCharacterEscape(JumpList& failures, const Escape&); - bool parseParentheses(JumpList& failures); - bool parseCharacterClass(JumpList& failures); - bool parseCharacterClassQuantifier(JumpList& failures, const CharacterClass& charClass, bool invert); - bool parseBackreferenceQuantifier(JumpList& failures, unsigned subpatternId); - - private: - class SavedState { - public: - SavedState(Parser& parser) - : m_parser(parser) - , m_index(parser.m_index) - { - } - - void restore() - { - m_parser.m_index = m_index; - } - - private: - Parser& m_parser; - unsigned m_index; - }; - - void reset() - { - m_index = 0; - m_numSubpatterns = 0; - m_error = 0; - } - - void setError(const char* error) - { - if (m_error) - return; - m_error = error; - } - - int peek() - { - if (m_index >= m_size) - return EndOfPattern; - return m_data[m_index]; - } - - int consume() - { - if (m_index >= m_size) - return EndOfPattern; - return m_data[m_index++]; - } - - bool peekIsDigit() - { - return WTF::isASCIIDigit(peek()); - } - - unsigned peekDigit() - { - ASSERT(peekIsDigit()); - return peek() - '0'; - } - - unsigned consumeDigit() - { - ASSERT(peekIsDigit()); - return consume() - '0'; - } - - unsigned consumeNumber() - { - int n = consumeDigit(); - while (peekIsDigit()) { - n *= 10; - n += consumeDigit(); - } - return n; - } - - int consumeHex(int count) - { - int n = 0; - while (count--) { - if (!WTF::isASCIIHexDigit(peek())) - return -1; - n = (n << 4) | WTF::toASCIIHexValue(consume()); - } - return n; - } - - unsigned consumeOctal() - { - unsigned n = 0; - while (n < 32 && WTF::isASCIIOctalDigit(peek())) - n = n * 8 + consumeDigit(); - return n; - } - - ALWAYS_INLINE Quantifier consumeGreedyQuantifier(); - Quantifier consumeQuantifier(); - Escape consumeEscape(bool inCharacterClass); - ParenthesesType consumeParenthesesType(); - - static const int EndOfPattern = -1; - - // Error messages. - static const char* QuantifierOutOfOrder; - static const char* QuantifierWithoutAtom; - static const char* ParenthesesUnmatched; - static const char* ParenthesesTypeInvalid; - static const char* ParenthesesNotSupported; - static const char* CharacterClassUnmatched; - static const char* CharacterClassOutOfOrder; - static const char* EscapeUnterminated; - - Generator m_generator; - const UChar* m_data; - unsigned m_size; - unsigned m_index; - bool m_ignoreCase; - bool m_multiline; - unsigned m_numSubpatterns; - const char* m_error; - }; - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) - -#endif // Parser_h diff --git a/JavaScriptCore/wscript b/JavaScriptCore/wscript index 7caf8b4..61ad1fb 100644 --- a/JavaScriptCore/wscript +++ b/JavaScriptCore/wscript @@ -30,7 +30,7 @@ import commands from settings import * jscore_excludes = ['jsc.cpp', 'ucptable.cpp'] -jscore_excludes.extend(get_excludes(jscore_dir, ['*CF.cpp', '*Symbian.cpp'])) +jscore_excludes.extend(get_excludes(jscore_dir, ['*Brew.cpp', '*CF.cpp', '*Symbian.cpp'])) sources = [] @@ -78,7 +78,7 @@ def build(bld): # 1. A simple program jscore = bld.new_task_gen( features = 'cxx cstaticlib', - includes = '. .. assembler wrec DerivedSources ForwardingHeaders ' + ' '.join(includes), + includes = '. .. assembler DerivedSources ForwardingHeaders ' + ' '.join(includes), source = sources, target = 'jscore', uselib = 'WX ICU ' + get_config(), @@ -89,7 +89,7 @@ def build(bld): obj = bld.new_task_gen( features = 'cxx cprogram', - includes = '. .. assembler wrec DerivedSources ForwardingHeaders ' + ' '.join(includes), + includes = '. .. assembler DerivedSources ForwardingHeaders ' + ' '.join(includes), source = 'jsc.cpp', target = 'jsc', uselib = 'WX ICU ' + get_config(), diff --git a/JavaScriptCore/wtf/ASCIICType.h b/JavaScriptCore/wtf/ASCIICType.h index 0c3c29f..b43bb37 100644 --- a/JavaScriptCore/wtf/ASCIICType.h +++ b/JavaScriptCore/wtf/ASCIICType.h @@ -30,7 +30,6 @@ #define WTF_ASCIICType_h #include <wtf/Assertions.h> -#include <wtf/Platform.h> // The behavior of many of the functions in the <ctype.h> header is dependent // on the current locale. But in the WebKit project, all uses of those functions diff --git a/JavaScriptCore/wtf/AlwaysInline.h b/JavaScriptCore/wtf/AlwaysInline.h index ce27df6..34f8b74 100644 --- a/JavaScriptCore/wtf/AlwaysInline.h +++ b/JavaScriptCore/wtf/AlwaysInline.h @@ -59,9 +59,17 @@ #ifndef NO_RETURN #if COMPILER(GCC) #define NO_RETURN __attribute((__noreturn__)) -#elif COMPILER(RVCT) +#elif COMPILER(MSVC) || COMPILER(RVCT) #define NO_RETURN __declspec(noreturn) #else #define NO_RETURN #endif #endif + +#ifndef NO_RETURN_WITH_VALUE +#if !COMPILER(MSVC) +#define NO_RETURN_WITH_VALUE NO_RETURN +#else +#define NO_RETURN_WITH_VALUE +#endif +#endif diff --git a/JavaScriptCore/wtf/Assertions.h b/JavaScriptCore/wtf/Assertions.h index 0e02af5..df8646f 100644 --- a/JavaScriptCore/wtf/Assertions.h +++ b/JavaScriptCore/wtf/Assertions.h @@ -56,6 +56,7 @@ #endif #ifdef NDEBUG +/* Disable ASSERT* macros in release mode. */ #define ASSERTIONS_DISABLED_DEFAULT 1 #else #define ASSERTIONS_DISABLED_DEFAULT 0 @@ -148,8 +149,14 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann } #endif -/* CRASH -- gets us into the debugger or the crash reporter -- signals are ignored by the crash reporter so we must do better */ +/* CRASH() - Raises a fatal error resulting in program termination and triggering either the debugger or the crash reporter. + Use CRASH() in response to known, unrecoverable errors like out-of-memory. + Macro is enabled in both debug and release mode. + To test for unknown errors and verify assumptions, use ASSERT instead, to avoid impacting performance in release builds. + + Signals are ignored by the crash reporter on OS X so we must do better. +*/ #ifndef CRASH #if OS(SYMBIAN) #define CRASH() do { \ @@ -164,7 +171,11 @@ void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChann #endif #endif -/* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED */ +/* ASSERT, ASSERT_NOT_REACHED, ASSERT_UNUSED + + These macros are compiled out of release builds. + Expressions inside them are evaluated in debug builds only. +*/ #if OS(WINCE) && !PLATFORM(TORCHMOBILE) /* FIXME: We include this here only to avoid a conflict with the ASSERT macro. */ diff --git a/JavaScriptCore/wtf/FastMalloc.cpp b/JavaScriptCore/wtf/FastMalloc.cpp index 90d1e3f..7824159 100644 --- a/JavaScriptCore/wtf/FastMalloc.cpp +++ b/JavaScriptCore/wtf/FastMalloc.cpp @@ -204,6 +204,16 @@ TryMallocReturnValue tryFastZeroedMalloc(size_t n) #if FORCE_SYSTEM_MALLOC +#if PLATFORM(BREWMP) +#include "brew/SystemMallocBrew.h" +#endif + +#if OS(DARWIN) +#include <malloc/malloc.h> +#elif COMPILER(MSVC) +#include <malloc.h> +#endif + namespace WTF { TryMallocReturnValue tryFastMalloc(size_t n) @@ -365,10 +375,21 @@ void releaseFastMallocFreeMemory() { } FastMallocStatistics fastMallocStatistics() { - FastMallocStatistics statistics = { 0, 0, 0, 0 }; + FastMallocStatistics statistics = { 0, 0, 0 }; return statistics; } +size_t fastMallocSize(const void* p) +{ +#if OS(DARWIN) + return malloc_size(p); +#elif COMPILER(MSVC) + return _msize(const_cast<void*>(p)); +#else + return 1; +#endif +} + } // namespace WTF #if OS(DARWIN) @@ -396,7 +417,6 @@ extern "C" const int jscore_fastmalloc_introspection = 0; #include <algorithm> #include <errno.h> #include <limits> -#include <new> #include <pthread.h> #include <stdarg.h> #include <stddef.h> @@ -411,7 +431,7 @@ extern "C" const int jscore_fastmalloc_introspection = 0; #include <windows.h> #endif -#if WTF_CHANGES +#ifdef WTF_CHANGES #if OS(DARWIN) #include "MallocZoneSupport.h" @@ -460,7 +480,7 @@ namespace WTF { #define CHECK_CONDITION ASSERT #if OS(DARWIN) -class Span; +struct Span; class TCMalloc_Central_FreeListPadded; class TCMalloc_PageHeap; class TCMalloc_ThreadCache; @@ -1232,18 +1252,26 @@ template <> class MapSelector<32> { // ------------------------------------------------------------------------- #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY -// The central page heap collects spans of memory that have been deleted but are still committed until they are released -// back to the system. We use a background thread to periodically scan the list of free spans and release some back to the -// system. Every 5 seconds, the background thread wakes up and does the following: -// - Check if we needed to commit memory in the last 5 seconds. If so, skip this scavenge because it's a sign that we are short -// of free committed pages and so we should not release them back to the system yet. -// - Otherwise, go through the list of free spans (from largest to smallest) and release up to a fraction of the free committed pages -// back to the system. -// - If the number of free committed pages reaches kMinimumFreeCommittedPageCount, we can stop the scavenging and block the -// scavenging thread until the number of free committed pages goes above kMinimumFreeCommittedPageCount. - -// Background thread wakes up every 5 seconds to scavenge as long as there is memory available to return to the system. -static const int kScavengeTimerDelayInSeconds = 5; +// The page heap maintains a free list for spans that are no longer in use by +// the central cache or any thread caches. We use a background thread to +// periodically scan the free list and release a percentage of it back to the OS. + +// If free_committed_pages_ exceeds kMinimumFreeCommittedPageCount, the +// background thread: +// - wakes up +// - pauses for kScavengeDelayInSeconds +// - returns to the OS a percentage of the memory that remained unused during +// that pause (kScavengePercentage * min_free_committed_pages_since_last_scavenge_) +// The goal of this strategy is to reduce memory pressure in a timely fashion +// while avoiding thrashing the OS allocator. + +// Time delay before the page heap scavenger will consider returning pages to +// the OS. +static const int kScavengeDelayInSeconds = 2; + +// Approximate percentage of free committed pages to return to the OS in one +// scavenge. +static const float kScavengePercentage = .5f; // Number of free committed pages that we want to keep around. static const size_t kMinimumFreeCommittedPageCount = 512; @@ -1353,8 +1381,9 @@ class TCMalloc_PageHeap { // Number of pages kept in free lists that are still committed. Length free_committed_pages_; - // Number of pages that we committed in the last scavenge wait interval. - Length pages_committed_since_last_scavenge_; + // Minimum number of free committed pages since last scavenge. (Can be 0 if + // we've committed new pages since the last scavenge.) + Length min_free_committed_pages_since_last_scavenge_; #endif bool GrowHeap(Length n); @@ -1399,13 +1428,13 @@ class TCMalloc_PageHeap { void initializeScavenger(); ALWAYS_INLINE void signalScavenger(); void scavenge(); - ALWAYS_INLINE bool shouldContinueScavenging() const; + ALWAYS_INLINE bool shouldScavenge() const; #if !HAVE(DISPATCH_H) - static NO_RETURN void* runScavengerThread(void*); + static NO_RETURN_WITH_VALUE void* runScavengerThread(void*); NO_RETURN void scavengerThread(); - // Keeps track of whether the background thread is actively scavenging memory every kScavengeTimerDelayInSeconds, or + // Keeps track of whether the background thread is actively scavenging memory every kScavengeDelayInSeconds, or // it's blocked waiting for more pages to be deleted. bool m_scavengeThreadActive; @@ -1431,7 +1460,7 @@ void TCMalloc_PageHeap::init() #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY free_committed_pages_ = 0; - pages_committed_since_last_scavenge_ = 0; + min_free_committed_pages_since_last_scavenge_ = 0; #endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY scavenge_counter_ = 0; @@ -1474,7 +1503,7 @@ void* TCMalloc_PageHeap::runScavengerThread(void* context) ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger() { - if (!m_scavengeThreadActive && shouldContinueScavenging()) + if (!m_scavengeThreadActive && shouldScavenge()) pthread_cond_signal(&m_scavengeCondition); } @@ -1484,15 +1513,15 @@ 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_time_t startTime = dispatch_time(DISPATCH_TIME_NOW, kScavengeDelayInSeconds * NSEC_PER_SEC); + dispatch_source_set_timer(m_scavengeTimer, startTime, kScavengeDelayInSeconds * 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()) { + if (!m_scavengingScheduled && shouldScavenge()) { m_scavengingScheduled = true; dispatch_resume(m_scavengeTimer); } @@ -1502,17 +1531,12 @@ ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger() void TCMalloc_PageHeap::scavenge() { - // If we've recently commited pages, our working set is growing, so now is - // not a good time to free pages. - if (pages_committed_since_last_scavenge_ > 0) { - pages_committed_since_last_scavenge_ = 0; - return; - } + size_t pagesToRelease = min_free_committed_pages_since_last_scavenge_ * kScavengePercentage; + size_t targetPageCount = std::max<size_t>(kMinimumFreeCommittedPageCount, free_committed_pages_ - pagesToRelease); - for (int i = kMaxPages; i >= 0 && shouldContinueScavenging(); i--) { + for (int i = kMaxPages; i >= 0 && free_committed_pages_ > targetPageCount; i--) { SpanList* slist = (static_cast<size_t>(i) == kMaxPages) ? &large_ : &free_[i]; - if (!DLL_IsEmpty(&slist->normal)) { - // Release the last span on the normal portion of this list + while (!DLL_IsEmpty(&slist->normal) && free_committed_pages_ > targetPageCount) { Span* s = slist->normal.prev; DLL_Remove(s); ASSERT(!s->decommitted); @@ -1527,11 +1551,10 @@ void TCMalloc_PageHeap::scavenge() } } - ASSERT(!shouldContinueScavenging()); - pages_committed_since_last_scavenge_ = 0; + min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; } -ALWAYS_INLINE bool TCMalloc_PageHeap::shouldContinueScavenging() const +ALWAYS_INLINE bool TCMalloc_PageHeap::shouldScavenge() const { return free_committed_pages_ > kMinimumFreeCommittedPageCount; } @@ -1563,9 +1586,6 @@ inline Span* TCMalloc_PageHeap::New(Length n) { if (result->decommitted) { TCMalloc_SystemCommit(reinterpret_cast<void*>(result->start << kPageShift), static_cast<size_t>(n << kPageShift)); result->decommitted = false; -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - pages_committed_since_last_scavenge_ += n; -#endif } #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY else { @@ -1573,6 +1593,8 @@ inline Span* TCMalloc_PageHeap::New(Length n) { // free committed pages count. ASSERT(free_committed_pages_ >= n); free_committed_pages_ -= n; + if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_) + min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; } #endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY ASSERT(Check()); @@ -1634,9 +1656,6 @@ Span* TCMalloc_PageHeap::AllocLarge(Length n) { if (best->decommitted) { TCMalloc_SystemCommit(reinterpret_cast<void*>(best->start << kPageShift), static_cast<size_t>(n << kPageShift)); best->decommitted = false; -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - pages_committed_since_last_scavenge_ += n; -#endif } #if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY else { @@ -1644,6 +1663,8 @@ Span* TCMalloc_PageHeap::AllocLarge(Length n) { // free committed pages count. ASSERT(free_committed_pages_ >= n); free_committed_pages_ -= n; + if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_) + min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; } #endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY ASSERT(Check()); @@ -1787,6 +1808,8 @@ inline void TCMalloc_PageHeap::Delete(Span* span) { // If the merged span is decommitted, that means we decommitted any neighboring spans that were // committed. Update the free committed pages count. free_committed_pages_ -= neighboringCommittedSpansLength; + if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_) + min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; } else { // If the merged span remains committed, add the deleted span's size to the free committed pages count. free_committed_pages_ += n; @@ -1951,10 +1974,6 @@ bool TCMalloc_PageHeap::GrowHeap(Length n) { } ask = actual_size >> kPageShift; -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - pages_committed_since_last_scavenge_ += ask; -#endif - uint64_t old_system_bytes = system_bytes_; system_bytes_ += (ask << kPageShift); const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; @@ -2352,15 +2371,15 @@ void TCMalloc_PageHeap::scavengerThread() #endif while (1) { - if (!shouldContinueScavenging()) { + if (!shouldScavenge()) { pthread_mutex_lock(&m_scavengeMutex); m_scavengeThreadActive = false; - // Block until there are enough freed pages to release back to the system. + // Block until there are enough free committed pages to release back to the system. pthread_cond_wait(&m_scavengeCondition, &m_scavengeMutex); m_scavengeThreadActive = true; pthread_mutex_unlock(&m_scavengeMutex); } - sleep(kScavengeTimerDelayInSeconds); + sleep(kScavengeDelayInSeconds); { SpinLockHolder h(&pageheap_lock); pageheap->scavenge(); @@ -2377,7 +2396,7 @@ void TCMalloc_PageHeap::periodicScavenge() pageheap->scavenge(); } - if (!shouldContinueScavenging()) { + if (!shouldScavenge()) { m_scavengingScheduled = false; dispatch_suspend(m_scavengeTimer); } @@ -3922,6 +3941,8 @@ static inline void* cpp_alloc(size_t size, bool nothrow) { } } +#if ENABLE(GLOBAL_FASTMALLOC_NEW) + void* operator new(size_t size) { void* p = cpp_alloc(size, false); // We keep this next instruction out of cpp_alloc for a reason: when @@ -3976,6 +3997,8 @@ void operator delete[](void* p, const std::nothrow_t&) __THROW { do_free(p); } +#endif + extern "C" void* memalign(size_t align, size_t size) __THROW { void* result = do_memalign(align, size); MallocHook::InvokeNewHook(result, size); @@ -4091,7 +4114,62 @@ void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride; #endif -#if defined(WTF_CHANGES) && OS(DARWIN) +#ifdef WTF_CHANGES +void releaseFastMallocFreeMemory() +{ + // Flush free pages in the current thread cache back to the page heap. + // Low watermark mechanism in Scavenge() prevents full return on the first pass. + // The second pass flushes everything. + if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPresent()) { + threadCache->Scavenge(); + threadCache->Scavenge(); + } + + SpinLockHolder h(&pageheap_lock); + pageheap->ReleaseFreePages(); +} + +FastMallocStatistics fastMallocStatistics() +{ + FastMallocStatistics statistics; + + SpinLockHolder lockHolder(&pageheap_lock); + statistics.reservedVMBytes = static_cast<size_t>(pageheap->SystemBytes()); + statistics.committedVMBytes = statistics.reservedVMBytes - pageheap->ReturnedBytes(); + + statistics.freeListBytes = 0; + for (unsigned cl = 0; cl < kNumClasses; ++cl) { + const int length = central_cache[cl].length(); + const int tc_length = central_cache[cl].tc_length(); + + statistics.freeListBytes += ByteSizeForClass(cl) * (length + tc_length); + } + for (TCMalloc_ThreadCache* threadCache = thread_heaps; threadCache ; threadCache = threadCache->next_) + statistics.freeListBytes += threadCache->Size(); + + return statistics; +} + +size_t fastMallocSize(const void* ptr) +{ + const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; + Span* span = pageheap->GetDescriptorEnsureSafe(p); + + if (!span || span->free) + return 0; + + for (void* free = span->objects; free != NULL; free = *((void**) free)) { + if (ptr == free) + return 0; + } + + if (size_t cl = span->sizeclass) + return ByteSizeForClass(cl); + + return span->length << kPageShift; +} + +#if OS(DARWIN) class FreeObjectFinder { const RemoteMemoryReader& m_reader; @@ -4377,6 +4455,9 @@ malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enum #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 +#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !OS(IPHONE_OS) + , 0, 0, 0, 0 // These members will not be used unless the zone advertises itself as version seven or higher. +#endif }; } @@ -4408,44 +4489,9 @@ void FastMallocZone::init() static FastMallocZone zone(pageheap, &thread_heaps, static_cast<TCMalloc_Central_FreeListPadded*>(central_cache), &span_allocator, &threadheap_allocator); } -#endif - -#if WTF_CHANGES -void releaseFastMallocFreeMemory() -{ - // Flush free pages in the current thread cache back to the page heap. - // Low watermark mechanism in Scavenge() prevents full return on the first pass. - // The second pass flushes everything. - if (TCMalloc_ThreadCache* threadCache = TCMalloc_ThreadCache::GetCacheIfPresent()) { - threadCache->Scavenge(); - threadCache->Scavenge(); - } - - SpinLockHolder h(&pageheap_lock); - pageheap->ReleaseFreePages(); -} - -FastMallocStatistics fastMallocStatistics() -{ - FastMallocStatistics statistics; - { - SpinLockHolder lockHolder(&pageheap_lock); - statistics.heapSize = static_cast<size_t>(pageheap->SystemBytes()); - statistics.freeSizeInHeap = static_cast<size_t>(pageheap->FreeBytes()); - statistics.returnedSize = pageheap->ReturnedBytes(); - statistics.freeSizeInCaches = 0; - for (TCMalloc_ThreadCache* threadCache = thread_heaps; threadCache ; threadCache = threadCache->next_) - statistics.freeSizeInCaches += threadCache->Size(); - } - for (unsigned cl = 0; cl < kNumClasses; ++cl) { - const int length = central_cache[cl].length(); - const int tc_length = central_cache[cl].tc_length(); - statistics.freeSizeInCaches += ByteSizeForClass(cl) * (length + tc_length); - } - return statistics; -} +#endif // OS(DARWIN) } // namespace WTF -#endif +#endif // WTF_CHANGES #endif // FORCE_SYSTEM_MALLOC diff --git a/JavaScriptCore/wtf/FastMalloc.h b/JavaScriptCore/wtf/FastMalloc.h index 74d4307..1ccd6a6 100644 --- a/JavaScriptCore/wtf/FastMalloc.h +++ b/JavaScriptCore/wtf/FastMalloc.h @@ -34,6 +34,7 @@ namespace WTF { void* fastCalloc(size_t numElements, size_t elementSize); void* fastRealloc(void*, size_t); char* fastStrDup(const char*); + size_t fastMallocSize(const void*); struct TryMallocReturnValue { TryMallocReturnValue(void* data) @@ -82,10 +83,9 @@ namespace WTF { void releaseFastMallocFreeMemory(); struct FastMallocStatistics { - size_t heapSize; - size_t freeSizeInHeap; - size_t freeSizeInCaches; - size_t returnedSize; + size_t reservedVMBytes; + size_t committedVMBytes; + size_t freeListBytes; }; FastMallocStatistics fastMallocStatistics(); @@ -180,16 +180,17 @@ namespace WTF { } // namespace WTF -using WTF::fastMalloc; -using WTF::fastZeroedMalloc; using WTF::fastCalloc; +using WTF::fastFree; +using WTF::fastMalloc; +using WTF::fastMallocSize; using WTF::fastRealloc; -using WTF::tryFastMalloc; -using WTF::tryFastZeroedMalloc; +using WTF::fastStrDup; +using WTF::fastZeroedMalloc; using WTF::tryFastCalloc; +using WTF::tryFastMalloc; using WTF::tryFastRealloc; -using WTF::fastFree; -using WTF::fastStrDup; +using WTF::tryFastZeroedMalloc; #ifndef NDEBUG using WTF::fastMallocForbid; @@ -215,8 +216,7 @@ using WTF::fastMallocAllow; // debug-only code to make sure we don't use the system malloc via the default operator // new by accident. -// We musn't customize the global operator new and delete for the Qt port. -#if !PLATFORM(QT) +#if ENABLE(GLOBAL_FASTMALLOC_NEW) #if COMPILER(MSVC) #pragma warning(push) diff --git a/JavaScriptCore/wtf/HashCountedSet.h b/JavaScriptCore/wtf/HashCountedSet.h index 165eb41..4ed75c5 100644 --- a/JavaScriptCore/wtf/HashCountedSet.h +++ b/JavaScriptCore/wtf/HashCountedSet.h @@ -43,7 +43,7 @@ namespace WTF { int capacity() const; bool isEmpty() const; - // iterators iterate over pairs of values and counts + // Iterators iterate over pairs of values and counts. iterator begin(); iterator end(); const_iterator begin() const; @@ -54,21 +54,21 @@ namespace WTF { bool contains(const ValueType&) const; unsigned count(const ValueType&) const; - // increases the count if an equal value is already present - // the return value is a pair of an interator to the new value's location, - // and a bool that is true if an new entry was added + // Increases the count if an equal value is already present + // the return value is a pair of an interator to the new value's + // location, and a bool that is true if an new entry was added. std::pair<iterator, bool> add(const ValueType&); - // reduces the count of the value, and removes it if count - // goes down to zero - void remove(const ValueType&); - void remove(iterator); + // Reduces the count of the value, and removes it if count + // goes down to zero, returns true if the value is removed. + bool remove(const ValueType&); + bool remove(iterator); - // removes the value, regardless of its count + // Removes the value, regardless of its count. void removeAll(iterator); void removeAll(const ValueType&); - // clears the whole set + // Clears the whole set. void clear(); private: @@ -150,24 +150,27 @@ namespace WTF { } template<typename Value, typename HashFunctions, typename Traits> - inline void HashCountedSet<Value, HashFunctions, Traits>::remove(const ValueType& value) + inline bool HashCountedSet<Value, HashFunctions, Traits>::remove(const ValueType& value) { - remove(find(value)); + return remove(find(value)); } template<typename Value, typename HashFunctions, typename Traits> - inline void HashCountedSet<Value, HashFunctions, Traits>::remove(iterator it) + inline bool HashCountedSet<Value, HashFunctions, Traits>::remove(iterator it) { if (it == end()) - return; + return false; unsigned oldVal = it->second; - ASSERT(oldVal != 0); + ASSERT(oldVal); unsigned newVal = oldVal - 1; - if (newVal == 0) - m_impl.remove(it); - else + if (newVal) { it->second = newVal; + return false; + } + + m_impl.remove(it); + return true; } template<typename Value, typename HashFunctions, typename Traits> diff --git a/JavaScriptCore/wtf/HashMap.h b/JavaScriptCore/wtf/HashMap.h index d63a8d4..09094d1 100644 --- a/JavaScriptCore/wtf/HashMap.h +++ b/JavaScriptCore/wtf/HashMap.h @@ -133,9 +133,10 @@ namespace WTF { 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) + static void translate(ValueType& location, const T& key, const MappedType& mapped, unsigned hashCode) { Translator::translate(location.first, key, hashCode); + location.second = mapped; } }; diff --git a/JavaScriptCore/wtf/MathExtras.h b/JavaScriptCore/wtf/MathExtras.h index 089e8ff..ac9bf60 100644 --- a/JavaScriptCore/wtf/MathExtras.h +++ b/JavaScriptCore/wtf/MathExtras.h @@ -123,6 +123,8 @@ inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); } #if COMPILER(MSVC) +inline long long abs(long long num) { return _abs64(num); } + inline bool isinf(double num) { return !_finite(num) && !_isnan(num); } inline bool isnan(double num) { return !!_isnan(num); } inline bool signbit(double num) { return _copysign(1.0, num) < 0; } diff --git a/JavaScriptCore/wtf/OwnFastMallocPtr.h b/JavaScriptCore/wtf/OwnFastMallocPtr.h index c88235a..8b6cbf4 100644 --- a/JavaScriptCore/wtf/OwnFastMallocPtr.h +++ b/JavaScriptCore/wtf/OwnFastMallocPtr.h @@ -35,7 +35,7 @@ namespace WTF { ~OwnFastMallocPtr() { - fastFree(m_ptr); + fastFree(const_cast<void*>(static_cast<const void*>(const_cast<const T*>(m_ptr)))); } T* get() const { return m_ptr; } diff --git a/JavaScriptCore/wtf/OwnPtr.h b/JavaScriptCore/wtf/OwnPtr.h index b7e62b1..af1684b 100644 --- a/JavaScriptCore/wtf/OwnPtr.h +++ b/JavaScriptCore/wtf/OwnPtr.h @@ -40,7 +40,6 @@ namespace WTF { typedef ValueType* PtrType; explicit OwnPtr(PtrType ptr = 0) : m_ptr(ptr) { } - OwnPtr(std::auto_ptr<ValueType> autoPtr) : m_ptr(autoPtr.release()) { } // See comment in PassOwnPtr.h for why this takes a const reference. template <typename U> OwnPtr(const PassOwnPtr<U>& o); @@ -58,8 +57,6 @@ namespace WTF { // FIXME: This should be renamed to adopt. void set(PtrType ptr) { ASSERT(!ptr || m_ptr != ptr); deleteOwnedPtr(m_ptr); m_ptr = ptr; } - void adopt(std::auto_ptr<ValueType> autoPtr) { ASSERT(!autoPtr.get() || m_ptr != autoPtr.get()); deleteOwnedPtr(m_ptr); m_ptr = autoPtr.release(); } - void clear() { deleteOwnedPtr(m_ptr); m_ptr = 0; } ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; } diff --git a/JavaScriptCore/wrec/WREC.h b/JavaScriptCore/wtf/OwnPtrBrew.cpp index 13324e7..c8384e1 100644 --- a/JavaScriptCore/wrec/WREC.h +++ b/JavaScriptCore/wtf/OwnPtrBrew.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2010 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 @@ -10,10 +10,10 @@ * 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 + * 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 INC. OR + * 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 @@ -23,32 +23,31 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef WREC_h -#define WREC_h +#include "config.h" +#include "OwnPtr.h" -#include <wtf/Platform.h> +#include <AEEBitmap.h> +#include <AEEFile.h> +#include <AEEStdLib.h> -#if ENABLE(WREC) +namespace WTF { -#include <wtf/unicode/Unicode.h> - -#if COMPILER(GCC) && CPU(X86) -#define WREC_CALL __attribute__ ((regparm (3))) -#else -#define WREC_CALL -#endif - -namespace JSC { - class Interpreter; - class UString; +void deleteOwnedPtr(IFileMgr* ptr) +{ + if (ptr) + IFILEMGR_Release(ptr); } -namespace JSC { namespace WREC { - - typedef int (*CompiledRegExp)(const UChar* input, unsigned start, unsigned length, int* output) WREC_CALL; - -} } // namespace JSC::WREC +void deleteOwnedPtr(IFile* ptr) +{ + if (ptr) + IFILE_Release(ptr); +} -#endif // ENABLE(WREC) +void deleteOwnedPtr(IBitmap* ptr) +{ + if (ptr) + IBitmap_Release(ptr); +} -#endif // WREC_h +} diff --git a/JavaScriptCore/wtf/OwnPtrCommon.h b/JavaScriptCore/wtf/OwnPtrCommon.h index 6d91a54..c59fdc5 100644 --- a/JavaScriptCore/wtf/OwnPtrCommon.h +++ b/JavaScriptCore/wtf/OwnPtrCommon.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2009 Apple Inc. All rights reserved. * Copyright (C) 2009 Torch Mobile, Inc. + * Copyright (C) 2010 Company 100 Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,6 +38,14 @@ typedef struct HPEN__* HPEN; typedef struct HRGN__* HRGN; #endif +#if PLATFORM(BREWMP) +// Forward delcarations at this point avoid the need to include BREW includes +// in WTF headers. +typedef struct _IFileMgr IFileMgr; +typedef struct _IFile IFile; +typedef struct IBitmap IBitmap; +#endif + namespace WTF { template <typename T> inline void deleteOwnedPtr(T* ptr) @@ -56,6 +65,12 @@ namespace WTF { void deleteOwnedPtr(HRGN); #endif +#if PLATFORM(BREWMP) + void deleteOwnedPtr(IFileMgr*); + void deleteOwnedPtr(IFile*); + void deleteOwnedPtr(IBitmap*); +#endif + } // namespace WTF #endif // WTF_OwnPtrCommon_h diff --git a/JavaScriptCore/wtf/PassRefPtr.h b/JavaScriptCore/wtf/PassRefPtr.h index 9c6e44f..d7a9341 100644 --- a/JavaScriptCore/wtf/PassRefPtr.h +++ b/JavaScriptCore/wtf/PassRefPtr.h @@ -33,19 +33,32 @@ namespace WTF { // Remove inline for WINSCW compiler to prevent the compiler agressively resolving // T::ref() and T::deref(), which will fail compiling when PassRefPtr<T> is used as // a class member or function arguments before T is defined. + + // [Qt]r57240 broke Qt build (might be a gcc bug) + // FIXME! See: https://bugs.webkit.org/show_bug.cgi?id=37253 template<typename T> #if !COMPILER(WINSCW) +#if !PLATFORM(QT) + ALWAYS_INLINE +#else inline #endif +#endif void refIfNotNull(T* ptr) { if (UNLIKELY(ptr != 0)) ptr->ref(); } + // [Qt]r57240 broke Qt build (might be a gcc bug) + // FIXME! See: https://bugs.webkit.org/show_bug.cgi?id=37253 template<typename T> #if !COMPILER(WINSCW) - inline +#if !PLATFORM(QT) + ALWAYS_INLINE +#else + inline +#endif #endif void derefIfNotNull(T* ptr) { diff --git a/JavaScriptCore/wtf/Platform.h b/JavaScriptCore/wtf/Platform.h index a6ded58..405d3e7 100644 --- a/JavaScriptCore/wtf/Platform.h +++ b/JavaScriptCore/wtf/Platform.h @@ -79,13 +79,21 @@ #endif /* COMPILER(MINGW) - MinGW GCC */ -#if defined(MINGW) || defined(__MINGW32__) +/* COMPILER(MINGW64) - mingw-w64 GCC - only used as additional check to exclude mingw.org specific functions */ +#if defined(__MINGW32__) #define WTF_COMPILER_MINGW 1 -#endif +#include <_mingw.h> /* private MinGW header */ + #if defined(__MINGW64_VERSION_MAJOR) /* best way to check for mingw-w64 vs mingw.org */ + #define WTF_COMPILER_MINGW64 1 + #endif /* __MINGW64_VERSION_MAJOR */ +#endif /* __MINGW32__ */ /* COMPILER(WINSCW) - CodeWarrior for Symbian emulator */ #if defined(__WINSCW__) #define WTF_COMPILER_WINSCW 1 +/* cross-compiling, it is not really windows */ +#undef WIN32 +#undef _WIN32 #endif @@ -102,7 +110,28 @@ /* CPU(IA64) - Itanium / IA-64 */ #if defined(__ia64__) #define WTF_CPU_IA64 1 +/* 32-bit mode on Itanium */ +#if !defined(__LP64__) +#define WTF_CPU_IA64_32 1 +#endif +#endif + +/* CPU(MIPS) - MIPS 32-bit */ +/* Note: Only O32 ABI is tested, so we enable it for O32 ABI for now. */ +#if (defined(mips) || defined(__mips__)) \ + && defined(_ABIO32) +#define WTF_CPU_MIPS 1 +#if defined(__MIPSEB__) +#define WTF_CPU_BIG_ENDIAN 1 #endif +#define WTF_MIPS_PIC (defined __PIC__) +#define WTF_MIPS_ARCH __mips +#define WTF_MIPS_ISA(v) (defined WTF_MIPS_ARCH && WTF_MIPS_ARCH == v) +#define WTF_MIPS_ISA_AT_LEAST(v) (defined WTF_MIPS_ARCH && WTF_MIPS_ARCH >= v) +#define WTF_MIPS_ARCH_REV __mips_isa_rev +#define WTF_MIPS_ISA_REV(v) (defined WTF_MIPS_ARCH_REV && WTF_MIPS_ARCH_REV == v) +#define WTF_MIPS_DOUBLE_FLOAT (defined __mips_hard_float && !defined __mips_single_float) +#endif /* MIPS */ /* CPU(PPC) - PowerPC 32-bit */ #if defined(__ppc__) \ @@ -142,7 +171,7 @@ /* CPU(SPARC) - any SPARC, true for CPU(SPARC32) and CPU(SPARC64) */ #if CPU(SPARC32) || CPU(SPARC64) -#define WTF_CPU_SPARC +#define WTF_CPU_SPARC 1 #endif /* CPU(X86) - i386 / x86 32-bit */ @@ -162,7 +191,9 @@ /* CPU(ARM) - ARM, any version*/ #if defined(arm) \ - || defined(__arm__) + || defined(__arm__) \ + || defined(ARM) \ + || defined(_ARM_) #define WTF_CPU_ARM 1 #if defined(__ARMEB__) @@ -171,6 +202,7 @@ #elif !defined(__ARM_EABI__) \ && !defined(__EABI__) \ && !defined(__VFP_FP__) \ + && !defined(_WIN32_WCE) \ && !defined(ANDROID) #define WTF_CPU_MIDDLE_ENDIAN 1 @@ -371,9 +403,6 @@ /* 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 @@ -537,6 +566,9 @@ #if PLATFORM(QT) #define WTF_USE_QT4_UNICODE 1 +#if !defined(ENABLE_WIDGETS_10_SUPPORT) +#define ENABLE_WIDGETS_10_SUPPORT 1 +#endif #elif OS(WINCE) #define WTF_USE_WINCE_UNICODE 1 #elif PLATFORM(GTK) @@ -562,10 +594,15 @@ #define HAVE_RUNLOOP_TIMER 1 #endif /* PLATFORM(MAC) && !PLATFORM(IPHONE) */ +#if PLATFORM(MAC) +#define WTF_USE_CARBON_SECURE_INPUT_MODE 1 +#endif + #if PLATFORM(CHROMIUM) && OS(DARWIN) #define WTF_PLATFORM_CF 1 #define WTF_USE_PTHREADS 1 #define HAVE_PTHREAD_RWLOCK 1 +#define WTF_USE_CARBON_SECURE_INPUT_MODE 1 #endif #if PLATFORM(QT) && OS(DARWIN) @@ -608,6 +645,7 @@ #if PLATFORM(WX) #define ENABLE_ASSEMBLER 1 +#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 #if OS(DARWIN) #define WTF_PLATFORM_CF 1 #endif @@ -743,6 +781,11 @@ /* ENABLE macro defaults */ +#if PLATFORM(QT) +// We musn't customize the global operator new and delete for the Qt port. +#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 +#endif + /* fastMalloc match validation allows for runtime verification that new is matched by delete, fastMalloc is matched by fastFree, etc. */ #if !defined(ENABLE_FAST_MALLOC_MATCH_VALIDATION) @@ -777,6 +820,10 @@ #define ENABLE_DASHBOARD_SUPPORT 0 #endif +#if !defined(ENABLE_WIDGETS_10_SUPPORT) +#define ENABLE_WIDGETS_10_SUPPORT 0 +#endif + #if !defined(ENABLE_INSPECTOR) #define ENABLE_INSPECTOR 1 #endif @@ -801,6 +848,10 @@ #define ENABLE_OPCODE_STATS 0 #endif +#if !defined(ENABLE_GLOBAL_FASTMALLOC_NEW) +#define ENABLE_GLOBAL_FASTMALLOC_NEW 1 +#endif + #define ENABLE_SAMPLING_COUNTERS 0 #define ENABLE_SAMPLING_FLAGS 0 #define ENABLE_OPCODE_SAMPLING 0 @@ -820,6 +871,10 @@ #define ENABLE_NOTIFICATIONS 0 #endif +#if PLATFORM(IPHONE) +#define ENABLE_TEXT_CARET 0 +#endif + #if !defined(ENABLE_TEXT_CARET) #define ENABLE_TEXT_CARET 1 #endif @@ -840,9 +895,12 @@ #endif #if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32) && !defined(WTF_USE_JSVALUE32_64) -#if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) || CPU(IA64) || CPU(ALPHA) +#if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) \ + || (CPU(IA64) && !CPU(IA64_32)) \ + || CPU(ALPHA) \ + || CPU(SPARC64) #define WTF_USE_JSVALUE64 1 -#elif CPU(ARM) || CPU(PPC64) +#elif CPU(ARM) || CPU(PPC64) || CPU(MIPS) #define WTF_USE_JSVALUE32 1 #elif OS(WINDOWS) && COMPILER(MINGW) /* Using JSVALUE32_64 causes padding/alignement issues for JITStubArg @@ -885,6 +943,8 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #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_64) && OS(WINDOWS) && COMPILER(MINGW64) && GCC_VERSION >= 40100 + #define ENABLE_JIT 1 #elif CPU(X86) && OS(WINDOWS) && COMPILER(MSVC) #define ENABLE_JIT 1 #define WTF_USE_JIT_STUB_ARGUMENT_REGISTER 1 @@ -895,6 +955,9 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #define ENABLE_JIT 1 #elif CPU(ARM_TRADITIONAL) && OS(LINUX) #define ENABLE_JIT 1 +#elif CPU(MIPS) && OS(LINUX) + #define ENABLE_JIT 1 + #define WTF_USE_JIT_STUB_ARGUMENT_VA_LIST 0 #endif #endif /* PLATFORM(QT) */ @@ -959,10 +1022,12 @@ on MinGW. See https://bugs.webkit.org/show_bug.cgi?id=29268 */ #if PLATFORM(QT) #if (CPU(X86) && OS(WINDOWS) && COMPILER(MINGW) && GCC_VERSION >= 40100) \ + || (CPU(X86_64) && OS(WINDOWS) && COMPILER(MINGW64) && 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)) + || (CPU(ARM_TRADITIONAL) && OS(LINUX)) \ + || (CPU(MIPS) && OS(LINUX)) #define ENABLE_YARR 1 #define ENABLE_YARR_JIT 1 #endif diff --git a/JavaScriptCore/wtf/StaticConstructors.h b/JavaScriptCore/wtf/StaticConstructors.h new file mode 100644 index 0000000..97af339 --- /dev/null +++ b/JavaScriptCore/wtf/StaticConstructors.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. + * + * 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 StaticConstructors_h +#define StaticConstructors_h + +// We need to avoid having static constructors. We achieve this +// with two separate methods for GCC and MSVC. Both methods prevent the static +// initializers from being registered and called on program startup. On GCC, we +// declare the global objects with a different type that can be POD default +// initialized by the linker/loader. On MSVC we use a special compiler feature +// to have the CRT ignore our static initializers. The constructors will never +// be called and the objects will be left uninitialized. +// +// With both of these approaches, we must define and explicitly call an init +// routine that uses placement new to create the objects and overwrite the +// uninitialized placeholders. +// +// This is not completely portable, but is what we have for now without +// changing how a lot of code accesses these global objects. + +#ifdef SKIP_STATIC_CONSTRUCTORS_ON_MSVC +// - Assume that all includes of this header want ALL of their static +// initializers ignored. This is currently the case. This means that if +// a .cc includes this header (or it somehow gets included), all static +// initializers after the include will not be executed. +// - We do this with a pragma, so that all of the static initializer pointers +// go into our own section, and the CRT won't call them. Eventually it would +// be nice if the section was discarded, because we don't want the pointers. +// See: http://msdn.microsoft.com/en-us/library/7977wcck(VS.80).aspx +#pragma warning(disable:4075) +#pragma init_seg(".unwantedstaticinits") +#endif + +#ifndef SKIP_STATIC_CONSTRUCTORS_ON_GCC + // Define an global in the normal way. +#if COMPILER(MSVC7) +#define DEFINE_GLOBAL(type, name) \ + const type name; +#elif COMPILER(WINSCW) +#define DEFINE_GLOBAL(type, name, arg...) \ + const type name; +#else +#define DEFINE_GLOBAL(type, name, ...) \ + const type name; +#endif + +#else +// Define an correctly-sized array of pointers to avoid static initialization. +// Use an array of pointers instead of an array of char in case there is some alignment issue. +#if COMPILER(MSVC7) +#define DEFINE_GLOBAL(type, name) \ + void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; +#elif COMPILER(WINSCW) +#define DEFINE_GLOBAL(type, name, arg...) \ + void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; +#else +#define DEFINE_GLOBAL(type, name, ...) \ + void * name[(sizeof(type) + sizeof(void *) - 1) / sizeof(void *)]; +#endif +#endif + +#endif // StaticConstructors_h diff --git a/JavaScriptCore/wtf/StdLibExtras.h b/JavaScriptCore/wtf/StdLibExtras.h index 9dfb969..96a929c 100644 --- a/JavaScriptCore/wtf/StdLibExtras.h +++ b/JavaScriptCore/wtf/StdLibExtras.h @@ -26,7 +26,6 @@ #ifndef WTF_StdLibExtras_h #define WTF_StdLibExtras_h -#include <wtf/Platform.h> #include <wtf/Assertions.h> // Use these to declare and define a static local variable (static T;) so that diff --git a/JavaScriptCore/wtf/TCSystemAlloc.cpp b/JavaScriptCore/wtf/TCSystemAlloc.cpp index 4d02919..c46ff31 100644 --- a/JavaScriptCore/wtf/TCSystemAlloc.cpp +++ b/JavaScriptCore/wtf/TCSystemAlloc.cpp @@ -38,6 +38,7 @@ #include "Assertions.h" #include "TCSpinLock.h" #include "UnusedParam.h" +#include "VMTags.h" #if HAVE(STDINT_H) #include <stdint.h> @@ -178,7 +179,7 @@ static void* TryMmap(size_t size, size_t *actual_size, size_t alignment) { void* result = mmap(NULL, size + extra, PROT_READ | PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, - -1, 0); + VM_TAG_FOR_TCMALLOC_MEMORY, 0); if (result == reinterpret_cast<void*>(MAP_FAILED)) { mmap_failure = true; return NULL; diff --git a/JavaScriptCore/wtf/Threading.h b/JavaScriptCore/wtf/Threading.h index 1599562..768aecf 100644 --- a/JavaScriptCore/wtf/Threading.h +++ b/JavaScriptCore/wtf/Threading.h @@ -75,7 +75,7 @@ #include <libkern/OSAtomic.h> #elif OS(ANDROID) #include <cutils/atomic.h> -#elif COMPILER(GCC) +#elif COMPILER(GCC) && !OS(SYMBIAN) #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) #include <ext/atomicity.h> #else @@ -86,7 +86,7 @@ #if USE(PTHREADS) #include <pthread.h> #elif PLATFORM(GTK) -#include <wtf/gtk/GOwnPtr.h> +#include "GOwnPtr.h" typedef struct _GMutex GMutex; typedef struct _GCond GCond; #endif @@ -239,7 +239,7 @@ inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Bar 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 +#elif COMPILER(GCC) && !CPU(SPARC64) && !OS(SYMBIAN) // 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/JavaScriptCore/wtf/VMTags.h b/JavaScriptCore/wtf/VMTags.h index 1ec79d9..6600050 100644 --- a/JavaScriptCore/wtf/VMTags.h +++ b/JavaScriptCore/wtf/VMTags.h @@ -26,30 +26,65 @@ #ifndef VMTags_h #define VMTags_h -#include <wtf/Platform.h> - // 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 OS(DARWIN) && !defined(BUILDING_ON_TIGER) +#if OS(DARWIN) #include <mach/vm_statistics.h> -#if 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) -#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE) -#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) +#if !defined(TARGETING_TIGER) + +#if defined(VM_MEMORY_TCMALLOC) +#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(VM_MEMORY_TCMALLOC) +#else +#define VM_TAG_FOR_TCMALLOC_MEMORY VM_MAKE_TAG(53) +#endif // defined(VM_MEMORY_TCMALLOC) + +#if defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) #define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) #else -#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63) #define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY VM_MAKE_TAG(64) +#endif // defined(VM_MEMORY_JAVASCRIPT_JIT_EXECUTABLE_ALLOCATOR) + +#if defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) +#define VM_TAG_FOR_REGISTERFILE_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) +#else #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) +#endif // defined(VM_MEMORY_JAVASCRIPT_JIT_REGISTER_FILE) + +#else // !defined(TARGETING_TIGER) + +// mmap on Tiger fails with tags that work on Leopard, so fall +// back to Tiger-compatible tags (that also work on Leopard) +// when targeting Tiger. +#define VM_TAG_FOR_TCMALLOC_MEMORY -1 +#define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1 +#define VM_TAG_FOR_REGISTERFILE_MEMORY -1 + +#endif // !defined(TARGETING_TIGER) + +// Tags for vm_map and vm_allocate work on both Tiger and Leopard. + +#if defined(VM_MEMORY_JAVASCRIPT_CORE) +#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(VM_MEMORY_JAVASCRIPT_CORE) +#else +#define VM_TAG_FOR_COLLECTOR_MEMORY VM_MAKE_TAG(63) +#endif // defined(VM_MEMORY_JAVASCRIPT_CORE) + +#if defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS) +#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS) +#else +#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY VM_MAKE_TAG(69) +#endif // defined(VM_MEMORY_WEBCORE_PURGEABLE_BUFFERS) -#else // OS(DARWIN) && !defined(BUILDING_ON_TIGER) +#else // OS(DARWIN) +#define VM_TAG_FOR_TCMALLOC_MEMORY -1 #define VM_TAG_FOR_COLLECTOR_MEMORY -1 #define VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY -1 #define VM_TAG_FOR_REGISTERFILE_MEMORY -1 +#define VM_TAG_FOR_WEBCORE_PURGEABLE_MEMORY -1 -#endif // OS(DARWIN) && !defined(BUILDING_ON_TIGER) +#endif // OS(DARWIN) #endif // VMTags_h diff --git a/JavaScriptCore/wtf/ValueCheck.h b/JavaScriptCore/wtf/ValueCheck.h index cd321b8..2a86eb0 100644 --- a/JavaScriptCore/wtf/ValueCheck.h +++ b/JavaScriptCore/wtf/ValueCheck.h @@ -26,12 +26,7 @@ #ifndef ValueCheck_h #define ValueCheck_h -// For malloc_size and _msize. -#if OS(DARWIN) -#include <malloc/malloc.h> -#elif COMPILER(MSVC) -#include <malloc.h> -#endif +#include <wtf/FastMalloc.h> namespace WTF { @@ -47,13 +42,7 @@ template<typename P> struct ValueCheck<P*> { { if (!p) return; -#if (defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) || !defined(NDEBUG) -#if OS(DARWIN) - ASSERT(malloc_size(p)); -#elif COMPILER(MSVC) - ASSERT(_msize(const_cast<P*>(p))); -#endif -#endif + ASSERT(fastMallocSize(p)); ValueCheck<P>::checkConsistency(*p); } }; diff --git a/JavaScriptCore/wtf/Vector.h b/JavaScriptCore/wtf/Vector.h index 81ea321..6f55e53 100644 --- a/JavaScriptCore/wtf/Vector.h +++ b/JavaScriptCore/wtf/Vector.h @@ -286,6 +286,20 @@ namespace WTF { m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T))); } + bool tryAllocateBuffer(size_t newCapacity) + { + if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) + return false; + + T* newBuffer; + if (tryFastMalloc(newCapacity * sizeof(T)).getValue(newBuffer)) { + m_capacity = newCapacity; + m_buffer = newBuffer; + return true; + } + return false; + } + void deallocateBuffer(T* bufferToDeallocate) { if (m_buffer == bufferToDeallocate) { @@ -361,6 +375,7 @@ namespace WTF { void restoreInlineBufferIfNeeded() { } using Base::allocateBuffer; + using Base::tryAllocateBuffer; using Base::deallocateBuffer; using Base::buffer; @@ -405,6 +420,15 @@ namespace WTF { } } + bool tryAllocateBuffer(size_t newCapacity) + { + if (newCapacity > inlineCapacity) + return Base::tryAllocateBuffer(newCapacity); + m_buffer = inlineBuffer(); + m_capacity = inlineCapacity; + return true; + } + void deallocateBuffer(T* bufferToDeallocate) { if (bufferToDeallocate == inlineBuffer()) @@ -538,6 +562,7 @@ namespace WTF { void grow(size_t size); void resize(size_t size); void reserveCapacity(size_t newCapacity); + bool tryReserveCapacity(size_t newCapacity); void reserveInitialCapacity(size_t initialCapacity); void shrinkCapacity(size_t newCapacity); void shrinkToFit() { shrinkCapacity(size()); } @@ -548,6 +573,7 @@ namespace WTF { template<typename U> void append(const U&); template<typename U> void uncheckedAppend(const U& val); template<size_t otherCapacity> void append(const Vector<T, otherCapacity>&); + template<typename U> bool tryAppend(const U*, size_t); template<typename U> void insert(size_t position, const U*, size_t); template<typename U> void insert(size_t position, const U&); @@ -592,6 +618,8 @@ namespace WTF { private: void expandCapacity(size_t newMinCapacity); const T* expandCapacity(size_t newMinCapacity, const T*); + bool tryExpandCapacity(size_t newMinCapacity); + const T* tryExpandCapacity(size_t newMinCapacity, const T*); template<typename U> U* expandCapacity(size_t newMinCapacity, U*); size_t m_size; @@ -742,6 +770,26 @@ namespace WTF { return begin() + index; } + template<typename T, size_t inlineCapacity> + bool Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity) + { + return tryReserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1))); + } + + template<typename T, size_t inlineCapacity> + const T* Vector<T, inlineCapacity>::tryExpandCapacity(size_t newMinCapacity, const T* ptr) + { + if (ptr < begin() || ptr >= end()) { + if (!tryExpandCapacity(newMinCapacity)) + return 0; + return ptr; + } + size_t index = ptr - begin(); + if (!tryExpandCapacity(newMinCapacity)) + return 0; + return begin() + index; + } + template<typename T, size_t inlineCapacity> template<typename U> inline U* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, U* ptr) { @@ -797,6 +845,21 @@ namespace WTF { } template<typename T, size_t inlineCapacity> + bool Vector<T, inlineCapacity>::tryReserveCapacity(size_t newCapacity) + { + if (newCapacity <= capacity()) + return true; + T* oldBuffer = begin(); + T* oldEnd = end(); + if (!m_buffer.tryAllocateBuffer(newCapacity)) + return false; + ASSERT(begin()); + TypeOperations::move(oldBuffer, oldEnd, begin()); + m_buffer.deallocateBuffer(oldBuffer); + return true; + } + + template<typename T, size_t inlineCapacity> inline void Vector<T, inlineCapacity>::reserveInitialCapacity(size_t initialCapacity) { ASSERT(!m_size); @@ -848,6 +911,25 @@ namespace WTF { } template<typename T, size_t inlineCapacity> template<typename U> + bool Vector<T, inlineCapacity>::tryAppend(const U* data, size_t dataSize) + { + size_t newSize = m_size + dataSize; + if (newSize > capacity()) { + data = tryExpandCapacity(newSize, data); + if (!data) + return false; + ASSERT(begin()); + } + if (newSize < m_size) + return false; + T* dest = end(); + for (size_t i = 0; i < dataSize; ++i) + new (&dest[i]) T(data[i]); + m_size = newSize; + return true; + } + + template<typename T, size_t inlineCapacity> template<typename U> ALWAYS_INLINE void Vector<T, inlineCapacity>::append(const U& val) { const U* ptr = &val; diff --git a/JavaScriptCore/wtf/VectorTraits.h b/JavaScriptCore/wtf/VectorTraits.h index bf77878..3f33b29 100644 --- a/JavaScriptCore/wtf/VectorTraits.h +++ b/JavaScriptCore/wtf/VectorTraits.h @@ -80,9 +80,6 @@ namespace WTF { template<typename P> struct VectorTraits<OwnPtr<P> > : SimpleClassVectorTraits { }; - template<typename P> - struct VectorTraits<std::auto_ptr<P> > : SimpleClassVectorTraits { }; - template<typename First, typename Second> struct VectorTraits<pair<First, Second> > { diff --git a/JavaScriptCore/wrec/CharacterClass.h b/JavaScriptCore/wtf/WTFThreadData.cpp index 8a9d2fc..bbc9986 100644 --- a/JavaScriptCore/wrec/CharacterClass.h +++ b/JavaScriptCore/wtf/WTFThreadData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2010 Apple Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -10,10 +10,10 @@ * 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 + * 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 INC. OR + * 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 @@ -21,48 +21,34 @@ * 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 CharacterClass_h -#define CharacterClass_h - -#include <wtf/Platform.h> - -#if ENABLE(WREC) - -#include <wtf/unicode/Unicode.h> - -namespace JSC { namespace WREC { - - struct CharacterRange { - UChar begin; - UChar end; - }; - - struct CharacterClass { - static const CharacterClass& newline(); - static const CharacterClass& digits(); - static const CharacterClass& spaces(); - static const CharacterClass& wordchar(); - static const CharacterClass& nondigits(); - static const CharacterClass& nonspaces(); - static const CharacterClass& nonwordchar(); - - const UChar* matches; - unsigned numMatches; - - const CharacterRange* ranges; - unsigned numRanges; - - const UChar* matchesUnicode; - unsigned numMatchesUnicode; - - const CharacterRange* rangesUnicode; - unsigned numRangesUnicode; - }; - -} } // namespace JSC::WREC - -#endif // ENABLE(WREC) - -#endif // CharacterClass_h +#include "config.h" +#include "WTFThreadData.h" + +namespace WTF { + +#if WTFTHREADDATA_MULTITHREADED +ThreadSpecific<WTFThreadData>* WTFThreadData::staticData; +#else +WTFThreadData* WTFThreadData::staticData; +#endif + +WTFThreadData::WTFThreadData() + : m_atomicStringTable(0) + , m_atomicStringTableDestructor(0) +#if USE(JSC) + , m_defaultIdentifierTable(0) + , m_currentIdentifierTable(0) +#endif +{ +} + +WTFThreadData::~WTFThreadData() +{ + if (m_atomicStringTableDestructor) + m_atomicStringTableDestructor(m_atomicStringTable); +} + +} // namespace WebCore diff --git a/JavaScriptCore/wtf/WTFThreadData.h b/JavaScriptCore/wtf/WTFThreadData.h new file mode 100644 index 0000000..d2c379b --- /dev/null +++ b/JavaScriptCore/wtf/WTFThreadData.h @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2008 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 WTFThreadData_h +#define WTFThreadData_h + +#include <wtf/HashMap.h> +#include <wtf/HashSet.h> +#include <wtf/Noncopyable.h> +#include <wtf/text/StringHash.h> + +// This was ENABLE(WORKERS) in WebCore, but this is not defined when compiling JSC. +// However this check was not correct anyway, re this comment: +// // FIXME: Workers are not necessarily the only feature that make per-thread global data necessary. +// // We need to check for e.g. database objects manipulating strings on secondary threads. +// Always enabling this is safe, and should be a better option until we can come up +// with a better define. +#define WTFTHREADDATA_MULTITHREADED 1 + +#if WTFTHREADDATA_MULTITHREADED +#include <wtf/ThreadSpecific.h> +#include <wtf/Threading.h> +#endif + +// FIXME: This is a temporary layering violation while we move more string code to WTF. +namespace WebCore { +class AtomicStringTable; +class StringImpl; +} +using WebCore::StringImpl; + +typedef void (*AtomicStringTableDestructor)(WebCore::AtomicStringTable*); + +#if USE(JSC) +// FIXME: This is a temporary layering violation while we move more string code to WTF. +namespace JSC { + +typedef HashMap<const char*, RefPtr<StringImpl>, PtrHash<const char*> > LiteralIdentifierTable; + +class IdentifierTable : public FastAllocBase { +public: + ~IdentifierTable(); + + std::pair<HashSet<StringImpl*>::iterator, bool> add(StringImpl* value); + template<typename U, typename V> + std::pair<HashSet<StringImpl*>::iterator, bool> add(U value); + + void remove(StringImpl* r) { m_table.remove(r); } + + LiteralIdentifierTable& literalTable() { return m_literalTable; } + +private: + HashSet<StringImpl*> m_table; + LiteralIdentifierTable m_literalTable; +}; + +} +#endif + +namespace WTF { + +class WTFThreadData : public Noncopyable { +public: + WTFThreadData(); + ~WTFThreadData(); + + WebCore::AtomicStringTable* atomicStringTable() + { + return m_atomicStringTable; + } + +#if USE(JSC) + void initializeIdentifierTable(JSC::IdentifierTable* identifierTable) + { + m_defaultIdentifierTable = identifierTable; + m_currentIdentifierTable = identifierTable; + } + + JSC::IdentifierTable* currentIdentifierTable() + { + return m_currentIdentifierTable; + } + + JSC::IdentifierTable* setCurrentIdentifierTable(JSC::IdentifierTable* identifierTable) + { + JSC::IdentifierTable* oldIdentifierTable = m_currentIdentifierTable; + m_currentIdentifierTable = identifierTable; + return oldIdentifierTable; + } + + void resetCurrentIdentifierTable() + { + m_currentIdentifierTable = m_defaultIdentifierTable; + } +#endif + +private: + WebCore::AtomicStringTable* m_atomicStringTable; + AtomicStringTableDestructor m_atomicStringTableDestructor; + +#if USE(JSC) + JSC::IdentifierTable* m_defaultIdentifierTable; + JSC::IdentifierTable* m_currentIdentifierTable; +#endif + +#if WTFTHREADDATA_MULTITHREADED + static JS_EXPORTDATA ThreadSpecific<WTFThreadData>* staticData; +#else + static JS_EXPORTDATA WTFThreadData* staticData; +#endif + friend WTFThreadData& wtfThreadData(); + friend class WebCore::AtomicStringTable; +}; + +inline WTFThreadData& wtfThreadData() +{ +#if WTFTHREADDATA_MULTITHREADED + // WRT WebCore: + // WTFThreadData is used on main thread before it could possibly be used + // on secondary ones, so there is no need for synchronization here. + // WRT JavaScriptCore: + // wtfThreadData() is initially called from initializeThreading(), ensuring + // this is initially called in a pthread_once locked context. + if (!WTFThreadData::staticData) + WTFThreadData::staticData = new ThreadSpecific<WTFThreadData>; + return **WTFThreadData::staticData; +#else + if (!WTFThreadData::staticData) { + WTFThreadData::staticData = static_cast<WTFThreadData*>(fastMalloc(sizeof(WTFThreadData))); + // WTFThreadData constructor indirectly uses staticData, so we need to set up the memory before invoking it. + new (WTFThreadData::staticData) WTFThreadData; + } + return *WTFThreadData::staticData; +#endif +} + +} // namespace WTF + +using WTF::WTFThreadData; +using WTF::wtfThreadData; + +#endif // WTFThreadData_h diff --git a/JavaScriptCore/wtf/brew/OwnPtrBrew.cpp b/JavaScriptCore/wtf/brew/OwnPtrBrew.cpp deleted file mode 100644 index dadd82e..0000000 --- a/JavaScriptCore/wtf/brew/OwnPtrBrew.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2010 Company 100, Inc. - * - * 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 "OwnPtrBrew.h" - -#include <AEEBitmap.h> -#include <AEEFile.h> -#include <AEEStdLib.h> - -namespace WTF { - -template <> void freeOwnedPtrBrew<IFileMgr>(IFileMgr* ptr) -{ - if (ptr) - IFILEMGR_Release(ptr); -} - -template <> void freeOwnedPtrBrew<IFile>(IFile* ptr) -{ - if (ptr) - IFILE_Release(ptr); -} - -template <> void freeOwnedPtrBrew<IBitmap>(IBitmap* ptr) -{ - if (ptr) - IBitmap_Release(ptr); -} - -template <typename T> void freeOwnedPtrBrew(T* ptr) -{ - FREEIF(ptr); -} - -} // namespace WTF diff --git a/JavaScriptCore/wtf/brew/OwnPtrBrew.h b/JavaScriptCore/wtf/brew/OwnPtrBrew.h deleted file mode 100644 index 1bb44fc..0000000 --- a/JavaScriptCore/wtf/brew/OwnPtrBrew.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2008 Collabora Ltd. - * Copyright (C) 2010 Company 100, Inc. - * - * 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 OwnPtrBrew_h -#define OwnPtrBrew_h - -#include <algorithm> -#include <wtf/Assertions.h> -#include <wtf/Noncopyable.h> - -// Forward delcarations at this point avoid the need to include BREW includes -// in WTF headers. -typedef struct _IFileMgr IFileMgr; -typedef struct _IFile IFile; -typedef struct IBitmap IBitmap; - -namespace WTF { - -template <typename T> void freeOwnedPtrBrew(T* ptr); -template<> void freeOwnedPtrBrew<IFileMgr>(IFileMgr*); -template<> void freeOwnedPtrBrew<IFile>(IFile*); -template<> void freeOwnedPtrBrew<IBitmap>(IBitmap*); - -template <typename T> class OwnPtrBrew : public Noncopyable { -public: - explicit OwnPtrBrew(T* ptr = 0) : m_ptr(ptr) { } - ~OwnPtrBrew() { freeOwnedPtrBrew(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); - freeOwnedPtrBrew(m_ptr); - m_ptr = ptr; - } - - void clear() - { - freeOwnedPtrBrew(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* OwnPtrBrew::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtrBrew::m_ptr : 0; } - - void swap(OwnPtrBrew& o) { std::swap(m_ptr, o.m_ptr); } - -private: - T* m_ptr; -}; - -template <typename T> inline void swap(OwnPtrBrew<T>& a, OwnPtrBrew<T>& b) -{ - a.swap(b); -} - -template <typename T, typename U> inline bool operator==(const OwnPtrBrew<T>& a, U* b) -{ - return a.get() == b; -} - -template <typename T, typename U> inline bool operator==(T* a, const OwnPtrBrew<U>& b) -{ - return a == b.get(); -} - -template <typename T, typename U> inline bool operator!=(const OwnPtrBrew<T>& a, U* b) -{ - return a.get() != b; -} - -template <typename T, typename U> inline bool operator!=(T* a, const OwnPtrBrew<U>& b) -{ - return a != b.get(); -} - -template <typename T> inline typename OwnPtrBrew<T>::PtrType getPtr(const OwnPtrBrew<T>& p) -{ - return p.get(); -} - -} // namespace WTF - -using WTF::OwnPtrBrew; - -#endif // OwnPtrBrew_h diff --git a/JavaScriptCore/wtf/brew/ShellBrew.h b/JavaScriptCore/wtf/brew/ShellBrew.h new file mode 100644 index 0000000..7416eca --- /dev/null +++ b/JavaScriptCore/wtf/brew/ShellBrew.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2010 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 ShellBrew_h +#define ShellBrew_h + +#include <AEEAppGen.h> +#include <AEEStdLib.h> + +#include <wtf/Assertions.h> +#include <wtf/PassOwnPtr.h> + +namespace WTF { + +template <typename T> +static inline PassOwnPtr<T> createInstance(AEECLSID cls) +{ + T* instance = 0; + + IShell* shell = reinterpret_cast<AEEApplet*>(GETAPPINSTANCE())->m_pIShell; + ISHELL_CreateInstance(shell, cls, reinterpret_cast<void**>(&instance)); + ASSERT(instance); + + return instance; +} + +} // namespace WTF + +using WTF::createInstance; + +#endif // ShellBrew_h diff --git a/JavaScriptCore/wtf/brew/SystemMallocBrew.h b/JavaScriptCore/wtf/brew/SystemMallocBrew.h new file mode 100644 index 0000000..c973b30 --- /dev/null +++ b/JavaScriptCore/wtf/brew/SystemMallocBrew.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2010 Company 100, Inc. + * + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 SystemMallocBrew_h +#define SystemMallocBrew_h + +#include <AEEStdLib.h> + +static inline void* mallocBrew(size_t n) +{ + // By default, memory allocated using MALLOC() is initialized + // to zero. This behavior can be disabled by performing a bitwise + // OR of the flag ALLOC_NO_ZMEM with the dwSize parameter. + return MALLOC(n | ALLOC_NO_ZMEM); +} + +static inline void* callocBrew(size_t numElements, size_t elementSize) +{ + return MALLOC(numElements * elementSize); +} + +static inline void freeBrew(void* p) +{ + return FREE(p); +} + +static inline void* reallocBrew(void* p, size_t n) +{ + return REALLOC(p, n | ALLOC_NO_ZMEM); +} + +// Use MALLOC macro instead of the standard malloc function. +// Although RVCT provides malloc, we can't use it in BREW +// because the loader does not initialize the base address properly. +#define malloc(n) mallocBrew(n) +#define calloc(n, s) callocBrew(n, s) +#define realloc(p, n) reallocBrew(p, n) +#define free(p) freeBrew(p) + +#endif // SystemMallocBrew_h diff --git a/JavaScriptCore/wtf/efl/MainThreadEfl.cpp b/JavaScriptCore/wtf/efl/MainThreadEfl.cpp new file mode 100644 index 0000000..fe32d1b --- /dev/null +++ b/JavaScriptCore/wtf/efl/MainThreadEfl.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) + * Copyright (C) 2008 Diego Gonzalez + * Copyright (C) 2008 Kenneth Rohde Christiansen + * Copyright (C) 2009-2010 ProFUSION embedded systems + * Copyright (C) 2009-2010 Samsung Electronics + * + * 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. + * 3. Neither the name of Apple Inc. ("Apple") 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 APPLE 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 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. + */ + +#include "config.h" +#include "MainThread.h" + +#include <Ecore.h> + +namespace WTF { + +void initializeMainThreadPlatform() +{ +} + +static int timeoutFired(void*) +{ + dispatchFunctionsFromMainThread(); + return ECORE_CALLBACK_CANCEL; +} + +void scheduleDispatchFunctionsOnMainThread() +{ + ecore_timer_add(0, timeoutFired, 0); +} + + +} diff --git a/JavaScriptCore/wtf/gtk/GOwnPtr.cpp b/JavaScriptCore/wtf/gobject/GOwnPtr.cpp index da0d839..da0d839 100644 --- a/JavaScriptCore/wtf/gtk/GOwnPtr.cpp +++ b/JavaScriptCore/wtf/gobject/GOwnPtr.cpp diff --git a/JavaScriptCore/wtf/gtk/GOwnPtr.h b/JavaScriptCore/wtf/gobject/GOwnPtr.h index 1fc594c..1fc594c 100644 --- a/JavaScriptCore/wtf/gtk/GOwnPtr.h +++ b/JavaScriptCore/wtf/gobject/GOwnPtr.h diff --git a/JavaScriptCore/wtf/gtk/GRefPtr.cpp b/JavaScriptCore/wtf/gobject/GRefPtr.cpp index e7cf34b..e7cf34b 100644 --- a/JavaScriptCore/wtf/gtk/GRefPtr.cpp +++ b/JavaScriptCore/wtf/gobject/GRefPtr.cpp diff --git a/JavaScriptCore/wtf/gtk/GRefPtr.h b/JavaScriptCore/wtf/gobject/GRefPtr.h index 66739ef..66739ef 100644 --- a/JavaScriptCore/wtf/gtk/GRefPtr.h +++ b/JavaScriptCore/wtf/gobject/GRefPtr.h diff --git a/JavaScriptCore/wtf/mac/MainThreadMac.mm b/JavaScriptCore/wtf/mac/MainThreadMac.mm index 0ddd5f6..586ef4d 100644 --- a/JavaScriptCore/wtf/mac/MainThreadMac.mm +++ b/JavaScriptCore/wtf/mac/MainThreadMac.mm @@ -29,8 +29,10 @@ #import "config.h" #import "MainThread.h" +#import <CoreFoundation/CoreFoundation.h> #import <Foundation/NSThread.h> #import <wtf/Assertions.h> +#import <wtf/Threading.h> @interface WTFMainThreadCaller : NSObject { } @@ -63,9 +65,36 @@ void initializeMainThreadPlatform() #endif } +static bool isTimerPosted; // This is only accessed on the 'main' thread. + +static void timerFired(CFRunLoopTimerRef timer, void*) +{ + CFRelease(timer); + isTimerPosted = false; + WTF::dispatchFunctionsFromMainThread(); +} + +static void postTimer() +{ + ASSERT(isMainThread()); + + if (isTimerPosted) + return; + + isTimerPosted = true; + CFRunLoopAddTimer(CFRunLoopGetCurrent(), CFRunLoopTimerCreate(0, 0, 0, 0, 0, timerFired, 0), kCFRunLoopCommonModes); +} + + void scheduleDispatchFunctionsOnMainThread() { ASSERT(staticMainThreadCaller); + + if (isMainThread()) { + postTimer(); + return; + } + #if USE(WEB_THREAD) [staticMainThreadCaller performSelector:@selector(call) onThread:webThread withObject:nil waitUntilDone:NO]; #else diff --git a/JavaScriptCore/wtf/qt/StringQt.cpp b/JavaScriptCore/wtf/qt/StringQt.cpp new file mode 100644 index 0000000..b2c621a --- /dev/null +++ b/JavaScriptCore/wtf/qt/StringQt.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org> + * + * 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" + +#include <wtf/text/WTFString.h> + +#include <QString> + +namespace WebCore { + +// String conversions +String::String(const QString& qstr) +{ + if (qstr.isNull()) + return; + m_impl = StringImpl::create(reinterpret_cast<const UChar*>(qstr.constData()), qstr.length()); +} + +String::String(const QStringRef& ref) +{ + if (!ref.string()) + return; + m_impl = StringImpl::create(reinterpret_cast<const UChar*>(ref.unicode()), ref.length()); +} + +String::operator QString() const +{ + return QString(reinterpret_cast<const QChar*>(characters()), length()); +} + +QDataStream& operator<<(QDataStream& stream, const String& str) +{ + // could be faster + stream << QString(str); + return stream; +} + +QDataStream& operator>>(QDataStream& stream, String& str) +{ + // mabe not the fastest way, but really easy + QString tmp; + stream >> tmp; + str = tmp; + return stream; +} + +} + +// vim: ts=4 sw=4 et diff --git a/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp b/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp new file mode 100644 index 0000000..6a28e9e --- /dev/null +++ b/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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. + */ + +#include "config.h" + +#if OS(SYMBIAN) + +#include "BlockAllocatorSymbian.h" + + +namespace WTF { + +/** Efficiently allocates blocks of size blockSize with blockSize alignment. + * Primarly designed for JSC Collector's needs. + * Not thread-safe. + */ +AlignedBlockAllocator::AlignedBlockAllocator(TUint32 reservationSize, TUint32 blockSize ) + : m_reservation(reservationSize), + m_blockSize(blockSize) +{ + + // Get system's page size value. + SYMBIAN_PAGESIZE(m_pageSize); + + // We only accept multiples of system page size for both initial reservation and the alignment/block size + m_reservation = SYMBIAN_ROUNDUPTOMULTIPLE(m_reservation, m_pageSize); + __ASSERT_ALWAYS(SYMBIAN_ROUNDUPTOMULTIPLE(m_blockSize, m_pageSize), User::Panic(_L("AlignedBlockAllocator1"), KErrArgument)); + + // Calculate max. bit flags we need to carve a reservationSize range into blockSize-sized blocks + m_map.numBits = m_reservation / m_blockSize; + const TUint32 bitsPerWord = 8*sizeof(TUint32); + const TUint32 numWords = (m_map.numBits + bitsPerWord -1) / bitsPerWord; + + m_map.bits = new TUint32[numWords]; + __ASSERT_ALWAYS(m_map.bits, User::Panic(_L("AlignedBlockAllocator2"), KErrNoMemory)); + m_map.clearAll(); + + // Open a Symbian RChunk, and reserve requested virtual address range + // Any thread in this process can operate this rchunk due to EOwnerProcess access rights. + TInt ret = m_chunk.CreateDisconnectedLocal(0 , 0, (TInt)m_reservation , EOwnerProcess); + if (ret != KErrNone) + User::Panic(_L("AlignedBlockAllocator3"), ret); + + // This is the offset to m_chunk.Base() required to make it m_blockSize-aligned + m_offset = SYMBIAN_ROUNDUPTOMULTIPLE(TUint32(m_chunk.Base()), m_blockSize) - TUint(m_chunk.Base()); + +} + +void* AlignedBlockAllocator::alloc() +{ + + TInt freeRam = 0; + void* address = 0; + + // Look up first free slot in bit map + const TInt freeIdx = m_map.findFree(); + + // Pseudo OOM: We ate up the address space we reserved.. + // ..even though the device may have free RAM left + if (freeIdx < 0) + return 0; + + TInt ret = m_chunk.Commit(m_offset + (m_blockSize * freeIdx), m_blockSize); + if (ret != KErrNone) + return 0; // True OOM: Device didn't have physical RAM to spare + + // Updated bit to mark region as in use. + m_map.set(freeIdx); + + // Calculate address of committed region (block) + address = (void*)( (m_chunk.Base() + m_offset) + (TUint)(m_blockSize * freeIdx) ); + + return address; +} + +void AlignedBlockAllocator::free(void* block) +{ + // Calculate index of block to be freed + TInt idx = TUint(static_cast<TUint8*>(block) - m_chunk.Base() - m_offset) / m_blockSize; + + __ASSERT_DEBUG(idx >= 0 && idx < m_map.numBits, User::Panic(_L("AlignedBlockAllocator4"), KErrCorrupt)); // valid index check + __ASSERT_DEBUG(m_map.get(idx), User::Panic(_L("AlignedBlockAllocator5"), KErrCorrupt)); // in-use flag check + + // Return committed region to system RAM pool (the physical RAM becomes usable by others) + TInt ret = m_chunk.Decommit(m_offset + m_blockSize * idx, m_blockSize); + + // mark this available again + m_map.clear(idx); +} + +void AlignedBlockAllocator::destroy() +{ + // release everything! + m_chunk.Decommit(0, m_chunk.MaxSize()); + m_map.clearAll(); +} + +AlignedBlockAllocator::~AlignedBlockAllocator() +{ + destroy(); + m_chunk.Close(); + delete [] m_map.bits; +} + +} // end of namespace + +#endif // SYMBIAN diff --git a/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h b/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h new file mode 100644 index 0000000..21422f6 --- /dev/null +++ b/JavaScriptCore/wtf/symbian/BlockAllocatorSymbian.h @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * + * 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. + * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE 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 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 BlockAllocatorSymbian_h +#define BlockAllocatorSymbian_h + +#include <e32cmn.h> +#include <e32std.h> +#include <hal.h> + + +#define SYMBIAN_PAGESIZE(x) (HAL::Get(HALData::EMemoryPageSize, x)); +#define SYMBIAN_FREERAM(x) (HAL::Get(HALData::EMemoryRAMFree, x)); +#define SYMBIAN_ROUNDUPTOMULTIPLE(x, multipleof) ( (x + multipleof - 1) & ~(multipleof - 1) ) + +// Set sane defaults if -D<flagname=value> wasn't provided via compiler args +#ifndef JSCCOLLECTOR_VIRTUALMEM_RESERVATION +#if defined(__WINS__) + // Emulator has limited virtual address space + #define JSCCOLLECTOR_VIRTUALMEM_RESERVATION (4*1024*1024) +#else + // HW has plenty of virtual addresses + #define JSCCOLLECTOR_VIRTUALMEM_RESERVATION (128*1024*1024) +#endif +#endif + +namespace WTF { + +/** + * Allocates contiguous region of size blockSize with blockSize-aligned address. + * blockSize must be a multiple of system page size (typically 4K on Symbian/ARM) + * + * @param reservationSize Virtual address range to be reserved upon creation of chunk (bytes). + * @param blockSize Size of a single allocation. Returned address will also be blockSize-aligned. + */ +class AlignedBlockAllocator { + public: + AlignedBlockAllocator(TUint32 reservationSize, TUint32 blockSize); + ~AlignedBlockAllocator(); + void destroy(); + void* alloc(); + void free(void* data); + + private: + RChunk m_chunk; // Symbian chunk that lets us reserve/commit/decommit + TUint m_offset; // offset of first committed region from base + TInt m_pageSize; // cached value of system page size, typically 4K on Symbian + TUint32 m_reservation; + TUint32 m_blockSize; + + // Tracks comitted/decommitted state of a blockSize region + struct { + + TUint32 *bits; // array of bit flags + TUint32 numBits; // number of regions to keep track of + + bool get(TUint32 n) const + { + return !!(bits[n >> 5] & (1 << (n & 0x1F))); + } + + void set(TUint32 n) + { + bits[n >> 5] |= (1 << (n & 0x1F)); + } + + void clear(TUint32 n) + { + bits[n >> 5] &= ~(1 << (n & 0x1F)); + } + + void clearAll() + { + for (TUint32 i = 0; i < numBits; i++) + clear(i); + } + + TInt findFree() const + { + for (TUint32 i = 0; i < numBits; i++) { + if (!get(i)) + return i; + } + return -1; + } + + } m_map; + +}; + +} + +#endif // end of BlockAllocatorSymbian_h + + diff --git a/JavaScriptCore/wtf/text/AtomicString.cpp b/JavaScriptCore/wtf/text/AtomicString.cpp new file mode 100644 index 0000000..79b9ab5 --- /dev/null +++ b/JavaScriptCore/wtf/text/AtomicString.cpp @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2007, 2008 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. + * + */ + +#include "config.h" + +#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC +#define ATOMICSTRING_HIDE_GLOBALS 1 +#endif + +#include "AtomicString.h" + +#include "StaticConstructors.h" +#include "StringHash.h" +#include <wtf/Threading.h> +#include <wtf/HashSet.h> +#include <wtf/WTFThreadData.h> + +namespace WebCore { + +class AtomicStringTable { +public: + static AtomicStringTable* create() + { + AtomicStringTable* table = new AtomicStringTable; + + WTFThreadData& data = wtfThreadData(); + data.m_atomicStringTable = table; + data.m_atomicStringTableDestructor = AtomicStringTable::destroy; + + return table; + } + + HashSet<StringImpl*>& table() + { + return m_table; + } + +private: + static void destroy(AtomicStringTable* table) + { + delete table; + } + + HashSet<StringImpl*> m_table; +}; + +static inline HashSet<StringImpl*>& stringTable() +{ + // Once possible we should make this non-lazy (constructed in WTFThreadData's constructor). + AtomicStringTable* table = wtfThreadData().atomicStringTable(); + if (UNLIKELY(!table)) + table = AtomicStringTable::create(); + return table->table(); +} + +struct CStringTranslator { + static unsigned hash(const char* c) + { + return StringImpl::computeHash(c); + } + + static bool equal(StringImpl* r, const char* s) + { + int length = r->length(); + const UChar* d = r->characters(); + for (int i = 0; i != length; ++i) { + unsigned char c = s[i]; + if (d[i] != c) + return false; + } + return s[length] == 0; + } + + static void translate(StringImpl*& location, const char* const& c, unsigned hash) + { + location = StringImpl::create(c).releaseRef(); + location->setHash(hash); + location->setInTable(); + } +}; + +bool operator==(const AtomicString& a, const char* b) +{ + StringImpl* impl = a.impl(); + if ((!impl || !impl->characters()) && !b) + return true; + if ((!impl || !impl->characters()) || !b) + return false; + return CStringTranslator::equal(impl, b); +} + +PassRefPtr<StringImpl> AtomicString::add(const char* c) +{ + if (!c) + return 0; + if (!*c) + return StringImpl::empty(); + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<const char*, CStringTranslator>(c); + if (!addResult.second) + return *addResult.first; + return adoptRef(*addResult.first); +} + +struct UCharBuffer { + const UChar* s; + unsigned length; +}; + +static inline bool equal(StringImpl* string, const UChar* characters, unsigned length) +{ + if (string->length() != length) + return false; + + // FIXME: perhaps we should have a more abstract macro that indicates when + // going 4 bytes at a time is unsafe +#if CPU(ARM) || CPU(SH4) + const UChar* stringCharacters = string->characters(); + for (unsigned i = 0; i != length; ++i) { + if (*stringCharacters++ != *characters++) + return false; + } + return true; +#else + /* Do it 4-bytes-at-a-time on architectures where it's safe */ + + const uint32_t* stringCharacters = reinterpret_cast<const uint32_t*>(string->characters()); + const uint32_t* bufferCharacters = reinterpret_cast<const uint32_t*>(characters); + + unsigned halfLength = length >> 1; + for (unsigned i = 0; i != halfLength; ++i) { + if (*stringCharacters++ != *bufferCharacters++) + return false; + } + + if (length & 1 && *reinterpret_cast<const uint16_t*>(stringCharacters) != *reinterpret_cast<const uint16_t*>(bufferCharacters)) + return false; + + return true; +#endif +} + +struct UCharBufferTranslator { + static unsigned hash(const UCharBuffer& buf) + { + return StringImpl::computeHash(buf.s, buf.length); + } + + static bool equal(StringImpl* const& str, const UCharBuffer& buf) + { + return WebCore::equal(str, buf.s, buf.length); + } + + static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash) + { + location = StringImpl::create(buf.s, buf.length).releaseRef(); + location->setHash(hash); + location->setInTable(); + } +}; + +struct HashAndCharacters { + unsigned hash; + const UChar* characters; + unsigned length; +}; + +struct HashAndCharactersTranslator { + static unsigned hash(const HashAndCharacters& buffer) + { + ASSERT(buffer.hash == StringImpl::computeHash(buffer.characters, buffer.length)); + return buffer.hash; + } + + static bool equal(StringImpl* const& string, const HashAndCharacters& buffer) + { + return WebCore::equal(string, buffer.characters, buffer.length); + } + + static void translate(StringImpl*& location, const HashAndCharacters& buffer, unsigned hash) + { + location = StringImpl::create(buffer.characters, buffer.length).releaseRef(); + location->setHash(hash); + location->setInTable(); + } +}; + +PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length) +{ + if (!s) + return 0; + + if (length == 0) + return StringImpl::empty(); + + UCharBuffer buf = { s, length }; + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); + + // If the string is newly-translated, then we need to adopt it. + // The boolean in the pair tells us if that is so. + return addResult.second ? adoptRef(*addResult.first) : *addResult.first; +} + +PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsigned existingHash) +{ + ASSERT(s); + ASSERT(existingHash); + + if (length == 0) + return StringImpl::empty(); + + HashAndCharacters buffer = { existingHash, s, length }; + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<HashAndCharacters, HashAndCharactersTranslator>(buffer); + if (!addResult.second) + return *addResult.first; + return adoptRef(*addResult.first); +} + +PassRefPtr<StringImpl> AtomicString::add(const UChar* s) +{ + if (!s) + return 0; + + int length = 0; + while (s[length] != UChar(0)) + length++; + + if (length == 0) + return StringImpl::empty(); + + UCharBuffer buf = {s, length}; + pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<UCharBuffer, UCharBufferTranslator>(buf); + + // If the string is newly-translated, then we need to adopt it. + // The boolean in the pair tells us if that is so. + return addResult.second ? adoptRef(*addResult.first) : *addResult.first; +} + +PassRefPtr<StringImpl> AtomicString::add(StringImpl* r) +{ + if (!r || r->inTable()) + return r; + + if (r->length() == 0) + return StringImpl::empty(); + + StringImpl* result = *stringTable().add(r).first; + if (result == r) + r->setInTable(); + return result; +} + +AtomicStringImpl* AtomicString::find(const UChar* s, unsigned length, unsigned existingHash) +{ + ASSERT(s); + ASSERT(existingHash); + + if (length == 0) + return static_cast<AtomicStringImpl*>(StringImpl::empty()); + + HashAndCharacters buffer = { existingHash, s, length }; + HashSet<StringImpl*>::iterator iterator = stringTable().find<HashAndCharacters, HashAndCharactersTranslator>(buffer); + if (iterator == stringTable().end()) + return 0; + return static_cast<AtomicStringImpl*>(*iterator); +} + +void AtomicString::remove(StringImpl* r) +{ + stringTable().remove(r); +} + +AtomicString AtomicString::lower() const +{ + // Note: This is a hot function in the Dromaeo benchmark. + StringImpl* impl = this->impl(); + RefPtr<StringImpl> newImpl = impl->lower(); + if (LIKELY(newImpl == impl)) + return *this; + return AtomicString(newImpl); +} + +JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, nullAtom) +JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, emptyAtom, "") +JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, textAtom, "#text") +JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, commentAtom, "#comment") +JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, starAtom, "*") +JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, xmlAtom, "xml") +JS_EXPORTDATA DEFINE_GLOBAL(AtomicString, xmlnsAtom, "xmlns") + +void AtomicString::init() +{ + static bool initialized; + if (!initialized) { + // Initialization is not thread safe, so this function must be called from the main thread first. + ASSERT(isMainThread()); + + // Use placement new to initialize the globals. + new ((void*)&nullAtom) AtomicString; + new ((void*)&emptyAtom) AtomicString(""); + new ((void*)&textAtom) AtomicString("#text"); + new ((void*)&commentAtom) AtomicString("#comment"); + new ((void*)&starAtom) AtomicString("*"); + new ((void*)&xmlAtom) AtomicString("xml"); + new ((void*)&xmlnsAtom) AtomicString("xmlns"); + + initialized = true; + } +} + +} diff --git a/JavaScriptCore/wtf/text/AtomicString.h b/JavaScriptCore/wtf/text/AtomicString.h new file mode 100644 index 0000000..9db70f4 --- /dev/null +++ b/JavaScriptCore/wtf/text/AtomicString.h @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2004, 2005, 2006, 2008 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 AtomicString_h +#define AtomicString_h + +#include "AtomicStringImpl.h" +#include "WTFString.h" + +// Define 'NO_IMPLICIT_ATOMICSTRING' before including this header, +// to disallow (expensive) implicit String-->AtomicString conversions. +#ifdef NO_IMPLICIT_ATOMICSTRING +#define ATOMICSTRING_CONVERSION explicit +#else +#define ATOMICSTRING_CONVERSION +#endif + +// FIXME: This is a temporary layering violation while we move string code to WTF. +// Landing the file moves in one patch, will follow on with patches to change the namespaces. +namespace WebCore { + +struct AtomicStringHash; + +class AtomicString : public FastAllocBase { +public: + static void init(); + + AtomicString() { } + AtomicString(const char* s) : m_string(add(s)) { } + AtomicString(const UChar* s, unsigned length) : m_string(add(s, length)) { } + AtomicString(const UChar* s, unsigned length, unsigned existingHash) : m_string(add(s, length, existingHash)) { } + AtomicString(const UChar* s) : m_string(add(s)) { } + ATOMICSTRING_CONVERSION AtomicString(StringImpl* imp) : m_string(add(imp)) { } + AtomicString(AtomicStringImpl* imp) : m_string(imp) { } + ATOMICSTRING_CONVERSION AtomicString(const String& s) : m_string(add(s.impl())) { } + + // Hash table deleted values, which are only constructed and never copied or destroyed. + AtomicString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { } + bool isHashTableDeletedValue() const { return m_string.isHashTableDeletedValue(); } + + static AtomicStringImpl* find(const UChar* s, unsigned length, unsigned existingHash); + + operator const String&() const { return m_string; } + const String& string() const { return m_string; }; + + AtomicStringImpl* impl() const { return static_cast<AtomicStringImpl *>(m_string.impl()); } + + const UChar* characters() const { return m_string.characters(); } + unsigned length() const { return m_string.length(); } + + UChar operator[](unsigned int i) const { return m_string[i]; } + + bool contains(UChar c) const { return m_string.contains(c); } + bool contains(const char* s, bool caseSensitive = true) const + { return m_string.contains(s, caseSensitive); } + bool contains(const String& s, bool caseSensitive = true) const + { return m_string.contains(s, caseSensitive); } + + int find(UChar c, int start = 0) const { return m_string.find(c, start); } + int find(const char* s, int start = 0, bool caseSentitive = true) const + { return m_string.find(s, start, caseSentitive); } + int find(const String& s, int start = 0, bool caseSentitive = true) const + { return m_string.find(s, start, caseSentitive); } + + bool startsWith(const String& s, bool caseSensitive = true) const + { return m_string.startsWith(s, caseSensitive); } + bool endsWith(const String& s, bool caseSensitive = true) const + { return m_string.endsWith(s, caseSensitive); } + + AtomicString lower() const; + AtomicString upper() const { return AtomicString(impl()->upper()); } + + int toInt(bool* ok = 0) const { return m_string.toInt(ok); } + double toDouble(bool* ok = 0) const { return m_string.toDouble(ok); } + float toFloat(bool* ok = 0) const { return m_string.toFloat(ok); } + bool percentage(int& p) const { return m_string.percentage(p); } + + bool isNull() const { return m_string.isNull(); } + bool isEmpty() const { return m_string.isEmpty(); } + + static void remove(StringImpl*); + +#if PLATFORM(CF) + AtomicString(CFStringRef s) : m_string(add(String(s).impl())) { } + CFStringRef createCFString() const { return m_string.createCFString(); } +#endif +#ifdef __OBJC__ + AtomicString(NSString* s) : m_string(add(String(s).impl())) { } + operator NSString*() const { return m_string; } +#endif +#if PLATFORM(QT) + AtomicString(const QString& s) : m_string(add(String(s).impl())) { } + operator QString() const { return m_string; } +#endif + +private: + String m_string; + + static PassRefPtr<StringImpl> add(const char*); + static PassRefPtr<StringImpl> add(const UChar*, unsigned length); + static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash); + static PassRefPtr<StringImpl> add(const UChar*); + static PassRefPtr<StringImpl> add(StringImpl*); +}; + +inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); } +bool operator==(const AtomicString& a, const char* b); +inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); } +inline bool operator==(const char* a, const AtomicString& b) { return b == a; } +inline bool operator==(const String& a, const AtomicString& b) { return equal(a.impl(), b.impl()); } + +inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); } +inline bool operator!=(const AtomicString& a, const char *b) { return !(a == b); } +inline bool operator!=(const AtomicString& a, const String& b) { return !equal(a.impl(), b.impl()); } +inline bool operator!=(const char* a, const AtomicString& b) { return !(b == a); } +inline bool operator!=(const String& a, const AtomicString& b) { return !equal(a.impl(), b.impl()); } + +inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); } +inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), b); } +inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); } +inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); } +inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); } + +// Define external global variables for the commonly used atomic strings. +// These are only usable from the main thread. +#ifndef ATOMICSTRING_HIDE_GLOBALS + extern const JS_EXPORTDATA AtomicString nullAtom; + extern const JS_EXPORTDATA AtomicString emptyAtom; + extern const JS_EXPORTDATA AtomicString textAtom; + extern const JS_EXPORTDATA AtomicString commentAtom; + extern const JS_EXPORTDATA AtomicString starAtom; + extern const JS_EXPORTDATA AtomicString xmlAtom; + extern const JS_EXPORTDATA AtomicString xmlnsAtom; +#endif + +} // namespace WebCore + + +namespace WTF { + + // AtomicStringHash is the default hash for AtomicString + template<typename T> struct DefaultHash; + template<> struct DefaultHash<WebCore::AtomicString> { + typedef WebCore::AtomicStringHash Hash; + }; + +} // namespace WTF + +#endif // AtomicString_h diff --git a/JavaScriptCore/wtf/text/AtomicStringImpl.h b/JavaScriptCore/wtf/text/AtomicStringImpl.h new file mode 100644 index 0000000..d21a00a --- /dev/null +++ b/JavaScriptCore/wtf/text/AtomicStringImpl.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2006 Apple Computer, Inc. + * + * 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 AtomicStringImpl_h +#define AtomicStringImpl_h + +#include "StringImpl.h" + +// FIXME: This is a temporary layering violation while we move string code to WTF. +// Landing the file moves in one patch, will follow on with patches to change the namespaces. +namespace WebCore { + +class AtomicStringImpl : public StringImpl +{ +}; + +} + +#endif diff --git a/JavaScriptCore/wtf/text/CString.cpp b/JavaScriptCore/wtf/text/CString.cpp new file mode 100644 index 0000000..d93a5a3 --- /dev/null +++ b/JavaScriptCore/wtf/text/CString.cpp @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2003, 2006, 2008, 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. + */ + + +#include "config.h" +#include "CString.h" + +using std::min; + +namespace WTF { + +CString::CString(const char* str) +{ + init(str, strlen(str)); +} + +CString::CString(const char* str, unsigned length) +{ + init(str, length); +} + +void CString::init(const char* str, unsigned length) +{ + if (!str) + return; + + m_buffer = CStringBuffer::create(length + 1); + memcpy(m_buffer->mutableData(), str, length); + m_buffer->mutableData()[length] = '\0'; +} + +const char* CString::data() const +{ + return m_buffer ? m_buffer->data() : 0; +} + +char* CString::mutableData() +{ + copyBufferIfNeeded(); + if (!m_buffer) + return 0; + return m_buffer->mutableData(); +} + +unsigned CString::length() const +{ + return m_buffer ? m_buffer->length() - 1 : 0; +} + +CString CString::newUninitialized(size_t length, char*& characterBuffer) +{ + CString result; + result.m_buffer = CStringBuffer::create(length + 1); + char* bytes = result.m_buffer->mutableData(); + bytes[length] = '\0'; + characterBuffer = bytes; + return result; +} + +void CString::copyBufferIfNeeded() +{ + if (!m_buffer || m_buffer->hasOneRef()) + return; + + int len = m_buffer->length(); + RefPtr<CStringBuffer> m_temp = m_buffer; + m_buffer = CStringBuffer::create(len); + memcpy(m_buffer->mutableData(), m_temp->data(), len); +} + +bool operator==(const CString& a, const CString& b) +{ + if (a.isNull() != b.isNull()) + return false; + if (a.length() != b.length()) + return false; + return !strncmp(a.data(), b.data(), min(a.length(), b.length())); +} + +} // namespace WTF diff --git a/JavaScriptCore/wtf/text/CString.h b/JavaScriptCore/wtf/text/CString.h new file mode 100644 index 0000000..47f7675 --- /dev/null +++ b/JavaScriptCore/wtf/text/CString.h @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2003, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE 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 CString_h +#define CString_h + +#include "PassRefPtr.h" +#include "RefCounted.h" +#include "Vector.h" + +namespace WTF { + +class CStringBuffer : public RefCounted<CStringBuffer> { +public: + const char* data() { return m_vector.data(); } + size_t length() { return m_vector.size(); } + +private: + friend class CString; + + static PassRefPtr<CStringBuffer> create(unsigned length) { return adoptRef(new CStringBuffer(length)); } + CStringBuffer(unsigned length) : m_vector(length) { } + char* mutableData() { return m_vector.data(); } + + Vector<char> m_vector; +}; + +// A container for a null-terminated char array supporting copy-on-write +// assignment. The contained char array may be null. +class CString { +public: + CString() { } + CString(const char*); + CString(const char*, unsigned length); + CString(CStringBuffer* buffer) : m_buffer(buffer) { } + static CString newUninitialized(size_t length, char*& characterBuffer); + + const char* data() const; + char* mutableData(); + unsigned length() const; + + bool isNull() const { return !m_buffer; } + + CStringBuffer* buffer() const { return m_buffer.get(); } + +private: + void copyBufferIfNeeded(); + void init(const char*, unsigned length); + RefPtr<CStringBuffer> m_buffer; +}; + +bool operator==(const CString& a, const CString& b); +inline bool operator!=(const CString& a, const CString& b) { return !(a == b); } + +} // namespace WTF + +using WTF::CString; + +#endif // CString_h diff --git a/JavaScriptCore/wtf/text/StringBuffer.h b/JavaScriptCore/wtf/text/StringBuffer.h new file mode 100644 index 0000000..353a44a --- /dev/null +++ b/JavaScriptCore/wtf/text/StringBuffer.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2008 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. + * 3. Neither the name of Apple Inc. ("Apple") 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 APPLE 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 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 StringBuffer_h +#define StringBuffer_h + +#include <wtf/Assertions.h> +#include <wtf/Noncopyable.h> +#include <wtf/unicode/Unicode.h> + +namespace WebCore { + +class StringBuffer : public Noncopyable { +public: + explicit StringBuffer(unsigned length) + : m_length(length) + , m_data(static_cast<UChar*>(fastMalloc(length * sizeof(UChar)))) + { + } + ~StringBuffer() + { + fastFree(m_data); + } + + void shrink(unsigned newLength) + { + ASSERT(newLength <= m_length); + m_length = newLength; + } + + void resize(unsigned newLength) + { + if (newLength > m_length) + m_data = static_cast<UChar*>(fastRealloc(m_data, newLength * sizeof(UChar))); + m_length = newLength; + } + + unsigned length() const { return m_length; } + UChar* characters() { return m_data; } + + UChar& operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; } + + UChar* release() { UChar* data = m_data; m_data = 0; return data; } + +private: + unsigned m_length; + UChar* m_data; +}; + +} + +#endif diff --git a/JavaScriptCore/wtf/text/StringHash.h b/JavaScriptCore/wtf/text/StringHash.h new file mode 100644 index 0000000..b820004 --- /dev/null +++ b/JavaScriptCore/wtf/text/StringHash.h @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved + * Copyright (C) Research In Motion Limited 2009. 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 StringHash_h +#define StringHash_h + +#include "AtomicString.h" +#include "WTFString.h" +#include <wtf/HashTraits.h> +#include <wtf/StringHashFunctions.h> +#include <wtf/unicode/Unicode.h> + +// FIXME: This is a temporary layering violation while we move string code to WTF. +// Landing the file moves in one patch, will follow on with patches to change the namespaces. +namespace WebCore { + + // The hash() functions on StringHash and CaseFoldingHash do not support + // null strings. get(), contains(), and add() on HashMap<String,..., StringHash> + // cause a null-pointer dereference when passed null strings. + + // FIXME: We should really figure out a way to put the computeHash function that's + // currently a member function of StringImpl into this file so we can be a little + // closer to having all the nearly-identical hash functions in one place. + + struct StringHash { + static unsigned hash(StringImpl* key) { return key->hash(); } + static bool equal(const StringImpl* a, const StringImpl* b) + { + if (a == b) + return true; + if (!a || !b) + return false; + + unsigned aLength = a->length(); + unsigned bLength = b->length(); + if (aLength != bLength) + return false; + + // FIXME: perhaps we should have a more abstract macro that indicates when + // going 4 bytes at a time is unsafe +#if CPU(ARM) || CPU(SH4) + const UChar* aChars = a->characters(); + const UChar* bChars = b->characters(); + for (unsigned i = 0; i != aLength; ++i) { + if (*aChars++ != *bChars++) + return false; + } + return true; +#else + /* Do it 4-bytes-at-a-time on architectures where it's safe */ + const uint32_t* aChars = reinterpret_cast<const uint32_t*>(a->characters()); + const uint32_t* bChars = reinterpret_cast<const uint32_t*>(b->characters()); + + unsigned halfLength = aLength >> 1; + for (unsigned i = 0; i != halfLength; ++i) + if (*aChars++ != *bChars++) + return false; + + if (aLength & 1 && *reinterpret_cast<const uint16_t*>(aChars) != *reinterpret_cast<const uint16_t*>(bChars)) + return false; + + return true; +#endif + } + + static unsigned hash(const RefPtr<StringImpl>& key) { return key->hash(); } + static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b) + { + return equal(a.get(), b.get()); + } + + static unsigned hash(const String& key) { return key.impl()->hash(); } + static bool equal(const String& a, const String& b) + { + return equal(a.impl(), b.impl()); + } + + static const bool safeToCompareToEmptyOrDeleted = false; + }; + + class CaseFoldingHash { + public: + // Paul Hsieh's SuperFastHash + // http://www.azillionmonkeys.com/qed/hash.html + static unsigned hash(const UChar* data, unsigned length) + { + unsigned l = length; + const UChar* s = data; + uint32_t hash = WTF::stringHashingStartValue; + uint32_t tmp; + + int rem = l & 1; + l >>= 1; + + // Main loop. + for (; l > 0; l--) { + hash += WTF::Unicode::foldCase(s[0]); + tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + s += 2; + hash += hash >> 11; + } + + // Handle end case. + if (rem) { + hash += WTF::Unicode::foldCase(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. + hash |= !hash << 31; + + return hash; + } + + static unsigned hash(StringImpl* str) + { + return hash(str->characters(), str->length()); + } + + static unsigned hash(const char* str, unsigned length) + { + // 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 will give matching results. + + unsigned l = length; + const char* s = str; + uint32_t hash = WTF::stringHashingStartValue; + uint32_t tmp; + + int rem = l & 1; + l >>= 1; + + // Main loop + for (; l > 0; l--) { + hash += WTF::Unicode::foldCase(s[0]); + tmp = (WTF::Unicode::foldCase(s[1]) << 11) ^ hash; + hash = (hash << 16) ^ tmp; + s += 2; + hash += hash >> 11; + } + + // Handle end case + if (rem) { + hash += WTF::Unicode::foldCase(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 + hash |= !hash << 31; + + return hash; + } + + static bool equal(const StringImpl* a, const StringImpl* b) + { + if (a == b) + return true; + if (!a || !b) + return false; + unsigned length = a->length(); + if (length != b->length()) + return false; + return WTF::Unicode::umemcasecmp(a->characters(), b->characters(), length) == 0; + } + + static unsigned hash(const RefPtr<StringImpl>& key) + { + return hash(key.get()); + } + + static bool equal(const RefPtr<StringImpl>& a, const RefPtr<StringImpl>& b) + { + return equal(a.get(), b.get()); + } + + static unsigned hash(const String& key) + { + return hash(key.impl()); + } + static unsigned hash(const AtomicString& key) + { + return hash(key.impl()); + } + static bool equal(const String& a, const String& b) + { + return equal(a.impl(), b.impl()); + } + static bool equal(const AtomicString& a, const AtomicString& b) + { + return (a == b) || equal(a.impl(), b.impl()); + } + + static const bool safeToCompareToEmptyOrDeleted = false; + }; + + // This hash can be used in cases where the key is a hash of a string, but we don't + // want to store the string. It's not really specific to string hashing, but all our + // current uses of it are for strings. + struct AlreadyHashed : IntHash<unsigned> { + static unsigned hash(unsigned key) { return key; } + + // To use a hash value as a key for a hash table, we need to eliminate the + // "deleted" value, which is negative one. That could be done by changing + // the string hash function to never generate negative one, but this works + // and is still relatively efficient. + static unsigned avoidDeletedValue(unsigned hash) + { + ASSERT(hash); + unsigned newHash = hash | (!(hash + 1) << 31); + ASSERT(newHash); + ASSERT(newHash != 0xFFFFFFFF); + return newHash; + } + }; + +} + +namespace WTF { + + template<> struct HashTraits<WebCore::String> : GenericHashTraits<WebCore::String> { + static const bool emptyValueIsZero = true; + static void constructDeletedValue(WebCore::String& slot) { new (&slot) WebCore::String(HashTableDeletedValue); } + static bool isDeletedValue(const WebCore::String& slot) { return slot.isHashTableDeletedValue(); } + }; + +} + +#endif diff --git a/JavaScriptCore/wtf/text/StringImpl.cpp b/JavaScriptCore/wtf/text/StringImpl.cpp new file mode 100644 index 0000000..287e529 --- /dev/null +++ b/JavaScriptCore/wtf/text/StringImpl.cpp @@ -0,0 +1,953 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2001 Dirk Mueller ( mueller@kde.org ) + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) + * + * 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 "StringImpl.h" + +#include "AtomicString.h" +#include "StringBuffer.h" +#include "StringHash.h" +#include <wtf/StdLibExtras.h> +#include <wtf/WTFThreadData.h> + +using namespace WTF; +using namespace Unicode; + +namespace WebCore { + +static const unsigned minLengthToShare = 20; + +StringImpl::~StringImpl() +{ + ASSERT(!isStatic()); + + if (inTable()) + AtomicString::remove(this); +#if USE(JSC) + if (isIdentifier()) + wtfThreadData().currentIdentifierTable()->remove(this); +#endif + + BufferOwnership ownership = bufferOwnership(); + if (ownership != BufferInternal) { + if (ownership == BufferOwned) { + ASSERT(!m_sharedBuffer); + ASSERT(m_data); + fastFree(const_cast<UChar*>(m_data)); + } else if (ownership == BufferSubstring) { + ASSERT(m_substringBuffer); + m_substringBuffer->deref(); + } else { + ASSERT(ownership == BufferShared); + ASSERT(m_sharedBuffer); + m_sharedBuffer->deref(); + } + } +} + +StringImpl* StringImpl::empty() +{ + // FIXME: This works around a bug in our port of PCRE, that a regular expression + // run on the empty string may still perform a read from the first element, and + // as such we need this to be a valid pointer. No code should ever be reading + // from a zero length string, so this should be able to be a non-null pointer + // into the zero-page. + // Replace this with 'reinterpret_cast<UChar*>(static_cast<intptr_t>(1))' once + // PCRE goes away. + static UChar emptyUCharData = 0; + DEFINE_STATIC_LOCAL(StringImpl, emptyString, (&emptyUCharData, 0, ConstructStaticString)); + return &emptyString; +} + +PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, UChar*& data) +{ + if (!length) { + data = 0; + return empty(); + } + + // Allocate a single buffer large enough to contain the StringImpl + // struct as well as the data which it contains. This removes one + // heap allocation from this call. + if (length > ((std::numeric_limits<size_t>::max() - sizeof(StringImpl)) / sizeof(UChar))) + CRASH(); + size_t size = sizeof(StringImpl) + length * sizeof(UChar); + StringImpl* string = static_cast<StringImpl*>(fastMalloc(size)); + + data = reinterpret_cast<UChar*>(string + 1); + return adoptRef(new (string) StringImpl(length)); +} + +PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length) +{ + if (!characters || !length) + return empty(); + + UChar* data; + PassRefPtr<StringImpl> string = createUninitialized(length, data); + memcpy(data, characters, length * sizeof(UChar)); + return string; +} + +PassRefPtr<StringImpl> StringImpl::create(const char* characters, unsigned length) +{ + if (!characters || !length) + return empty(); + + UChar* data; + PassRefPtr<StringImpl> string = createUninitialized(length, data); + for (unsigned i = 0; i != length; ++i) { + unsigned char c = characters[i]; + data[i] = c; + } + return string; +} + +PassRefPtr<StringImpl> StringImpl::create(const char* string) +{ + if (!string) + return empty(); + return create(string, strlen(string)); +} + +PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) +{ + ASSERT(characters); + ASSERT(minLengthToShare && length >= minLengthToShare); + return adoptRef(new StringImpl(characters, length, sharedBuffer)); +} + +SharedUChar* StringImpl::sharedBuffer() +{ + if (m_length < minLengthToShare) + return 0; + // All static strings are smaller that the minimim length to share. + ASSERT(!isStatic()); + + BufferOwnership ownership = bufferOwnership(); + + if (ownership == BufferInternal) + return 0; + if (ownership == BufferSubstring) + return m_substringBuffer->sharedBuffer(); + if (ownership == BufferOwned) { + ASSERT(!m_sharedBuffer); + m_sharedBuffer = SharedUChar::create(new SharableUChar(m_data)).releaseRef(); + m_refCountAndFlags = (m_refCountAndFlags & ~s_refCountMaskBufferOwnership) | BufferShared; + } + + ASSERT(bufferOwnership() == BufferShared); + ASSERT(m_sharedBuffer); + return m_sharedBuffer; +} + +bool StringImpl::containsOnlyWhitespace() +{ + // FIXME: The definition of whitespace here includes a number of characters + // that are not whitespace from the point of view of RenderText; I wonder if + // that's a problem in practice. + for (unsigned i = 0; i < m_length; i++) + if (!isASCIISpace(m_data[i])) + return false; + return true; +} + +PassRefPtr<StringImpl> StringImpl::substring(unsigned start, unsigned length) +{ + if (start >= m_length) + return empty(); + unsigned maxLength = m_length - start; + if (length >= maxLength) { + if (!start) + return this; + length = maxLength; + } + return create(m_data + start, length); +} + +UChar32 StringImpl::characterStartingAt(unsigned i) +{ + if (U16_IS_SINGLE(m_data[i])) + return m_data[i]; + if (i + 1 < m_length && U16_IS_LEAD(m_data[i]) && U16_IS_TRAIL(m_data[i + 1])) + return U16_GET_SUPPLEMENTARY(m_data[i], m_data[i + 1]); + return 0; +} + +PassRefPtr<StringImpl> StringImpl::lower() +{ + // Note: This is a hot function in the Dromaeo benchmark, specifically the + // no-op code path up through the first 'return' statement. + + // First scan the string for uppercase and non-ASCII characters: + UChar ored = 0; + bool noUpper = true; + const UChar *end = m_data + m_length; + for (const UChar* chp = m_data; chp != end; chp++) { + if (UNLIKELY(isASCIIUpper(*chp))) + noUpper = false; + ored |= *chp; + } + + // Nothing to do if the string is all ASCII with no uppercase. + if (noUpper && !(ored & ~0x7F)) + return this; + + int32_t length = m_length; + UChar* data; + RefPtr<StringImpl> newImpl = createUninitialized(m_length, data); + + if (!(ored & ~0x7F)) { + // Do a faster loop for the case where all the characters are ASCII. + for (int i = 0; i < length; i++) { + UChar c = m_data[i]; + data[i] = toASCIILower(c); + } + return newImpl; + } + + // Do a slower implementation for cases that include non-ASCII characters. + bool error; + int32_t realLength = Unicode::toLower(data, length, m_data, m_length, &error); + if (!error && realLength == length) + return newImpl; + newImpl = createUninitialized(realLength, data); + Unicode::toLower(data, realLength, m_data, m_length, &error); + if (error) + return this; + return newImpl; +} + +PassRefPtr<StringImpl> StringImpl::upper() +{ + // This function could be optimized for no-op cases the way lower() is, + // but in empirical testing, few actual calls to upper() are no-ops, so + // it wouldn't be worth the extra time for pre-scanning. + UChar* data; + PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data); + int32_t length = m_length; + + // Do a faster loop for the case where all the characters are ASCII. + UChar ored = 0; + for (int i = 0; i < length; i++) { + UChar c = m_data[i]; + ored |= c; + data[i] = toASCIIUpper(c); + } + if (!(ored & ~0x7F)) + return newImpl; + + // Do a slower implementation for cases that include non-ASCII characters. + bool error; + int32_t realLength = Unicode::toUpper(data, length, m_data, m_length, &error); + if (!error && realLength == length) + return newImpl; + newImpl = createUninitialized(realLength, data); + Unicode::toUpper(data, realLength, m_data, m_length, &error); + if (error) + return this; + return newImpl; +} + +PassRefPtr<StringImpl> StringImpl::secure(UChar aChar) +{ + UChar* data; + PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data); + int32_t length = m_length; + for (int i = 0; i < length; ++i) + data[i] = aChar; + return newImpl; +} + +PassRefPtr<StringImpl> StringImpl::foldCase() +{ + UChar* data; + PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data); + int32_t length = m_length; + + // Do a faster loop for the case where all the characters are ASCII. + UChar ored = 0; + for (int i = 0; i < length; i++) { + UChar c = m_data[i]; + ored |= c; + data[i] = toASCIILower(c); + } + if (!(ored & ~0x7F)) + return newImpl; + + // Do a slower implementation for cases that include non-ASCII characters. + bool error; + int32_t realLength = Unicode::foldCase(data, length, m_data, m_length, &error); + if (!error && realLength == length) + return newImpl; + newImpl = createUninitialized(realLength, data); + Unicode::foldCase(data, realLength, m_data, m_length, &error); + if (error) + return this; + return newImpl; +} + +PassRefPtr<StringImpl> StringImpl::stripWhiteSpace() +{ + if (!m_length) + return empty(); + + unsigned start = 0; + unsigned end = m_length - 1; + + // skip white space from start + while (start <= end && isSpaceOrNewline(m_data[start])) + start++; + + // only white space + if (start > end) + return empty(); + + // skip white space from end + while (end && isSpaceOrNewline(m_data[end])) + end--; + + if (!start && end == m_length - 1) + return this; + return create(m_data + start, end + 1 - start); +} + +PassRefPtr<StringImpl> StringImpl::removeCharacters(CharacterMatchFunctionPtr findMatch) +{ + const UChar* from = m_data; + const UChar* fromend = from + m_length; + + // Assume the common case will not remove any characters + while (from != fromend && !findMatch(*from)) + from++; + if (from == fromend) + return this; + + StringBuffer data(m_length); + UChar* to = data.characters(); + unsigned outc = from - m_data; + + if (outc) + memcpy(to, m_data, outc * sizeof(UChar)); + + while (true) { + while (from != fromend && findMatch(*from)) + from++; + while (from != fromend && !findMatch(*from)) + to[outc++] = *from++; + if (from == fromend) + break; + } + + data.shrink(outc); + + return adopt(data); +} + +PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace() +{ + StringBuffer data(m_length); + + const UChar* from = m_data; + const UChar* fromend = from + m_length; + int outc = 0; + bool changedToSpace = false; + + UChar* to = data.characters(); + + while (true) { + while (from != fromend && isSpaceOrNewline(*from)) { + if (*from != ' ') + changedToSpace = true; + from++; + } + while (from != fromend && !isSpaceOrNewline(*from)) + to[outc++] = *from++; + if (from != fromend) + to[outc++] = ' '; + else + break; + } + + if (outc > 0 && to[outc - 1] == ' ') + outc--; + + if (static_cast<unsigned>(outc) == m_length && !changedToSpace) + return this; + + data.shrink(outc); + + return adopt(data); +} + +int StringImpl::toIntStrict(bool* ok, int base) +{ + return charactersToIntStrict(m_data, m_length, ok, base); +} + +unsigned StringImpl::toUIntStrict(bool* ok, int base) +{ + return charactersToUIntStrict(m_data, m_length, ok, base); +} + +int64_t StringImpl::toInt64Strict(bool* ok, int base) +{ + return charactersToInt64Strict(m_data, m_length, ok, base); +} + +uint64_t StringImpl::toUInt64Strict(bool* ok, int base) +{ + return charactersToUInt64Strict(m_data, m_length, ok, base); +} + +intptr_t StringImpl::toIntPtrStrict(bool* ok, int base) +{ + return charactersToIntPtrStrict(m_data, m_length, ok, base); +} + +int StringImpl::toInt(bool* ok) +{ + return charactersToInt(m_data, m_length, ok); +} + +unsigned StringImpl::toUInt(bool* ok) +{ + return charactersToUInt(m_data, m_length, ok); +} + +int64_t StringImpl::toInt64(bool* ok) +{ + return charactersToInt64(m_data, m_length, ok); +} + +uint64_t StringImpl::toUInt64(bool* ok) +{ + return charactersToUInt64(m_data, m_length, ok); +} + +intptr_t StringImpl::toIntPtr(bool* ok) +{ + return charactersToIntPtr(m_data, m_length, ok); +} + +double StringImpl::toDouble(bool* ok) +{ + return charactersToDouble(m_data, m_length, ok); +} + +float StringImpl::toFloat(bool* ok) +{ + return charactersToFloat(m_data, m_length, ok); +} + +static bool equal(const UChar* a, const char* b, int length) +{ + ASSERT(length >= 0); + while (length--) { + unsigned char bc = *b++; + if (*a++ != bc) + return false; + } + return true; +} + +bool equalIgnoringCase(const UChar* a, const char* b, unsigned length) +{ + while (length--) { + unsigned char bc = *b++; + if (foldCase(*a++) != foldCase(bc)) + return false; + } + return true; +} + +static inline bool equalIgnoringCase(const UChar* a, const UChar* b, int length) +{ + ASSERT(length >= 0); + return umemcasecmp(a, b, length) == 0; +} + +int StringImpl::find(const char* chs, int index, bool caseSensitive) +{ + if (!chs || index < 0) + return -1; + + int chsLength = strlen(chs); + int n = m_length - index; + if (n < 0) + return -1; + n -= chsLength - 1; + if (n <= 0) + return -1; + + const char* chsPlusOne = chs + 1; + int chsLengthMinusOne = chsLength - 1; + + const UChar* ptr = m_data + index - 1; + if (caseSensitive) { + UChar c = *chs; + do { + if (*++ptr == c && equal(ptr + 1, chsPlusOne, chsLengthMinusOne)) + return m_length - chsLength - n + 1; + } while (--n); + } else { + UChar lc = Unicode::foldCase(*chs); + do { + if (Unicode::foldCase(*++ptr) == lc && equalIgnoringCase(ptr + 1, chsPlusOne, chsLengthMinusOne)) + return m_length - chsLength - n + 1; + } while (--n); + } + + return -1; +} + +int StringImpl::find(UChar c, int start) +{ + return WebCore::find(m_data, m_length, c, start); +} + +int StringImpl::find(CharacterMatchFunctionPtr matchFunction, int start) +{ + return WebCore::find(m_data, m_length, matchFunction, start); +} + +int StringImpl::find(StringImpl* str, int index, bool caseSensitive) +{ + /* + We use a simple trick for efficiency's sake. Instead of + comparing strings, we compare the sum of str with that of + a part of this string. Only if that matches, we call memcmp + or ucstrnicmp. + */ + ASSERT(str); + if (index < 0) + index += m_length; + int lstr = str->m_length; + int lthis = m_length - index; + if ((unsigned)lthis > m_length) + return -1; + int delta = lthis - lstr; + if (delta < 0) + return -1; + + const UChar* uthis = m_data + index; + const UChar* ustr = str->m_data; + unsigned hthis = 0; + unsigned hstr = 0; + if (caseSensitive) { + for (int i = 0; i < lstr; i++) { + hthis += uthis[i]; + hstr += ustr[i]; + } + int i = 0; + while (1) { + if (hthis == hstr && memcmp(uthis + i, ustr, lstr * sizeof(UChar)) == 0) + return index + i; + if (i == delta) + return -1; + hthis += uthis[i + lstr]; + hthis -= uthis[i]; + i++; + } + } else { + for (int i = 0; i < lstr; i++ ) { + hthis += toASCIILower(uthis[i]); + hstr += toASCIILower(ustr[i]); + } + int i = 0; + while (1) { + if (hthis == hstr && equalIgnoringCase(uthis + i, ustr, lstr)) + return index + i; + if (i == delta) + return -1; + hthis += toASCIILower(uthis[i + lstr]); + hthis -= toASCIILower(uthis[i]); + i++; + } + } +} + +int StringImpl::reverseFind(UChar c, int index) +{ + return WebCore::reverseFind(m_data, m_length, c, index); +} + +int StringImpl::reverseFind(StringImpl* str, int index, bool caseSensitive) +{ + /* + See StringImpl::find() for explanations. + */ + ASSERT(str); + int lthis = m_length; + if (index < 0) + index += lthis; + + int lstr = str->m_length; + int delta = lthis - lstr; + if ( index < 0 || index > lthis || delta < 0 ) + return -1; + if ( index > delta ) + index = delta; + + const UChar *uthis = m_data; + const UChar *ustr = str->m_data; + unsigned hthis = 0; + unsigned hstr = 0; + int i; + if (caseSensitive) { + for ( i = 0; i < lstr; i++ ) { + hthis += uthis[index + i]; + hstr += ustr[i]; + } + i = index; + while (1) { + if (hthis == hstr && memcmp(uthis + i, ustr, lstr * sizeof(UChar)) == 0) + return i; + if (i == 0) + return -1; + i--; + hthis -= uthis[i + lstr]; + hthis += uthis[i]; + } + } else { + for (i = 0; i < lstr; i++) { + hthis += toASCIILower(uthis[index + i]); + hstr += toASCIILower(ustr[i]); + } + i = index; + while (1) { + if (hthis == hstr && equalIgnoringCase(uthis + i, ustr, lstr) ) + return i; + if (i == 0) + return -1; + i--; + hthis -= toASCIILower(uthis[i + lstr]); + hthis += toASCIILower(uthis[i]); + } + } + + // Should never get here. + return -1; +} + +bool StringImpl::endsWith(StringImpl* m_data, bool caseSensitive) +{ + ASSERT(m_data); + int start = m_length - m_data->m_length; + if (start >= 0) + return (find(m_data, start, caseSensitive) == start); + return false; +} + +PassRefPtr<StringImpl> StringImpl::replace(UChar oldC, UChar newC) +{ + if (oldC == newC) + return this; + unsigned i; + for (i = 0; i != m_length; ++i) + if (m_data[i] == oldC) + break; + if (i == m_length) + return this; + + UChar* data; + PassRefPtr<StringImpl> newImpl = createUninitialized(m_length, data); + + for (i = 0; i != m_length; ++i) { + UChar ch = m_data[i]; + if (ch == oldC) + ch = newC; + data[i] = ch; + } + return newImpl; +} + +PassRefPtr<StringImpl> StringImpl::replace(unsigned position, unsigned lengthToReplace, StringImpl* str) +{ + position = min(position, length()); + lengthToReplace = min(lengthToReplace, length() - position); + unsigned lengthToInsert = str ? str->length() : 0; + if (!lengthToReplace && !lengthToInsert) + return this; + UChar* data; + PassRefPtr<StringImpl> newImpl = + createUninitialized(length() - lengthToReplace + lengthToInsert, data); + memcpy(data, characters(), position * sizeof(UChar)); + if (str) + memcpy(data + position, str->characters(), lengthToInsert * sizeof(UChar)); + memcpy(data + position + lengthToInsert, characters() + position + lengthToReplace, + (length() - position - lengthToReplace) * sizeof(UChar)); + return newImpl; +} + +PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacement) +{ + if (!replacement) + return this; + + int repStrLength = replacement->length(); + int srcSegmentStart = 0; + int matchCount = 0; + + // Count the matches + while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) { + ++matchCount; + ++srcSegmentStart; + } + + // If we have 0 matches, we don't have to do any more work + if (!matchCount) + return this; + + UChar* data; + PassRefPtr<StringImpl> newImpl = + createUninitialized(m_length - matchCount + (matchCount * repStrLength), data); + + // Construct the new data + int srcSegmentEnd; + int srcSegmentLength; + srcSegmentStart = 0; + int dstOffset = 0; + + while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) { + srcSegmentLength = srcSegmentEnd - srcSegmentStart; + memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); + dstOffset += srcSegmentLength; + memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar)); + dstOffset += repStrLength; + srcSegmentStart = srcSegmentEnd + 1; + } + + srcSegmentLength = m_length - srcSegmentStart; + memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); + + ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length())); + + return newImpl; +} + +PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* replacement) +{ + if (!pattern || !replacement) + return this; + + int patternLength = pattern->length(); + if (!patternLength) + return this; + + int repStrLength = replacement->length(); + int srcSegmentStart = 0; + int matchCount = 0; + + // Count the matches + while ((srcSegmentStart = find(pattern, srcSegmentStart)) >= 0) { + ++matchCount; + srcSegmentStart += patternLength; + } + + // If we have 0 matches, we don't have to do any more work + if (!matchCount) + return this; + + UChar* data; + PassRefPtr<StringImpl> newImpl = + createUninitialized(m_length + matchCount * (repStrLength - patternLength), data); + + // Construct the new data + int srcSegmentEnd; + int srcSegmentLength; + srcSegmentStart = 0; + int dstOffset = 0; + + while ((srcSegmentEnd = find(pattern, srcSegmentStart)) >= 0) { + srcSegmentLength = srcSegmentEnd - srcSegmentStart; + memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); + dstOffset += srcSegmentLength; + memcpy(data + dstOffset, replacement->m_data, repStrLength * sizeof(UChar)); + dstOffset += repStrLength; + srcSegmentStart = srcSegmentEnd + patternLength; + } + + srcSegmentLength = m_length - srcSegmentStart; + memcpy(data + dstOffset, m_data + srcSegmentStart, srcSegmentLength * sizeof(UChar)); + + ASSERT(dstOffset + srcSegmentLength == static_cast<int>(newImpl->length())); + + return newImpl; +} + +bool equal(const StringImpl* a, const StringImpl* b) +{ + return StringHash::equal(a, b); +} + +bool equal(const StringImpl* a, const char* b) +{ + if (!a) + return !b; + if (!b) + return !a; + + unsigned length = a->length(); + const UChar* as = a->characters(); + for (unsigned i = 0; i != length; ++i) { + unsigned char bc = b[i]; + if (!bc) + return false; + if (as[i] != bc) + return false; + } + + return !b[length]; +} + +bool equalIgnoringCase(StringImpl* a, StringImpl* b) +{ + return CaseFoldingHash::equal(a, b); +} + +bool equalIgnoringCase(StringImpl* a, const char* b) +{ + if (!a) + return !b; + if (!b) + return !a; + + unsigned length = a->length(); + const UChar* as = a->characters(); + + // Do a faster loop for the case where all the characters are ASCII. + UChar ored = 0; + bool equal = true; + for (unsigned i = 0; i != length; ++i) { + char bc = b[i]; + if (!bc) + return false; + UChar ac = as[i]; + ored |= ac; + equal = equal && (toASCIILower(ac) == toASCIILower(bc)); + } + + // Do a slower implementation for cases that include non-ASCII characters. + if (ored & ~0x7F) { + equal = true; + for (unsigned i = 0; i != length; ++i) { + unsigned char bc = b[i]; + equal = equal && (foldCase(as[i]) == foldCase(bc)); + } + } + + return equal && !b[length]; +} + +bool equalIgnoringNullity(StringImpl* a, StringImpl* b) +{ + if (StringHash::equal(a, b)) + return true; + if (!a && b && !b->length()) + return true; + if (!b && a && !a->length()) + return true; + + return false; +} + +Vector<char> StringImpl::ascii() +{ + Vector<char> buffer(m_length + 1); + for (unsigned i = 0; i != m_length; ++i) { + UChar c = m_data[i]; + if ((c >= 0x20 && c < 0x7F) || c == 0x00) + buffer[i] = c; + else + buffer[i] = '?'; + } + buffer[m_length] = '\0'; + return buffer; +} + +WTF::Unicode::Direction StringImpl::defaultWritingDirection() +{ + for (unsigned i = 0; i < m_length; ++i) { + WTF::Unicode::Direction charDirection = WTF::Unicode::direction(m_data[i]); + if (charDirection == WTF::Unicode::LeftToRight) + return WTF::Unicode::LeftToRight; + if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic) + return WTF::Unicode::RightToLeft; + } + return WTF::Unicode::LeftToRight; +} + +// This is a hot function because it's used when parsing HTML. +PassRefPtr<StringImpl> StringImpl::createStrippingNullCharactersSlowCase(const UChar* characters, unsigned length) +{ + StringBuffer strippedCopy(length); + unsigned strippedLength = 0; + for (unsigned i = 0; i < length; i++) { + if (int c = characters[i]) + strippedCopy[strippedLength++] = c; + } + ASSERT(strippedLength < length); // Only take the slow case when stripping. + strippedCopy.shrink(strippedLength); + return adopt(strippedCopy); +} + +PassRefPtr<StringImpl> StringImpl::adopt(StringBuffer& buffer) +{ + unsigned length = buffer.length(); + if (length == 0) + return empty(); + return adoptRef(new StringImpl(buffer.release(), length)); +} + +PassRefPtr<StringImpl> StringImpl::createWithTerminatingNullCharacter(const StringImpl& string) +{ + // Use createUninitialized instead of 'new StringImpl' so that the string and its buffer + // get allocated in a single malloc block. + UChar* data; + int length = string.m_length; + RefPtr<StringImpl> terminatedString = createUninitialized(length + 1, data); + memcpy(data, string.m_data, length * sizeof(UChar)); + data[length] = 0; + terminatedString->m_length--; + terminatedString->m_hash = string.m_hash; + terminatedString->m_refCountAndFlags |= s_refCountFlagHasTerminatingNullCharacter; + return terminatedString.release(); +} + +PassRefPtr<StringImpl> StringImpl::threadsafeCopy() const +{ + return create(m_data, m_length); +} + +PassRefPtr<StringImpl> StringImpl::crossThreadString() +{ + if (SharedUChar* sharedBuffer = this->sharedBuffer()) + return adoptRef(new StringImpl(m_data, m_length, sharedBuffer->crossThreadCopy())); + + // If no shared buffer is available, create a copy. + return threadsafeCopy(); +} + +} // namespace WebCore diff --git a/JavaScriptCore/wtf/text/StringImpl.h b/JavaScriptCore/wtf/text/StringImpl.h new file mode 100644 index 0000000..6ac9e40 --- /dev/null +++ b/JavaScriptCore/wtf/text/StringImpl.h @@ -0,0 +1,389 @@ +/* + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2009 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 + * 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 StringImpl_h +#define StringImpl_h + +#include <limits.h> +#include <wtf/ASCIICType.h> +#include <wtf/CrossThreadRefCounted.h> +#include <wtf/OwnFastMallocPtr.h> +#include <wtf/StringHashFunctions.h> +#include <wtf/Vector.h> +#include <wtf/text/StringImplBase.h> +#include <wtf/unicode/Unicode.h> + +#if PLATFORM(CF) +typedef const struct __CFString * CFStringRef; +#endif + +#ifdef __OBJC__ +@class NSString; +#endif + +// FIXME: This is a temporary layering violation while we move string code to WTF. +// Landing the file moves in one patch, will follow on with patches to change the namespaces. +namespace JSC { + +struct IdentifierCStringTranslator; +struct IdentifierUCharBufferTranslator; + +} + +// FIXME: This is a temporary layering violation while we move string code to WTF. +// Landing the file moves in one patch, will follow on with patches to change the namespaces. +namespace WebCore { + +class StringBuffer; + +struct CStringTranslator; +struct HashAndCharactersTranslator; +struct StringHash; +struct UCharBufferTranslator; + +enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive }; + +typedef OwnFastMallocPtr<const UChar> SharableUChar; +typedef CrossThreadRefCounted<SharableUChar> SharedUChar; +typedef bool (*CharacterMatchFunctionPtr)(UChar); + +class StringImpl : public StringImplBase { + friend struct JSC::IdentifierCStringTranslator; + friend struct JSC::IdentifierUCharBufferTranslator; + friend struct CStringTranslator; + friend struct HashAndCharactersTranslator; + friend struct UCharBufferTranslator; +private: + // 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. + StringImpl(const UChar* characters, unsigned length, StaticStringConstructType) + : StringImplBase(length, ConstructStaticString) + , m_data(characters) + , m_buffer(0) + , m_hash(0) + { + // Ensure that the hash is computed so that AtomicStringHash can call existingHash() + // with impunity. The empty string is special because it is never entered into + // AtomicString's HashKey, but still needs to compare correctly. + hash(); + } + + // Create a normal string with internal storage (BufferInternal) + StringImpl(unsigned length) + : StringImplBase(length, BufferInternal) + , m_data(reinterpret_cast<const UChar*>(this + 1)) + , m_buffer(0) + , m_hash(0) + { + ASSERT(m_data); + ASSERT(m_length); + } + + // Create a StringImpl adopting ownership of the provided buffer (BufferOwned) + StringImpl(const UChar* characters, unsigned length) + : StringImplBase(length, BufferOwned) + , m_data(characters) + , m_buffer(0) + , m_hash(0) + { + ASSERT(m_data); + ASSERT(m_length); + } + + // Used to create new strings that are a substring of an existing StringImpl (BufferSubstring) + StringImpl(const UChar* characters, unsigned length, PassRefPtr<StringImpl> base) + : StringImplBase(length, BufferSubstring) + , m_data(characters) + , m_substringBuffer(base.releaseRef()) + , m_hash(0) + { + ASSERT(m_data); + ASSERT(m_length); + ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring); + } + + // Used to construct new strings sharing an existing SharedUChar (BufferShared) + StringImpl(const UChar* characters, unsigned length, PassRefPtr<SharedUChar> sharedBuffer) + : StringImplBase(length, BufferShared) + , m_data(characters) + , m_sharedBuffer(sharedBuffer.releaseRef()) + , m_hash(0) + { + ASSERT(m_data); + ASSERT(m_length); + } + + // For use only by AtomicString's XXXTranslator helpers. + void setHash(unsigned hash) + { + ASSERT(!isStatic()); + ASSERT(!m_hash); + ASSERT(hash == computeHash(m_data, m_length)); + m_hash = hash; + } + +public: + ~StringImpl(); + + static PassRefPtr<StringImpl> create(const UChar*, unsigned length); + static PassRefPtr<StringImpl> create(const char*, unsigned length); + static PassRefPtr<StringImpl> create(const char*); + static PassRefPtr<StringImpl> create(const UChar*, unsigned length, PassRefPtr<SharedUChar> sharedBuffer); + static PassRefPtr<StringImpl> create(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length) + { + ASSERT(rep); + ASSERT(length <= rep->length()); + + if (!length) + return empty(); + + StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get(); + return adoptRef(new StringImpl(rep->m_data + offset, length, ownerRep)); + } + + static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data); + static PassRefPtr<StringImpl> tryCreateUninitialized(unsigned length, UChar*& output) + { + if (!length) { + output = 0; + return empty(); + } + + if (length > ((std::numeric_limits<size_t>::max() - sizeof(StringImpl)) / sizeof(UChar))) + return 0; + StringImpl* resultImpl; + if (!tryFastMalloc(sizeof(UChar) * length + sizeof(StringImpl)).getValue(resultImpl)) + return 0; + output = reinterpret_cast<UChar*>(resultImpl + 1); + return adoptRef(new(resultImpl) StringImpl(length)); + } + + static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&); + static PassRefPtr<StringImpl> createStrippingNullCharacters(const UChar*, unsigned length); + + template<size_t inlineCapacity> + static PassRefPtr<StringImpl> adopt(Vector<UChar, inlineCapacity>& vector) + { + if (size_t size = vector.size()) { + ASSERT(vector.data()); + return adoptRef(new StringImpl(vector.releaseBuffer(), size)); + } + return empty(); + } + static PassRefPtr<StringImpl> adopt(StringBuffer&); + + SharedUChar* sharedBuffer(); + const UChar* characters() const { return m_data; } + + size_t cost() + { + // For substrings, return the cost of the base string. + if (bufferOwnership() == BufferSubstring) + return m_substringBuffer->cost(); + + if (m_refCountAndFlags & s_refCountFlagShouldReportedCost) { + m_refCountAndFlags &= ~s_refCountFlagShouldReportedCost; + return m_length; + } + return 0; + } + + bool isIdentifier() const { return m_refCountAndFlags & s_refCountFlagIsIdentifier; } + void setIsIdentifier(bool isIdentifier) + { + ASSERT(!isStatic()); + if (isIdentifier) + m_refCountAndFlags |= s_refCountFlagIsIdentifier; + else + m_refCountAndFlags &= ~s_refCountFlagIsIdentifier; + } + + bool hasTerminatingNullCharacter() const { return m_refCountAndFlags & s_refCountFlagHasTerminatingNullCharacter; } + + bool inTable() const { return m_refCountAndFlags & s_refCountFlagInTable; } + void setInTable() { m_refCountAndFlags |= s_refCountFlagInTable; } + + unsigned hash() const { if (!m_hash) m_hash = computeHash(m_data, m_length); return m_hash; } + unsigned existingHash() const { ASSERT(m_hash); return m_hash; } + static unsigned computeHash(const UChar* data, unsigned length) { return WTF::stringHash(data, length); } + static unsigned computeHash(const char* data, unsigned length) { return WTF::stringHash(data, length); } + static unsigned computeHash(const char* data) { return WTF::stringHash(data); } + + ALWAYS_INLINE void deref() { m_refCountAndFlags -= s_refCountIncrement; if (!(m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic))) delete this; } + ALWAYS_INLINE bool hasOneRef() const { return (m_refCountAndFlags & (s_refCountMask | s_refCountFlagStatic)) == s_refCountIncrement; } + + static StringImpl* empty(); + + 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)); + } + + // Returns a StringImpl suitable for use on another thread. + PassRefPtr<StringImpl> crossThreadString(); + // Makes a deep copy. Helpful only if you need to use a String on another thread + // (use crossThreadString if the method call doesn't need to be threadsafe). + // Since StringImpl objects are immutable, there's no other reason to make a copy. + PassRefPtr<StringImpl> threadsafeCopy() const; + + PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX); + + UChar operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; } + UChar32 characterStartingAt(unsigned); + + bool containsOnlyWhitespace(); + + int toIntStrict(bool* ok = 0, int base = 10); + unsigned toUIntStrict(bool* ok = 0, int base = 10); + int64_t toInt64Strict(bool* ok = 0, int base = 10); + uint64_t toUInt64Strict(bool* ok = 0, int base = 10); + intptr_t toIntPtrStrict(bool* ok = 0, int base = 10); + + int toInt(bool* ok = 0); // ignores trailing garbage + unsigned toUInt(bool* ok = 0); // ignores trailing garbage + int64_t toInt64(bool* ok = 0); // ignores trailing garbage + uint64_t toUInt64(bool* ok = 0); // ignores trailing garbage + intptr_t toIntPtr(bool* ok = 0); // ignores trailing garbage + + double toDouble(bool* ok = 0); + float toFloat(bool* ok = 0); + + PassRefPtr<StringImpl> lower(); + PassRefPtr<StringImpl> upper(); + PassRefPtr<StringImpl> secure(UChar aChar); + PassRefPtr<StringImpl> foldCase(); + + PassRefPtr<StringImpl> stripWhiteSpace(); + PassRefPtr<StringImpl> simplifyWhiteSpace(); + + PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr); + + int find(const char*, int index = 0, bool caseSensitive = true); + int find(UChar, int index = 0); + int find(CharacterMatchFunctionPtr, int index = 0); + int find(StringImpl*, int index, bool caseSensitive = true); + + int reverseFind(UChar, int index); + int reverseFind(StringImpl*, int index, bool caseSensitive = true); + + bool startsWith(StringImpl* str, bool caseSensitive = true) { return reverseFind(str, 0, caseSensitive) == 0; } + bool endsWith(StringImpl*, bool caseSensitive = true); + + PassRefPtr<StringImpl> replace(UChar, UChar); + PassRefPtr<StringImpl> replace(UChar, StringImpl*); + PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*); + PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*); + + Vector<char> ascii(); + + WTF::Unicode::Direction defaultWritingDirection(); + +#if PLATFORM(CF) + CFStringRef createCFString(); +#endif +#ifdef __OBJC__ + operator NSString*(); +#endif + +private: + // This number must be at least 2 to avoid sharing empty, null as well as 1 character strings from SmallStrings. + static const unsigned s_copyCharsInlineCutOff = 20; + + static PassRefPtr<StringImpl> createStrippingNullCharactersSlowCase(const UChar*, unsigned length); + + BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_refCountAndFlags & s_refCountMaskBufferOwnership); } + bool isStatic() const { return m_refCountAndFlags & s_refCountFlagStatic; } + + const UChar* m_data; + union { + void* m_buffer; + StringImpl* m_substringBuffer; + SharedUChar* m_sharedBuffer; + }; + mutable unsigned m_hash; +}; + +bool equal(const StringImpl*, const StringImpl*); +bool equal(const StringImpl*, const char*); +inline bool equal(const char* a, StringImpl* b) { return equal(b, a); } + +bool equalIgnoringCase(StringImpl*, StringImpl*); +bool equalIgnoringCase(StringImpl*, const char*); +inline bool equalIgnoringCase(const char* a, StringImpl* b) { return equalIgnoringCase(b, a); } +bool equalIgnoringCase(const UChar* a, const char* b, unsigned length); +inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, a, length); } + +bool equalIgnoringNullity(StringImpl*, StringImpl*); + +static inline bool isSpaceOrNewline(UChar c) +{ + // Use isASCIISpace() for basic Latin-1. + // This will include newlines, which aren't included in Unicode DirWS. + return c <= 0x7F ? WTF::isASCIISpace(c) : WTF::Unicode::direction(c) == WTF::Unicode::WhiteSpaceNeutral; +} + +// This is a hot function because it's used when parsing HTML. +inline PassRefPtr<StringImpl> StringImpl::createStrippingNullCharacters(const UChar* characters, unsigned length) +{ + ASSERT(characters); + ASSERT(length); + + // Optimize for the case where there are no Null characters by quickly + // searching for nulls, and then using StringImpl::create, which will + // memcpy the whole buffer. This is faster than assigning character by + // character during the loop. + + // Fast case. + int foundNull = 0; + for (unsigned i = 0; !foundNull && i < length; i++) { + int c = characters[i]; // more efficient than using UChar here (at least on Intel Mac OS) + foundNull |= !c; + } + if (!foundNull) + return StringImpl::create(characters, length); + + return StringImpl::createStrippingNullCharactersSlowCase(characters, length); +} + +} + +using WebCore::equal; + +namespace WTF { + + // WebCore::StringHash is the default hash for StringImpl* and RefPtr<StringImpl> + template<typename T> struct DefaultHash; + template<> struct DefaultHash<WebCore::StringImpl*> { + typedef WebCore::StringHash Hash; + }; + template<> struct DefaultHash<RefPtr<WebCore::StringImpl> > { + typedef WebCore::StringHash Hash; + }; + +} + +#endif diff --git a/JavaScriptCore/wtf/text/StringImplBase.h b/JavaScriptCore/wtf/text/StringImplBase.h new file mode 100644 index 0000000..a8e3385 --- /dev/null +++ b/JavaScriptCore/wtf/text/StringImplBase.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef StringImplBase_h +#define StringImplBase_h + +#include <wtf/Noncopyable.h> +#include <wtf/unicode/Unicode.h> + +namespace WTF { + +class StringImplBase : public Noncopyable { +public: + bool isStringImpl() { return (m_refCountAndFlags & s_refCountInvalidForStringImpl) != s_refCountInvalidForStringImpl; } + unsigned length() const { return m_length; } + void ref() { m_refCountAndFlags += s_refCountIncrement; } + +protected: + enum BufferOwnership { + BufferInternal, + BufferOwned, + BufferSubstring, + BufferShared, + }; + + using Noncopyable::operator new; + void* operator new(size_t, void* inPlace) { ASSERT(inPlace); return inPlace; } + + // For SmallStringStorage, which allocates an array and uses an in-place new. + StringImplBase() { } + + StringImplBase(unsigned length, BufferOwnership ownership) + : m_refCountAndFlags(s_refCountIncrement | s_refCountFlagShouldReportedCost | ownership) + , m_length(length) + { + ASSERT(isStringImpl()); + } + + enum StaticStringConstructType { ConstructStaticString }; + StringImplBase(unsigned length, StaticStringConstructType) + : m_refCountAndFlags(s_refCountFlagStatic | s_refCountFlagIsIdentifier | BufferOwned) + , m_length(length) + { + ASSERT(isStringImpl()); + } + + // This constructor is not used when creating StringImpl objects, + // and sets the flags into a state marking the object as such. + enum NonStringImplConstructType { ConstructNonStringImpl }; + StringImplBase(NonStringImplConstructType) + : m_refCountAndFlags(s_refCountIncrement | s_refCountInvalidForStringImpl) + , m_length(0) + { + ASSERT(!isStringImpl()); + } + + // The bottom 7 bits hold flags, the top 25 bits hold the ref count. + // When dereferencing StringImpls we check for the ref count AND the + // static bit both being zero - static strings are never deleted. + static const unsigned s_refCountMask = 0xFFFFFF80; + static const unsigned s_refCountIncrement = 0x80; + static const unsigned s_refCountFlagStatic = 0x40; + static const unsigned s_refCountFlagHasTerminatingNullCharacter = 0x20; + static const unsigned s_refCountFlagInTable = 0x10; + static const unsigned s_refCountFlagShouldReportedCost = 0x8; + static const unsigned s_refCountFlagIsIdentifier = 0x4; + static const unsigned s_refCountMaskBufferOwnership = 0x3; + // An invalid permutation of flags (static & shouldReportedCost - static strings do not + // set shouldReportedCost in the constructor, and this bit is only ever cleared, not set). + // Used by "ConstructNonStringImpl" constructor, above. + static const unsigned s_refCountInvalidForStringImpl = s_refCountFlagStatic | s_refCountFlagShouldReportedCost; + + unsigned m_refCountAndFlags; + unsigned m_length; +}; + +} // namespace WTF + +using WTF::StringImplBase; + +#endif diff --git a/JavaScriptCore/wtf/text/WTFString.cpp b/JavaScriptCore/wtf/text/WTFString.cpp new file mode 100644 index 0000000..a683e3d --- /dev/null +++ b/JavaScriptCore/wtf/text/WTFString.cpp @@ -0,0 +1,960 @@ +/* + * (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2007-2009 Torch Mobile, Inc. + * + * 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 "WTFString.h" + +#include <limits> +#include <stdarg.h> +#include <wtf/ASCIICType.h> +#include <wtf/text/CString.h> +#include <wtf/StringExtras.h> +#include <wtf/Vector.h> +#include <wtf/dtoa.h> +#include <wtf/unicode/UTF8.h> +#include <wtf/unicode/Unicode.h> + +using namespace WTF; +using namespace WTF::Unicode; + +namespace WebCore { + +String::String(const UChar* str, unsigned len) +{ + if (!str) + return; + m_impl = StringImpl::create(str, len); +} + +String::String(const UChar* str) +{ + if (!str) + return; + + int len = 0; + while (str[len] != UChar(0)) + len++; + + m_impl = StringImpl::create(str, len); +} + +String::String(const char* str) +{ + if (!str) + return; + m_impl = StringImpl::create(str); +} + +String::String(const char* str, unsigned length) +{ + if (!str) + return; + m_impl = StringImpl::create(str, length); +} + +void String::append(const String& str) +{ + if (str.isEmpty()) + return; + + // FIXME: This is extremely inefficient. So much so that we might want to take this + // out of String's API. We can make it better by optimizing the case where exactly + // one String is pointing at this StringImpl, but even then it's going to require a + // call to fastMalloc every single time. + if (str.m_impl) { + if (m_impl) { + UChar* data; + RefPtr<StringImpl> newImpl = + StringImpl::createUninitialized(m_impl->length() + str.length(), data); + memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); + memcpy(data + m_impl->length(), str.characters(), str.length() * sizeof(UChar)); + m_impl = newImpl.release(); + } else + m_impl = str.m_impl; + } +} + +void String::append(char c) +{ + // FIXME: This is extremely inefficient. So much so that we might want to take this + // out of String's API. We can make it better by optimizing the case where exactly + // one String is pointing at this StringImpl, but even then it's going to require a + // call to fastMalloc every single time. + if (m_impl) { + UChar* data; + RefPtr<StringImpl> newImpl = + StringImpl::createUninitialized(m_impl->length() + 1, data); + memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); + data[m_impl->length()] = c; + m_impl = newImpl.release(); + } else + m_impl = StringImpl::create(&c, 1); +} + +void String::append(UChar c) +{ + // FIXME: This is extremely inefficient. So much so that we might want to take this + // out of String's API. We can make it better by optimizing the case where exactly + // one String is pointing at this StringImpl, but even then it's going to require a + // call to fastMalloc every single time. + if (m_impl) { + UChar* data; + RefPtr<StringImpl> newImpl = + StringImpl::createUninitialized(m_impl->length() + 1, data); + memcpy(data, m_impl->characters(), m_impl->length() * sizeof(UChar)); + data[m_impl->length()] = c; + m_impl = newImpl.release(); + } else + m_impl = StringImpl::create(&c, 1); +} + +String operator+(const String& a, const String& b) +{ + if (a.isEmpty()) + return b; + if (b.isEmpty()) + return a; + String c = a; + c += b; + return c; +} + +String operator+(const String& s, const char* cs) +{ + return s + String(cs); +} + +String operator+(const char* cs, const String& s) +{ + return String(cs) + s; +} + +void String::insert(const String& str, unsigned pos) +{ + if (str.isEmpty()) { + if (str.isNull()) + return; + if (isNull()) + m_impl = str.impl(); + return; + } + insert(str.characters(), str.length(), pos); +} + +void String::append(const UChar* charactersToAppend, unsigned lengthToAppend) +{ + if (!m_impl) { + if (!charactersToAppend) + return; + m_impl = StringImpl::create(charactersToAppend, lengthToAppend); + return; + } + + if (!lengthToAppend) + return; + + ASSERT(charactersToAppend); + UChar* data; + RefPtr<StringImpl> newImpl = + StringImpl::createUninitialized(length() + lengthToAppend, data); + memcpy(data, characters(), length() * sizeof(UChar)); + memcpy(data + length(), charactersToAppend, lengthToAppend * sizeof(UChar)); + m_impl = newImpl.release(); +} + +void String::insert(const UChar* charactersToInsert, unsigned lengthToInsert, unsigned position) +{ + if (position >= length()) { + append(charactersToInsert, lengthToInsert); + return; + } + + ASSERT(m_impl); + + if (!lengthToInsert) + return; + + ASSERT(charactersToInsert); + UChar* data; + RefPtr<StringImpl> newImpl = + StringImpl::createUninitialized(length() + lengthToInsert, data); + memcpy(data, characters(), position * sizeof(UChar)); + memcpy(data + position, charactersToInsert, lengthToInsert * sizeof(UChar)); + memcpy(data + position + lengthToInsert, characters() + position, (length() - position) * sizeof(UChar)); + m_impl = newImpl.release(); +} + +UChar String::operator[](unsigned i) const +{ + if (!m_impl || i >= m_impl->length()) + return 0; + return m_impl->characters()[i]; +} + +UChar32 String::characterStartingAt(unsigned i) const +{ + if (!m_impl || i >= m_impl->length()) + return 0; + return m_impl->characterStartingAt(i); +} + +unsigned String::length() const +{ + if (!m_impl) + return 0; + return m_impl->length(); +} + +void String::truncate(unsigned position) +{ + if (position >= length()) + return; + UChar* data; + RefPtr<StringImpl> newImpl = StringImpl::createUninitialized(position, data); + memcpy(data, characters(), position * sizeof(UChar)); + m_impl = newImpl.release(); +} + +void String::remove(unsigned position, int lengthToRemove) +{ + if (lengthToRemove <= 0) + return; + if (position >= length()) + return; + if (static_cast<unsigned>(lengthToRemove) > length() - position) + lengthToRemove = length() - position; + UChar* data; + RefPtr<StringImpl> newImpl = + StringImpl::createUninitialized(length() - lengthToRemove, data); + memcpy(data, characters(), position * sizeof(UChar)); + memcpy(data + position, characters() + position + lengthToRemove, + (length() - lengthToRemove - position) * sizeof(UChar)); + m_impl = newImpl.release(); +} + +String String::substring(unsigned pos, unsigned len) const +{ + if (!m_impl) + return String(); + return m_impl->substring(pos, len); +} + +String String::lower() const +{ + if (!m_impl) + return String(); + return m_impl->lower(); +} + +String String::upper() const +{ + if (!m_impl) + return String(); + return m_impl->upper(); +} + +String String::stripWhiteSpace() const +{ + if (!m_impl) + return String(); + return m_impl->stripWhiteSpace(); +} + +String String::simplifyWhiteSpace() const +{ + if (!m_impl) + return String(); + return m_impl->simplifyWhiteSpace(); +} + +String String::removeCharacters(CharacterMatchFunctionPtr findMatch) const +{ + if (!m_impl) + return String(); + return m_impl->removeCharacters(findMatch); +} + +String String::foldCase() const +{ + if (!m_impl) + return String(); + return m_impl->foldCase(); +} + +bool String::percentage(int& result) const +{ + if (!m_impl || !m_impl->length()) + return false; + + if ((*m_impl)[m_impl->length() - 1] != '%') + return false; + + result = charactersToIntStrict(m_impl->characters(), m_impl->length() - 1); + return true; +} + +const UChar* String::characters() const +{ + if (!m_impl) + return 0; + return m_impl->characters(); +} + +const UChar* String::charactersWithNullTermination() +{ + if (!m_impl) + return 0; + if (m_impl->hasTerminatingNullCharacter()) + return m_impl->characters(); + m_impl = StringImpl::createWithTerminatingNullCharacter(*m_impl); + return m_impl->characters(); +} + +String String::format(const char *format, ...) +{ +#if PLATFORM(QT) + // Use QString::vsprintf to avoid the locale dependent formatting of vsnprintf. + // https://bugs.webkit.org/show_bug.cgi?id=18994 + va_list args; + va_start(args, format); + + QString buffer; + buffer.vsprintf(format, args); + + va_end(args); + + return buffer; + +#elif OS(WINCE) + va_list args; + va_start(args, format); + + Vector<char, 256> buffer; + + int bufferSize = 256; + buffer.resize(bufferSize); + for (;;) { + int written = vsnprintf(buffer.data(), bufferSize, format, args); + va_end(args); + + if (written == 0) + return String(""); + if (written > 0) + return StringImpl::create(buffer.data(), written); + + bufferSize <<= 1; + buffer.resize(bufferSize); + va_start(args, format); + } + +#else + va_list args; + va_start(args, format); + + Vector<char, 256> buffer; + + // Do the format once to get the length. +#if COMPILER(MSVC) + int result = _vscprintf(format, args); +#else + char ch; + int result = vsnprintf(&ch, 1, format, args); + // We need to call va_end() and then va_start() again here, as the + // contents of args is undefined after the call to vsnprintf + // according to http://man.cx/snprintf(3) + // + // Not calling va_end/va_start here happens to work on lots of + // systems, but fails e.g. on 64bit Linux. + va_end(args); + va_start(args, format); +#endif + + if (result == 0) + return String(""); + if (result < 0) + return String(); + unsigned len = result; + buffer.grow(len + 1); + + // Now do the formatting again, guaranteed to fit. + vsnprintf(buffer.data(), buffer.size(), format, args); + + va_end(args); + + return StringImpl::create(buffer.data(), len); +#endif +} + +String String::number(short n) +{ + return String::format("%hd", n); +} + +String String::number(unsigned short n) +{ + return String::format("%hu", n); +} + +String String::number(int n) +{ + return String::format("%d", n); +} + +String String::number(unsigned n) +{ + return String::format("%u", n); +} + +String String::number(long n) +{ + return String::format("%ld", n); +} + +String String::number(unsigned long n) +{ + return String::format("%lu", n); +} + +String String::number(long long n) +{ +#if OS(WINDOWS) && !PLATFORM(QT) + return String::format("%I64i", n); +#else + return String::format("%lli", n); +#endif +} + +String String::number(unsigned long long n) +{ +#if OS(WINDOWS) && !PLATFORM(QT) + return String::format("%I64u", n); +#else + return String::format("%llu", n); +#endif +} + +String String::number(double n) +{ + return String::format("%.6lg", n); +} + +int String::toIntStrict(bool* ok, int base) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toIntStrict(ok, base); +} + +unsigned String::toUIntStrict(bool* ok, int base) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toUIntStrict(ok, base); +} + +int64_t String::toInt64Strict(bool* ok, int base) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toInt64Strict(ok, base); +} + +uint64_t String::toUInt64Strict(bool* ok, int base) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toUInt64Strict(ok, base); +} + +intptr_t String::toIntPtrStrict(bool* ok, int base) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toIntPtrStrict(ok, base); +} + + +int String::toInt(bool* ok) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toInt(ok); +} + +unsigned String::toUInt(bool* ok) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toUInt(ok); +} + +int64_t String::toInt64(bool* ok) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toInt64(ok); +} + +uint64_t String::toUInt64(bool* ok) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toUInt64(ok); +} + +intptr_t String::toIntPtr(bool* ok) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0; + } + return m_impl->toIntPtr(ok); +} + +double String::toDouble(bool* ok) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0.0; + } + return m_impl->toDouble(ok); +} + +float String::toFloat(bool* ok) const +{ + if (!m_impl) { + if (ok) + *ok = false; + return 0.0f; + } + return m_impl->toFloat(ok); +} + +String String::threadsafeCopy() const +{ + if (!m_impl) + return String(); + return m_impl->threadsafeCopy(); +} + +String String::crossThreadString() const +{ + if (!m_impl) + return String(); + return m_impl->crossThreadString(); +} + +bool String::isEmpty() const +{ + return !m_impl || !m_impl->length(); +} + +void String::split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const +{ + result.clear(); + + int startPos = 0; + int endPos; + while ((endPos = find(separator, startPos)) != -1) { + if (allowEmptyEntries || startPos != endPos) + result.append(substring(startPos, endPos - startPos)); + startPos = endPos + separator.length(); + } + if (allowEmptyEntries || startPos != static_cast<int>(length())) + result.append(substring(startPos)); +} + +void String::split(const String& separator, Vector<String>& result) const +{ + return split(separator, false, result); +} + +void String::split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const +{ + result.clear(); + + int startPos = 0; + int endPos; + while ((endPos = find(separator, startPos)) != -1) { + if (allowEmptyEntries || startPos != endPos) + result.append(substring(startPos, endPos - startPos)); + startPos = endPos + 1; + } + if (allowEmptyEntries || startPos != static_cast<int>(length())) + result.append(substring(startPos)); +} + +void String::split(UChar separator, Vector<String>& result) const +{ + return split(String(&separator, 1), false, result); +} + +Vector<char> String::ascii() const +{ + if (m_impl) + return m_impl->ascii(); + + const char* nullMsg = "(null impl)"; + Vector<char, 2048> buffer; + for (int i = 0; nullMsg[i]; ++i) + buffer.append(nullMsg[i]); + + buffer.append('\0'); + return buffer; +} + +CString String::latin1() const +{ + // Basic Latin1 (ISO) encoding - Unicode characters 0..255 are + // preserved, characters outside of this range are converted to '?'. + + unsigned length = this->length(); + const UChar* characters = this->characters(); + + char* characterBuffer; + CString result = CString::newUninitialized(length, characterBuffer); + + for (unsigned i = 0; i < length; ++i) { + UChar ch = characters[i]; + characterBuffer[i] = ch > 255 ? '?' : ch; + } + + return result; +} + +// Helper to write a three-byte UTF-8 code point to the buffer, caller must check room is available. +static inline void putUTF8Triple(char*& buffer, UChar ch) +{ + ASSERT(ch >= 0x0800); + *buffer++ = static_cast<char>(((ch >> 12) & 0x0F) | 0xE0); + *buffer++ = static_cast<char>(((ch >> 6) & 0x3F) | 0x80); + *buffer++ = static_cast<char>((ch & 0x3F) | 0x80); +} + +CString String::utf8() const +{ + unsigned length = this->length(); + const UChar* characters = this->characters(); + + // Allocate a buffer big enough to hold all the characters + // (an individual UTF-16 UChar can only expand to 3 UTF-8 bytes). + // Optimization ideas, if we find this function is hot: + // * We could speculatively create a CStringBuffer to contain 'length' + // characters, and resize if necessary (i.e. if the buffer contains + // non-ascii characters). (Alternatively, scan the buffer first for + // ascii characters, so we know this will be sufficient). + // * We could allocate a CStringBuffer with an appropriate size to + // have a good chance of being able to write the string into the + // buffer without reallocing (say, 1.5 x length). + Vector<char, 1024> bufferVector(length * 3); + + char* buffer = bufferVector.data(); + ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), false); + ASSERT(result != sourceIllegal); // Only produced from strict conversion. + ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion + + // If a high surrogate is left unconverted, treat it the same was as an unpaired high surrogate + // would have been handled in the middle of a string with non-strict conversion - which is to say, + // simply encode it to UTF-8. + if (result == sourceExhausted) { + // This should be one unpaired high surrogate. + ASSERT((characters + 1) == (characters + length)); + ASSERT((*characters >= 0xD800) && (*characters <= 0xDBFF)); + // There should be room left, since one UChar hasn't been converted. + ASSERT((buffer + 3) <= (buffer + bufferVector.size())); + putUTF8Triple(buffer, *characters); + } + + return CString(bufferVector.data(), buffer - bufferVector.data()); +} + +String String::fromUTF8(const char* stringStart, size_t length) +{ + if (!stringStart) + return String(); + + // We'll use a StringImpl as a buffer; if the source string only contains ascii this should be + // the right length, if there are any multi-byte sequences this buffer will be too large. + UChar* buffer; + String stringBuffer(StringImpl::createUninitialized(length, buffer)); + UChar* bufferEnd = buffer + length; + + // Try converting into the buffer. + const char* stringCurrent = stringStart; + if (convertUTF8ToUTF16(&stringCurrent, stringStart + length, &buffer, bufferEnd) != conversionOK) + return String(); + + // stringBuffer is full (the input must have been all ascii) so just return it! + if (buffer == bufferEnd) + return stringBuffer; + + // stringBuffer served its purpose as a buffer, copy the contents out into a new string. + unsigned utf16Length = buffer - stringBuffer.characters(); + ASSERT(utf16Length < length); + return String(stringBuffer.characters(), utf16Length); +} + +String String::fromUTF8(const char* string) +{ + if (!string) + return String(); + return fromUTF8(string, strlen(string)); +} + +String String::fromUTF8WithLatin1Fallback(const char* string, size_t size) +{ + String utf8 = fromUTF8(string, size); + if (!utf8) + return String(string, size); + return utf8; +} + +// String Operations + +static bool isCharacterAllowedInBase(UChar c, int base) +{ + if (c > 0x7F) + return false; + if (isASCIIDigit(c)) + return c - '0' < base; + if (isASCIIAlpha(c)) { + if (base > 36) + base = 36; + return (c >= 'a' && c < 'a' + base - 10) + || (c >= 'A' && c < 'A' + base - 10); + } + return false; +} + +template <typename IntegralType> +static inline IntegralType toIntegralType(const UChar* data, size_t length, bool* ok, int base) +{ + static const IntegralType integralMax = std::numeric_limits<IntegralType>::max(); + static const bool isSigned = std::numeric_limits<IntegralType>::is_signed; + const IntegralType maxMultiplier = integralMax / base; + + IntegralType value = 0; + bool isOk = false; + bool isNegative = false; + + if (!data) + goto bye; + + // skip leading whitespace + while (length && isSpaceOrNewline(*data)) { + length--; + data++; + } + + if (isSigned && length && *data == '-') { + length--; + data++; + isNegative = true; + } else if (length && *data == '+') { + length--; + data++; + } + + if (!length || !isCharacterAllowedInBase(*data, base)) + goto bye; + + while (length && isCharacterAllowedInBase(*data, base)) { + length--; + IntegralType digitValue; + UChar c = *data; + if (isASCIIDigit(c)) + digitValue = c - '0'; + else if (c >= 'a') + digitValue = c - 'a' + 10; + else + digitValue = c - 'A' + 10; + + if (value > maxMultiplier || (value == maxMultiplier && digitValue > (integralMax % base) + isNegative)) + goto bye; + + value = base * value + digitValue; + data++; + } + +#if COMPILER(MSVC) +#pragma warning(push, 0) +#pragma warning(disable:4146) +#endif + + if (isNegative) + value = -value; + +#if COMPILER(MSVC) +#pragma warning(pop) +#endif + + // skip trailing space + while (length && isSpaceOrNewline(*data)) { + length--; + data++; + } + + if (!length) + isOk = true; +bye: + if (ok) + *ok = isOk; + return isOk ? value : 0; +} + +static unsigned lengthOfCharactersAsInteger(const UChar* data, size_t length) +{ + size_t i = 0; + + // Allow leading spaces. + for (; i != length; ++i) { + if (!isSpaceOrNewline(data[i])) + break; + } + + // Allow sign. + if (i != length && (data[i] == '+' || data[i] == '-')) + ++i; + + // Allow digits. + for (; i != length; ++i) { + if (!isASCIIDigit(data[i])) + break; + } + + return i; +} + +int charactersToIntStrict(const UChar* data, size_t length, bool* ok, int base) +{ + return toIntegralType<int>(data, length, ok, base); +} + +unsigned charactersToUIntStrict(const UChar* data, size_t length, bool* ok, int base) +{ + return toIntegralType<unsigned>(data, length, ok, base); +} + +int64_t charactersToInt64Strict(const UChar* data, size_t length, bool* ok, int base) +{ + return toIntegralType<int64_t>(data, length, ok, base); +} + +uint64_t charactersToUInt64Strict(const UChar* data, size_t length, bool* ok, int base) +{ + return toIntegralType<uint64_t>(data, length, ok, base); +} + +intptr_t charactersToIntPtrStrict(const UChar* data, size_t length, bool* ok, int base) +{ + return toIntegralType<intptr_t>(data, length, ok, base); +} + +int charactersToInt(const UChar* data, size_t length, bool* ok) +{ + return toIntegralType<int>(data, lengthOfCharactersAsInteger(data, length), ok, 10); +} + +unsigned charactersToUInt(const UChar* data, size_t length, bool* ok) +{ + return toIntegralType<unsigned>(data, lengthOfCharactersAsInteger(data, length), ok, 10); +} + +int64_t charactersToInt64(const UChar* data, size_t length, bool* ok) +{ + return toIntegralType<int64_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); +} + +uint64_t charactersToUInt64(const UChar* data, size_t length, bool* ok) +{ + return toIntegralType<uint64_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); +} + +intptr_t charactersToIntPtr(const UChar* data, size_t length, bool* ok) +{ + return toIntegralType<intptr_t>(data, lengthOfCharactersAsInteger(data, length), ok, 10); +} + +double charactersToDouble(const UChar* data, size_t length, bool* ok) +{ + if (!length) { + if (ok) + *ok = false; + return 0.0; + } + + Vector<char, 256> bytes(length + 1); + for (unsigned i = 0; i < length; ++i) + bytes[i] = data[i] < 0x7F ? data[i] : '?'; + bytes[length] = '\0'; + char* end; + double val = WTF::strtod(bytes.data(), &end); + if (ok) + *ok = (end == 0 || *end == '\0'); + return val; +} + +float charactersToFloat(const UChar* data, size_t length, bool* ok) +{ + // FIXME: This will return ok even when the string fits into a double but not a float. + return static_cast<float>(charactersToDouble(data, length, ok)); +} + +} // namespace WebCore + +#ifndef NDEBUG +// For use in the debugger - leaks memory +WebCore::String* string(const char*); + +WebCore::String* string(const char* s) +{ + return new WebCore::String(s); +} +#endif diff --git a/JavaScriptCore/wtf/text/WTFString.h b/JavaScriptCore/wtf/text/WTFString.h new file mode 100644 index 0000000..7c3c2dd --- /dev/null +++ b/JavaScriptCore/wtf/text/WTFString.h @@ -0,0 +1,398 @@ +/* + * (C) 1999 Lars Knoll (knoll@kde.org) + * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 WTFString_h +#define WTFString_h + +// This file would be called String.h, but that conflicts with <string.h> +// on systems without case-sensitive file systems. + +#include "StringImpl.h" + +#ifdef __OBJC__ +#include <objc/objc.h> +#endif + +#if PLATFORM(CF) +typedef const struct __CFString * CFStringRef; +#endif + +#if PLATFORM(QT) +QT_BEGIN_NAMESPACE +class QString; +QT_END_NAMESPACE +#include <QDataStream> +#endif + +#if PLATFORM(WX) +class wxString; +#endif + +#if PLATFORM(HAIKU) +class BString; +#endif + +namespace WTF { +class CString; +} +using WTF::CString; + +// FIXME: This is a temporary layering violation while we move string code to WTF. +// Landing the file moves in one patch, will follow on with patches to change the namespaces. +namespace WebCore { + +class SharedBuffer; +struct StringHash; + +// Declarations of string operations + +bool charactersAreAllASCII(const UChar*, size_t); +int charactersToIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10); +unsigned charactersToUIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10); +int64_t charactersToInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10); +uint64_t charactersToUInt64Strict(const UChar*, size_t, bool* ok = 0, int base = 10); +intptr_t charactersToIntPtrStrict(const UChar*, size_t, bool* ok = 0, int base = 10); + +int charactersToInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage +unsigned charactersToUInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage +int64_t charactersToInt64(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage +uint64_t charactersToUInt64(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage +intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage + +double charactersToDouble(const UChar*, size_t, bool* ok = 0); +float charactersToFloat(const UChar*, size_t, bool* ok = 0); + +int find(const UChar*, size_t, UChar, int startPosition = 0); +int reverseFind(const UChar*, size_t, UChar, int startPosition = -1); + +class String { +public: + String() { } // gives null string, distinguishable from an empty string + String(const UChar*, unsigned length); + String(const UChar*); // Specifically for null terminated UTF-16 + String(const char*); + String(const char*, unsigned length); + String(StringImpl* i) : m_impl(i) { } + String(PassRefPtr<StringImpl> i) : m_impl(i) { } + String(RefPtr<StringImpl> i) : m_impl(i) { } + + void swap(String& o) { m_impl.swap(o.m_impl); } + + // Hash table deleted values, which are only constructed and never copied or destroyed. + String(WTF::HashTableDeletedValueType) : m_impl(WTF::HashTableDeletedValue) { } + bool isHashTableDeletedValue() const { return m_impl.isHashTableDeletedValue(); } + + static String adopt(StringBuffer& buffer) { return StringImpl::adopt(buffer); } + static String adopt(Vector<UChar>& vector) { return StringImpl::adopt(vector); } + + unsigned length() const; + const UChar* characters() const; + const UChar* charactersWithNullTermination(); + + UChar operator[](unsigned i) const; // if i >= length(), returns 0 + UChar32 characterStartingAt(unsigned) const; // Ditto. + + bool contains(UChar c) const { return find(c) != -1; } + bool contains(const char* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != -1; } + bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != -1; } + + int find(UChar c, int start = 0) const + { return m_impl ? m_impl->find(c, start) : -1; } + int find(CharacterMatchFunctionPtr matchFunction, int start = 0) const + { return m_impl ? m_impl->find(matchFunction, start) : -1; } + int find(const char* str, int start = 0, bool caseSensitive = true) const + { return m_impl ? m_impl->find(str, start, caseSensitive) : -1; } + int find(const String& str, int start = 0, bool caseSensitive = true) const + { return m_impl ? m_impl->find(str.impl(), start, caseSensitive) : -1; } + + int reverseFind(UChar c, int start = -1) const + { return m_impl ? m_impl->reverseFind(c, start) : -1; } + int reverseFind(const String& str, int start = -1, bool caseSensitive = true) const + { return m_impl ? m_impl->reverseFind(str.impl(), start, caseSensitive) : -1; } + + bool startsWith(const String& s, bool caseSensitive = true) const + { return m_impl ? m_impl->startsWith(s.impl(), caseSensitive) : s.isEmpty(); } + bool endsWith(const String& s, bool caseSensitive = true) const + { return m_impl ? m_impl->endsWith(s.impl(), caseSensitive) : s.isEmpty(); } + + void append(const String&); + void append(char); + void append(UChar); + void append(const UChar*, unsigned length); + void insert(const String&, unsigned pos); + void insert(const UChar*, unsigned length, unsigned pos); + + String& replace(UChar a, UChar b) { if (m_impl) m_impl = m_impl->replace(a, b); return *this; } + String& replace(UChar a, const String& b) { if (m_impl) m_impl = m_impl->replace(a, b.impl()); return *this; } + String& replace(const String& a, const String& b) { if (m_impl) m_impl = m_impl->replace(a.impl(), b.impl()); return *this; } + String& replace(unsigned index, unsigned len, const String& b) { if (m_impl) m_impl = m_impl->replace(index, len, b.impl()); return *this; } + + void makeLower() { if (m_impl) m_impl = m_impl->lower(); } + void makeUpper() { if (m_impl) m_impl = m_impl->upper(); } + void makeSecure(UChar aChar) { if (m_impl) m_impl = m_impl->secure(aChar); } + + void truncate(unsigned len); + void remove(unsigned pos, int len = 1); + + String substring(unsigned pos, unsigned len = UINT_MAX) const; + String left(unsigned len) const { return substring(0, len); } + String right(unsigned len) const { return substring(length() - len, len); } + + // Returns a lowercase/uppercase version of the string + String lower() const; + String upper() const; + + String stripWhiteSpace() const; + String simplifyWhiteSpace() const; + + String removeCharacters(CharacterMatchFunctionPtr) const; + + // Return the string with case folded for case insensitive comparison. + String foldCase() const; + + static String number(short); + static String number(unsigned short); + static String number(int); + static String number(unsigned); + static String number(long); + static String number(unsigned long); + static String number(long long); + static String number(unsigned long long); + static String number(double); + + static String format(const char *, ...) WTF_ATTRIBUTE_PRINTF(1, 2); + + // Returns an uninitialized string. The characters needs to be written + // into the buffer returned in data before the returned string is used. + // Failure to do this will have unpredictable results. + static String createUninitialized(unsigned length, UChar*& data) { return StringImpl::createUninitialized(length, data); } + + void split(const String& separator, Vector<String>& result) const; + void split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const; + void split(UChar separator, Vector<String>& result) const; + void split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const; + + int toIntStrict(bool* ok = 0, int base = 10) const; + unsigned toUIntStrict(bool* ok = 0, int base = 10) const; + int64_t toInt64Strict(bool* ok = 0, int base = 10) const; + uint64_t toUInt64Strict(bool* ok = 0, int base = 10) const; + intptr_t toIntPtrStrict(bool* ok = 0, int base = 10) const; + + int toInt(bool* ok = 0) const; + unsigned toUInt(bool* ok = 0) const; + int64_t toInt64(bool* ok = 0) const; + uint64_t toUInt64(bool* ok = 0) const; + intptr_t toIntPtr(bool* ok = 0) const; + double toDouble(bool* ok = 0) const; + float toFloat(bool* ok = 0) const; + + bool percentage(int& percentage) const; + + // Returns a StringImpl suitable for use on another thread. + String crossThreadString() const; + // Makes a deep copy. Helpful only if you need to use a String on another thread + // (use crossThreadString if the method call doesn't need to be threadsafe). + // Since the underlying StringImpl objects are immutable, there's no other reason + // to ever prefer copy() over plain old assignment. + String threadsafeCopy() const; + + bool isNull() const { return !m_impl; } + bool isEmpty() const; + + StringImpl* impl() const { return m_impl.get(); } + +#if PLATFORM(CF) + String(CFStringRef); + CFStringRef createCFString() const; +#endif + +#ifdef __OBJC__ + String(NSString*); + + // This conversion maps NULL to "", which loses the meaning of NULL, but we + // need this mapping because AppKit crashes when passed nil NSStrings. + operator NSString*() const { if (!m_impl) return @""; return *m_impl; } +#endif + +#if PLATFORM(QT) + String(const QString&); + String(const QStringRef&); + operator QString() const; +#endif + +#if PLATFORM(WX) + String(const wxString&); + operator wxString() const; +#endif + +#if PLATFORM(HAIKU) + String(const BString&); + operator BString() const; +#endif + + Vector<char> ascii() const; + + CString latin1() const; + CString utf8() const; + + static String fromUTF8(const char*, size_t); + static String fromUTF8(const char*); + + // Tries to convert the passed in string to UTF-8, but will fall back to Latin-1 if the string is not valid UTF-8. + static String fromUTF8WithLatin1Fallback(const char*, size_t); + + // Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3. + WTF::Unicode::Direction defaultWritingDirection() const { return m_impl ? m_impl->defaultWritingDirection() : WTF::Unicode::LeftToRight; } + + bool containsOnlyASCII() const { return charactersAreAllASCII(characters(), length()); } + +private: + RefPtr<StringImpl> m_impl; +}; + +#if PLATFORM(QT) +QDataStream& operator<<(QDataStream& stream, const String& str); +QDataStream& operator>>(QDataStream& stream, String& str); +#endif + +String operator+(const String&, const String&); +String operator+(const String&, const char*); +String operator+(const char*, const String&); + +inline String& operator+=(String& a, const String& b) { a.append(b); return a; } + +inline bool operator==(const String& a, const String& b) { return equal(a.impl(), b.impl()); } +inline bool operator==(const String& a, const char* b) { return equal(a.impl(), b); } +inline bool operator==(const char* a, const String& b) { return equal(a, b.impl()); } + +inline bool operator!=(const String& a, const String& b) { return !equal(a.impl(), b.impl()); } +inline bool operator!=(const String& a, const char* b) { return !equal(a.impl(), b); } +inline bool operator!=(const char* a, const String& b) { return !equal(a, b.impl()); } + +inline bool equalIgnoringCase(const String& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); } +inline bool equalIgnoringCase(const String& a, const char* b) { return equalIgnoringCase(a.impl(), b); } +inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(a, b.impl()); } + +inline bool equalPossiblyIgnoringCase(const String& a, const String& b, bool ignoreCase) +{ + return ignoreCase ? equalIgnoringCase(a, b) : (a == b); +} + +inline bool equalIgnoringNullity(const String& a, const String& b) { return equalIgnoringNullity(a.impl(), b.impl()); } + +inline bool operator!(const String& str) { return str.isNull(); } + +inline void swap(String& a, String& b) { a.swap(b); } + +// Definitions of string operations + +#ifdef __OBJC__ +// This is for situations in WebKit where the long standing behavior has been +// "nil if empty", so we try to maintain longstanding behavior for the sake of +// entrenched clients +inline NSString* nsStringNilIfEmpty(const String& str) { return str.isEmpty() ? nil : (NSString*)str; } +#endif + +inline bool charactersAreAllASCII(const UChar* characters, size_t length) +{ + UChar ored = 0; + for (size_t i = 0; i < length; ++i) + ored |= characters[i]; + return !(ored & 0xFF80); +} + +inline int find(const UChar* characters, size_t length, UChar character, int startPosition) +{ + if (startPosition >= static_cast<int>(length)) + return -1; + for (size_t i = startPosition; i < length; ++i) { + if (characters[i] == character) + return static_cast<int>(i); + } + return -1; +} + +inline int find(const UChar* characters, size_t length, CharacterMatchFunctionPtr matchFunction, int startPosition) +{ + if (startPosition >= static_cast<int>(length)) + return -1; + for (size_t i = startPosition; i < length; ++i) { + if (matchFunction(characters[i])) + return static_cast<int>(i); + } + return -1; +} + +inline int reverseFind(const UChar* characters, size_t length, UChar character, int startPosition) +{ + if (startPosition >= static_cast<int>(length) || !length) + return -1; + if (startPosition < 0) + startPosition += static_cast<int>(length); + while (true) { + if (characters[startPosition] == character) + return startPosition; + if (!startPosition) + return -1; + startPosition--; + } + ASSERT_NOT_REACHED(); + return -1; +} + +inline void append(Vector<UChar>& vector, const String& string) +{ + vector.append(string.characters(), string.length()); +} + +inline void appendNumber(Vector<UChar>& vector, unsigned char number) +{ + int numberLength = number > 99 ? 3 : (number > 9 ? 2 : 1); + size_t vectorSize = vector.size(); + vector.grow(vectorSize + numberLength); + + switch (numberLength) { + case 3: + vector[vectorSize + 2] = number % 10 + '0'; + number /= 10; + + case 2: + vector[vectorSize + 1] = number % 10 + '0'; + number /= 10; + + case 1: + vector[vectorSize] = number % 10 + '0'; + } +} + +} // namespace WebCore + +namespace WTF { + + // StringHash is the default hash for String + template<typename T> struct DefaultHash; + template<> struct DefaultHash<WebCore::String> { + typedef WebCore::StringHash Hash; + }; + +} + +#endif diff --git a/JavaScriptCore/wtf/unicode/Collator.h b/JavaScriptCore/wtf/unicode/Collator.h index 51e8a06..fe6a809 100644 --- a/JavaScriptCore/wtf/unicode/Collator.h +++ b/JavaScriptCore/wtf/unicode/Collator.h @@ -29,8 +29,8 @@ #ifndef WTF_Collator_h #define WTF_Collator_h -#include <memory> #include <wtf/Noncopyable.h> +#include <wtf/PassOwnPtr.h> #include <wtf/unicode/Unicode.h> #if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION @@ -47,7 +47,7 @@ namespace WTF { ~Collator(); void setOrderLowerFirst(bool); - static std::auto_ptr<Collator> userDefault(); + static PassOwnPtr<Collator> userDefault(); Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const; diff --git a/JavaScriptCore/wtf/unicode/CollatorDefault.cpp b/JavaScriptCore/wtf/unicode/CollatorDefault.cpp index eddbe53..4e05432 100644 --- a/JavaScriptCore/wtf/unicode/CollatorDefault.cpp +++ b/JavaScriptCore/wtf/unicode/CollatorDefault.cpp @@ -45,9 +45,9 @@ void Collator::setOrderLowerFirst(bool) { } -std::auto_ptr<Collator> Collator::userDefault() +PassOwnPtr<Collator> Collator::userDefault() { - return std::auto_ptr<Collator>(new Collator(0)); + return new Collator(0); } // A default implementation for platforms that lack Unicode-aware collation. diff --git a/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h b/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h index d72e707..46b00ea 100644 --- a/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h +++ b/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h @@ -26,7 +26,7 @@ #define UnicodeGLib_h #include "UnicodeMacrosFromICU.h" -#include <wtf/gtk/GOwnPtr.h> +#include "GOwnPtr.h" #include <glib.h> #include <pango/pango.h> diff --git a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp index a1753a4..ecab5bd 100644 --- a/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp +++ b/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp @@ -57,7 +57,7 @@ Collator::Collator(const char* locale) { } -std::auto_ptr<Collator> Collator::userDefault() +PassOwnPtr<Collator> Collator::userDefault() { #if OS(DARWIN) && PLATFORM(CF) // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work. @@ -71,11 +71,11 @@ std::auto_ptr<Collator> Collator::userDefault() char buf[256]; if (collationOrder) { CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII); - return std::auto_ptr<Collator>(new Collator(buf)); + return new Collator(buf); } else - return std::auto_ptr<Collator>(new Collator("")); + return new Collator(""); #else - return std::auto_ptr<Collator>(new Collator(0)); + return new Collator(0); #endif } diff --git a/JavaScriptCore/yarr/RegexCompiler.cpp b/JavaScriptCore/yarr/RegexCompiler.cpp index 9cd3d12..9fbe213 100644 --- a/JavaScriptCore/yarr/RegexCompiler.cpp +++ b/JavaScriptCore/yarr/RegexCompiler.cpp @@ -36,6 +36,8 @@ using namespace WTF; namespace JSC { namespace Yarr { +#include "RegExpJitTables.h" + class CharacterClassConstructor { public: CharacterClassConstructor(bool isCaseInsensitive = false) @@ -141,7 +143,7 @@ public: CharacterClass* charClass() { - CharacterClass* characterClass = new CharacterClass(); + CharacterClass* characterClass = new CharacterClass(0); characterClass->m_matches.append(m_matches); characterClass->m_ranges.append(m_ranges); @@ -233,105 +235,6 @@ private: Vector<CharacterRange> m_rangesUnicode; }; - -CharacterClass* newlineCreate() -{ - CharacterClass* characterClass = new CharacterClass(); - - characterClass->m_matches.append('\n'); - characterClass->m_matches.append('\r'); - characterClass->m_matchesUnicode.append(0x2028); - characterClass->m_matchesUnicode.append(0x2029); - - return characterClass; -} - -CharacterClass* digitsCreate() -{ - CharacterClass* characterClass = new CharacterClass(); - - characterClass->m_ranges.append(CharacterRange('0', '9')); - - return characterClass; -} - -CharacterClass* spacesCreate() -{ - CharacterClass* characterClass = new CharacterClass(); - - characterClass->m_matches.append(' '); - characterClass->m_ranges.append(CharacterRange('\t', '\r')); - characterClass->m_matchesUnicode.append(0x00a0); - characterClass->m_matchesUnicode.append(0x1680); - characterClass->m_matchesUnicode.append(0x180e); - characterClass->m_matchesUnicode.append(0x2028); - characterClass->m_matchesUnicode.append(0x2029); - characterClass->m_matchesUnicode.append(0x202f); - characterClass->m_matchesUnicode.append(0x205f); - characterClass->m_matchesUnicode.append(0x3000); - characterClass->m_rangesUnicode.append(CharacterRange(0x2000, 0x200a)); - - return characterClass; -} - -CharacterClass* wordcharCreate() -{ - CharacterClass* characterClass = new CharacterClass(); - - characterClass->m_matches.append('_'); - characterClass->m_ranges.append(CharacterRange('0', '9')); - characterClass->m_ranges.append(CharacterRange('A', 'Z')); - characterClass->m_ranges.append(CharacterRange('a', 'z')); - - return characterClass; -} - -CharacterClass* nondigitsCreate() -{ - CharacterClass* characterClass = new CharacterClass(); - - characterClass->m_ranges.append(CharacterRange(0, '0' - 1)); - characterClass->m_ranges.append(CharacterRange('9' + 1, 0x7f)); - characterClass->m_rangesUnicode.append(CharacterRange(0x80, 0xffff)); - - return characterClass; -} - -CharacterClass* nonspacesCreate() -{ - CharacterClass* characterClass = new CharacterClass(); - - characterClass->m_ranges.append(CharacterRange(0, '\t' - 1)); - characterClass->m_ranges.append(CharacterRange('\r' + 1, ' ' - 1)); - characterClass->m_ranges.append(CharacterRange(' ' + 1, 0x7f)); - characterClass->m_rangesUnicode.append(CharacterRange(0x0080, 0x009f)); - characterClass->m_rangesUnicode.append(CharacterRange(0x00a1, 0x167f)); - characterClass->m_rangesUnicode.append(CharacterRange(0x1681, 0x180d)); - characterClass->m_rangesUnicode.append(CharacterRange(0x180f, 0x1fff)); - characterClass->m_rangesUnicode.append(CharacterRange(0x200b, 0x2027)); - characterClass->m_rangesUnicode.append(CharacterRange(0x202a, 0x202e)); - characterClass->m_rangesUnicode.append(CharacterRange(0x2030, 0x205e)); - characterClass->m_rangesUnicode.append(CharacterRange(0x2060, 0x2fff)); - characterClass->m_rangesUnicode.append(CharacterRange(0x3001, 0xffff)); - - return characterClass; -} - -CharacterClass* nonwordcharCreate() -{ - CharacterClass* characterClass = new CharacterClass(); - - characterClass->m_matches.append('`'); - characterClass->m_ranges.append(CharacterRange(0, '0' - 1)); - characterClass->m_ranges.append(CharacterRange('9' + 1, 'A' - 1)); - characterClass->m_ranges.append(CharacterRange('Z' + 1, '_' - 1)); - characterClass->m_ranges.append(CharacterRange('z' + 1, 0x7f)); - characterClass->m_rangesUnicode.append(CharacterRange(0x80, 0xffff)); - - return characterClass; -} - - class RegexPatternConstructor { public: RegexPatternConstructor(RegexPattern& pattern) @@ -469,6 +372,7 @@ public: void atomBackReference(unsigned subpatternId) { ASSERT(subpatternId); + m_pattern.m_shouldFallBack = true; m_pattern.m_maxBackReference = std::max(m_pattern.m_maxBackReference, subpatternId); if (subpatternId > m_pattern.m_numSubpatterns) { @@ -544,6 +448,9 @@ public: return; } + if (max > 1 && term.type == PatternTerm::TypeParenthesesSubpattern) + m_pattern.m_shouldFallBack = true; + if (min == 0) term.quantify(max, greedy ? QuantifierGreedy : QuantifierNonGreedy); else if (min == max) diff --git a/JavaScriptCore/yarr/RegexCompiler.h b/JavaScriptCore/yarr/RegexCompiler.h index 3ed2be9..9d2443a 100644 --- a/JavaScriptCore/yarr/RegexCompiler.h +++ b/JavaScriptCore/yarr/RegexCompiler.h @@ -26,13 +26,11 @@ #ifndef RegexCompiler_h #define RegexCompiler_h -#include <wtf/Platform.h> - #if ENABLE(YARR) -#include <wtf/unicode/Unicode.h> #include "RegexParser.h" #include "RegexPattern.h" +#include <wtf/unicode/Unicode.h> namespace JSC { namespace Yarr { diff --git a/JavaScriptCore/yarr/RegexInterpreter.cpp b/JavaScriptCore/yarr/RegexInterpreter.cpp index d088086..c2cb1c2 100644 --- a/JavaScriptCore/yarr/RegexInterpreter.cpp +++ b/JavaScriptCore/yarr/RegexInterpreter.cpp @@ -280,20 +280,6 @@ public: return false; } - bool tryConsumeCharacter(int testChar) - { - if (input.atEnd()) - return false; - - int ch = input.read(); - - if (pattern->m_ignoreCase ? ((Unicode::toLower(testChar) == ch) || (Unicode::toUpper(testChar) == ch)) : (testChar == ch)) { - input.next(); - return true; - } - return false; - } - bool checkCharacter(int testChar, int inputPosition) { return testChar == input.readChecked(inputPosition); @@ -305,23 +291,6 @@ public: return (loChar == ch) || (hiChar == ch); } - bool tryConsumeCharacterClass(CharacterClass* characterClass, bool invert) - { - if (input.atEnd()) - return false; - - bool match = testCharacterClass(characterClass, input.read()); - - if (invert) - match = !match; - - if (match) { - input.next(); - return true; - } - return false; - } - bool checkCharacterClass(CharacterClass* characterClass, bool invert, int inputPosition) { bool match = testCharacterClass(characterClass, input.readChecked(inputPosition)); diff --git a/JavaScriptCore/yarr/RegexInterpreter.h b/JavaScriptCore/yarr/RegexInterpreter.h index 48c9a5e..e3c3122 100644 --- a/JavaScriptCore/yarr/RegexInterpreter.h +++ b/JavaScriptCore/yarr/RegexInterpreter.h @@ -26,13 +26,11 @@ #ifndef RegexInterpreter_h #define RegexInterpreter_h -#include <wtf/Platform.h> - #if ENABLE(YARR) -#include <wtf/unicode/Unicode.h> #include "RegexParser.h" #include "RegexPattern.h" +#include <wtf/unicode/Unicode.h> namespace JSC { namespace Yarr { diff --git a/JavaScriptCore/yarr/RegexJIT.cpp b/JavaScriptCore/yarr/RegexJIT.cpp index fcb8d86..340b53d 100644 --- a/JavaScriptCore/yarr/RegexJIT.cpp +++ b/JavaScriptCore/yarr/RegexJIT.cpp @@ -40,7 +40,6 @@ using namespace WTF; 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); @@ -54,6 +53,16 @@ class RegexGenerator : private MacroAssembler { static const RegisterID regT1 = ARMRegisters::r6; static const RegisterID returnRegister = ARMRegisters::r0; +#elif CPU(MIPS) + static const RegisterID input = MIPSRegisters::a0; + static const RegisterID index = MIPSRegisters::a1; + static const RegisterID length = MIPSRegisters::a2; + static const RegisterID output = MIPSRegisters::a3; + + static const RegisterID regT0 = MIPSRegisters::t4; + static const RegisterID regT1 = MIPSRegisters::t5; + + static const RegisterID returnRegister = MIPSRegisters::v0; #elif CPU(X86) static const RegisterID input = X86Registers::eax; static const RegisterID index = X86Registers::edx; @@ -145,6 +154,11 @@ class RegexGenerator : private MacroAssembler { void matchCharacterClass(RegisterID character, JumpList& matchDest, const CharacterClass* charClass) { + if (charClass->m_table) { + ExtendedAddress tableEntry(character, reinterpret_cast<intptr_t>(charClass->m_table->m_table)); + matchDest.append(branchTest8(charClass->m_table->m_inverted ? Zero : NonZero, tableEntry)); + return; + } Jump unicodeFail; if (charClass->m_matchesUnicode.size() || charClass->m_rangesUnicode.size()) { Jump isAscii = branch32(LessThanOrEqual, character, Imm32(0x7f)); @@ -599,9 +613,14 @@ class RegexGenerator : private MacroAssembler { ASSERT(!m_pattern.m_ignoreCase || (Unicode::toLower(ch) == Unicode::toUpper(ch))); failures.append(jumpIfCharNotEquals(ch, state.inputOffset())); } + add32(Imm32(1), countRegister); add32(Imm32(1), index); - branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this); + if (term.quantityCount != 0xffffffff) + branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this); + else + jump(loop); + failures.append(jump()); Label backtrackBegin(this); @@ -636,7 +655,8 @@ class RegexGenerator : private MacroAssembler { loadFromFrame(term.frameLocation, countRegister); atEndOfInput().linkTo(hardFail, this); - branch32(Equal, countRegister, Imm32(term.quantityCount), hardFail); + if (term.quantityCount != 0xffffffff) + branch32(Equal, countRegister, Imm32(term.quantityCount), hardFail); if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) { readCharacter(state.inputOffset(), character); or32(Imm32(32), character); @@ -722,7 +742,11 @@ class RegexGenerator : private MacroAssembler { add32(Imm32(1), countRegister); add32(Imm32(1), index); - branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this); + if (term.quantityCount != 0xffffffff) + branch32(NotEqual, countRegister, Imm32(term.quantityCount)).linkTo(loop, this); + else + jump(loop); + failures.append(jump()); Label backtrackBegin(this); @@ -1078,17 +1102,15 @@ class RegexGenerator : private MacroAssembler { break; case PatternTerm::TypeBackReference: - m_generationFailed = true; + ASSERT_NOT_REACHED(); break; case PatternTerm::TypeForwardReference: break; case PatternTerm::TypeParenthesesSubpattern: - if ((term.quantityCount == 1) && !term.parentheses.isCopy) - generateParenthesesSingle(state); - else - m_generationFailed = true; + ASSERT((term.quantityCount == 1) && !term.parentheses.isCopy); // must fallback to pcre before this point + generateParenthesesSingle(state); break; case PatternTerm::TypeParentheticalAssertion: @@ -1313,6 +1335,8 @@ class RegexGenerator : private MacroAssembler { push(ARMRegisters::r5); push(ARMRegisters::r6); move(ARMRegisters::r3, output); +#elif CPU(MIPS) + // Do nothing. #endif } @@ -1330,6 +1354,8 @@ class RegexGenerator : private MacroAssembler { pop(ARMRegisters::r6); pop(ARMRegisters::r5); pop(ARMRegisters::r4); +#elif CPU(MIPS) + // Do nothing #endif ret(); } @@ -1337,7 +1363,6 @@ class RegexGenerator : private MacroAssembler { public: RegexGenerator(RegexPattern& pattern) : m_pattern(pattern) - , m_generationFailed(false) { } @@ -1367,15 +1392,9 @@ public: jitObject.set(patchBuffer.finalizeCode()); } - bool generationFailed() - { - return m_generationFailed; - } - private: RegexPattern& m_pattern; Vector<AlternativeBacktrackRecord> m_backtrackRecords; - bool m_generationFailed; }; void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const UString& patternString, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline) @@ -1387,13 +1406,13 @@ void jitCompileRegex(JSGlobalData* globalData, RegexCodeBlock& jitObject, const numSubpatterns = pattern.m_numSubpatterns; - RegexGenerator generator(pattern); - generator.compile(globalData, jitObject); - - if (generator.generationFailed()) { + if (pattern.m_shouldFallBack) { JSRegExpIgnoreCaseOption ignoreCaseOption = ignoreCase ? JSRegExpIgnoreCase : JSRegExpDoNotIgnoreCase; JSRegExpMultilineOption multilineOption = multiline ? JSRegExpMultiline : JSRegExpSingleLine; jitObject.setFallback(jsRegExpCompile(reinterpret_cast<const UChar*>(patternString.data()), patternString.size(), ignoreCaseOption, multilineOption, &numSubpatterns, &error)); + } else { + RegexGenerator generator(pattern); + generator.compile(globalData, jitObject); } } diff --git a/JavaScriptCore/yarr/RegexJIT.h b/JavaScriptCore/yarr/RegexJIT.h index 935b9a3..7f9c16e 100644 --- a/JavaScriptCore/yarr/RegexJIT.h +++ b/JavaScriptCore/yarr/RegexJIT.h @@ -26,8 +26,6 @@ #ifndef RegexJIT_h #define RegexJIT_h -#include <wtf/Platform.h> - #if ENABLE(YARR_JIT) #include "MacroAssembler.h" @@ -68,7 +66,7 @@ public: JSRegExp* getFallback() { return m_fallback; } void setFallback(JSRegExp* fallback) { m_fallback = fallback; } - bool operator!() { return !m_ref.m_code.executableAddress(); } + bool operator!() { return (!m_ref.m_code.executableAddress() && !m_fallback); } void set(MacroAssembler::CodeRef ref) { m_ref = ref; } int execute(const UChar* input, unsigned start, unsigned length, int* output) diff --git a/JavaScriptCore/yarr/RegexParser.h b/JavaScriptCore/yarr/RegexParser.h index 64e8463..c946c2e 100644 --- a/JavaScriptCore/yarr/RegexParser.h +++ b/JavaScriptCore/yarr/RegexParser.h @@ -26,14 +26,12 @@ #ifndef RegexParser_h #define RegexParser_h -#include <wtf/Platform.h> - #if ENABLE(YARR) #include <UString.h> +#include <limits.h> #include <wtf/ASCIICType.h> #include <wtf/unicode/Unicode.h> -#include <limits.h> namespace JSC { namespace Yarr { diff --git a/JavaScriptCore/yarr/RegexPattern.h b/JavaScriptCore/yarr/RegexPattern.h index dd7512d..3271cc1 100644 --- a/JavaScriptCore/yarr/RegexPattern.h +++ b/JavaScriptCore/yarr/RegexPattern.h @@ -26,7 +26,6 @@ #ifndef RegexPattern_h #define RegexPattern_h -#include <wtf/Platform.h> #if ENABLE(YARR) @@ -57,11 +56,35 @@ struct CharacterRange { } }; +struct CharacterClassTable : RefCounted<CharacterClassTable> { + const char* m_table; + bool m_inverted; + static PassRefPtr<CharacterClassTable> create(const char* table, bool inverted) + { + return adoptRef(new CharacterClassTable(table, inverted)); + } + +private: + CharacterClassTable(const char* table, bool inverted) + : m_table(table) + , m_inverted(inverted) + { + } +}; + struct CharacterClass : FastAllocBase { + // All CharacterClass instances have to have the full set of matches and ranges, + // they may have an optional table for faster lookups (which must match the + // specified matches and ranges) + CharacterClass(PassRefPtr<CharacterClassTable> table) + : m_table(table) + { + } Vector<UChar> m_matches; Vector<CharacterRange> m_ranges; Vector<UChar> m_matchesUnicode; Vector<CharacterRange> m_rangesUnicode; + RefPtr<CharacterClassTable> m_table; }; enum QuantifierType { @@ -248,6 +271,7 @@ struct RegexPattern { , m_multiline(multiline) , m_numSubpatterns(0) , m_maxBackReference(0) + , m_shouldFallBack(false) , newlineCached(0) , digitsCached(0) , spacesCached(0) @@ -269,6 +293,8 @@ struct RegexPattern { m_numSubpatterns = 0; m_maxBackReference = 0; + m_shouldFallBack = false; + newlineCached = 0; digitsCached = 0; spacesCached = 0; @@ -335,6 +361,7 @@ struct RegexPattern { bool m_multiline; unsigned m_numSubpatterns; unsigned m_maxBackReference; + bool m_shouldFallBack; PatternDisjunction* m_body; Vector<PatternDisjunction*, 4> m_disjunctions; Vector<CharacterClass*> m_userCharacterClasses; |