diff options
Diffstat (limited to 'Source/JavaScriptCore')
600 files changed, 18147 insertions, 68988 deletions
diff --git a/Source/JavaScriptCore/API/APICast.h b/Source/JavaScriptCore/API/APICast.h index 4294d3d68..f019a7a4b 100644 --- a/Source/JavaScriptCore/API/APICast.h +++ b/Source/JavaScriptCore/API/APICast.h @@ -69,7 +69,7 @@ inline JSC::JSValue toJS(JSC::ExecState* exec, JSValueRef v) if (!jsCell) return JSC::JSValue(); if (jsCell->isAPIValueWrapper()) - return static_cast<JSC::JSAPIValueWrapper*>(jsCell)->value(); + return JSC::jsCast<JSC::JSAPIValueWrapper*>(jsCell)->value(); return jsCell; #else return JSC::JSValue::decode(reinterpret_cast<JSC::EncodedJSValue>(const_cast<OpaqueJSValue*>(v))); diff --git a/Source/JavaScriptCore/API/JSBase.cpp b/Source/JavaScriptCore/API/JSBase.cpp index eafd8c60b..d0ffa3114 100644 --- a/Source/JavaScriptCore/API/JSBase.cpp +++ b/Source/JavaScriptCore/API/JSBase.cpp @@ -100,13 +100,7 @@ void JSGarbageCollect(JSContextRef ctx) ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec, false); - JSGlobalData& globalData = exec->globalData(); - if (!globalData.heap.isBusy()) - globalData.heap.collectAllGarbage(); - - // FIXME: Perhaps we should trigger a second mark and sweep - // once the garbage collector is done if this is called when - // the collector is busy. + exec->globalData().heap.reportAbandonedObjectGraph(); } void JSReportExtraMemoryCost(JSContextRef ctx, size_t size) diff --git a/Source/JavaScriptCore/API/JSCallbackConstructor.cpp b/Source/JavaScriptCore/API/JSCallbackConstructor.cpp index 1349e4f3f..c8b4c0659 100644 --- a/Source/JavaScriptCore/API/JSCallbackConstructor.cpp +++ b/Source/JavaScriptCore/API/JSCallbackConstructor.cpp @@ -70,7 +70,7 @@ static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec) JSContextRef ctx = toRef(exec); JSObjectRef constructorRef = toRef(constructor); - JSObjectCallAsConstructorCallback callback = static_cast<JSCallbackConstructor*>(constructor)->callback(); + JSObjectCallAsConstructorCallback callback = jsCast<JSCallbackConstructor*>(constructor)->callback(); if (callback) { int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); @@ -85,10 +85,13 @@ static EncodedJSValue JSC_HOST_CALL constructJSCallback(ExecState* exec) } if (exception) throwError(exec, toJS(exec, exception)); + // result must be a valid JSValue. + if (!result) + return throwVMTypeError(exec); return JSValue::encode(toJS(result)); } - return JSValue::encode(toJS(JSObjectMake(ctx, static_cast<JSCallbackConstructor*>(constructor)->classRef(), 0))); + return JSValue::encode(toJS(JSObjectMake(ctx, jsCast<JSCallbackConstructor*>(constructor)->classRef(), 0))); } ConstructType JSCallbackConstructor::getConstructData(JSCell*, ConstructData& constructData) diff --git a/Source/JavaScriptCore/API/JSCallbackFunction.cpp b/Source/JavaScriptCore/API/JSCallbackFunction.cpp index 3fbc00470..d287ab778 100644 --- a/Source/JavaScriptCore/API/JSCallbackFunction.cpp +++ b/Source/JavaScriptCore/API/JSCallbackFunction.cpp @@ -30,7 +30,6 @@ #include "APICast.h" #include "CodeBlock.h" #include "ExceptionHelpers.h" -#include "JSCallbackObject.h" #include "JSFunction.h" #include "FunctionPrototype.h" #include <runtime/JSGlobalObject.h> @@ -71,11 +70,15 @@ EncodedJSValue JSCallbackFunction::call(ExecState* exec) JSValueRef result; { APICallbackShim callbackShim(exec); - result = static_cast<JSCallbackFunction*>(toJS(functionRef))->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); + result = jsCast<JSCallbackFunction*>(toJS(functionRef))->m_callback(execRef, functionRef, thisObjRef, argumentCount, arguments.data(), &exception); } if (exception) throwError(exec, toJS(exec, exception)); + // result must be a valid JSValue. + if (!result) + return JSValue::encode(jsUndefined()); + return JSValue::encode(toJS(exec, result)); } @@ -85,35 +88,4 @@ CallType JSCallbackFunction::getCallData(JSCell*, CallData& callData) return CallTypeHost; } -JSValueRef JSCallbackFunction::toStringCallback(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef* exception) -{ - JSObject* object = toJS(thisObject); - if (object->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - for (JSClassRef jsClass = jsCast<JSCallbackObject<JSNonFinalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass) - if (jsClass->convertToType) - return jsClass->convertToType(ctx, thisObject, kJSTypeString, exception); - } else if (object->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - for (JSClassRef jsClass = jsCast<JSCallbackObject<JSGlobalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass) - if (jsClass->convertToType) - return jsClass->convertToType(ctx, thisObject, kJSTypeString, exception); - } - return 0; -} - -JSValueRef JSCallbackFunction::valueOfCallback(JSContextRef ctx, JSObjectRef, JSObjectRef thisObject, size_t, const JSValueRef[], JSValueRef* exception) -{ - JSObject* object = toJS(thisObject); - if (object->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - for (JSClassRef jsClass = jsCast<JSCallbackObject<JSNonFinalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass) - if (jsClass->convertToType) - return jsClass->convertToType(ctx, thisObject, kJSTypeNumber, exception); - } else if (object->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - for (JSClassRef jsClass = jsCast<JSCallbackObject<JSGlobalObject>*>(object)->classRef(); jsClass; jsClass = jsClass->parentClass) - if (jsClass->convertToType) - return jsClass->convertToType(ctx, thisObject, kJSTypeNumber, exception); - } - return 0; -} - - } // namespace JSC diff --git a/Source/JavaScriptCore/API/JSCallbackFunction.h b/Source/JavaScriptCore/API/JSCallbackFunction.h index b61d45c86..fec4136f8 100644 --- a/Source/JavaScriptCore/API/JSCallbackFunction.h +++ b/Source/JavaScriptCore/API/JSCallbackFunction.h @@ -55,9 +55,6 @@ public: return Structure::create(globalData, globalObject, proto, TypeInfo(ObjectType, StructureFlags), &s_info); } - static JSValueRef toStringCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); - static JSValueRef valueOfCallback(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception); - private: static CallType getCallData(JSCell*, CallData&); diff --git a/Source/JavaScriptCore/API/JSCallbackObject.cpp b/Source/JavaScriptCore/API/JSCallbackObject.cpp index ef9cb925c..68c26824d 100644 --- a/Source/JavaScriptCore/API/JSCallbackObject.cpp +++ b/Source/JavaScriptCore/API/JSCallbackObject.cpp @@ -65,8 +65,7 @@ void JSCallbackObjectData::finalize(Handle<Unknown> handle, void* context) for (; jsClass; jsClass = jsClass->parentClass) if (JSObjectFinalizeCallback finalize = jsClass->finalize) finalize(thisRef); - HandleSlot slot = handle.slot(); - HandleHeap::heapFor(slot)->deallocate(slot); + WeakSet::deallocate(WeakImpl::asWeakImpl(handle.slot())); } } // namespace JSC diff --git a/Source/JavaScriptCore/API/JSCallbackObject.h b/Source/JavaScriptCore/API/JSCallbackObject.h index 8f907167e..9aca0c7e1 100644 --- a/Source/JavaScriptCore/API/JSCallbackObject.h +++ b/Source/JavaScriptCore/API/JSCallbackObject.h @@ -89,7 +89,7 @@ struct JSCallbackObjectData : WeakHandleOwner { void setPrivateProperty(JSGlobalData& globalData, JSCell* owner, const Identifier& propertyName, JSValue value) { WriteBarrier<Unknown> empty; - m_propertyMap.add(propertyName.impl(), empty).first->second.set(globalData, owner, value); + m_propertyMap.add(propertyName.impl(), empty).iterator->second.set(globalData, owner, value); } void deletePrivateProperty(const Identifier& propertyName) @@ -175,6 +175,8 @@ private: static void destroy(JSCell*); + static JSValue defaultValue(const JSObject*, ExecState*, PreferredPrimitiveType); + static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier&, PropertySlot&); static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); diff --git a/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h b/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h index cab5883da..b909dde71 100644 --- a/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h +++ b/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h @@ -46,7 +46,7 @@ template <class Parent> inline JSCallbackObject<Parent>* JSCallbackObject<Parent>::asCallbackObject(JSValue value) { ASSERT(asObject(value)->inherits(&s_info)); - return static_cast<JSCallbackObject*>(asObject(value)); + return jsCast<JSCallbackObject*>(asObject(value)); } template <class Parent> @@ -80,7 +80,7 @@ void JSCallbackObject<Parent>::finishCreation(JSGlobalData& globalData) ASSERT(Parent::inherits(&s_info)); ASSERT(Parent::isGlobalObject()); Base::finishCreation(globalData); - init(static_cast<JSGlobalObject*>(this)->globalExec()); + init(jsCast<JSGlobalObject*>(this)->globalExec()); } template <class Parent> @@ -102,14 +102,11 @@ void JSCallbackObject<Parent>::init(ExecState* exec) initialize(toRef(exec), toRef(this)); } - bool needsFinalizer = false; - for (JSClassRef jsClassPtr = classRef(); jsClassPtr && !needsFinalizer; jsClassPtr = jsClassPtr->parentClass) - needsFinalizer = jsClassPtr->finalize; - if (needsFinalizer) { - HandleSlot slot = exec->globalData().heap.handleHeap()->allocate(); - HandleHeap::heapFor(slot)->makeWeak(slot, m_callbackObjectData.get(), classRef()); - HandleHeap::heapFor(slot)->writeBarrier(slot, this); - *slot = this; + for (JSClassRef jsClassPtr = classRef(); jsClassPtr; jsClassPtr = jsClassPtr->parentClass) { + if (jsClassPtr->finalize) { + WeakSet::allocate(this, m_callbackObjectData.get(), classRef()); + break; + } } } @@ -184,6 +181,30 @@ bool JSCallbackObject<Parent>::getOwnPropertySlot(JSCell* cell, ExecState* exec, } template <class Parent> +JSValue JSCallbackObject<Parent>::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint) +{ + const JSCallbackObject* thisObject = jsCast<const JSCallbackObject*>(object); + JSContextRef ctx = toRef(exec); + JSObjectRef thisRef = toRef(thisObject); + ::JSType jsHint = hint == PreferString ? kJSTypeString : kJSTypeNumber; + + for (JSClassRef jsClass = thisObject->classRef(); jsClass; jsClass = jsClass->parentClass) { + if (JSObjectConvertToTypeCallback convertToType = jsClass->convertToType) { + JSValueRef exception = 0; + JSValueRef result = convertToType(ctx, thisRef, jsHint, &exception); + if (exception) { + throwError(exec, toJS(exec, exception)); + return jsUndefined(); + } + if (result) + return toJS(exec, result); + } + } + + return Parent::defaultValue(object, exec, hint); +} + +template <class Parent> bool JSCallbackObject<Parent>::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { JSCallbackObject* thisObject = jsCast<JSCallbackObject*>(object); @@ -333,7 +354,7 @@ EncodedJSValue JSCallbackObject<Parent>::construct(ExecState* exec) JSContextRef execRef = toRef(exec); JSObjectRef constructorRef = toRef(constructor); - for (JSClassRef jsClass = static_cast<JSCallbackObject<Parent>*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) { + for (JSClassRef jsClass = jsCast<JSCallbackObject<Parent>*>(constructor)->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectCallAsConstructorCallback callAsConstructor = jsClass->callAsConstructor) { int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); @@ -399,7 +420,7 @@ EncodedJSValue JSCallbackObject<Parent>::call(ExecState* exec) JSObjectRef functionRef = toRef(exec->callee()); JSObjectRef thisObjRef = toRef(exec->hostThisValue().toThisObject(exec)); - for (JSClassRef jsClass = static_cast<JSCallbackObject<Parent>*>(toJS(functionRef))->classRef(); jsClass; jsClass = jsClass->parentClass) { + for (JSClassRef jsClass = jsCast<JSCallbackObject<Parent>*>(toJS(functionRef))->classRef(); jsClass; jsClass = jsClass->parentClass) { if (JSObjectCallAsFunctionCallback callAsFunction = jsClass->callAsFunction) { int argumentCount = static_cast<int>(exec->argumentCount()); Vector<JSValueRef, 16> arguments(argumentCount); diff --git a/Source/JavaScriptCore/API/JSClassRef.cpp b/Source/JavaScriptCore/API/JSClassRef.cpp index 298c734ea..08fa5c5e0 100644 --- a/Source/JavaScriptCore/API/JSClassRef.cpp +++ b/Source/JavaScriptCore/API/JSClassRef.cpp @@ -164,7 +164,7 @@ OpaqueJSClassContextData::OpaqueJSClassContextData(JSC::JSGlobalData&, OpaqueJSC OpaqueJSClassContextData& OpaqueJSClass::contextData(ExecState* exec) { - OwnPtr<OpaqueJSClassContextData>& contextData = exec->globalData().opaqueJSClassData.add(this, nullptr).first->second; + OwnPtr<OpaqueJSClassContextData>& contextData = exec->globalData().opaqueJSClassData.add(this, nullptr).iterator->second; if (!contextData) contextData = adoptPtr(new OpaqueJSClassContextData(exec->globalData(), this)); return *contextData; @@ -204,17 +204,6 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec) * DerivedClass | DerivedClassPrototype */ - if (convertToType) { - if (!prototypeClass) - prototypeClass = OpaqueJSClass::create(&kJSClassDefinitionEmpty).leakRef(); - if (!prototypeClass->m_staticFunctions) - prototypeClass->m_staticFunctions = adoptPtr(new OpaqueJSClassStaticFunctionsTable); - const Identifier& toString = exec->propertyNames().toString; - const Identifier& valueOf = exec->propertyNames().valueOf; - prototypeClass->m_staticFunctions->add(StringImpl::create(toString.characters(), toString.length()), adoptPtr(new StaticFunctionEntry(&JSCallbackFunction::toStringCallback, 0))); - prototypeClass->m_staticFunctions->add(StringImpl::create(valueOf.characters(), valueOf.length()), adoptPtr(new StaticFunctionEntry(&JSCallbackFunction::valueOfCallback, 0))); - } - if (!prototypeClass) return 0; @@ -222,7 +211,7 @@ JSObject* OpaqueJSClass::prototype(ExecState* exec) if (!jsClassData.cachedPrototype) { // Recursive, but should be good enough for our purposes - jsClassData.cachedPrototype = PassWeak<JSObject>(exec->globalData(), JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData), 0); // set jsClassData as the object's private data, so it can clear our reference on destruction + jsClassData.cachedPrototype = PassWeak<JSObject>(JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), prototypeClass, &jsClassData), 0); // set jsClassData as the object's private data, so it can clear our reference on destruction if (parentClass) { if (JSObject* prototype = parentClass->prototype(exec)) jsClassData.cachedPrototype->setPrototype(exec->globalData(), prototype); diff --git a/Source/JavaScriptCore/API/JSContextRef.cpp b/Source/JavaScriptCore/API/JSContextRef.cpp index 71cb1ab74..746febfbb 100644 --- a/Source/JavaScriptCore/API/JSContextRef.cpp +++ b/Source/JavaScriptCore/API/JSContextRef.cpp @@ -38,15 +38,13 @@ #include "UStringBuilder.h" #include <wtf/text/StringHash.h> - -#if OS(DARWIN) -#include <mach-o/dyld.h> - -static const int32_t webkitFirstVersionWithConcurrentGlobalContexts = 0x2100500; // 528.5.0 -#endif - using namespace JSC; +// From the API's perspective, a context group remains alive iff +// (a) it has been JSContextGroupRetained +// OR +// (b) one of its contexts has been JSContextRetained + JSContextGroupRef JSContextGroupCreate() { initializeThreading(); @@ -64,22 +62,11 @@ void JSContextGroupRelease(JSContextGroupRef group) toJS(group)->deref(); } +// From the API's perspective, a global context remains alive iff it has been JSGlobalContextRetained. + JSGlobalContextRef JSGlobalContextCreate(JSClassRef globalObjectClass) { initializeThreading(); -#if OS(DARWIN) - // When running on Tiger or Leopard, or if the application was linked before JSGlobalContextCreate was changed - // to use a unique JSGlobalData, we use a shared one for compatibility. -#ifndef BUILDING_ON_LEOPARD - if (NSVersionOfLinkTimeLibrary("JavaScriptCore") <= webkitFirstVersionWithConcurrentGlobalContexts) { -#else - { -#endif - JSLock lock(LockForReal); - return JSGlobalContextCreateInGroup(toRef(&JSGlobalData::sharedInstance()), globalObjectClass); - } -#endif // OS(DARWIN) - return JSGlobalContextCreateInGroup(0, globalObjectClass); } @@ -125,33 +112,13 @@ void JSGlobalContextRelease(JSGlobalContextRef ctx) JSLock lock(exec); JSGlobalData& globalData = exec->globalData(); - 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 - tickle the activity callback to - // garbage collect soon. - // * 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.clearBuiltinStructures(); - globalData.heap.destroy(); - } else if (releasingGlobalObject) { + bool protectCountIsZero = Heap::heap(exec->dynamicGlobalObject())->unprotect(exec->dynamicGlobalObject()); + if (protectCountIsZero) { globalData.heap.activityCallback()->synchronize(); - (*globalData.heap.activityCallback())(); + globalData.heap.reportAbandonedObjectGraph(); } - globalData.deref(); wtfThreadData().setCurrentIdentifierTable(savedIdentifierTable); @@ -210,7 +177,7 @@ JSStringRef JSContextCreateBacktrace(JSContextRef ctx, unsigned maxStackSize) exec->interpreter()->retrieveLastCaller(callFrame, signedLineNumber, sourceID, urlString, function); if (function) - functionName = asFunction(function)->name(exec); + functionName = jsCast<JSFunction*>(function)->name(exec); else { // Caller is unknown, but if frame is empty we should still add the frame, because // something called us, and gave us arguments. diff --git a/Source/JavaScriptCore/API/JSObjectRef.cpp b/Source/JavaScriptCore/API/JSObjectRef.cpp index 17329ad87..e01214d5e 100644 --- a/Source/JavaScriptCore/API/JSObjectRef.cpp +++ b/Source/JavaScriptCore/API/JSObjectRef.cpp @@ -341,9 +341,9 @@ void* JSObjectGetPrivate(JSObjectRef object) JSObject* jsObject = toJS(object); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) - return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate(); + return jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate(); if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) - return static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivate(); + return jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivate(); return 0; } @@ -353,11 +353,11 @@ bool JSObjectSetPrivate(JSObjectRef object, void* data) JSObject* jsObject = toJS(object); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data); + jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data); return true; } if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivate(data); + jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivate(data); return true; } @@ -372,9 +372,9 @@ JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSSt JSValue result; Identifier name(propertyName->identifier(&exec->globalData())); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) - result = static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name); + result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name); else if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) - result = static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivateProperty(name); + result = jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivateProperty(name); return toRef(exec, result); } @@ -386,11 +386,11 @@ bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRe JSValue jsValue = value ? toJS(exec, value) : JSValue(); Identifier name(propertyName->identifier(&exec->globalData())); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue); + jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue); return true; } if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue); + jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue); return true; } return false; @@ -403,11 +403,11 @@ bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStrin JSObject* jsObject = toJS(object); Identifier name(propertyName->identifier(&exec->globalData())); if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) { - static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name); + jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name); return true; } if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) { - static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->deletePrivateProperty(name); + jsCast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->deletePrivateProperty(name); return true; } return false; diff --git a/Source/JavaScriptCore/API/JSValueRef.cpp b/Source/JavaScriptCore/API/JSValueRef.cpp index 1b4e03bde..9b7268a2d 100644 --- a/Source/JavaScriptCore/API/JSValueRef.cpp +++ b/Source/JavaScriptCore/API/JSValueRef.cpp @@ -130,9 +130,9 @@ bool JSValueIsObjectOfClass(JSContextRef ctx, JSValueRef value, JSClassRef jsCla if (JSObject* o = jsValue.getObject()) { if (o->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) - return static_cast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass); + return jsCast<JSCallbackObject<JSGlobalObject>*>(o)->inherits(jsClass); if (o->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) - return static_cast<JSCallbackObject<JSNonFinalObject>*>(o)->inherits(jsClass); + return jsCast<JSCallbackObject<JSNonFinalObject>*>(o)->inherits(jsClass); } return false; } diff --git a/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp b/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp index 4292a60bd..bdd56f602 100644 --- a/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp +++ b/Source/JavaScriptCore/API/JSWeakObjectMapRefPrivate.cpp @@ -65,7 +65,7 @@ JSObjectRef JSWeakObjectMapGet(JSContextRef ctx, JSWeakObjectMapRef map, void* k { ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); - return toRef(static_cast<JSObject*>(map->map().get(key))); + return toRef(jsCast<JSObject*>(map->map().get(key))); } void JSWeakObjectMapRemove(JSContextRef ctx, JSWeakObjectMapRef map, void* key) diff --git a/Source/JavaScriptCore/API/tests/testapi.c b/Source/JavaScriptCore/API/tests/testapi.c index efcfc0d12..91978bbfd 100644 --- a/Source/JavaScriptCore/API/tests/testapi.c +++ b/Source/JavaScriptCore/API/tests/testapi.c @@ -311,6 +311,16 @@ static JSValueRef MyObject_convertToType(JSContextRef context, JSObjectRef objec return JSValueMakeNull(context); } +static JSValueRef MyObject_convertToTypeWrapper(JSContextRef context, JSObjectRef object, JSType type, JSValueRef* exception) +{ + UNUSED_PARAM(context); + UNUSED_PARAM(object); + UNUSED_PARAM(type); + UNUSED_PARAM(exception); + // Forward to default object class + return 0; +} + static bool MyObject_set_nullGetForwardSet(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception) { UNUSED_PARAM(ctx); @@ -355,14 +365,65 @@ JSClassDefinition MyObject_definition = { MyObject_convertToType, }; +JSClassDefinition MyObject_convertToTypeWrapperDefinition = { + 0, + kJSClassAttributeNone, + + "MyObject", + NULL, + + NULL, + NULL, + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + MyObject_convertToTypeWrapper, +}; + +JSClassDefinition MyObject_nullWrapperDefinition = { + 0, + kJSClassAttributeNone, + + "MyObject", + NULL, + + NULL, + NULL, + + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + static JSClassRef MyObject_class(JSContextRef context) { UNUSED_PARAM(context); static JSClassRef jsClass; - if (!jsClass) - jsClass = JSClassCreate(&MyObject_definition); - + if (!jsClass) { + JSClassRef baseClass = JSClassCreate(&MyObject_definition); + MyObject_convertToTypeWrapperDefinition.parentClass = baseClass; + JSClassRef wrapperClass = JSClassCreate(&MyObject_convertToTypeWrapperDefinition); + MyObject_nullWrapperDefinition.parentClass = wrapperClass; + jsClass = JSClassCreate(&MyObject_nullWrapperDefinition); + } + return jsClass; } @@ -617,9 +678,22 @@ static JSValueRef Base_callAsFunction(JSContextRef ctx, JSObjectRef function, JS return JSValueMakeNumber(ctx, 1); // distinguish base call from derived call } +static JSValueRef Base_returnHardNull(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + UNUSED_PARAM(ctx); + UNUSED_PARAM(function); + UNUSED_PARAM(thisObject); + UNUSED_PARAM(argumentCount); + UNUSED_PARAM(arguments); + UNUSED_PARAM(exception); + + return 0; // should convert to undefined! +} + static JSStaticFunction Base_staticFunctions[] = { { "baseProtoDup", NULL, kJSPropertyAttributeNone }, { "baseProto", Base_callAsFunction, kJSPropertyAttributeNone }, + { "baseHardNull", Base_returnHardNull, kJSPropertyAttributeNone }, { 0, 0, 0 } }; @@ -791,6 +865,17 @@ static JSObjectRef myConstructor_callAsConstructor(JSContextRef context, JSObjec return result; } +static JSObjectRef myBadConstructor_callAsConstructor(JSContextRef context, JSObjectRef constructorObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) +{ + UNUSED_PARAM(context); + UNUSED_PARAM(constructorObject); + UNUSED_PARAM(argumentCount); + UNUSED_PARAM(arguments); + UNUSED_PARAM(exception); + + return 0; +} + static void globalObject_initialize(JSContextRef context, JSObjectRef object) { @@ -1387,6 +1472,11 @@ int main(int argc, char* argv[]) JSObjectSetProperty(context, globalObject, myConstructorIString, myConstructor, kJSPropertyAttributeNone, NULL); JSStringRelease(myConstructorIString); + JSStringRef myBadConstructorIString = JSStringCreateWithUTF8CString("MyBadConstructor"); + JSObjectRef myBadConstructor = JSObjectMakeConstructor(context, NULL, myBadConstructor_callAsConstructor); + JSObjectSetProperty(context, globalObject, myBadConstructorIString, myBadConstructor, kJSPropertyAttributeNone, NULL); + JSStringRelease(myBadConstructorIString); + ASSERT(!JSObjectSetPrivate(myConstructor, (void*)1)); ASSERT(!JSObjectGetPrivate(myConstructor)); diff --git a/Source/JavaScriptCore/API/tests/testapi.js b/Source/JavaScriptCore/API/tests/testapi.js index 5257b882e..28fa54433 100644 --- a/Source/JavaScriptCore/API/tests/testapi.js +++ b/Source/JavaScriptCore/API/tests/testapi.js @@ -155,7 +155,7 @@ shouldBe("typeof myObject", "object"); shouldBe("MyObject ? 1 : 0", true); // toBoolean shouldBe("+MyObject", 1); // toNumber shouldBe("(Object.prototype.toString.call(MyObject))", "[object MyObject]"); // Object.prototype.toString -shouldBe("(MyObject.toString())", "MyObjectAsString"); // toString +shouldBe("(MyObject.toString())", "[object MyObject]"); // toString shouldBe("String(MyObject)", "MyObjectAsString"); // toString shouldBe("MyObject - 0", 1); // toNumber shouldBe("MyObject.valueOf()", 1); // valueOf @@ -167,6 +167,8 @@ shouldBe("constructedObject.value", 1); shouldBe("myObject instanceof MyObject", true); shouldBe("(new Object()) instanceof MyObject", false); +shouldThrow("new MyBadConstructor()"); + MyObject.nullGetSet = 1; shouldBe("MyObject.nullGetSet", 1); shouldThrow("MyObject.nullCall()"); @@ -186,6 +188,8 @@ shouldBe("derived.protoOnly()", 2); shouldBe("derived.protoDup", 2); shouldBe("derived.derivedOnly", 2) +shouldBe("derived.baseHardNull()", undefined) + // base properties throw 1 when set; derived, 2 shouldBe("derived.baseDup = 0", 2); shouldBe("derived.baseOnly = 0", 1); diff --git a/Source/JavaScriptCore/CMakeLists.txt b/Source/JavaScriptCore/CMakeLists.txt index d4a51d214..bf48f970d 100644 --- a/Source/JavaScriptCore/CMakeLists.txt +++ b/Source/JavaScriptCore/CMakeLists.txt @@ -17,7 +17,7 @@ SET(JavaScriptCore_INCLUDE_DIRECTORIES "${JAVASCRIPTCORE_DIR}/runtime" "${JAVASCRIPTCORE_DIR}/tools" "${JAVASCRIPTCORE_DIR}/yarr" - "${JAVASCRIPTCORE_DIR}/wtf" + "${WTF_DIR}" "${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}" "${CMAKE_SOURCE_DIR}/Source" ) @@ -58,7 +58,6 @@ SET(JavaScriptCore_SOURCES bytecompiler/NodesCodegen.cpp dfg/DFGAbstractState.cpp - dfg/DFGArithNodeFlagsInferencePhase.cpp dfg/DFGAssemblyHelpers.cpp dfg/DFGByteCodeParser.cpp dfg/DFGCapabilities.cpp @@ -66,9 +65,10 @@ SET(JavaScriptCore_SOURCES dfg/DFGCorrectableJumpPoint.cpp dfg/DFGCSEPhase.cpp dfg/DFGDriver.cpp + dfg/DFGFixupPhase.cpp dfg/DFGGraph.cpp dfg/DFGJITCompiler.cpp - dfg/DFGNode.cpp + dfg/DFGNodeFlags.cpp dfg/DFGOSREntry.cpp dfg/DFGOSRExit.cpp dfg/DFGOSRExitCompiler.cpp @@ -85,17 +85,21 @@ SET(JavaScriptCore_SOURCES dfg/DFGThunks.cpp dfg/DFGVirtualRegisterAllocationPhase.cpp + heap/BlockAllocator.cpp heap/CopiedSpace.cpp + heap/ConservativeRoots.cpp heap/DFGCodeBlocks.cpp - heap/Heap.cpp - heap/HandleHeap.cpp + heap/HandleSet.cpp heap/HandleStack.cpp + heap/Heap.cpp heap/MachineStackMarker.cpp heap/MarkedAllocator.cpp heap/MarkedBlock.cpp heap/MarkedSpace.cpp - heap/ConservativeRoots.cpp heap/MarkStack.cpp + heap/WeakSet.cpp + heap/WeakHandleOwner.cpp + heap/WeakBlock.cpp debugger/Debugger.cpp debugger/DebuggerActivation.cpp @@ -163,7 +167,6 @@ SET(JavaScriptCore_SOURCES runtime/JSActivation.cpp runtime/JSAPIValueWrapper.cpp runtime/JSArray.cpp - runtime/JSByteArray.cpp runtime/JSCell.cpp runtime/JSDateMath.cpp runtime/JSFunction.cpp @@ -179,6 +182,7 @@ SET(JavaScriptCore_SOURCES runtime/JSPropertyNameIterator.cpp runtime/JSStaticScopeObject.cpp runtime/JSString.cpp + runtime/JSStringJoiner.cpp runtime/JSValue.cpp runtime/JSVariableObject.cpp runtime/JSWrapperObject.cpp @@ -200,6 +204,8 @@ SET(JavaScriptCore_SOURCES runtime/RegExp.cpp runtime/RegExpCache.cpp runtime/RegExpConstructor.cpp + runtime/RegExpCachedResult.cpp + runtime/RegExpMatchesArray.cpp runtime/RegExpObject.cpp runtime/RegExpPrototype.cpp runtime/ScopeChain.cpp @@ -217,6 +223,7 @@ SET(JavaScriptCore_SOURCES tools/CodeProfile.cpp tools/CodeProfiling.cpp + yarr/YarrCanonicalizeUCS2.cpp yarr/YarrPattern.cpp yarr/YarrInterpreter.cpp yarr/YarrJIT.cpp @@ -295,7 +302,6 @@ ENDIF () WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() -ADD_SUBDIRECTORY(wtf) ADD_SUBDIRECTORY(shell) WEBKIT_WRAP_SOURCELIST(${JavaScriptCore_SOURCES}) @@ -303,6 +309,7 @@ INCLUDE_DIRECTORIES(${JavaScriptCore_INCLUDE_DIRECTORIES}) ADD_DEFINITIONS(-DBUILDING_JavaScriptCore) ADD_LIBRARY(${JavaScriptCore_LIBRARY_NAME} ${JavaScriptCore_LIBRARY_TYPE} ${JavaScriptCore_HEADERS} ${JavaScriptCore_SOURCES}) TARGET_LINK_LIBRARIES(${JavaScriptCore_LIBRARY_NAME} ${JavaScriptCore_LIBRARIES}) +SET_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} PROPERTIES FOLDER "JavaScriptCore") SET_TARGET_PROPERTIES(${JavaScriptCore_LIBRARY_NAME} PROPERTIES LINK_INTERFACE_LIBRARIES "") IF (JavaScriptCore_LINK_FLAGS) diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog index 0092392f0..0774438d1 100644 --- a/Source/JavaScriptCore/ChangeLog +++ b/Source/JavaScriptCore/ChangeLog @@ -1,3 +1,6407 @@ +2012-05-05 Gavin Barraclough <barraclough@apple.com> + + Remove TrustedImm32::m_isPointer + https://bugs.webkit.org/show_bug.cgi?id=85726 + + Rubber stamped by Sam Weinig. + + We used to rely on being able to generate code with known, fixed offsets – to do so we + would inhibit more optimal code generation for pointers. This is no longer necessary. + + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::TrustedImm32::TrustedImm32): + (TrustedImm32): + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::store32): + (JSC::MacroAssemblerARM::move): + (JSC::MacroAssemblerARM::branch32): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::move): + * assembler/MacroAssemblerMIPS.h: + (JSC::MacroAssemblerMIPS::add32): + (JSC::MacroAssemblerMIPS::and32): + (JSC::MacroAssemblerMIPS::mul32): + (JSC::MacroAssemblerMIPS::or32): + (JSC::MacroAssemblerMIPS::sub32): + (JSC::MacroAssemblerMIPS::store32): + (JSC::MacroAssemblerMIPS::move): + +2012-05-04 Filip Pizlo <fpizlo@apple.com> + + DFG should not Flush GetLocal's + https://bugs.webkit.org/show_bug.cgi?id=85663 + <rdar://problem/11373600> + + Reviewed by Oliver Hunt. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::flushArgument): + (JSC::DFG::ByteCodeParser::handleCall): + +2012-05-04 Allan Sandfeld Jensen <allan.jensen@nokia.com> + + Doesn't build with ENABLE_JIT=0 + https://bugs.webkit.org/show_bug.cgi?id=85042 + + Reviewed by Gavin Barraclough. + + * bytecode/Operands.h: + +2012-05-03 Oliver Hunt <oliver@apple.com> + + Regression(r114702): Clobbering the caller frame register before we've stored it. + https://bugs.webkit.org/show_bug.cgi?id=85564 + + Reviewed by Filip Pizlo. + + Don't use t0 as a temporary, when we're about to use the value in t0. + + * llint/LowLevelInterpreter32_64.asm: + +2012-05-03 Mark Hahnenberg <mhahnenberg@apple.com> + + Removing remainder of accidental printfs. + + * heap/Heap.cpp: + (JSC::Heap::collect): + +2012-05-03 Andy Estes <aestes@apple.com> + + If you add printf()s to your garbage collector, the layout tests are gonna have a bad time. + + * runtime/GCActivityCallbackCF.cpp: + (JSC::DefaultGCActivityCallbackPlatformData::timerDidFire): + +2012-05-03 Mark Hahnenberg <mhahnenberg@apple.com> + + Heap::reportAbandonedObjectGraph should not hasten an allocation-triggered collection + https://bugs.webkit.org/show_bug.cgi?id=85543 + + Reviewed by Filip Pizlo. + + Currently reportAbandonedObjectGraph causes the Heap to think it is closer to its + allocation limit for the current cycle, thus hastening an allocation-triggered collection. + In reality, it should just affect the opportunistic GC timer. We should track the bytes + we think have been abandoned and the bytes that have been allocated separately. + + * heap/Heap.cpp: Added a new field m_abandonedBytes to Heap to keep track of how much + we think we've abandoned. + (JSC::Heap::Heap): + (JSC::Heap::reportAbandonedObjectGraph): + (JSC): + (JSC::Heap::didAbandon): Added this function for reportAbandonedObjectGraph to call + rather than didAllocate. Works the same as didAllocate, but modifies bytes abandoned rather + than bytes allocated. Also notifies the timer, summing the two values together. + (JSC::Heap::collect): + (JSC::Heap::didAllocate): Now adds the bytes allocated and bytes abandoned when reporting + to GCActivityCallback. + * heap/Heap.h: + (Heap): + +2012-05-02 Eric Seidel <eric@webkit.org> + + Sort ENABLE_ defines in FeatureDefines.xcconfig files to make them easier to compare with one another (and easier to autogenerate) + https://bugs.webkit.org/show_bug.cgi?id=85433 + + Reviewed by Adam Barth. + + I have a script which can autogenerate these xcconfig files as well as the + vsprops files (and soon the Chromium, cmake, gnumake and qmake) feature lists + from a central feature list file. + In preparation for posting such a tool, I'm re-sorting these xcconfig files to be + alphabetically ordered (currently they're close, but not quite). + There is also at least one inconsistency between these files (CSS_LEGACY_PREFIXES) which + I will fix in a second pass. I will also sort the FEATURE_DEFINES = line in a follow-up patch. + + * Configurations/FeatureDefines.xcconfig: + +2012-05-02 Hojong Han <hojong.han@samsung.com> + + ARM_TRADITIONAL build fix + https://bugs.webkit.org/show_bug.cgi?id=85358 + + Reviewed by Gavin Barraclough. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::lshift32): + (MacroAssemblerARM): + (JSC::MacroAssemblerARM::or32): + (JSC::MacroAssemblerARM::urshift32): + (JSC::MacroAssemblerARM::xor32): + (JSC::MacroAssemblerARM::branchSub32): + +2012-05-02 Mark Hahnenberg <mhahnenberg@apple.com> + + Opportunistic GC should give up if the Heap is paged out + https://bugs.webkit.org/show_bug.cgi?id=85411 + + Reviewed by Filip Pizlo. + + Opportunistic GC is punishing us severely in limited memory situations because its + assumptions about how much time a collection will take are way out of whack when the Heap + has been paged out by the OS. We should add a simple detection function to the Heap that + detects if its is paged out. It will do this by iterating each block of both the MarkedSpace + and CopiedSpace. If that operation takes longer than a fixed amount of time (e.g. 100ms), + the function returns true. This function will only be run prior to an opportunistic + collection (i.e. it will not run during our normal allocation-triggered collections). + + In my tests, steady state was drastically improved in high memory pressure situations (i.e. + the browser was still usable, significant reduction in SPODs). Occasionally, a normal GC + would be triggered due to pages doing things in the background, which would cause a + significant pause. As we close pages we now cause normal collections rather than full + collections, which prevents us from collecting all of the dead memory immediately. One + nice way to deal with this issue might be to do incremental sweeping. + + + * heap/CopiedSpace.cpp: + (JSC::isBlockListPagedOut): Helper function to reduce code duplication when iterating over + to-space, from-space, and the oversize blocks. + (JSC): + (JSC::CopiedSpace::isPagedOut): Tries to determine whether or not CopiedSpace is paged out + by iterating all of the blocks. + * heap/CopiedSpace.h: + (CopiedSpace): + * heap/Heap.cpp: + (JSC::Heap::isPagedOut): Tries to determine whether the Heap is paged out by asking the + MarkedSpace and CopiedSpace if they are paged out. + (JSC): + * heap/Heap.h: + (Heap): + (JSC::Heap::increaseLastGCLength): Added this so that the GC timer can linearly back off + each time it determines that the Heap is paged out. + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::isPagedOut): Tries to determine if this particular MarkedAllocator's + list of blocks are paged out. + (JSC): + * heap/MarkedAllocator.h: + (MarkedAllocator): + * heap/MarkedSpace.cpp: + (JSC::MarkedSpace::isPagedOut): For each MarkedAllocator, check to see if they're paged out. + * heap/MarkedSpace.h: + (MarkedSpace): + * runtime/GCActivityCallback.cpp: + (JSC::DefaultGCActivityCallback::cancel): + (JSC): + * runtime/GCActivityCallback.h: + (JSC::GCActivityCallback::cancel): + (DefaultGCActivityCallback): + * runtime/GCActivityCallbackCF.cpp: Added a constant of 100ms for the timeout in determining + whether the Heap is paged out or not. + (JSC): + (JSC::DefaultGCActivityCallbackPlatformData::timerDidFire): Added the check to see if we + should attempt a collection based on whether or not we can iterate the blocks of the Heap in + 100ms. If we can't, we cancel the timer and tell the Heap we just wasted 100ms more trying to + do a collection. This gives us a nice linear backoff so we're not constantly re-trying in + steady state paged-out-ness. + (JSC::DefaultGCActivityCallback::cancel): Added this function which, while currently doing + exactly the same thing as willCollect, is more obvious as to what it's doing when we call it + in timerDidFire. + +2012-05-02 Yong Li <yoli@rim.com> + + Fix GCC X86 build error + https://bugs.webkit.org/show_bug.cgi?id=85379 + + Reviewed by Rob Buis. + + Always explicitly claim ".text" to make sure + functions defined with inline assembly will be + created in the correct section. + + * dfg/DFGOperations.cpp: + (JSC): + +2012-05-02 Oliver Hunt <oliver@apple.com> + + Unreviewed, rolling out r115388. + http://trac.webkit.org/changeset/115388 + https://bugs.webkit.org/show_bug.cgi?id=85011 + + This caused many weird performance problems, and needs to be + landed in pieces. + + * dfg/DFGOperations.cpp: + * heap/Heap.cpp: + (JSC::Heap::getConservativeRegisterRoots): + (JSC::Heap::markRoots): + * interpreter/CallFrame.cpp: + (JSC::CallFrame::dumpCaller): + (JSC): + * interpreter/CallFrame.h: + (JSC::ExecState::init): + (ExecState): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + (JSC::Interpreter::executeCall): + (JSC::Interpreter::executeConstruct): + (JSC::Interpreter::prepareForRepeatCall): + (JSC::Interpreter::privateExecute): + * interpreter/Interpreter.h: + (JSC::Interpreter::execute): + * interpreter/RegisterFile.cpp: + (JSC::RegisterFile::growSlowCase): + (JSC::RegisterFile::gatherConservativeRoots): + * interpreter/RegisterFile.h: + (JSC::RegisterFile::end): + (JSC::RegisterFile::size): + (JSC::RegisterFile::addressOfEnd): + (RegisterFile): + (JSC::RegisterFile::RegisterFile): + (JSC::RegisterFile::shrink): + (JSC::RegisterFile::grow): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + (JSC::jitCompileFor): + (JSC::lazyLinkFor): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + (JSC::LLInt::handleHostCall): + * llint/LowLevelInterpreter.asm: + * runtime/CommonSlowPaths.h: + (JSC::CommonSlowPaths::arityCheckFor): + +2012-05-01 Oliver Hunt <oliver@apple.com> + + Physijs demo crashes due to DFG not updating topCallFrame correctly. + https://bugs.webkit.org/show_bug.cgi?id=85311 + + Reviewed by Filip Pizlo. + + A few of the dfg operations failed to correctly set the topCallFrame, + and so everything goes wrong. This patch corrects the effected operations, + and makes debug builds poison topCallFrame before calling a dfg operation. + + * dfg/DFGOperations.cpp: + (JSC::DFG::putByVal): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::callOperation): + (SpeculativeJIT): + (JSC::DFG::SpeculativeJIT::prepareForExternalCall): + (JSC::DFG::SpeculativeJIT::appendCallWithExceptionCheck): + (JSC::DFG::SpeculativeJIT::appendCallSetResult): + +2012-04-30 Gavin Barraclough <barraclough@apple.com> + + Should be able to use YARR JIT without the JS language JIT + https://bugs.webkit.org/show_bug.cgi?id=85252 + + Reviewed by Geoff Garen. + + Need to split canUseRegExpJIT out of canUseJIT. + + * runtime/JSGlobalData.cpp: + (JSC): + (JSC::useJIT): + (JSC::JSGlobalData::JSGlobalData): + - replace m_canUseJIT with m_canUseAssembler + * runtime/JSGlobalData.h: + (JSGlobalData): + (JSC::JSGlobalData::canUseRegExpJIT): + - Added canUseRegExpJIT, distinct from canUseJIT. + * runtime/RegExp.cpp: + (JSC::RegExp::compile): + (JSC::RegExp::compileMatchOnly): + - Call canUseRegExpJIT instead of canUseJIT. + +2012-04-30 Gavin Barraclough <barraclough@apple.com> + + Should be able to build YARR JIT without the JS language JIT + https://bugs.webkit.org/show_bug.cgi?id=85242 + + Reviewed by Michael Saboff. + + Some build macros are wrong. + + * assembler/RepatchBuffer.h: + * jit/ExecutableAllocator.h: + (JSC): + * jit/JITExceptions.cpp: + * runtime/InitializeThreading.cpp: + (JSC::initializeThreadingOnce): + +2012-04-26 Gavin Barraclough <barraclough@apple.com> + + Arguments object resets attributes on redefinition of a parameter + https://bugs.webkit.org/show_bug.cgi?id=84994 + + Rubber stamped by Oliver Hunt. + + There is a bug that we always re-add the original property before + redefinition, doing so in a way that will reset the attributes + without checking configurability. + + * runtime/Arguments.cpp: + (JSC::Arguments::defineOwnProperty): + - Only instantiate the property once - do not re-add if + it has already been added, or if it has been deleted. + +2012-04-30 Ryosuke Niwa <rniwa@webkit.org> + + Remove an erroneous assertion after r115655. + + * runtime/NumberPrototype.cpp: + (JSC::toUStringWithRadix): + +2012-04-30 Myles Maxfield <mmaxfield@google.com> + + End of Interpreter::tryCacheGetByID can trigger the garbage collector + https://bugs.webkit.org/show_bug.cgi?id=84927 + + Reviewed by Oliver Hunt. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::tryCacheGetByID): + +2012-04-30 Benjamin Poulain <benjamin@webkit.org> + + jsSingleCharacterString and jsSingleCharacterSubstring are not inlined + https://bugs.webkit.org/show_bug.cgi?id=85147 + + Reviewed by Darin Adler. + + The functions jsSingleCharacterString() and jsSingleCharacterSubstring() were not inlined + by the compiler. This annihilate the gains of using SmallStrings. + + On stringProtoFuncCharAt(), this patch improves the performance by 11%. + + * runtime/JSString.h: + (JSC::jsSingleCharacterString): + (JSC::jsSingleCharacterSubstring): + +2012-04-30 Benjamin Poulain <bpoulain@apple.com> + + Add fast patch for radix == 10 on numberProtoFuncToString + https://bugs.webkit.org/show_bug.cgi?id=85120 + + Reviewed by Darin Adler. + + When radix, we use to turn the doubleValue into a JSValue just to convert + it to a String. The problem is that was using the slow path for conversion and + for the toString() operation. + + This patch shortcuts the creation of a JSValue and uses NumericStrings directly. + The conversion is split between Integer and Double to ensure the fastest conversion + for the common case of integer arguments. + + Converting number with radix 10 becomes 5% faster. + + Due to the simpler conversion of number to string for integer, converting + integers that do not fall in the two previous optimizations get 32% faster. + + * runtime/NumberPrototype.cpp: + (JSC::extractRadixFromArgs): + (JSC::integerValueToString): + (JSC::numberProtoFuncToString): + +2012-04-30 Carlos Garcia Campos <cgarcia@igalia.com> + + Unreviewed. Fix make distcheck. + + * GNUmakefile.list.am: Add missing header. + +2012-04-28 Geoffrey Garen <ggaren@apple.com> + + Factored threaded block allocation into a separate object + https://bugs.webkit.org/show_bug.cgi?id=85148 + + Reviewed by Sam Weinig. + + 99% of this patch just moves duplicated block allocation and + deallocation code into a new object named BlockAllocator, with these + exceptions: + + * heap/BlockAllocator.h: Added. + (BlockAllocator::BlockAllocator): The order of declarations here now + guards us against an unlikely race condition during startup. + + * heap/BlockAllocator.cpp: + JSC::BlockAllocator::blockFreeingThreadMain): Added a FIXME to + highlight a lack of clarity we have in our block deallocation routines. + +2012-04-28 Sam Weinig <sam@webkit.org> + + Try to fix the Qt build. + + * heap/Heap.cpp: + (JSC::Heap::lastChanceToFinalize): + +2012-04-28 Geoffrey Garen <ggaren@apple.com> + + Try to fix the Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-04-28 Geoffrey Garen <ggaren@apple.com> + + Clarified JSGlobalData (JavaScript VM) lifetime + https://bugs.webkit.org/show_bug.cgi?id=85142 + + Reviewed by Anders Carlsson. + + This was so confusing that I didn't feel like I could reason about + memory lifetime in the heap without fixing it. + + The rules are: + + (1) JSGlobalData owns the virtual machine and all memory in it. + + (2) Deleting a JSGlobalData frees the virtual machine and all memory + in it. + + (Caveat emptor: if you delete the virtual machine while you're running + JIT code or accessing GC objects, you're gonna have a bad time.) + + (I opted not to make arbitrary sub-objects keep the virtual machine + alive automatically because: + + (a) doing that right would be complex and slow; + + (b) in the case of an exiting thread or process, there's no + clear way to give the garbage collector a chance to try again + later; + + (c) continuing to run the garbage collector after we've been + asked to shut down the virtual machine seems rude; + + (d) we've never really supported that feature, anyway.) + + (3) Normal ref-counting will do. No need to call a battery of + specialty functions to tear down a JSGlobalData. Its foibles + notwithstanding, C++ does in fact know how to execute destructors in + order. + + * API/JSContextRef.cpp: + (JSGlobalContextCreate): Removed compatibility shim for older + operating systems because it's no longer used. + + (JSGlobalContextRelease): Now that we can rely on JSGlobalData to "do + the right thing", this code is much simpler. We still have one special + case to notify the garbage collector if we're removing the last + reference to the global object, since this can improve memory behavior. + + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::freeAllBlocks): + * heap/CopiedSpace.h: + (CopiedSpace): Renamed "destroy" => "freeAllBlocks" because true + destruction-time behaviors should be limited to our C++ destructor. + + * heap/Heap.cpp: + (JSC::Heap::~Heap): + (JSC): + (JSC::Heap::lastChanceToFinalize): + * heap/Heap.h: + (Heap): + (JSC::Heap::heap): Renamed "destroy" => "lastChanceToFinalize" because + true destruction-time behaviors should be limited to our C++ + destructor. + + Reorganized the code, putting code that must run before any objects + get torn down into lastChanceToFinalize, and code that just tears down + objects into our destructor. + + * heap/Local.h: + (JSC::LocalStack::LocalStack): + (JSC::LocalStack::push): + (LocalStack): See rule (2). + + * jsc.cpp: + (functionQuit): + (main): + (printUsageStatement): + (parseArguments): + (jscmain): + * testRegExp.cpp: + (main): + (printUsageStatement): + (parseArguments): + (realMain): See rule (3). + + I removed the feature of ensuring orderly tear-down when calling quit() + or running in --help mode because it didn't seem very useful and + making it work with Windows structured exception handling and + NO_RETURN didn't seem like a fun way to spend a Saturday. + + * runtime/JSGlobalData.h: + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): Moved heap to be the first data + member in JSGlobalData to ensure that it's destructed last, so other + objects that reference it destruct without crashing. This allowed me + to remove clearBuiltinStructures() altogether, and helped guarantee + rule (3). + + (JSC::JSGlobalData::~JSGlobalData): Explicitly call + lastChanceToFinalize() at the head of our destructor to ensure that + all pending finalizers run while the virtual machine is still in a + valid state. Trying to resurrect (re-ref) the virtual machine at this + point is not valid, but all other operations are. + + Changed a null to a 0xbbadbeef to clarify just how bad this beef is. + + * runtime/JSGlobalObject.cpp: + (JSC::JSGlobalObject::init): + * runtime/JSGlobalObject.h: + (JSGlobalObject): + (JSC::JSGlobalObject::globalData): See rule (3). + +2012-04-27 Geoffrey Garen <ggaren@apple.com> + + Try to fix the Windows build. + + * heap/WeakBlock.h: + (WeakBlock): + +2012-04-27 Geoffrey Garen <ggaren@apple.com> + + Made WeakSet::allocate() static and removed its JSGlobalData argument + https://bugs.webkit.org/show_bug.cgi?id=85128 + + Reviewed by Anders Carlsson. + + This is a step toward faster finalization. + + WeakSet::allocate() now deduces which WeakSet to allocate from based on + its JSCell* argument. (Currently, there's only one WeakSet, but soon + there will be many.) + + This was a global replace of "globalData.heap.weakSet()->allocate" with + "WeakSet::allocate", plus by-hand removal of the JSGlobalData argument. + + * heap/WeakSetInlines.h: Copied from Source/JavaScriptCore/heap/WeakSet.h. + + I had to split out WeakSet::allocate() in to a separate header to avoid + a cycle. + + (JSC::WeakSet::allocate): We can mask the pointer we're passed to + figure out where to allocate our WeakImpl. (Soon, we'll use this to + associate the WeakImpl with the GC block it references.) + +2012-04-27 Geoffrey Garen <ggaren@apple.com> + + Stop using aligned allocation for WeakBlock + https://bugs.webkit.org/show_bug.cgi?id=85124 + + Reviewed by Anders Carlsson. + + We don't actually use the alignment for anything. + + * heap/WeakBlock.cpp: + (JSC::WeakBlock::create): + (JSC::WeakBlock::WeakBlock): Switched from aligned allocation to regular + allocation. + + * heap/WeakBlock.h: + (WeakBlock): Don't use HeapBlock because HeapBlock requires aligned + allocation. This change required me to add some declarations that we used + to inherit from HeapBlock. + + (WeakBlock::blockFor): Removed. This function relied on aligned allocation + but didn't do anything for us. + + (WeakBlock::deallocate): Removed. WeakBlock doesn't own any of the deallocation + logic, so it shouldn't own the function. + + * heap/WeakSet.cpp: + (JSC::WeakSet::~WeakSet): + (JSC::WeakSet::finalizeAll): + (JSC::WeakSet::visitLiveWeakImpls): + (JSC::WeakSet::visitDeadWeakImpls): + (JSC::WeakSet::sweep): + (JSC::WeakSet::shrink): + (JSC::WeakSet::resetAllocator): + (JSC::WeakSet::tryFindAllocator): + * heap/WeakSet.h: + (WeakSet): Updated declarations to reflect WeakBlock not inheriting from + HeapBlock. This allowed me to remove some casts, which was nice. + + (JSC::WeakSet::deallocate): Directly set the deallocated flag instead of + asking WeakBlock to do it for us. We don't need to have a WeakBlock + pointer to set the flag, so stop asking for one. + +2012-04-27 Kentaro Hara <haraken@chromium.org> + + [JSC] Implement a helper method createNotEnoughArgumentsError() + https://bugs.webkit.org/show_bug.cgi?id=85102 + + Reviewed by Geoffrey Garen. + + In bug 84787, kbr@ requested to avoid hard-coding + createTypeError(exec, "Not enough arguments") here and there. + This patch implements createNotEnoughArgumentsError(exec) + and uses it in JSC bindings. + + c.f. a corresponding bug for V8 bindings is bug 85097. + + * runtime/Error.cpp: + (JSC::createNotEnoughArgumentsError): + (JSC): + * runtime/Error.h: + (JSC): + +2012-04-27 Geoffrey Garen <ggaren@apple.com> + + Only allow non-null pointers in the WeakSet + https://bugs.webkit.org/show_bug.cgi?id=85119 + + Reviewed by Darin Adler. + + This is a step toward more efficient finalization. + + No clients put non-pointers (JSValues) into Weak<T> and PassWeak<T>. + + Some clients put null pointers into Weak<T> and PassWeak<T>, but this is + more efficient and straight-forward to model with a null in the Weak<T> + or PassWeak<T> instead of allocating a WeakImpl just to hold null. + + * heap/PassWeak.h: + (JSC): Removed the Unknown (JSValue) type of weak pointer because it's + unused now. + + (PassWeak): Don't provide a default initializer for our JSCell* argument. + This feature was only used in one place, and it was a bug. + + (JSC::::get): Don't check for a null stored inside our WeakImpl: that's + not allowed anymore. + + (JSC::PassWeak::PassWeak): Handle null as a null WeakImpl instead of + allocating a WeakImpl and storing null into it. + + * heap/Weak.h: + (Weak): + (JSC::::Weak): Same changes as in PassWeak<T>. + + * heap/WeakBlock.cpp: + (JSC::WeakBlock::visitLiveWeakImpls): + (JSC::WeakBlock::visitDeadWeakImpls): Only non-null cells are valid in + the WeakSet now, so no need to check for non-cells and null cell pointers. + + * heap/WeakImpl.h: + (JSC::WeakImpl::WeakImpl): Only non-null cells are valid in the WeakSet + now, so ASSERT that. + +2012-04-27 Gavin Barraclough <barraclough@apple.com> + + <rdar://problem/7909395> Math in JavaScript is inaccurate on iOS + + By defalut IEEE754 denormal support is disabled on iOS; + turn it on. + + Reviewed by Filip Pizlo. + + * jsc.cpp: + (main): + - clear the appropriate bit in the fpscr. + +2012-04-27 Michael Saboff <msaboff@apple.com> + + Memory wasted in JSString for non-rope strings + https://bugs.webkit.org/show_bug.cgi?id=84907 + + Reviewed by Geoffrey Garen. + + Split JSString into two classes, JSString as a base class that does not + include the fibers of a Rope, and a subclass JSRopeString that has the + rope functionality. Both classes "share" the same ClassInfo. Added + a bool to JSString to indicate that the string was allocated as a JSRopeString + to properly handle visiting the fiber children when the rope is resolved and + the JSRopeString appears as a JSString. Didn't change the interface of JSString + to require any JIT changes. + + As part of this change, removed "cellSize" from ClassInfo since both classes + share the same ClassInfo, but have different sizes. The only use I could find + for cellSize was an ASSERT in allocateCell(). + + This appears to be neutral on performance tests. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Changed JSString::resolveRope + to JSRopeString::resolveRope + * runtime/ClassInfo.h: + (JSC): + (ClassInfo): + * runtime/JSCell.h: + (JSC::allocateCell): + * runtime/JSString.cpp: + (JSC::JSRopeString::RopeBuilder::expand): + (JSC::JSString::visitChildren): + (JSC): + (JSC::JSRopeString::visitFibers): + (JSC::JSRopeString::resolveRope): + (JSC::JSRopeString::resolveRopeSlowCase8): + (JSC::JSRopeString::resolveRopeSlowCase): + (JSC::JSRopeString::outOfMemory): + (JSC::JSRopeString::getIndexSlowCase): + * runtime/JSString.h: + (JSC): + (JSString): + (JSC::JSString::finishCreation): + (JSC::JSString::create): + (JSC::JSString::isRope): + (JSC::JSString::is8Bit): + (JSRopeString): + (RopeBuilder): + (JSC::JSRopeString::RopeBuilder::RopeBuilder): + (JSC::JSRopeString::RopeBuilder::append): + (JSC::JSRopeString::RopeBuilder::release): + (JSC::JSRopeString::RopeBuilder::length): + (JSC::JSRopeString::JSRopeString): + (JSC::JSRopeString::finishCreation): + (JSC::JSRopeString::createNull): + (JSC::JSRopeString::create): + (JSC::JSString::value): + (JSC::JSString::tryGetValue): + (JSC::JSString::getIndex): + (JSC::jsStringBuilder): + * runtime/Operations.h: + (JSC::jsString): + (JSC::jsStringFromArguments): + +2012-04-27 Oliver Hunt <oliver@apple.com> + + Correct assertion. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): + +2012-04-27 Oliver Hunt <oliver@apple.com> + + Lazy link phase of baseline jit fails to propagate exception + https://bugs.webkit.org/show_bug.cgi?id=85092 + + Reviewed by Filip Pizlo. + + Very simple patch, when linking produces an error we need to actually store + the exception prior to throwing it. I can't find any other examples of this, + but as we're already in the slow path when throwing an exception I've hardened + exception throwing against null exceptions. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::throwException): + * jit/JITStubs.cpp: + (JSC::lazyLinkFor): + +2012-04-27 Benjamin Poulain <benjamin@webkit.org> + + Generalize the single character optimization of numberProtoFuncToString + https://bugs.webkit.org/show_bug.cgi?id=85027 + + Reviewed by Geoffrey Garen. + + The function numberProtoFuncToString() has an optimization to use SmallStrings::singleCharacterString() + when the radix is 36. + + This patch generalize the optimization for any radix. Any positive number smaller than its radix + can be represented by a single character of radixDigits. + + This makes numberProtoFuncToString() about twice as fast for this case of single digit conversion. + + * runtime/NumberPrototype.cpp: + (JSC::numberProtoFuncToString): + +2012-04-27 Gavin Peters <gavinp@chromium.org> + + Add new ENABLE_LINK_PRERENDER define to control the Prerendering API + https://bugs.webkit.org/show_bug.cgi?id=84871 + + Reviewed by Adam Barth. + + Prerendering is currently covered by the ENABLE_LINK_PREFETCH macro, but the new Prerendering + API separates it from prefetching. Having separate include guards lets ports enable prefetching, + a relatively easy change, without needing to build the infrastructure for prerendering, which + is considerably more complicated. + + * Configurations/FeatureDefines.xcconfig: + +2012-04-26 Oliver Hunt <oliver@apple.com> + + Allocating WeakImpl should not trigger GC, as that makes the world very tricksy. + https://bugs.webkit.org/show_bug.cgi?id=85020 + + Reviewed by Gavin Barraclough. + + Now in the event that we are unable to find an allocator for a new handle, just + add a new allocator rather than trying to recover "dead" handles through a GC. + + Find allocator is now much simpler, and addAllocator directly reports the + increased memory usage to the heap without causing any GC to happen immediately. + + * heap/WeakSet.cpp: + (JSC::WeakSet::findAllocator): + (JSC::WeakSet::addAllocator): + +2012-04-26 Oliver Hunt <oliver@apple.com> + + Remove RegisterFile::end()/m_end + https://bugs.webkit.org/show_bug.cgi?id=85011 + + Reviewed by Gavin Barraclough. + + Get rid of end() and m_end from RegisterFile. From now on + we only care about the end of the committed region when calling + code. When re-entering the VM we now plant the new CallFrame + immediately after whatever the current topCallFrame is. This + required adding a routine to CallFrame to determine exactly what + we should be doing (in the absence of an existing CallFrame, we + can't reason about the frameExtent() so we check for that). + + This also now means that the GC only marks the portion of the + RegisterFile that is actually in use, and that VM re-entry doesn't + exhaust the RegisterFile as rapidly. + + * dfg/DFGOperations.cpp: + * heap/Heap.cpp: + (JSC::Heap::getConservativeRegisterRoots): + (JSC::Heap::markRoots): + * interpreter/CallFrame.h: + (JSC::ExecState::init): + (JSC::ExecState::startOfReusableRegisterFile): + (ExecState): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + (JSC::Interpreter::executeCall): + (JSC::Interpreter::executeConstruct): + (JSC::Interpreter::prepareForRepeatCall): + (JSC::Interpreter::privateExecute): + * interpreter/Interpreter.h: + (JSC::Interpreter::execute): + * interpreter/RegisterFile.cpp: + (JSC::RegisterFile::growSlowCase): + (JSC::RegisterFile::gatherConservativeRoots): + * interpreter/RegisterFile.h: + (JSC::RegisterFile::commitEnd): + (JSC::RegisterFile::addressOfEnd): + (RegisterFile): + (JSC::RegisterFile::RegisterFile): + (JSC::RegisterFile::shrink): + (JSC::RegisterFile::grow): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + (JSC::jitCompileFor): + (JSC::lazyLinkFor): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + (JSC::LLInt::handleHostCall): + * llint/LowLevelInterpreter.asm: + * runtime/CommonSlowPaths.h: + (JSC::CommonSlowPaths::arityCheckFor): + +2012-04-26 Filip Pizlo <fpizlo@apple.com> + + DFG ARMv7 backend should optimize Float32 arrays + https://bugs.webkit.org/show_bug.cgi?id=85000 + <rdar://problem/10652827> + + Reviewed by Gavin Barraclough. + + * assembler/ARMv7Assembler.h: + (ARMv7Assembler): + (JSC::ARMv7Assembler::flds): + (JSC::ARMv7Assembler::fsts): + (JSC::ARMv7Assembler::vcvtds): + (JSC::ARMv7Assembler::vcvtsd): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::loadFloat): + (MacroAssemblerARMv7): + (JSC::MacroAssemblerARMv7::storeFloat): + (JSC::MacroAssemblerARMv7::convertFloatToDouble): + (JSC::MacroAssemblerARMv7::convertDoubleToFloat): + * bytecode/PredictedType.h: + (JSC::isActionableFloatMutableArrayPrediction): + * dfg/DFGNode.h: + (JSC::DFG::Node::shouldSpeculateFloat32Array): + +2012-04-25 Benjamin Poulain <benjamin@webkit.org> + + Add a version of StringImpl::find() without offset + https://bugs.webkit.org/show_bug.cgi?id=83968 + + Reviewed by Sam Weinig. + + Add support for the new StringImpl::find() to UString. + + Change stringProtoFuncIndexOf() to specifically take advatage of the feature. + This gives a 12% gains on a distribution of strings between 30 and 100 characters. + + * runtime/StringPrototype.cpp: + (JSC::substituteBackreferences): + (JSC::stringProtoFuncIndexOf): + * runtime/UString.h: + (UString): + (JSC::UString::find): + +2012-04-25 Mark Hahnenberg <mhahnenberg@apple.com> + + WebCore shouldn't call collectAllGarbage directly + https://bugs.webkit.org/show_bug.cgi?id=84897 + + Reviewed by Geoffrey Garen. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Exported symbol + for reportAbanondedObjectGraph so WebCore can use it. + * heap/Heap.h: Ditto. + +2012-04-25 Oliver Hunt <oliver@apple.com> + + Biolab disaster crashes on ToT + https://bugs.webkit.org/show_bug.cgi?id=84898 + + Reviewed by Filip Pizlo. + + Whoops, committed without saving reviewer requested change. + + * dfg/DFGVirtualRegisterAllocationPhase.cpp: + (JSC::DFG::VirtualRegisterAllocationPhase::run): + +2012-04-25 Oliver Hunt <oliver@apple.com> + + Biolab disaster crashes on ToT + https://bugs.webkit.org/show_bug.cgi?id=84898 + + Reviewed by Filip Pizlo. + + I recently added an assertion to the Interpreter to catch incorrect + updates of topCallFrame. This caused a bunch of sites (including biolab + disaster) to crash as we were not correctly handling callee registers + of inlined functions, leading to a mismatch. + + I could not actually make this trigger directly, although it does trigger + already on some of the GTK and QT bots. + + * dfg/DFGVirtualRegisterAllocationPhase.cpp: + (JSC::DFG::VirtualRegisterAllocationPhase::run): + +2012-04-25 Kenneth Russell <kbr@google.com> + + Delete CanvasPixelArray, ByteArray, JSByteArray and JSC code once unreferenced + https://bugs.webkit.org/show_bug.cgi?id=83655 + + Reviewed by Oliver Hunt. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.gypi: + * JavaScriptCore.order: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * bytecode/PredictedType.cpp: + (JSC::predictionToString): + (JSC::predictionToAbbreviatedString): + (JSC::predictionFromClassInfo): + * bytecode/PredictedType.h: + (JSC): + (JSC::isActionableIntMutableArrayPrediction): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::initialize): + (JSC::DFG::AbstractState::execute): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::performNodeCSE): + * dfg/DFGFixupPhase.cpp: + (JSC::DFG::FixupPhase::fixupNode): + * dfg/DFGNode.h: + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGOperations.cpp: + (JSC::DFG::putByVal): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::checkArgumentTypes): + (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::ValueSource::forPrediction): + (SpeculativeJIT): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * jit/JITStubs.h: + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::getByVal): + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + * runtime/JSByteArray.cpp: Removed. + * runtime/JSByteArray.h: Removed. + * runtime/JSGlobalData.cpp: + +2012-04-25 Filip Pizlo <fpizlo@apple.com> + + http://bellard.org/jslinux/ triggers an assertion failure in the DFG JIT + https://bugs.webkit.org/show_bug.cgi?id=84815 + <rdar://problem/11319514> + + Reviewed by Gavin Barraclough. + + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::forwardSpeculationCheck): + +2012-04-25 Michael Saboff <msaboff@apple.com> + + Closure in try {} with catch captures all locals from the enclosing function + https://bugs.webkit.org/show_bug.cgi?id=84804 + + Reviewed by Oliver Hunt. + + Changed the capturing of local variables from capturing when eval is used, + within a "with" or within a "catch" to be just when an eval is used. + Renamed the function returning that we should capture from + getCapturedVariables() to usesEval(), since that what it noew returns. + Needed to fix the "with" code to only range check when the activation + has actually been torn off. Added m_isTornOff to JSActivation to + track this. + + * parser/Parser.h: + (JSC::Scope::usesEval): + (JSC::Scope::getCapturedVariables): + * runtime/JSActivation.cpp: + (JSC::JSActivation::JSActivation): + (JSC::JSActivation::symbolTableGet): + (JSC::JSActivation::symbolTablePut): + * runtime/JSActivation.h: + (JSActivation): + (JSC::JSActivation::tearOff): + +2012-04-24 Mark Hahnenberg <mhahnenberg@apple.com> + + GC Activity Callback timer should be based on how much has been allocated since the last collection + https://bugs.webkit.org/show_bug.cgi?id=84763 + + Reviewed by Geoffrey Garen. + + The desired behavior for the GC timer is to collect at some point in the future, + regardless of how little we've allocated. A secondary goal, which is almost if not + as important, is for the timer to collect sooner if there is the potential to + collect a greater amount of memory. Conversely, as we allocate more memory we'd + like to reduce the delay to the next collection. If we're allocating quickly enough, + the timer should be preempted in favor of a normal allocation-triggered collection. + If allocation were to slow or stop, we'd like the timer to be able to opportunistically + run a collection without us having to allocate to the hard limit set by the Heap. + + This type of policy can be described in terms of the amount of CPU we are willing + to dedicate to reclaim a single MB of memory. For example, we might be willing to + dedicate 1% of our CPU to reclaim 1 MB. We base our CPU usage off of the length of + the last collection, e.g. if our last collection took 1ms, we would want to wait about + 100ms before running another collection to reclaim 1 MB. These constants should be + tune-able, e.g. 0.1% CPU = 1 MB vs. 1% CPU = 1 MB vs. 10% CPU = 1 MB. + + * API/JSBase.cpp: Use the new reportAbandonedObjectGraph. + (JSGarbageCollect): + * API/JSContextRef.cpp: Ditto. + * heap/Heap.cpp: + (JSC::Heap::Heap): + (JSC::Heap::reportAbandonedObjectGraph): Similar to reportExtraMemoryCost. Clients call + this function to notify the Heap that some unknown number of JSC objects might have just + been abandoned and are now garbage. The Heap might schedule a new collection timer based + on this notification. + (JSC): + (JSC::Heap::collect): Renamed m_lastFullGCSize to the less confusing m_sizeAfterLastCollect. + * heap/Heap.h: + (Heap): + * heap/MarkedAllocator.h: + (JSC::MarkedAllocator::zapFreeList): Fixed a bug in zapFreeList that failed to nullify the + current allocator's FreeList once zapping was complete. + * runtime/GCActivityCallback.cpp: Removed didAbandonObjectGraph because it was replaced by + Heap::reportAbandonedObjectGraph. + (JSC): + * runtime/GCActivityCallback.h: + (JSC::GCActivityCallback::willCollect): + (DefaultGCActivityCallback): + * runtime/GCActivityCallbackCF.cpp: Refactored the GC timer code so that we now schedule the + timer based on how much we have allocated since the last collection up to a certain amount. + We use the length of the previous GC to try to keep our total cost of opportunistic timer-triggered + collections around 1% of the CPU per MB of garbage we expect to reclaim up to a maximum of 5 MB. + (DefaultGCActivityCallbackPlatformData): + (JSC): + (JSC::DefaultGCActivityCallback::~DefaultGCActivityCallback): + (JSC::DefaultGCActivityCallback::commonConstructor): + (JSC::scheduleTimer): + (JSC::cancelTimer): + (JSC::DefaultGCActivityCallback::didAllocate): + +2012-04-24 Michael Saboff <msaboff@apple.com> + + objectProtoFuncToString creates new string every invocation + https://bugs.webkit.org/show_bug.cgi?id=84781 + + Reviewed by Geoffrey Garen. + + Cache the results of object toString() in the attached Structure. + + * runtime/ObjectPrototype.cpp: + (JSC::objectProtoFuncToString): + * runtime/Structure.cpp: + (JSC::Structure::visitChildren): visit new m_hasObjectToStringValue. + * runtime/Structure.h: Added new member m_hasObjectToStringValue + (JSC): + (JSC::Structure::objectToStringValue): + (Structure): + (JSC::Structure::setObjectToStringValue): + +2012-04-24 Thouraya ANDOLSI <thouraya.andolsi@st.com> + + Reviewed by Oliver Hunt. + + https://bugs.webkit.org/show_bug.cgi?id=84727. + Fix build when ENABLE_JIT_CONSTANT_BLINDING enabled. + + * assembler/MacroAssemblerSH4.h: + (JSC::MacroAssemblerSH4::or32): + (JSC::MacroAssemblerSH4::and32): + (JSC::MacroAssemblerSH4::lshift32): + (JSC::MacroAssemblerSH4::xor32): + (JSC::MacroAssemblerSH4::branchSub32): + (JSC::MacroAssemblerSH4::urshift32): + +2012-04-24 Gavin Barraclough <barraclough@apple.com> + + Add explicit patchableBranchPtrWithPatch/patchableJump methods + https://bugs.webkit.org/show_bug.cgi?id=84498 + + Reviewed by Filip Pizlo. + + Don't rely on inUninterruptedSequence to distinguish which jumps we need to be able to repatch. + + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::PatchableJump::PatchableJump): + (PatchableJump): + (JSC::AbstractMacroAssembler::PatchableJump::operator Jump&): + (AbstractMacroAssembler): + (JSC::AbstractMacroAssembler::AbstractMacroAssembler): + - Added PatchableJump type, removed inUninterruptedSequence. + * assembler/LinkBuffer.h: + (LinkBuffer): + (JSC::LinkBuffer::locationOf): + - Only allow the location to be taken of patchable branches + * assembler/MacroAssembler.h: + (MacroAssembler): + (JSC::MacroAssembler::patchableBranchPtrWithPatch): + (JSC::MacroAssembler::patchableJump): + (JSC::MacroAssembler::shouldBlind): + - Added default implementation of patchableBranchPtrWithPatch, patchableJump. + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::MacroAssemblerARMv7): + (MacroAssemblerARMv7): + (JSC::MacroAssemblerARMv7::patchableBranchPtrWithPatch): + (JSC::MacroAssemblerARMv7::patchableJump): + (JSC::MacroAssemblerARMv7::jump): + (JSC::MacroAssemblerARMv7::makeBranch): + - Added ARMv7 implementation of patchableBranchPtrWithPatch, patchableJump. + * dfg/DFGCorrectableJumpPoint.h: + (DFG): + (JSC::DFG::CorrectableJumpPoint::switchToLateJump): + - Late jumps are PatchableJumps. + * dfg/DFGJITCompiler.cpp: + (JSC::DFG::JITCompiler::linkOSRExits): + - replace use of inUninterruptedSequence + * dfg/DFGJITCompiler.h: + (JSC::DFG::PropertyAccessRecord::PropertyAccessRecord): + (PropertyAccessRecord): + - replace use of inUninterruptedSequence + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::cachedGetById): + (JSC::DFG::SpeculativeJIT::cachedPutById): + - replace use of inUninterruptedSequence + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::cachedGetById): + (JSC::DFG::SpeculativeJIT::cachedPutById): + - replace use of inUninterruptedSequence + * jit/JIT.h: + (PropertyStubCompilationInfo): + - replace use of inUninterruptedSequence + * jit/JITInlineMethods.h: + (JSC::JIT::beginUninterruptedSequence): + (JSC::JIT::endUninterruptedSequence): + - replace use of inUninterruptedSequence + * jit/JITPropertyAccess.cpp: + (JSC::JIT::compileGetByIdHotPath): + - replace use of inUninterruptedSequence + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::compileGetByIdHotPath): + - replace use of inUninterruptedSequence + +2012-04-24 Benjamin Poulain <bpoulain@apple.com> + + Generalize the single character optimization of r114072 + https://bugs.webkit.org/show_bug.cgi?id=83961 + + Reviewed by Eric Seidel. + + Use the regular String::find(StringImpl*) in all cases now that it has been made faster. + + * runtime/StringPrototype.cpp: + (JSC::replaceUsingStringSearch): + +2012-04-24 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, 32-bit build fix. + + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-04-24 Filip Pizlo <fpizlo@apple.com> + + DFG performs incorrect DCE on (some?) intrinsics + https://bugs.webkit.org/show_bug.cgi?id=84746 + <rdar://problem/11310772> + + Reviewed by Oliver Hunt. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGByteCodeParser.cpp: + (ByteCodeParser): + (JSC::DFG::ByteCodeParser::setIntrinsicResult): + (JSC::DFG::ByteCodeParser::handleMinMax): + (JSC::DFG::ByteCodeParser::handleIntrinsic): + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-04-24 Mark Hahnenberg <mhahnenberg@apple.com> + + Failure to allocate ArrayStorage in emit_op_new_array leads to poisonous JSArray + https://bugs.webkit.org/show_bug.cgi?id=84648 + + Reviewed by Geoffrey Garen. + + When emit_op_new_array successfully allocates a new JSArray but fails to allocate + the corresponding ArrayStorage for it, it falls back to the out-of-line stub call + to constructArray, which constructs and entirely new JSArray/ArrayStorage pair. + This leaves us with a JSArray hanging around on the stack or in a register that + did not go through its own constructor, thus giving it uninitialized memory in the + two fields that are checked in JSArray::visitChildren. + + * jit/JITInlineMethods.h: + (JSC::JIT::emitAllocateJSArray): We try to allocate the ArrayStorage first, so that + if we fail we haven't generated the poisonous JSArray that can cause a GC crash. + * jit/JITOpcodes.cpp: + (JSC::JIT::emitSlow_op_new_array): + +2012-04-23 Filip Pizlo <fpizlo@apple.com> + + DFG on ARMv7 should not OSR exit on every integer division + https://bugs.webkit.org/show_bug.cgi?id=84661 + + Reviewed by Oliver Hunt. + + On ARMv7, ArithDiv no longer has to know whether or not to speculate integer (since + that was broken with the introduction of Int32ToDouble) nor does it have to know + whether or not to convert its result to integer. This is now taken care of for free + with the addition of the DoubleAsInt32 node, which represents a double-is-really-int + speculation. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::performNodeCSE): + * dfg/DFGFixupPhase.cpp: + (JSC::DFG::FixupPhase::fixupNode): + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGOSRExit.cpp: + (JSC::DFG::OSRExit::OSRExit): + (JSC::DFG::OSRExit::considerAddingAsFrequentExitSiteSlow): + * dfg/DFGOSRExit.h: + (OSRExit): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor): + (JSC::DFG::SpeculativeJIT::compileDoubleAsInt32): + (DFG): + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + (JSC::DFG::SpeculativeJIT::speculationCheck): + (JSC::DFG::SpeculativeJIT::forwardSpeculationCheck): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-04-24 Geoffrey Garen <ggaren@apple.com> + + "GlobalHandle" HandleHeap (now WeakSet) allocations grow but do not shrink + https://bugs.webkit.org/show_bug.cgi?id=84740 + <rdar://problem/9917638> + + Reviewed by Gavin Barraclough. + + Shrink! + + * heap/Heap.cpp: + (JSC::Heap::destroy): Be more specific about what's shrinking, since we + can also shrink the WeakSet, but we don't do so here. + + (JSC::Heap::collect): If we're going to shrink the heap, shrink the + WeakSet too. Otherwise, its footprint is permanent. + + * heap/Heap.h: + (Heap): Removed shrink() as a public interface, since it's vague about + which parts of the heap it affects, and it's really an internal detail. + + * heap/WeakSet.cpp: + (JSC::WeakSet::shrink): Nix any free blocks. We assume that sweep() has + already taken place, since that's the convention for shrink() in the heap. + + * heap/WeakSet.h: + (WeakSet): New function! + +2012-04-24 Adam Klein <adamk@chromium.org> + + Fix includes in StrongInlines.h and ScriptValue.h + https://bugs.webkit.org/show_bug.cgi?id=84659 + + Reviewed by Geoffrey Garen. + + * heap/StrongInlines.h: Include JSGlobalData.h, since JSGlobalData's + definiition is required here. + +2012-04-23 Filip Pizlo <fpizlo@apple.com> + + DFG OSR exit should ensure that all variables have been initialized + https://bugs.webkit.org/show_bug.cgi?id=84653 + <rdar://problem/11258183> + + Reviewed by Gavin Barraclough. + + Initialize all uncaptured dead variables to undefined on OSR exit. + + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::ValueSource::dump): + (JSC::DFG::SpeculativeJIT::compile): + (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor): + * dfg/DFGSpeculativeJIT.h: + +2012-04-23 Oliver Hunt <oliver@apple.com> + + Call instruction for the baseline JIT stores origin info in wrong callframe + https://bugs.webkit.org/show_bug.cgi?id=84645 + + Reviewed by Gavin Barraclough. + + The baseline JIT was updating the wrong callframe when making a call. If the + call failed during dispatch (unable to perform codegen, calling a non-object) + we would attempt to use this information, but it would be completely wrong. + + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + * jit/JITCall32_64.cpp: + (JSC::JIT::compileOpCall): + +2012-04-23 Filip Pizlo <fpizlo@apple.com> + + DFG must keep alive values that it will perform speculations on + https://bugs.webkit.org/show_bug.cgi?id=84638 + <rdar://problem/11258183> + + Reviewed by Oliver Hunt. + + * dfg/DFGNodeType.h: + (DFG): + +2012-04-23 Oliver Hunt <oliver@apple.com> + + Fix non-LLInt builds by temporarily removing an over-enthusiastic assertion + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::executeCall): + +2012-04-22 Jon Lee <jonlee@apple.com> + + Remove notifications support on Mac Lion. + https://bugs.webkit.org/show_bug.cgi?id=84554 + <rdar://problem/11297128> + + Reviewed by Sam Weinig. + + * Configurations/FeatureDefines.xcconfig: + +2012-04-21 Darin Adler <darin@apple.com> + + Change JavaScript lexer to use 0 instead of -1 for sentinel, eliminating the need to put characters into ints + https://bugs.webkit.org/show_bug.cgi?id=84523 + + Reviewed by Oliver Hunt. + + Profiles showed that checks against -1 were costly, and I saw they could be eliminated. + Streamlined this code to use standard character types and 0 rather than -1. One benefit + of this is that there's no widening and narrowing. Another is that there are many cases + where we already have the correct behavior for 0, so can eliminate a branch that was + used to test for -1 before. Also eliminates typecasts in the code. + + * parser/Lexer.cpp: + (JSC::Lexer::invalidCharacterMessage): Updated use of String::format since m_current is now a + character type, not an int. + (JSC::Lexer::setCode): Use 0 rather than -1 when past the end. + (JSC::Lexer::shift): Ditto. Also spruced up the comment a bit. + (JSC::Lexer::atEnd): Added. New function that distinguishes an actual 0 character from the end + of the code. This can be used places we used to cheeck for -1. + (JSC::Lexer::peek): Updated to use -1 instead of 0. Removed meaningless comment. + (JSC::Lexer::parseFourDigitUnicodeHex): Changed to use character types instead of int. + (JSC::Lexer::shiftLineTerminator): Removed now-unneeded type casts. Changed local variable that + had a data-member-style name. + (JSC::Lexer::parseIdentifier): Removed now-unneeded explicit checks for -1, since the isIdentPart + function already returns false for the 0 character. Updated types in a couple other places. Used + the atEnd function where needed. + (JSC::Lexer::parseIdentifierSlowCase): More of the same. + (JSC::characterRequiresParseStringSlowCase): Added overloaded helper function for parseString. + (JSC::Lexer::parseString): Ditto. + (JSC::Lexer::parseStringSlowCase): Ditto. + (JSC::Lexer::parseMultilineComment): Ditto. + (JSC::Lexer::lex): More of the same. Also changed code to set the startOffset directly in + the tokenInfo instead of putting it in a local variable first, saving some memory access. + (JSC::Lexer::scanRegExp): Ditto. + (JSC::Lexer::skipRegExp): Ditto. + + * parser/Lexer.h: Changed return type of the peek function and type of m_current from int to + the character type. Added atEnd function. + (JSC::Lexer::setOffset): Used 0 instead of -1 and removed an overzealous attempt to optimize. + (JSC::Lexer::lexExpectIdentifier): Used 0 instead of -1. + +2012-04-21 Darin Adler <darin@apple.com> + + Change JavaScript lexer to use 0 instead of -1 for sentinel, eliminating the need to put characters into ints + https://bugs.webkit.org/show_bug.cgi?id=84523 + + Reviewed by Oliver Hunt. + + Separate preparation step of copyright dates, renaming, and other small tweaks. + + * parser/Lexer.cpp: + (JSC::Lexer::invalidCharacterMessage): Removed "get" from name to match WebKit naming conventions. + (JSC::Lexer::peek): Removed meaningless comment. + (JSC::Lexer::parseFourDigitUnicodeHex): Renamed from getUnicodeCharacter to be more precise about + what this function does. + (JSC::Lexer::shiftLineTerminator): Renamed local variable that had a data-member-style name. + (JSC::Lexer::parseStringSlowCase): Updated for new name of parseFourDigitUnicodeHex. + (JSC::Lexer::lex): Updated for new name of invalidCharacterMessage. + + * parser/Lexer.h: Removed an unneeded forward declaration of the RegExp class. + Renamed getInvalidCharMessage to invalidCharacterMessage and made it const. Renamed + getUnicodeCharacter to parseFourDigitUnicodeHex. + +2012-04-20 Filip Pizlo <fpizlo@apple.com> + + DFG should optimize int8 and int16 arrays on ARMv7 + https://bugs.webkit.org/show_bug.cgi?id=84503 + + Reviewed by Oliver Hunt. + + * assembler/ARMv7Assembler.h: + (ARMv7Assembler): + (JSC::ARMv7Assembler::ldrsb): + (JSC::ARMv7Assembler::ldrsh): + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::load16Signed): + (JSC::MacroAssemblerARMv7::load8Signed): + * bytecode/PredictedType.h: + (JSC::isActionableIntMutableArrayPrediction): + * dfg/DFGNode.h: + (JSC::DFG::Node::shouldSpeculateInt8Array): + (JSC::DFG::Node::shouldSpeculateInt16Array): + +2012-04-20 Oliver Hunt <oliver@apple.com> + + Add an ability to find the extent of a callframe + https://bugs.webkit.org/show_bug.cgi?id=84513 + + Reviewed by Filip Pizlo. + + Add a function to get the extent of a callframe and + use that function for a new assertion to make sure the + RegisterFile makes sense using that information. + + * interpreter/CallFrame.cpp: + (JSC::CallFrame::frameExtentInternal): + (JSC): + * interpreter/CallFrame.h: + (JSC::ExecState::frameExtent): + (ExecState): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::executeCall): + +2012-04-20 Benjamin Poulain <bpoulain@apple.com> + + Inline the JSArray constructor + https://bugs.webkit.org/show_bug.cgi?id=84416 + + Reviewed by Geoffrey Garen. + + The constructor is trivial, no reason to jump for it. + + This makes the creation of array ~5% faster (on non-trivial cases, no empty arrays). + + * runtime/JSArray.cpp: + (JSC): + * runtime/JSArray.h: + (JSC::JSArray::JSArray): + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-04-20 Mark Hahnenberg <mhahnenberg@apple.com> + + Heap should cancel GC timer at the start of the collection + https://bugs.webkit.org/show_bug.cgi?id=84477 + + Reviewed by Geoffrey Garen. + + Currently the Heap cancels the GC timer at the conclusion of a collection. + We should change this to be at the beginning because something (e.g. a finalizer) + could call didAbandonObjectGraph(), which will schedule the timer, but then + we'll immediately unschedule the timer at the conclusion of the collection, + thus potentially preventing large swaths of memory from being reclaimed in a timely manner. + + * API/JSBase.cpp: + (JSGarbageCollect): Remove outdated fix-me and remove check for whether the Heap is + busy or not, since we're just scheduling a timer to run a GC in the future. + * heap/Heap.cpp: + (JSC::Heap::collect): Rename didCollect to willCollect and move the call to the + top of Heap::collect. + * runtime/GCActivityCallback.cpp: Renamed didCollect to willCollect. + (JSC::DefaultGCActivityCallback::willCollect): + * runtime/GCActivityCallback.h: Ditto. + (JSC::GCActivityCallback::willCollect): + (DefaultGCActivityCallback): + * runtime/GCActivityCallbackCF.cpp: Ditto. + (JSC::DefaultGCActivityCallback::willCollect): + +2012-04-20 Mark Hahnenberg <mhahnenberg@apple.com> + + JSGarbageCollect should not call collectAllGarbage() + https://bugs.webkit.org/show_bug.cgi?id=84476 + + Reviewed by Geoffrey Garen. + + * API/JSBase.cpp: + (JSGarbageCollect): Notify the Heap's GCActivityCallback using didAbandonObjectGraph. + +2012-04-19 Oliver Hunt <oliver@apple.com> + + Exception stack traces aren't complete when the exception starts in native code + https://bugs.webkit.org/show_bug.cgi?id=84073 + + Reviewed by Filip Pizlo. + + Refactored building the stack trace to so that we can construct + it earlier, and don't rely on any prior work performed in the + exception handling machinery. Also updated LLInt and the DFG to + completely initialise the callframes of host function calls. + + Also fixed a few LLInt paths that failed to correctly update the + topCallFrame. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * dfg/DFGJITCompiler.h: + * dfg/DFGOperations.cpp: + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::emitCall): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::emitCall): + * interpreter/Interpreter.cpp: + (JSC::eval): + (JSC::Interpreter::getStackTrace): + (JSC::Interpreter::addStackTraceIfNecessary): + (JSC): + (JSC::Interpreter::throwException): + * interpreter/Interpreter.h: + (Interpreter): + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + * jit/JITCall32_64.cpp: + (JSC::JIT::compileOpCall): + * jit/JITOpcodes.cpp: + (JSC::JIT::privateCompileCTINativeCall): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::privateCompileCTINativeCall): + * jsc.cpp: + (functionJSCStack): + * llint/LLIntExceptions.cpp: + (JSC::LLInt::interpreterThrowInCaller): + (JSC::LLInt::returnToThrow): + (JSC::LLInt::callToThrow): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::handleHostCall): + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + * parser/Parser.h: + (JSC::::parse): + * runtime/Error.cpp: + (JSC::addErrorInfo): + (JSC::throwError): + * runtime/Error.h: + (JSC): + +2012-04-19 Mark Hahnenberg <mhahnenberg@apple.com> + + We're collecting pathologically due to small allocations + https://bugs.webkit.org/show_bug.cgi?id=84404 + + Reviewed by Geoffrey Garen. + + No change in performance on run-jsc-benchmarks. + + * dfg/DFGSpeculativeJIT.h: Replacing m_firstFreeCell with m_freeList. + (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject): + * heap/CopiedSpace.cpp: Getting rid of any water mark related stuff, since it's no + longer useful. + (JSC::CopiedSpace::CopiedSpace): + (JSC::CopiedSpace::tryAllocateSlowCase): We now only call didAllocate here rather than + carrying out a somewhat complicated accounting job for our old water mark throughout CopiedSpace. + (JSC::CopiedSpace::tryAllocateOversize): Call the new didAllocate to notify the Heap of + newly allocated stuff. + (JSC::CopiedSpace::tryReallocateOversize): + (JSC::CopiedSpace::doneFillingBlock): + (JSC::CopiedSpace::doneCopying): + (JSC::CopiedSpace::destroy): + * heap/CopiedSpace.h: + (CopiedSpace): + * heap/CopiedSpaceInlineMethods.h: + (JSC::CopiedSpace::startedCopying): + * heap/Heap.cpp: Removed water mark related stuff, replaced with new bytesAllocated and + bytesAllocatedLimit to track how much memory has been allocated since the last collection. + (JSC::Heap::Heap): + (JSC::Heap::reportExtraMemoryCostSlowCase): + (JSC::Heap::collect): We now set the new limit of bytes that we can allocate before triggering + a collection to be the size of the Heap after the previous collection. Thus, we still have our + 2x allocation amount. + (JSC::Heap::didAllocate): Notifies the GC activity timer of how many bytes have been allocated + thus far and then adds the new number of bytes to the current total. + (JSC): + * heap/Heap.h: Removed water mark related stuff. + (JSC::Heap::notifyIsSafeToCollect): + (Heap): + (JSC::Heap::shouldCollect): + (JSC): + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::tryAllocateHelper): Refactored to use MarkedBlock's new FreeList struct. + (JSC::MarkedAllocator::allocateSlowCase): + (JSC::MarkedAllocator::addBlock): + * heap/MarkedAllocator.h: + (MarkedAllocator): + (JSC::MarkedAllocator::MarkedAllocator): + (JSC::MarkedAllocator::allocate): + (JSC::MarkedAllocator::zapFreeList): Refactored to take in a FreeList instead of a FreeCell. + * heap/MarkedBlock.cpp: + (JSC::MarkedBlock::specializedSweep): + (JSC::MarkedBlock::sweep): + (JSC::MarkedBlock::sweepHelper): + (JSC::MarkedBlock::zapFreeList): + * heap/MarkedBlock.h: + (FreeList): Added a new struct that keeps track of the current MarkedAllocator's + free list including the number of bytes of stuff in the free list so that when the free list is + exhausted, the correct amount can be reported to Heap. + (MarkedBlock): + (JSC::MarkedBlock::FreeList::FreeList): + (JSC): + * heap/MarkedSpace.cpp: Removing all water mark related stuff. + (JSC::MarkedSpace::MarkedSpace): + (JSC::MarkedSpace::resetAllocators): + * heap/MarkedSpace.h: + (MarkedSpace): + (JSC): + * heap/WeakSet.cpp: + (JSC::WeakSet::findAllocator): Refactored to use the didAllocate interface with the Heap. This + function still needs work though now that the Heap knows how many bytes have been allocated + since the last collection. + * jit/JITInlineMethods.h: Refactored to use MarkedBlock's new FreeList struct. + (JSC::JIT::emitAllocateBasicJSObject): Ditto. + * llint/LowLevelInterpreter.asm: Ditto. + * runtime/GCActivityCallback.cpp: + (JSC::DefaultGCActivityCallback::didAllocate): + * runtime/GCActivityCallback.h: + (JSC::GCActivityCallback::didAllocate): Renamed willAllocate to didAllocate to indicate that + the allocation that is being reported has already taken place. + (DefaultGCActivityCallback): + * runtime/GCActivityCallbackCF.cpp: + (JSC): + (JSC::DefaultGCActivityCallback::didAllocate): Refactored to return early if the amount of + allocation since the last collection is not above a threshold (initially arbitrarily chosen to + be 128KB). + +2012-04-19 Filip Pizlo <fpizlo@apple.com> + + MacroAssemblerARMv7::branchTruncateDoubleToUint32 should obey the overflow signal + https://bugs.webkit.org/show_bug.cgi?id=84401 + + Reviewed by Gavin Barraclough. + + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::branchTruncateDoubleToUint32): + +2012-04-19 Don Olmstead <don.olmstead@am.sony.com> + + KeywordLookupGenerator.py should take an output file as an argument + https://bugs.webkit.org/show_bug.cgi?id=84292 + + Reviewed by Eric Seidel. + + Extended KeywordLookupGenerator to accept an additional argument specifying an output file. If this argument is found stdout is redirected to a file for the duration of the script. + + * KeywordLookupGenerator.py: + +2012-04-19 Filip Pizlo <fpizlo@apple.com> + + It should be possible to perform debugCall on ARMv7 + https://bugs.webkit.org/show_bug.cgi?id=84381 + + Reviewed by Oliver Hunt. + + debugCall() was clobbering the argument to the call it was making, leading to a + corrupt ExecState*. This change fixes that issue by using a scratch register that + does not clobber arguments, and it also introduces more assertions that we have + a valid call frame. + + * dfg/DFGAssemblyHelpers.cpp: + (DFG): + (JSC::DFG::AssemblyHelpers::jitAssertHasValidCallFrame): + * dfg/DFGAssemblyHelpers.h: + (JSC::DFG::AssemblyHelpers::selectScratchGPR): + (AssemblyHelpers): + (JSC::DFG::AssemblyHelpers::debugCall): + (JSC::DFG::AssemblyHelpers::jitAssertHasValidCallFrame): + * dfg/DFGJITCompiler.cpp: + (JSC::DFG::JITCompiler::linkOSRExits): + * dfg/DFGOSRExitCompiler.cpp: + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::selectScratchGPR): + +2012-04-19 Filip Pizlo <fpizlo@apple.com> + + LLInt no-JIT fallback native call trampoline's exception handler incorrectly assumes that + the PB/PC has been preserved + https://bugs.webkit.org/show_bug.cgi?id=84367 + + Reviewed by Oliver Hunt. + + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + +2012-04-19 Filip Pizlo <fpizlo@apple.com> + + It should be possible to load from Float64 arrays on ARMv7 without crashing + https://bugs.webkit.org/show_bug.cgi?id=84361 + + Reviewed by Oliver Hunt. + + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::loadDouble): + (JSC::MacroAssemblerARMv7::storeDouble): + +2012-04-19 Dominik Röttsches <dominik.rottsches@linux.intel.com> + + [CMake] Build fix after r114575 + https://bugs.webkit.org/show_bug.cgi?id=84322 + + Reviewed by Simon Hausmann. + + Build fix, adding WTF when linking jsc shell. + + * shell/CMakeLists.txt: + +2012-04-18 Filip Pizlo <fpizlo@apple.com> + + JSC testing should have complete coverage over typed array types + https://bugs.webkit.org/show_bug.cgi?id=84302 + + Reviewed by Geoff Garen. + + Added Uint8ClampedArray to the set of typed arrays that are supported by jsc + command-line. + + * JSCTypedArrayStubs.h: + (JSC): + * jsc.cpp: + (GlobalObject::finishCreation): + +2012-04-18 Filip Pizlo <fpizlo@apple.com> + + jsc command line should support typed arrays by default + https://bugs.webkit.org/show_bug.cgi?id=84298 + + Rubber stamped by Gavin Barraclough. + + * JSCTypedArrayStubs.h: + (JSC): + * jsc.cpp: + (GlobalObject::finishCreation): + +2012-04-18 Filip Pizlo <fpizlo@apple.com> + + JSVALUE32_64 should be able to perform division on ARM without crashing, and variables + forced double should not be scrambled when performing OSR entry + https://bugs.webkit.org/show_bug.cgi?id=84272 + + Reviewed by Geoff Garen. + + * dfg/DFGFixupPhase.cpp: + (JSC::DFG::FixupPhase::fixupNode): + * dfg/DFGOSREntry.cpp: + (JSC::DFG::prepareOSREntry): + +2012-04-18 Don Olmstead <don.olmstead@am.sony.com> + + JavaScriptCore.gypi not current + https://bugs.webkit.org/show_bug.cgi?id=84224 + + Reviewed by Eric Seidel. + + Updated JavaScriptCore.gypi to contain the latest sources. Removed os-win32 as it wasn't used. Also removed references to ICU files in the gypi file as ICU is most likely specified by the port itself. + + Private and public header files were determined by looking at copy-files.cmd within Apple's Visual Studio directory. + + * JavaScriptCore.gypi: + +2012-04-18 Benjamin Poulain <bpoulain@apple.com> + + Remove m_subclassData from JSArray, move the attribute to subclass as needed + https://bugs.webkit.org/show_bug.cgi?id=84249 + + Reviewed by Geoffrey Garen. + + JSArray's m_subclassData is only used by WebCore's RuntimeArray. This patch moves + the attribute to RuntimeArray to avoid allocating memory for the pointer in the common + case. + + This gives ~1% improvement in JSArray creation microbenchmark thanks to fewer allocations + of CopiedSpace. + + * jit/JITInlineMethods.h: + (JSC::JIT::emitAllocateJSArray): + * runtime/JSArray.cpp: + (JSC::JSArray::JSArray): + * runtime/JSArray.h: + +2012-04-18 Benjamin Poulain <bpoulain@apple.com> + + replaceUsingStringSearch: delay the creation of the replace string until needed + https://bugs.webkit.org/show_bug.cgi?id=83841 + + Reviewed by Geoffrey Garen. + + We do not need to obtain the replaceValue until we have a match. By moving the intialization + of replaceValue when needed, we save a few instructions when there is no match. + + * runtime/StringPrototype.cpp: + (JSC::replaceUsingRegExpSearch): + (JSC::replaceUsingStringSearch): + (JSC::stringProtoFuncReplace): + +2012-04-18 Mark Hahnenberg <mhahnenberg@apple.com> + + GC activity timer should be tied to allocation, not collection + https://bugs.webkit.org/show_bug.cgi?id=83919 + + Reviewed by Geoffrey Garen. + + * API/JSContextRef.cpp: Used the new didAbandonObjectGraph callback to indicate that now that we've + released a global object, we're abandoning a potentially large number of objects that JSC might want + to collect. + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::tryAllocateSlowCase): Added the call to timer's willAllocate function to indicate + that we've hit a slow path and are allocating now, so schedule the timer. + * heap/Heap.cpp: + (JSC::Heap::Heap): + (JSC::Heap::collectAllGarbage): Removed the call to discardAllCompiledCode because it was causing us to + throw away too much code during our benchmarks (especially vp8, which is very large and thus has large + amounts of compiled code). + (JSC::Heap::collect): Added the new call to didCollect at the conclusion of a collection so that we + can cancel the timer if we no longer need to run a collection. Also added a check at the beginning of a + collection to see if we should throw away our compiled code. Currently this is set to happen about once + every minute. + * heap/Heap.h: Added field to keep track of the last time we threw away our compiled code. + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::allocateSlowCase): Added call to willAllocate on the allocation slow path, just like + in CopiedSpace. + * runtime/GCActivityCallback.cpp: Added default stubs for non-CF platforms. + (JSC::DefaultGCActivityCallback::willAllocate): + (JSC): + (JSC::DefaultGCActivityCallback::didCollect): + (JSC::DefaultGCActivityCallback::didAbandonObjectGraph): + * runtime/GCActivityCallback.h: Added new functions to make JSC's GC timer less arcane. This includes replacing + the operator () with willAllocate() and adding an explicit didCollect() to cancel the timer after a collection + occurs rather than relying on the way the timer is invoked to cancel itself. Also added a callback for + when somebody else (e.g. WebCore or the JSC API) to notify JSC that they have just abandoned an entire graph of + objects and that JSC might want to clean them up. + (JSC::GCActivityCallback::~GCActivityCallback): + (JSC::GCActivityCallback::willAllocate): + (JSC::GCActivityCallback::didCollect): + (JSC::GCActivityCallback::didAbandonObjectGraph): + (JSC::GCActivityCallback::synchronize): + (DefaultGCActivityCallback): + * runtime/GCActivityCallbackCF.cpp: Re-wired all the run loop stuff to implement the aforementioned functions. + We added a flag to check whether the timer was active because the call to CFRunLoopTimerSetNextFireDate actually + turned out to be quite expensive (although Instruments couldn't tell us this). + (DefaultGCActivityCallbackPlatformData): + (JSC): + (JSC::DefaultGCActivityCallbackPlatformData::timerDidFire): + (JSC::DefaultGCActivityCallback::commonConstructor): + (JSC::scheduleTimer): + (JSC::cancelTimer): + (JSC::DefaultGCActivityCallback::willAllocate): + (JSC::DefaultGCActivityCallback::didCollect): + (JSC::DefaultGCActivityCallback::didAbandonObjectGraph): + +2012-04-17 Filip Pizlo <fpizlo@apple.com> + + DFG should not attempt to get rare case counts for op_mod on ARM + https://bugs.webkit.org/show_bug.cgi?id=84218 + + Reviewed by Geoff Garen. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::makeSafe): + * dfg/DFGCommon.h: + (JSC::DFG::isX86): + (DFG): + +2012-04-17 Myles Maxfield <mmaxfield@google.com> + + BumpPointerAllocator assumes page size is less than MINIMUM_BUMP_POOL_SIZE + https://bugs.webkit.org/show_bug.cgi?id=80912 + + Reviewed by Hajime Morita. + + * wtf/BumpPointerAllocator.h: + (WTF::BumpPointerPool::create): + +2012-04-17 Filip Pizlo <fpizlo@apple.com> + + Attempt to fix Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-04-17 Filip Pizlo <fpizlo@apple.com> + + It should be possible to create an inheritorID for the global this object without crashing + https://bugs.webkit.org/show_bug.cgi?id=84200 + <rdar://problem/11251082> + + Reviewed by Oliver Hunt. + + * runtime/JSGlobalThis.cpp: + (JSC::JSGlobalThis::setUnwrappedObject): + * runtime/JSGlobalThis.h: + (JSC::JSGlobalThis::unwrappedObject): + (JSGlobalThis): + * runtime/JSObject.cpp: + (JSC::JSObject::createInheritorID): + * runtime/JSObject.h: + (JSObject): + (JSC::JSObject::resetInheritorID): + +2012-04-17 Filip Pizlo <fpizlo@apple.com> + + DFG and LLInt should not clobber the frame pointer on ARMv7 + https://bugs.webkit.org/show_bug.cgi?id=84185 + <rdar://problem/10767252> + + Reviewed by Gavin Barraclough. + + Changed LLInt to use a different register. Changed DFG to use one fewer + registers. We should revisit this and switch the DFG to use a different + register instead of r7, but we can do that in a subsequent step since + the performance effect is tiny. + + * dfg/DFGGPRInfo.h: + (GPRInfo): + (JSC::DFG::GPRInfo::toRegister): + (JSC::DFG::GPRInfo::toIndex): + * offlineasm/armv7.rb: + +2012-04-17 Filip Pizlo <fpizlo@apple.com> + + use after free in JSC::DFG::Node::op / JSC::DFG::ByteCodeParser::flushArgument + https://bugs.webkit.org/show_bug.cgi?id=83942 + <rdar://problem/11247370> + + Reviewed by Gavin Barraclough. + + Don't use references to the graph after resizing the graph. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::flushArgument): + +2012-04-16 Gavin Barraclough <barraclough@apple.com> + + Array.prototype.toString should be generic + https://bugs.webkit.org/show_bug.cgi?id=81588 + + Reviewed by Sam Weinig. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + - check for join function, use fast case if base object is array & join is present & default. + * runtime/CommonIdentifiers.h: + - added 'join'. + +2012-04-16 Carlos Garcia Campos <cgarcia@igalia.com> + + Unreviewed. Fix make distcheck issues. + + * GNUmakefile.list.am: Add missing files. + +2012-04-16 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r114309. + http://trac.webkit.org/changeset/114309 + https://bugs.webkit.org/show_bug.cgi?id=84097 + + it broke everything (Requested by olliej on #webkit). + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * bytecode/CodeBlock.h: + * dfg/DFGOperations.cpp: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::getStackTrace): + (JSC::Interpreter::throwException): + * interpreter/Interpreter.h: + (Interpreter): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * jsc.cpp: + (functionJSCStack): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::handleHostCall): + * parser/Parser.h: + (JSC::::parse): + * runtime/Error.cpp: + (JSC::addErrorInfo): + (JSC::throwError): + * runtime/Error.h: + (JSC): + +2012-04-16 Oliver Hunt <oliver@apple.com> + + Exception stack traces aren't complete when the exception starts in native code + https://bugs.webkit.org/show_bug.cgi?id=84073 + + Reviewed by Gavin Barraclough. + + Refactored building the stack trace to so that we can construct + it earlier, and don't rely on any prior work performed in the + exception handling machinery. Also updated LLInt and the DFG to + completely initialise the callframes of host function calls. + + * bytecode/CodeBlock.h: + (JSC::CodeBlock::codeOriginIndexForReturn): + (CodeBlock): + * dfg/DFGOperations.cpp: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::getStackTrace): + (JSC::Interpreter::addStackTraceIfNecessary): + (JSC): + (JSC::Interpreter::throwException): + * interpreter/Interpreter.h: + (Interpreter): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * jsc.cpp: + (functionJSCStack): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::handleHostCall): + * parser/Parser.h: + (JSC::::parse): + * runtime/Error.cpp: + (JSC::addErrorInfo): + (JSC::throwError): + * runtime/Error.h: + (JSC): + +2012-04-16 Oliver Hunt <oliver@apple.com> + + Fix COMMANDLINE_TYPEDARRAYS build + https://bugs.webkit.org/show_bug.cgi?id=84051 + + Reviewed by Gavin Barraclough. + + Update for new putByIndex API and wtf changes. + + * JSCTypedArrayStubs.h: + (JSC): + +2012-04-16 Mark Hahnenberg <mhahnenberg@apple.com> + + GC in the middle of JSObject::allocatePropertyStorage can cause badness + https://bugs.webkit.org/show_bug.cgi?id=83839 + + Reviewed by Geoffrey Garen. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * jit/JITStubs.cpp: Making changes to use the new return value of growPropertyStorage. + (JSC::DEFINE_STUB_FUNCTION): + * runtime/JSObject.cpp: + (JSC::JSObject::growPropertyStorage): Renamed to more accurately reflect that we're + growing our already-existing PropertyStorage. + * runtime/JSObject.h: + (JSObject): + (JSC::JSObject::setPropertyStorage): "Atomically" sets the new property storage + and the new structure so that we can be sure a GC never occurs when our Structure + info is out of sync with our PropertyStorage. + (JSC): + (JSC::JSObject::putDirectInternal): Moved the check to see if we should + allocate more backing store before the actual property insertion into + the structure. + (JSC::JSObject::putDirectWithoutTransition): Ditto. + (JSC::JSObject::transitionTo): Ditto. + * runtime/Structure.cpp: + (JSC::Structure::suggestedNewPropertyStorageSize): Added to keep the resize policy + for property backing stores contained within the Structure class. + (JSC): + * runtime/Structure.h: + (JSC::Structure::shouldGrowPropertyStorage): Lets clients know if another insertion + into the Structure would require resizing the property backing store so that they can + preallocate the required storage. + (Structure): + +2012-04-13 Sheriff Bot <webkit.review.bot@gmail.com> + + Unreviewed, rolling out r114185. + http://trac.webkit.org/changeset/114185 + https://bugs.webkit.org/show_bug.cgi?id=83967 + + Broke a bunch of JavaScript related tests (Requested by + andersca on #webkit). + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + (JSC::arrayProtoFuncToLocaleString): + * runtime/CommonIdentifiers.h: + * tests/mozilla/ecma/Array/15.4.4.2.js: + (getTestCases): + +2012-04-13 Gavin Barraclough <barraclough@apple.com> + + Don't rely on fixed offsets to patch calls + https://bugs.webkit.org/show_bug.cgi?id=83966 + + Rubber stamped by Oliver Hunt. + + These aren't being used anywhere! + + * jit/JIT.h: + * jit/JITCall.cpp: + (JSC::JIT::compileOpCall): + * jit/JITCall32_64.cpp: + (JSC::JIT::compileOpCall): + +2012-04-13 Hojong Han <hojong.han@samsung.com> + + Array.prototype.toString and Array.prototype.toLocaleString should be generic + https://bugs.webkit.org/show_bug.cgi?id=81588 + + Reviewed by Gavin Barraclough. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + (JSC::arrayProtoFuncToLocaleString): + * runtime/CommonIdentifiers.h: + * tests/mozilla/ecma/Array/15.4.4.2.js: + (getTestCases.array.item.new.TestCase): + (getTestCases): + +2012-04-13 Gavin Barraclough <barraclough@apple.com> + + Don't rely on fixed offsets to patch method checks + https://bugs.webkit.org/show_bug.cgi?id=83958 + + Reviewed by Oliver Hunt. + + * bytecode/StructureStubInfo.h: + - Add fields for the method check info. + * jit/JIT.cpp: + (JSC::PropertyStubCompilationInfo::copyToStubInfo): + - Store the offsets on the stub info, instead of asserting. + * jit/JIT.h: + - Delete all the method check related offsets. + * jit/JITPropertyAccess.cpp: + (JSC::JIT::patchMethodCallProto): + - Use the offset from the stubInfo. + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + - Pass the stubInfo to patchMethodCallProto. + +2012-04-13 Gavin Barraclough <barraclough@apple.com> + + Don't rely on fixed offsets to patch get_by_id/put_by_id + https://bugs.webkit.org/show_bug.cgi?id=83924 + + Reviewed by Oliver Hunt. + + Store offsets in the structure stub info, as we do for the DFG JIT. + + * assembler/AbstractMacroAssembler.h: + (JSC::AbstractMacroAssembler::differenceBetween): + - this method can be static (now used from PropertyStubCompilationInfo::copyToStubInfo, will be removed soon!) + * bytecode/StructureStubInfo.h: + - added new fields for baseline JIT offsets. + * jit/JIT.cpp: + (JSC::PropertyStubCompilationInfo::copyToStubInfo): + - moved out from JIT::privateCompile. + (JSC::JIT::privateCompile): + - moved out code to PropertyStubCompilationInfo::copyToStubInfo. + * jit/JIT.h: + (PropertyStubCompilationInfo): + - added helper functions to initializae PropertyStubCompilationInfo, state to store more offset info. + - removed many offsets. + * jit/JITPropertyAccess.cpp: + (JSC::JIT::emit_op_method_check): + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::emit_op_put_by_id): + (JSC::JIT::emitSlow_op_put_by_id): + (JSC::JIT::patchGetByIdSelf): + (JSC::JIT::patchPutByIdReplace): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::resetPatchGetById): + (JSC::JIT::resetPatchPutById): + - changed code generation to use new interface to store info on PropertyStubCompilationInfo. + - changed repatch functions to read offsets from the structure stub info. + * jit/JITPropertyAccess32_64.cpp: + (JSC::JIT::emit_op_method_check): + (JSC::JIT::compileGetByIdHotPath): + (JSC::JIT::compileGetByIdSlowCase): + (JSC::JIT::emit_op_put_by_id): + (JSC::JIT::emitSlow_op_put_by_id): + (JSC::JIT::patchGetByIdSelf): + (JSC::JIT::patchPutByIdReplace): + (JSC::JIT::privateCompilePatchGetArrayLength): + (JSC::JIT::privateCompileGetByIdProto): + (JSC::JIT::privateCompileGetByIdSelfList): + (JSC::JIT::privateCompileGetByIdProtoList): + (JSC::JIT::privateCompileGetByIdChainList): + (JSC::JIT::privateCompileGetByIdChain): + (JSC::JIT::resetPatchGetById): + (JSC::JIT::resetPatchPutById): + - changed code generation to use new interface to store info on PropertyStubCompilationInfo. + - changed repatch functions to read offsets from the structure stub info. + +2012-04-13 Rob Buis <rbuis@rim.com> + + Fix some compiler warnings (miscellaneous) + https://bugs.webkit.org/show_bug.cgi?id=80790 + + Reviewed by Antonio Gomes. + + Fix signed/unsigned comparison warning. + + * parser/Lexer.cpp: + (JSC::::record16): + +2012-04-12 Benjamin Poulain <bpoulain@apple.com> + + Improve replaceUsingStringSearch() for case of a single character searchValue + https://bugs.webkit.org/show_bug.cgi?id=83738 + + Reviewed by Geoffrey Garen. + + This patch improves replaceUsingStringSearch() with the following: + -Add a special case for single character search, taking advantage of the faster WTF::find(). + -Inline replaceUsingStringSearch(). + -Use StringImpl::create() instead of UString::substringSharingImpl() since we know we are in the bounds + by definition. + + This gives less than 1% improvement for the multicharacter replace. + The single character search show about 9% improvement. + + * runtime/StringPrototype.cpp: + (JSC::replaceUsingStringSearch): + +2012-04-12 Michael Saboff <msaboff@apple.com> + + StructureStubInfo::reset() causes leaks of PolymorphicAccessStructureList and ExecutableMemoryHandle objects + https://bugs.webkit.org/show_bug.cgi?id=83823 + + Reviewed by Gavin Barraclough. + + Put the clearing of the accessType to after the call to deref() so that + deref() can use the accessType to delete referenced objects as needed. + + * bytecode/StructureStubInfo.h: + (JSC::StructureStubInfo::reset): + +2012-04-12 Balazs Kelemen <kbalazs@webkit.org> + + [Qt] Fix WebKit1 build with V8 + https://bugs.webkit.org/show_bug.cgi?id=83322 + + Reviewed by Adam Barth. + + * yarr/yarr.pri: + +2012-04-12 Gavin Barraclough <barraclough@apple.com> + + https://bugs.webkit.org/show_bug.cgi?id=83821 + Move dfg repatching properties of structure stub info into a union + + Reviewed by Oliver Hunt. + + We want to be able to have similar properties for the baseline JIT, some restructuring to prepare for this. + + * bytecode/StructureStubInfo.h: + (StructureStubInfo): + * dfg/DFGJITCompiler.cpp: + (JSC::DFG::JITCompiler::link): + * dfg/DFGRepatch.cpp: + (JSC::DFG::dfgRepatchByIdSelfAccess): + (JSC::DFG::linkRestoreScratch): + (JSC::DFG::generateProtoChainAccessStub): + (JSC::DFG::tryCacheGetByID): + (JSC::DFG::tryBuildGetByIDList): + (JSC::DFG::tryBuildGetByIDProtoList): + (JSC::DFG::emitPutReplaceStub): + (JSC::DFG::emitPutTransitionStub): + (JSC::DFG::tryCachePutByID): + (JSC::DFG::tryBuildPutByIdList): + (JSC::DFG::dfgResetGetByID): + (JSC::DFG::dfgResetPutByID): + +2012-04-12 Gavin Barraclough <barraclough@apple.com> + + Delete a bunch of unused, copy & pasted values in JIT.h + https://bugs.webkit.org/show_bug.cgi?id=83822 + + Reviewed by Oliver Hunt. + + The only architecture we support the JSVALUE64 JIT on is x86-64, all the patch offsets for other architectures are just nonsense. + + * jit/JIT.h: + (JIT): + +2012-04-12 Csaba Osztrogonác <ossy@webkit.org> + + [Qt][ARM] Buildfix after r113934. + + Reviewed by Zoltan Herczeg. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::compare8): + (MacroAssemblerARM): + +2012-04-11 Filip Pizlo <fpizlo@apple.com> + + It is incorrect to short-circuit Branch(LogicalNot(@a)) if boolean speculations on @a may fail + https://bugs.webkit.org/show_bug.cgi?id=83744 + <rdar://problem/11206946> + + Reviewed by Andy Estes. + + This does the conservative thing: it only short-circuits Branch(LogicalNot(@a)) if @a is a node + that is statically known to return boolean results. + + * dfg/DFGFixupPhase.cpp: + (JSC::DFG::FixupPhase::fixupNode): + +2012-04-11 Michael Saboff <msaboff@apple.com> + + Invalid Union Reference in StructureStubInfo.{cpp.h} + https://bugs.webkit.org/show_bug.cgi?id=83735 + + Reviewed by Filip Pizlo. + + Changed the references to u.getByIdProtoList and u.getByIdSelfList + to be consistent. + + * bytecode/StructureStubInfo.cpp: + (JSC::StructureStubInfo::visitWeakReferences): + * bytecode/StructureStubInfo.h: + (JSC::StructureStubInfo::initGetByIdSelfList): + +2012-04-11 Filip Pizlo <fpizlo@apple.com> + + Unreviewed attempting to make Qt's eccentric hardware work. + + * assembler/MacroAssemblerARM.h: + (JSC::MacroAssemblerARM::compare8): + (MacroAssemblerARM): + * assembler/MacroAssemblerMIPS.h: + (JSC::MacroAssemblerMIPS::compare8): + (MacroAssemblerMIPS): + * assembler/MacroAssemblerSH4.h: + (JSC::MacroAssemblerSH4::compare8): + (MacroAssemblerSH4): + +2012-04-11 Filip Pizlo <fpizlo@apple.com> + + op_is_foo should be optimized + https://bugs.webkit.org/show_bug.cgi?id=83666 + + Reviewed by Gavin Barraclough. + + This implements inlining of op_is_undefined, op_is_string, op_is_number, + and op_is_boolean in LLInt and the baseline JIT. op_is_object and + op_is_function are not inlined because they are quite a bit more complex. + + This also implements all of the op_is_foo opcodes in the DFG, but it does + not do any type profiling based optimizations, yet. + + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::compare8): + (MacroAssemblerARMv7): + * assembler/MacroAssemblerX86Common.h: + (JSC::MacroAssemblerX86Common::compare8): + (MacroAssemblerX86Common): + * assembler/MacroAssemblerX86_64.h: + (MacroAssemblerX86_64): + (JSC::MacroAssemblerX86_64::testPtr): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::parseBlock): + * dfg/DFGCCallHelpers.h: + (JSC::DFG::CCallHelpers::setupArguments): + (CCallHelpers): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::performNodeCSE): + * dfg/DFGCapabilities.h: + (JSC::DFG::canCompileOpcode): + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::callOperation): + (JSC::DFG::SpeculativeJIT::appendCallSetResult): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + * jit/JIT.h: + (JIT): + * jit/JITOpcodes.cpp: + (JSC::JIT::emit_op_is_undefined): + (JSC): + (JSC::JIT::emit_op_is_boolean): + (JSC::JIT::emit_op_is_number): + (JSC::JIT::emit_op_is_string): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::emit_op_is_undefined): + (JSC): + (JSC::JIT::emit_op_is_boolean): + (JSC::JIT::emit_op_is_number): + (JSC::JIT::emit_op_is_string): + * jit/JITStubs.cpp: + (JSC): + * llint/LLIntSlowPaths.cpp: + (LLInt): + * llint/LLIntSlowPaths.h: + (LLInt): + * llint/LowLevelInterpreter.asm: + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + * offlineasm/armv7.rb: + * offlineasm/instructions.rb: + * offlineasm/x86.rb: + +2012-04-11 Filip Pizlo <fpizlo@apple.com> + + If you use an IntegerOperand and want to return it with integerResult, you need to + zero extend to get rid of the box + https://bugs.webkit.org/show_bug.cgi?id=83734 + <rdar://problem/11232296> + + Reviewed by Oliver Hunt. + + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::fillInteger): + (JSC::DFG::SpeculativeJIT::nonSpeculativeValueToInt32): + +2012-04-11 Filip Pizlo <fpizlo@apple.com> + + SpeculativeJIT::fillStorage() should work with all the states that a cell may be in + https://bugs.webkit.org/show_bug.cgi?id=83722 + + Reviewed by Gavin Barraclough. + + It's now possible to do StorageOperand on a cell, in the case that the storage is + inline. But this means that fillStorage() must be able to handle all of the states + that a cell might be in. Previously it didn't. + + With this change, it now does handle all of the states, and moreover, it does so + by preserving the DataFormat of cells and performing all of the cell speculations + that should be performed if you're using a cell as storage. But if you use this on + something that is known to be storage already then it behaves as it did before. + + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::fillStorage): + +2012-04-11 Filip Pizlo <fpizlo@apple.com> + + Global variable predictions should not be coalesced unnecessarily + https://bugs.webkit.org/show_bug.cgi?id=83678 + + Reviewed by Geoff Garen. + + Removed the PredictionTracker and everyone who used it. Converted GetGlobalVar + to have a heapPrediction like a civilized DFG opcode ought to. + + No performance effect. + + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * bytecode/CodeBlock.h: + * bytecode/PredictionTracker.h: Removed. + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::parseBlock): + * dfg/DFGGenerationInfo.h: + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGGraph.h: + (Graph): + * dfg/DFGNode.h: + (JSC::DFG::Node::hasHeapPrediction): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + +2012-04-11 Benjamin Poulain <bpoulain@apple.com> + + Optimize String.split() for 1 character separator + https://bugs.webkit.org/show_bug.cgi?id=83546 + + Reviewed by Gavin Barraclough. + + This patch adds a serie of optimizations to make stringProtoFuncSplit() faster in the common case + where the separator is a single character. + + The two main gains are: + -Use of the find() function with a single character instead of doing a full string matching. + -Use of WTF::find() instead of UString::find() to avoid branching on is8Bit() and have a simpler inline + function. + + The code is also changed to avoid making unnecessary allocations by converting the 8bit string to 16bits. + + This makes String.split() faster by about 13% in that particular case. + + * runtime/StringPrototype.cpp: + (JSC): + (JSC::splitStringByOneCharacterImpl): + (JSC::stringProtoFuncSplit): + +2012-04-10 Carlos Garcia Campos <cgarcia@igalia.com> + + Unreviewed. Fix make distcheck issues. + + * GNUmakefile.list.am: Ad missing files. + +2012-04-10 Mark Rowe <mrowe@apple.com> + + Attempt to fix the Windows build. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-04-10 Patrick Gansterer <paroga@webkit.org> + + Cleanup wtf/Platform.h and config.h files + https://bugs.webkit.org/show_bug.cgi?id=83431 + + Reviewed by Eric Seidel. + + The ENABLE() and USE() macros take care about the case when the flag + isn't defined. So there is no need to define anything with 0. + + Also move duplicated code from the config.h files to Platform.h and + merge a few preprocessor commands to make the file more readable. + + * config.h: + +2012-04-10 Filip Pizlo <fpizlo@apple.com> + + DFG should flush SetLocals to arguments + https://bugs.webkit.org/show_bug.cgi?id=83554 + + Reviewed by Gavin Barraclough. + + This is necessary to match baseline JIT argument capture behavior. + + But to make this work right we need to have a story for arguments into + which we store values of different formats. This patch introduces the + notion of an ArgumentPosition - i.e. an argument in a particular inline + call frame - and forces unification of all data pertinent to selecting + the argument's data format. + + Also fixed an amusing bug in the handling of OSR on SetLocals if there + was any insertion/deletion of nodes in the basic block. This is benign + for now but won't be eventually since the DFG is getting smarter. So + better fix it now. + + Also fixed an amusing bug in the handling of OSR on SetLocals if they + are immediately followed by a Flush. I think this bug might have always + been there but now it'll happen more commonly, and it's covered by the + run-javascriptcore-tests. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGArgumentPosition.h: Added. + (DFG): + (ArgumentPosition): + (JSC::DFG::ArgumentPosition::ArgumentPosition): + (JSC::DFG::ArgumentPosition::addVariable): + (JSC::DFG::ArgumentPosition::mergeArgumentAwareness): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::setLocal): + (JSC::DFG::ByteCodeParser::setArgument): + (InlineStackEntry): + (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry): + * dfg/DFGDoubleFormatState.h: Added. + (DFG): + (JSC::DFG::mergeDoubleFormatStates): + (JSC::DFG::mergeDoubleFormatState): + (JSC::DFG::doubleFormatStateToString): + * dfg/DFGGraph.h: + (Graph): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGVariableAccessData.h: + (JSC::DFG::VariableAccessData::VariableAccessData): + (JSC::DFG::VariableAccessData::predict): + (JSC::DFG::VariableAccessData::argumentAwarePrediction): + (VariableAccessData): + (JSC::DFG::VariableAccessData::mergeArgumentAwarePrediction): + (JSC::DFG::VariableAccessData::doubleFormatState): + (JSC::DFG::VariableAccessData::shouldUseDoubleFormat): + (JSC::DFG::VariableAccessData::tallyVotesForShouldUseDoubleFormat): + (JSC::DFG::VariableAccessData::mergeDoubleFormatState): + (JSC::DFG::VariableAccessData::makePredictionForDoubleFormat): + +2012-04-10 Adam Klein <adamk@chromium.org> + + Remove unused NonNullPassRefPtr from WTF + https://bugs.webkit.org/show_bug.cgi?id=82389 + + Reviewed by Kentaro Hara. + + * JavaScriptCore.order: Remove nonexistent symbols referencing NonNullPassRefPtr. + +2012-04-10 Darin Adler <darin@apple.com> + + Remove unused data member from Lexer class + https://bugs.webkit.org/show_bug.cgi?id=83429 + + Reviewed by Kentaro Hara. + + I noticed that m_delimited was "write-only", so I deleted it. + + * parser/Lexer.cpp: + (JSC::Lexer::setCode): Removed code to set m_delimited. + (JSC::Lexer::parseIdentifier): Ditto. + (JSC::Lexer::parseIdentifierSlowCase): Ditto. + (JSC::Lexer::lex): Ditto. + * parser/Lexer.h: Deleted m_delimited. + +2012-04-10 Patrick Gansterer <paroga@webkit.org> + + [CMake] Enable USE_FOLDERS property + https://bugs.webkit.org/show_bug.cgi?id=83571 + + Reviewed by Daniel Bates. + + Setting the FOLDER property on targets gives more structure + to the generated Visual Studio solutions. + This does not affect other CMake generators. + + * CMakeLists.txt: + * shell/CMakeLists.txt: + +2012-04-10 Filip Pizlo <fpizlo@apple.com> + + It should be possible to see why a code block was not compiled by the DFG + https://bugs.webkit.org/show_bug.cgi?id=83553 + + Reviewed by Geoff Garen. + + If DFG_ENABLE(DEBUG_VERBOSE) and a code block is rejected, then print the + opcode that caused the rejection. + + * dfg/DFGCapabilities.cpp: + (JSC::DFG::debugFail): + (DFG): + (JSC::DFG::canHandleOpcodes): + +2012-04-09 Gavin Barraclough <barraclough@apple.com> + + If a callback constructor returns a C++ null, throw a type error. + https://bugs.webkit.org/show_bug.cgi?id=83537 + + Rubber Stamped by Geoff Garen. + + * API/JSCallbackConstructor.cpp: + (JSC::constructJSCallback): + - If a callback constructor returns a C++ null, throw a type error. + * API/tests/testapi.c: + (Base_returnHardNull): + * API/tests/testapi.js: + - Add a test case for callback constructors that return a C++ null. + +2012-04-09 Gavin Barraclough <barraclough@apple.com> + + If a callback function returns a C++ null, convert to undefined. + https://bugs.webkit.org/show_bug.cgi?id=83534 + + Reviewed by Geoff Garen. + + * API/JSCallbackFunction.cpp: + - If a callback function returns a C++ null, convert to undefined. + (JSC::JSCallbackFunction::call): + * API/tests/testapi.c: + (Base_returnHardNull): + * API/tests/testapi.js: + - Add a test case for callback functions that return a C++ null. + +2012-04-09 Filip Pizlo <fpizlo@apple.com> + + Classic interpreter's GC hooks shouldn't attempt to scan instructions for code blocks that + are currently being generated + https://bugs.webkit.org/show_bug.cgi?id=83531 + <rdar://problem/11215200> + + Reviewed by Gavin Barraclough. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::stronglyVisitStrongReferences): + +2012-04-09 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, modernize and clean up uses of ARM assembly mnemonics in inline asm blocks. + + * dfg/DFGOperations.cpp: + (JSC): + * offlineasm/armv7.rb: + +2012-04-09 Patrick Gansterer <paroga@webkit.org> + + Remove HAVE_STDINT_H + https://bugs.webkit.org/show_bug.cgi?id=83434 + + Reviewed by Kentaro Hara. + + HAVE_STDINT_H is defined with 1 all the time and we us stdint.h without HAVE(STDINT_H) already. + + * config.h: + +2012-04-08 Filip Pizlo <fpizlo@apple.com> + + DFG should not load the property storage if it is inline. + https://bugs.webkit.org/show_bug.cgi?id=83455 + + Reviewed by Gavin Barraclough. + + We had previously decided to have all property storage accesses go through + the property storage pointer even if they don't "really" have to, because + we were thinking this would help GC barriers somehow. Well, we never ended + up doing anything with that. Hence, doing these wasted loads of the + property storage pointer when the storage is inline is just a waste of CPU + cycles. + + This change makes the DFG's inline property accesses (GetByOffset and + PutByOffset) go directly to the inline property storage if the structure(s) + tell us that it's OK. + + This looks like an across-the-board 1% win. + + * bytecode/StructureSet.h: + (JSC): + (JSC::StructureSet::allAreUsingInlinePropertyStorage): + (StructureSet): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::parseBlock): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::fillStorage): + +2012-04-08 Filip Pizlo <fpizlo@apple.com> + + Command-line jsc's exception handling should be rationalized + https://bugs.webkit.org/show_bug.cgi?id=83437 + + Reviewed by Dan Bernstein. + + - If an exception is thrown during run() execution, it is now propagated, + so that it will terminate program execution unless it is caught. + + - If program execution terminates with an exception, the exception is now + always printed. + + - When printing the exception, the backtrace is now also printed if one is + available. It will only not be available if you use something akin to my + favorite line of code, 'throw "error"', since primitives don't have + properties and hence we cannot attach a "stack" property to them. + + * jsc.cpp: + (functionRun): + (runWithScripts): + +2012-04-04 Filip Pizlo <fpizlo@apple.com> + + Forced OSR exits should lead to recompilation based on count, not rate + https://bugs.webkit.org/show_bug.cgi?id=83247 + <rdar://problem/10720925> + + Reviewed by Geoff Garen. + + Track which OSR exits happen because of inadequate coverage. Count them + separately. If the count reaches a threshold, immediately trigger + reoptimization. + + This is in contrast to the recompilation trigger for all other OSR exits. + Normally recomp is triggered when the exit rate exceeds a certain ratio. + + Looks like a slight V8 speedup (sub 1%). + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::CodeBlock): + * bytecode/CodeBlock.h: + (JSC::CodeBlock::forcedOSRExitCounter): + (JSC::CodeBlock::addressOfForcedOSRExitCounter): + (JSC::CodeBlock::offsetOfForcedOSRExitCounter): + (JSC::CodeBlock::shouldReoptimizeNow): + (JSC::CodeBlock::shouldReoptimizeFromLoopNow): + (CodeBlock): + * bytecode/DFGExitProfile.h: + (JSC::DFG::exitKindToString): + * dfg/DFGOSRExitCompiler.cpp: + (JSC::DFG::OSRExitCompiler::handleExitCounts): + (DFG): + * dfg/DFGOSRExitCompiler.h: + (OSRExitCompiler): + * dfg/DFGOSRExitCompiler32_64.cpp: + (JSC::DFG::OSRExitCompiler::compileExit): + * dfg/DFGOSRExitCompiler64.cpp: + (JSC::DFG::OSRExitCompiler::compileExit): + * dfg/DFGOperations.cpp: + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * runtime/Options.cpp: + (Options): + (JSC::Options::initializeOptions): + * runtime/Options.h: + (Options): + +2012-04-06 Benjamin Poulain <bpoulain@apple.com> + + Do not abuse ArrayStorage's m_length for testing array consistency + https://bugs.webkit.org/show_bug.cgi?id=83403 + + Reviewed by Geoffrey Garen. + + Array creation from a list of values is a 3 steps process: + -JSArray::tryCreateUninitialized() + -JSArray::initializeIndex() for each values + -JSArray::completeInitialization() + + Previously, the attribute m_length was not set to the final size + JSArray::tryCreateUninitialized() because it was used to test the array + consistency JSArray::initializeIndex(). + + This caused the initialization loop using JSArray::initializeIndex() maintain + two counters: + -index of the loop + -storage->m_length++ + + This patch fixes this by using the index of the initialization loop for the indinces of + JSArray::initializeIndex(). For testing consistency, the variable m_initializationIndex + is introduced if CHECK_ARRAY_CONSISTENCY is defined. + + The patch also fixes minor unrelated build issue when CHECK_ARRAY_CONSISTENCY is defined. + + This improves the performance of JSArray creation from literals by 8%. + + * runtime/JSArray.cpp: + (JSC::JSArray::tryFinishCreationUninitialized): + (JSC::JSArray::checkConsistency): + * runtime/JSArray.h: + (ArrayStorage): + (JSC::JSArray::initializeIndex): + (JSC::JSArray::completeInitialization): + +2012-04-06 Jon Lee <jonlee@apple.com> + + Build fix for Windows bots. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: export missing symbol. + +2012-04-06 Geoffrey Garen <ggaren@apple.com> + + Renamed + + WeakHeap => WeakSet + HandleHeap => HandleSet + + Reviewed by Sam Weinig. + + These sets do have internal allocators, but it's confusing to call them + heaps because they're sub-objects of an object called "heap". + + * heap/HandleHeap.cpp: Removed. + * heap/HandleHeap.h: Removed. + * heap/HandleSet.cpp: Copied from JavaScriptCore/heap/HandleHeap.cpp. + * heap/WeakHeap.cpp: Removed. + * heap/WeakHeap.h: Removed. + * heap/WeakSet.cpp: Copied from JavaScriptCore/heap/WeakHeap.cpp. + * heap/WeakSet.h: Copied from JavaScriptCore/heap/WeakHeap.h. + + Plus global rename using grep. + +2012-04-06 Dan Bernstein <mitz@apple.com> + + <rdar://problem/10912476> HiDPI: Have canvas use a hidpi backing store, but downsample upon access + + Reviewed by Sam Weinig. + + * Configurations/FeatureDefines.xcconfig: Added ENABLE_HIGH_DPI_CANVAS. + +2012-04-06 Rob Buis <rbuis@rim.com> + + Fix cast-align warnings in JSC + https://bugs.webkit.org/show_bug.cgi?id=80790 + + Reviewed by George Staikos. + + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::computeJumpType): + (JSC::ARMv7Assembler::link): + * assembler/LinkBuffer.h: + (JSC::LinkBuffer::linkCode): + * heap/MarkStack.cpp: + (JSC::SlotVisitor::copyAndAppend): + * runtime/JSArray.cpp: + (JSC::JSArray::visitChildren): + * wtf/RefCountedArray.h: + (WTF::RefCountedArray::Header::payload): + +2012-04-06 Darin Adler <darin@apple.com> + + Streamline strtod and fix some related problems + https://bugs.webkit.org/show_bug.cgi?id=82857 + + Reviewed by Geoffrey Garen. + + * parser/Lexer.cpp: + (JSC::Lexer<>::lex): Use parseDouble. Since we have already scanned the number + and we know it has only correct characters, leading spaces, trailing junk, and + trailing spaces are not a possibility. No need to add a trailing null character. + + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::parseInt): Changed overflow based 10 case to use parseDouble. No need + to allow trailing junk since the code above already allows only numeric digits + in the string. This code path is used only in unusual cases, so it's not + optimized for 8-bit strings, but easily could be. + (JSC::jsStrDecimalLiteral): Removed the allow trailing junk argument to this + function template because all the callers are OK with trailing junk. Use the + parseDouble function. No need to copy the data into a byte buffer, because + parseDouble handles that. + (JSC::toDouble): Got rid of the DisallowTrailingJunk argument to the + jsStrDecimalLiteral function template. That's OK because this function + already checks for trailing junk and handles it appropriately. The old code + path was doing it twice. + (JSC::parseFloat): Got rid of the AllowTrailingJunk argument to the + jsStrDecimalLiteral function template; the template allows junk unconditionally. + + * runtime/LiteralParser.cpp: + (JSC::::Lexer::lexNumber): Use parseDouble. Since we have already scanned the number + and we know it has only correct characters, leading spaces, trailing junk, and + trailing spaces are not a possibility. No need to add a trailing null character. + No need to copy the data into a byte buffer, because parseDouble handles that. + We could optimize the UChar case even more because we know all the characters + are ASCII, but not doing that at this time. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: Updated. + +2012-04-06 Patrick Gansterer <paroga@webkit.org> + + Remove JSC dependency from GregorianDateTime + https://bugs.webkit.org/show_bug.cgi?id=83290 + + Reviewed by Geoffrey Garen. + + This allows us to move it to WTF later. + + * runtime/DateConstructor.cpp: + (JSC::callDate): + * runtime/JSDateMath.h: + +2012-04-05 Michael Saboff <msaboff@apple.com> + + Call Heap::discardAllCompiledCode() in low memory situations + https://bugs.webkit.org/show_bug.cgi?id=83335 + + Reviewed by Geoffrey Garen. + + Restructured Heap::discardAllCompiledCode() to do the "Is JavaScriptRunning?" + check inline so that it can be called directly without this check. + + * heap/Heap.cpp: + (JSC::Heap::discardAllCompiledCode): + (JSC::Heap::collectAllGarbage): + * heap/Heap.h: Added JS_EXPORT_PRIVATE to discardAllCompiledCode() so it can be + called from WebCore. + (Heap): + * runtime/JSGlobalData.h: Removed unused " void discardAllCompiledCode()" declaration. + (JSGlobalData): + +2012-04-05 Benjamin Poulain <bpoulain@apple.com> + + Speed up the conversion from JSValue to String for bulk operations + https://bugs.webkit.org/show_bug.cgi?id=83243 + + Reviewed by Geoffrey Garen. + + When making operations on primitive types, we loose some time converting + values to JSString in order to extract the string. + + This patch speeds up some basic Array operations by avoiding the creation + of intermediary JSString when possible. + + For the cases where we need to convert a lot of JSValue in a tight loop, + an inline conversion is used. + + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToString): + (JSC::arrayProtoFuncToLocaleString): + (JSC::arrayProtoFuncJoin): + (JSC::arrayProtoFuncPush): + (JSC::arrayProtoFuncSort): + * runtime/CommonIdentifiers.h: + * runtime/JSArray.cpp: + (JSC::JSArray::sort): + * runtime/JSString.h: + (JSC::JSValue::toUString): + (JSC): + (JSC::inlineJSValueNotStringtoUString): + (JSC::JSValue::toUStringInline): + * runtime/JSValue.cpp: + (JSC::JSValue::toUStringSlowCase): + (JSC): + * runtime/JSValue.h: + (JSValue): + +2012-04-05 Benjamin Poulain <bpoulain@apple.com> + + Use QuickSort when sorting primitive values by string representation + https://bugs.webkit.org/show_bug.cgi?id=83312 + + Reviewed by Gavin Barraclough. + + When the value we are sorting are all primitive values, we do not need to + ensure a stable sort as two values with equal string representation are + indistinguishable from JavaScript. + + This gives about 16% performance increase when sorting primitive values. + + * runtime/JSArray.cpp: + (JSC::JSArray::sort): + +2012-04-05 Oliver Hunt <oliver@apple.com> + + SIGILL in JavaScriptCore on a Geode processor + https://bugs.webkit.org/show_bug.cgi?id=82496 + + Reviewed by Gavin Barraclough. + + Don't attempt to use the DFG when SSE2 is not available. + + * dfg/DFGCapabilities.cpp: + (JSC::DFG::canCompileOpcodes): + +2012-04-05 Oliver Hunt <oliver@apple.com> + + Fix 32-bit build. + + * API/APICast.h: + (toJS): + +2012-04-05 Oliver Hunt <oliver@apple.com> + + Replace static_cast with jsCast when casting JSCell subclasses in JSC + https://bugs.webkit.org/show_bug.cgi?id=83307 + + Reviewed by Gavin Barraclough. + + Replace all usage of static_cast<JSCell subtype*> with jsCast<> in JavaScriptCore. + This results in assertions when unsafe casts are performed, but simply leaves + a static_cast<> in release builds. + + * API/APICast.h: + (toJS): + * API/JSCallbackConstructor.cpp: + (JSC::constructJSCallback): + * API/JSCallbackFunction.cpp: + (JSC::JSCallbackFunction::call): + * API/JSCallbackObjectFunctions.h: + (JSC::::asCallbackObject): + (JSC::::finishCreation): + (JSC::::construct): + (JSC::::call): + * API/JSObjectRef.cpp: + (JSObjectGetPrivate): + (JSObjectSetPrivate): + (JSObjectGetPrivateProperty): + (JSObjectSetPrivateProperty): + (JSObjectDeletePrivateProperty): + * API/JSValueRef.cpp: + (JSValueIsObjectOfClass): + * API/JSWeakObjectMapRefPrivate.cpp: + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::resolve): + (JSC::BytecodeGenerator::resolveConstDecl): + * debugger/DebuggerActivation.cpp: + (JSC::DebuggerActivation::finishCreation): + * dfg/DFGOperations.cpp: + * interpreter/Interpreter.cpp: + (JSC::Interpreter::execute): + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + * runtime/Executable.h: + (JSC::isHostFunction): + * runtime/JSActivation.h: + (JSC::asActivation): + * runtime/JSArray.cpp: + (JSC::JSArray::defineOwnProperty): + * runtime/JSArray.h: + (JSC::asArray): + * runtime/JSBoundFunction.cpp: + (JSC::boundFunctionCall): + (JSC::boundFunctionConstruct): + * runtime/JSByteArray.h: + (JSC::asByteArray): + * runtime/JSCell.cpp: + (JSC::JSCell::toObject): + * runtime/JSCell.h: + (JSC::jsCast): + * runtime/JSGlobalObject.h: + (JSC::asGlobalObject): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::globalFuncEval): + * runtime/JSObject.cpp: + (JSC::JSObject::setPrototypeWithCycleCheck): + (JSC::JSObject::allowsAccessFrom): + (JSC::JSObject::toThisObject): + (JSC::JSObject::unwrappedObject): + * runtime/JSObject.h: + (JSC::asObject): + * runtime/JSPropertyNameIterator.h: + (JSC::Register::propertyNameIterator): + * runtime/JSString.h: + (JSC::asString): + (JSC::JSValue::toString): + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncSubstr): + +2012-04-05 Benjamin Poulain <bpoulain@apple.com> + + Make something faster than JSStringBuilder for joining an array of JSValue + https://bugs.webkit.org/show_bug.cgi?id=83180 + + Reviewed by Geoffrey Garen. + + This patch add the class JSStringJoiner optimized for join() operations. + + This class makes stricter constraints than JSStringBuilder in order avoid + memory allocations. + + In the best case, the class allocate memory only twice: + -Allocate an array to keep a list of UString to join. + -Allocate the final string. + + We also avoid the conversion from 8bits strings to 16bits strings since + they are costly and unlikly to help for subsequent calls. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncToLocaleString): + (JSC::arrayProtoFuncJoin): + * runtime/JSStringJoiner.cpp: Added. + (JSC): + (JSC::appendStringToData): + (JSC::joinStrings): + (JSC::JSStringJoiner::build): + * runtime/JSStringJoiner.h: Added. + (JSC): + (JSStringJoiner): + (JSC::JSStringJoiner::JSStringJoiner): + (JSC::JSStringJoiner::append): + +2012-04-05 Gavin Barraclough <barraclough@apple.com> + + https://bugs.webkit.org/show_bug.cgi?id=77293 + [Un]Reserve 'let' + + Rubber stamped by Oliver Hunt. + + Revert r106198. + This does break the web - e.g. https://bvi.bnc.ca/index/bnc/indexen.html + If we're going to reserve let, we're going to have to do so in a more + circumspect fashion. + + * parser/Keywords.table: + +2012-04-05 Michael Saboff <msaboff@apple.com> + + Rolling out http://trac.webkit.org/changeset/113262. + Original code was fine. + + Rubber-stamped by Oliver Hunt. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::additionBlindedConstant): + +2012-04-05 Patrick Gansterer <paroga@webkit.org> + + [WinCE] Remove unnecessary function decleration + https://bugs.webkit.org/show_bug.cgi?id=83155 + + Reviewed by Kentaro Hara. + + * runtime/JSDateMath.cpp: + +2012-04-04 Patrick Gansterer <paroga@webkit.org> + + Add WTF::getCurrentLocalTime() + https://bugs.webkit.org/show_bug.cgi?id=83164 + + Reviewed by Alexey Proskuryakov. + + Replace the calls to WTF::getLocalTime() with time(0) with the new function. + This allows us to use Win32 API on windows to get the same result in a next step. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + * runtime/DateConstructor.cpp: + (JSC::callDate): + +2012-04-04 Oliver Hunt <oliver@apple.com> + + Parser fails to revert some state after parsing expression and object literals. + https://bugs.webkit.org/show_bug.cgi?id=83236 + + Reviewed by Gavin Barraclough. + + Reset left hand side counter after parsing the literals. + + * parser/Parser.cpp: + (JSC::::parseObjectLiteral): + (JSC::::parseStrictObjectLiteral): + (JSC::::parseArrayLiteral): + +2012-04-04 Filip Pizlo <fpizlo@apple.com> + + DFG InstanceOf should not uselessly speculate cell + https://bugs.webkit.org/show_bug.cgi?id=83234 + + Reviewed by Oliver Hunt. + + If InstanceOf is the only user of its child then don't speculate cell, since + the not-cell case is super easy to handle. + + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileInstanceOf): + +2012-04-04 Michael Saboff <msaboff@apple.com> + + Fixed minor error: "& 3" should be "& 2". + + Rubber-stamped by Oliver Hunt. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::additionBlindedConstant): + +2012-04-04 Michael Saboff <msaboff@apple.com> + + Constant Blinding for add/sub immediate crashes in ArmV7 when dest is SP + https://bugs.webkit.org/show_bug.cgi?id=83191 + + Reviewed by Oliver Hunt. + + Make are that blinded constant pairs are similarly aligned to the + original immediate values so that instructions that expect that + alignment work correctly. One example is ARMv7 add/sub imm to SP. + + * assembler/ARMv7Assembler.h: + (JSC::ARMv7Assembler::add): Added ASSERT that immediate is word aligned. + (JSC::ARMv7Assembler::sub): Added ASSERT that immediate is word aligned. + (JSC::ARMv7Assembler::sub_S): Added ASSERT that immediate is word aligned. + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::additionBlindedConstant): + +2012-04-04 Filip Pizlo <fpizlo@apple.com> + + DFG should short-circuit Branch(LogicalNot(...)) + https://bugs.webkit.org/show_bug.cgi?id=83181 + + Reviewed by Geoff Garen. + + Slight (sub 1%) speed-up on V8. + + * dfg/DFGFixupPhase.cpp: + (JSC::DFG::FixupPhase::fixupNode): + +2012-04-04 Geoffrey Garen <ggaren@apple.com> + + [Qt] REGRESSION(r113141): All tests assert on 32 bit debug mode + https://bugs.webkit.org/show_bug.cgi?id=83139 + + Reviewed by Sam Weinig. + + * heap/PassWeak.h: + (JSC::::get): 32-bit JSValue treats JSValue(nullptr).asCell() as an error, + so work around that here. (Long-term, we should make 32-bit and 64-bit + agree on the right behavior.) + +2012-04-03 Geoffrey Garen <ggaren@apple.com> + + Updated JSC expected test results to reflect recent bug fixes <disapproving look>. + + Reviewed by Sam Weinig. + + * tests/mozilla/expected.html: + +2012-03-29 Geoffrey Garen <ggaren@apple.com> + + First step toward incremental Weak<T> finalization + https://bugs.webkit.org/show_bug.cgi?id=82670 + + Reviewed by Filip Pizlo. + + This patch implements a Weak<T> heap that is compatible with incremental + finalization, while making as few behavior changes as possible. The behavior + changes it makes are: + + (*) Weak<T>'s raw JSValue no longer reverts to JSValue() automatically -- + instead, a separate flag indicates that the JSValue is no longer valid. + (This is required so that the JSValue can be preserved for later finalization.) + Objects dealing with WeakImpls directly must change to check the flag. + + (*) Weak<T> is no longer a subclass of Handle<T>. + + (*) DOM GC performance is different -- 9% faster in the geometric mean, + but 15% slower in one specific case: + gc-dom1.html: 6% faster + gc-dom2.html: 23% faster + gc-dom3.html: 17% faster + gc-dom4.html: 15% *slower* + + The key features of this new heap are: + + (*) Each block knows its own state, independent of any other blocks. + + (*) Each block caches its own sweep result. + + (*) The heap visits dead Weak<T>s at the end of GC. (It doesn't + mark them yet, since that would be a behavior change.) + + * API/JSCallbackObject.cpp: + (JSC::JSCallbackObjectData::finalize): + * API/JSCallbackObjectFunctions.h: + (JSC::::init): Updated to use the new WeakHeap API. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: Paid the build system tax since I added some new files. + + * heap/Handle.h: Made WeakBlock a friend and exposed slot() as public, + so we can keep passing a Handle<T> to finalizers, to avoid more surface + area change in this patch. A follow-up patch should change the type we + pass to finalizers. + + * heap/HandleHeap.cpp: + (JSC): + (JSC::HandleHeap::writeBarrier): + (JSC::HandleHeap::isLiveNode): + * heap/HandleHeap.h: + (JSC): + (HandleHeap): + (Node): + (JSC::HandleHeap::Node::Node): Removed all code related to Weak<T>, since + we have a separate WeakHeap now. + + * heap/Heap.cpp: + (JSC::Heap::Heap): Removed m_extraCost because extra cost is accounted + for through our watermark now. Removed m_waterMark because it was unused. + + (JSC::Heap::destroy): Updated for addition of WeakHeap. + + (JSC::Heap::reportExtraMemoryCostSlowCase): Changed from using its own + variable to participating in the watermark strategy. I wanted to standardize + WeakHeap and all other Heap clients on this strategy, to make sure it's + accurate. + + (JSC::Heap::markRoots): Updated for addition of WeakHeap. Added WeakHeap + dead visit pass, as explained above. + + (JSC::Heap::collect): + (JSC::Heap::resetAllocators): Updated for addition of WeakHeap. + + (JSC::Heap::addFinalizer): + (JSC::Heap::FinalizerOwner::finalize): Updated for new Weak<T> API. + + * heap/Heap.h: + (JSC::Heap::weakHeap): + (Heap): + (JSC::Heap::addToWaterMark): Added a way to participate in the watermarking + strategy, since this is the best way for WeakHeap to report its memory + cost. (I plan to update this in a follow-up patch to make it more accurate, + but for now it is not less accurate than it used to be.) + + * heap/MarkedSpace.cpp: + (JSC::MarkedSpace::MarkedSpace): + (JSC::MarkedSpace::resetAllocators): + * heap/MarkedSpace.h: + (MarkedSpace): + (JSC::MarkedSpace::addToWaterMark): + (JSC::MarkedSpace::didConsumeFreeList): Removed m_nurseryWaterMark because + it was unused, and I didn't want to update WeakHeap to keep an usused + variable working. Added API for above. + + * heap/PassWeak.h: + (JSC): + (WeakImplAccessor): + (PassWeak): + (JSC::::operator): + (JSC::::get): + (JSC::::was): + (JSC::::PassWeak): + (JSC::::~PassWeak): + (JSC::UnspecifiedBoolType): + (JSC::::leakImpl): + (JSC::adoptWeak): + * heap/Strong.h: + (JSC::Strong::operator!): + (Strong): + (JSC::Strong::operator UnspecifiedBoolType*): + (JSC::Strong::get): + * heap/Weak.h: + (Weak): + (JSC::::Weak): + (JSC): + (JSC::::isHashTableDeletedValue): + (JSC::::~Weak): + (JSC::::swap): + (JSC::=): + (JSC::::operator): + (JSC::UnspecifiedBoolType): + (JSC::::release): + (JSC::::clear): + (JSC::::hashTableDeletedValue): Lots of code changes here, but they boil + down to two things: + + (*) Allocate WeakImpls from the WeakHeap instead of Handles from the HandleHeap. + + (*) Explicitly check WeakImpl::state() for non-liveness before returning + a value (explained above). + + These files implement the new Weak<T> heap behavior described above: + + * heap/WeakBlock.cpp: Added. + * heap/WeakBlock.h: Added. + * heap/WeakHandleOwner.cpp: Added. + * heap/WeakHandleOwner.h: Added. + * heap/WeakHeap.cpp: Added. + * heap/WeakHeap.h: Added. + * heap/WeakImpl.h: Added. + + One interesting difference from the old heap is that we don't allow + clients to overwrite a WeakImpl after allocating it, and we don't recycle + WeakImpls prior to garbage collection. This is required for lazy finalization, + but it will also help us esablish a useful invariant in the future: allocating + a WeakImpl will be a binding contract to run a finalizer at some point in the + future, even if the WeakImpl is later deallocated. + + * jit/JITStubs.cpp: + (JSC::JITThunks::hostFunctionStub): Check the Weak<T> for ! instead of + its JSValue, since that's our API contract now, and the JSValue might + be stale. + + * runtime/JSCell.h: + (JSC::jsCast): Allow casting NULL pointers because it's useful and harmless. + + * runtime/Structure.cpp: + (JSC::StructureTransitionTable::add): I can't remember why I did this. + + * runtime/StructureTransitionTable.h: + * runtime/WeakGCMap.h: I had to update these classes because they allocate + and deallocate weak pointers manually. They should probably stop doing that. + +2012-04-03 Keishi Hattori <keishi@webkit.org> + + Disable ENABLE_DATALIST for now + https://bugs.webkit.org/show_bug.cgi?id=82871 + + Reviewed by Kent Tamura. + + * Configurations/FeatureDefines.xcconfig: Disabled ENABLE_DATALIST. + +2012-04-02 Filip Pizlo <fpizlo@apple.com> + + jsr/sret should be removed + https://bugs.webkit.org/show_bug.cgi?id=82986 + <rdar://problem/11017015> + + Reviewed by Sam Weinig and Geoff Garen. + + Replaces jsr/sret with finally block inlining. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::dump): + * bytecode/Opcode.h: + (JSC): + (JSC::padOpcodeName): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::pushFinallyContext): + (JSC::BytecodeGenerator::emitComplexJumpScopes): + (JSC): + * bytecompiler/BytecodeGenerator.h: + (FinallyContext): + (BytecodeGenerator): + * bytecompiler/NodesCodegen.cpp: + (JSC::TryNode::emitBytecode): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JIT.cpp: + (JSC::JIT::privateCompileMainPass): + (JSC::JIT::privateCompile): + * jit/JIT.h: + (JIT): + * jit/JITOpcodes.cpp: + (JSC): + * jit/JITOpcodes32_64.cpp: + (JSC): + * llint/LowLevelInterpreter32_64.asm: + * llint/LowLevelInterpreter64.asm: + +2012-04-03 Mark Rowe <mrowe@apple.com> + + Make it possible to install the JavaScriptCore test tools. + + Part of <rdar://problem/11158607>. + + Reviewed by Filip Pizlo. + + * JavaScriptCore.xcodeproj/project.pbxproj: Introduce an aggregate target named + Test Tools that builds testapi, minidom and testRegExp. Switch All from depending on + those targets individually to depending on the new aggregate target. + +2012-04-03 Filip Pizlo <fpizlo@apple.com> + + Offlineasm ARM backend has a very convoluted way of saying it wants to emit a + three-operand multiply instruction + https://bugs.webkit.org/show_bug.cgi?id=83100 + + Reviewed by Darin Adler. + + Changed the "muli"/"mulp" case to call emitArmV7() since that helper method was + already smart enough to do the Right Thing for multiply. + + * offlineasm/armv7.rb: + +2012-04-03 Filip Pizlo <fpizlo@apple.com> + + Offlineasm ARM backend uses the wrong mnemonic for multiply + https://bugs.webkit.org/show_bug.cgi?id=83098 + <rdar://problem/11168744> + + Reviewed by Gavin Barraclough. + + Use "mul" instead of "muls" since we're passing three operands, not two. + + * offlineasm/armv7.rb: + +2012-04-03 Gavin Barraclough <barraclough@apple.com> + + Linux crashes during boot + https://bugs.webkit.org/show_bug.cgi?id=83096 + + Reviewed by Filip Pizlo. + + The bug here is that we add empty JSValues to the sparse map, and then set them + - but a GC may occur before doing so (due to a call to reportExtraMemory cost). + We may want to consider making it safe to mark empty JSValues, but the simple & + contained fix to this specific bug is to just initialize these values to + something other than JSValue(). + + * runtime/JSArray.cpp: + (JSC::SparseArrayValueMap::add): + - Initialize sparse map entries. + +2012-04-02 Oliver Hunt <oliver@apple.com> + + Incorrect liveness information when inlining + https://bugs.webkit.org/show_bug.cgi?id=82985 + + Reviewed by Filip Pizlo. + + Don't remap register numbers that have already been remapped. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::handleInlining): + +2012-04-02 Filip Pizlo <fpizlo@apple.com> + + Activation tear-off neglects to copy the callee and scope chain, leading to crashes if we + try to create an arguments object from the activation + https://bugs.webkit.org/show_bug.cgi?id=82947 + <rdar://problem/11058598> + + Reviewed by Gavin Barraclough. + + We now copy the entire call frame header just to be sure. This is mostly perf-netural, + except for a 3.7% slow-down in V8/earley. + + * runtime/JSActivation.cpp: + (JSC::JSActivation::visitChildren): + * runtime/JSActivation.h: + (JSC::JSActivation::tearOff): + +2012-04-02 Daniel Bates <dbates@webkit.org> + + Remove Source/JavaScriptCore/wtf and its empty subdirectories + + Rubber-stamped by Eric Seidel. + + Following the move of WTF from Source/JavaScriptCore/wtf to Source/WTF + (https://bugs.webkit.org/show_bug.cgi?id=75673), remove directory + Source/JavaScriptCore/wtf and its empty subdirectories. + + * wtf: Removed. + * wtf/android: Removed. + * wtf/blackberry: Removed. + * wtf/chromium: Removed. + * wtf/dtoa: Removed. + * wtf/efl: Removed. + * wtf/gobject: Removed. + * wtf/gtk: Removed. + * wtf/mac: Removed. + * wtf/qt: Removed. + * wtf/qt/compat: Removed. + * wtf/tests: Removed. + * wtf/text: Removed. + * wtf/threads: Removed. + * wtf/threads/win: Removed. + * wtf/unicode: Removed. + * wtf/unicode/glib: Removed. + * wtf/unicode/icu: Removed. + * wtf/unicode/qt4: Removed. + * wtf/unicode/wince: Removed. + * wtf/url: Removed. + * wtf/url/api: Removed. + * wtf/url/src: Removed. + * wtf/win: Removed. + * wtf/wince: Removed. + * wtf/wx: Removed. + +2012-04-02 Carlos Garcia Campos <cgarcia@igalia.com> + + Unreviewed. Fix make distcheck issues. + + * GNUmakefile.list.am: Add missing file. + +2012-04-01 Darin Adler <darin@apple.com> + + Fix incorrect path for libWTF.a in Mac project file. + + * JavaScriptCore.xcodeproj/project.pbxproj: Removed the "../Release" prefix that + would cause other configurations to try to link with the "Release" version of + libWTF.a instead of the correct version. + +2012-03-29 Filip Pizlo <fpizlo@apple.com> + + DFG should optimize a==b for a being an object and b being either an object or + null/undefined, and vice versa + https://bugs.webkit.org/show_bug.cgi?id=82656 + + Reviewed by Oliver Hunt. + + Implements additional object equality optimizations for the case that one + operand is predicted to be an easily speculated object (like FinalObject or + Array) and the other is either an easily speculated object or Other, i.e. + Null or Undefined. + + 2-5% speed-up on V8/raytrace, leading to a sub-1% progression on V8. + + I also took the opportunity to clean up the control flow for the speculation + decisions in the various Compare opcodes. And to fix a build bug in SamplingTool. + And to remove debug cruft I stupidly committed in my last patch. + + * bytecode/SamplingTool.h: + (SamplingRegion): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGOperations.cpp: + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch): + (JSC::DFG::SpeculativeJIT::compare): + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch): + (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality): + (DFG): + (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranch): + (JSC::DFG::SpeculativeJIT::compileObjectToObjectOrOtherEquality): + (DFG): + (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality): + +2012-03-30 David Barr <davidbarr@chromium.org> + + Split up top-level .gitignore and .gitattributes + https://bugs.webkit.org/show_bug.cgi?id=82687 + + Reviewed by Tor Arne Vestbø. + + * JavaScriptCore.gyp/.gitignore: Added. + +2012-03-30 Steve Falkenburg <sfalken@apple.com> + + Windows (make based) build fix. + + * JavaScriptCore.vcproj/JavaScriptCore.make: Copy WTF header files into a place where JavaScriptCore build can see them. + +2012-03-30 Keishi Hattori <keishi@webkit.org> + + Change ENABLE_INPUT_COLOR to ENABLE_INPUT_TYPE_COLOR and enable it for chromium + https://bugs.webkit.org/show_bug.cgi?id=80972 + + Reviewed by Kent Tamura. + + * Configurations/FeatureDefines.xcconfig: + +2012-03-29 Mark Hahnenberg <mhahnenberg@apple.com> + + Refactor recompileAllJSFunctions() to be less expensive + https://bugs.webkit.org/show_bug.cgi?id=80330 + + Reviewed by Filip Pizlo. + + This change is performance neutral on the JS benchmarks we track. It's mostly to improve page + load performance, which currently does at least a couple full GCs per navigation. + + * heap/Heap.cpp: + (JSC::Heap::discardAllCompiledCode): Rename recompileAllJSFunctions to discardAllCompiledCode + because the function doesn't actually recompile anything (and never did); it simply throws code + away for it to be recompiled later if we determine we should do so. + (JSC): + (JSC::Heap::collectAllGarbage): + (JSC::Heap::addFunctionExecutable): Adds a newly created FunctionExecutable to the Heap's list. + (JSC::Heap::removeFunctionExecutable): Removes the specified FunctionExecutable from the Heap's list. + * heap/Heap.h: + (JSC): + (Heap): + * runtime/Executable.cpp: Added next and prev fields to FunctionExecutables so that they can + be used in DoublyLinkedLists. + (JSC::FunctionExecutable::FunctionExecutable): + (JSC::FunctionExecutable::finalize): Removes the FunctionExecutable from the Heap's list. + * runtime/Executable.h: + (FunctionExecutable): + (JSC::FunctionExecutable::create): Adds the FunctionExecutable to the Heap's list. + * runtime/JSGlobalData.cpp: Remove recompileAllJSFunctions, as it's the Heap's job to own and manage + the list of FunctionExecutables. + * runtime/JSGlobalData.h: + (JSGlobalData): + * runtime/JSGlobalObject.cpp: + (JSC::DynamicGlobalObjectScope::DynamicGlobalObjectScope): Use the new discardAllCompiledCode. + +2012-03-29 Filip Pizlo <fpizlo@apple.com> + + Unreviewed build fix for non-x86 platforms. + + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileSoftModulo): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::callOperation): + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emitSlow_op_mod): + +2012-03-29 Gavin Barraclough <barraclough@apple.com> + + Windows build fix p2. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-29 Gavin Barraclough <barraclough@apple.com> + + Windows build fix p1. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-29 Gavin Barraclough <barraclough@apple.com> + + Template the Yarr::Interpreter on the character type + https://bugs.webkit.org/show_bug.cgi?id=82637 + + Reviewed by Sam Weinig. + + We should be able to call to the interpreter after having already checked the character type, + without having to re-package the character pointer back up into a string! + + * runtime/RegExp.cpp: + (JSC::RegExp::match): + (JSC::RegExp::matchCompareWithInterpreter): + - Don't pass length. + * yarr/Yarr.h: + - moved function declarations to YarrInterpreter.h. + * yarr/YarrInterpreter.cpp: + (Yarr): + (Interpreter): + (JSC::Yarr::Interpreter::InputStream::InputStream): + (InputStream): + (JSC::Yarr::Interpreter::Interpreter): + (JSC::Yarr::interpret): + - templated Interpreter class on CharType. + * yarr/YarrInterpreter.h: + (Yarr): + - added function declarations. + +2012-03-29 David Kilzer <ddkilzer@apple.com> + + Don't use a flattened framework path when building on OS X + + Reviewed by Mark Rowe. + + * Configurations/ToolExecutable.xcconfig: Use REAL_PLATFORM_NAME + to select different INSTALL_PATH values. + +2012-03-29 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Unreviewed build fix, add Win-specific sources + the wx port needs after WTF move. + + * wscript: + +2012-03-29 Andy Estes <aestes@apple.com> + + Remove an unused variable that breaks the build with newer versions of clang. + + Rubber stamped by Gavin Barraclough. + + * yarr/YarrJIT.cpp: + (JSC::Yarr::YarrGenerator::backtrackCharacterClassNonGreedy): + +2012-03-29 Caio Marcelo de Oliveira Filho <caio.oliveira@openbossa.org> + + HashMap<>::add should return a more descriptive object + https://bugs.webkit.org/show_bug.cgi?id=71063 + + Reviewed by Ryosuke Niwa. + + Update code to use AddResult instead of a pair. Note that since WeakGCMap wraps + the iterator type, there's a need for its own AddResult type -- instantiated from + HashTableAddResult template class. + + * API/JSCallbackObject.h: + (JSC::JSCallbackObjectData::JSPrivatePropertyMap::setPrivateProperty): + * API/JSClassRef.cpp: + (OpaqueJSClass::contextData): + * bytecompiler/BytecodeGenerator.cpp: + (JSC::BytecodeGenerator::addVar): + (JSC::BytecodeGenerator::addGlobalVar): + (JSC::BytecodeGenerator::addConstant): + (JSC::BytecodeGenerator::addConstantValue): + (JSC::BytecodeGenerator::emitLoad): + (JSC::BytecodeGenerator::addStringConstant): + (JSC::BytecodeGenerator::emitLazyNewFunction): + * bytecompiler/NodesCodegen.cpp: + (JSC::PropertyListNode::emitBytecode): + * debugger/Debugger.cpp: + * dfg/DFGAssemblyHelpers.cpp: + (JSC::DFG::AssemblyHelpers::decodedCodeMapFor): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::cellConstant): + (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry): + * jit/JITStubs.cpp: + (JSC::JITThunks::ctiStub): + (JSC::JITThunks::hostFunctionStub): + * parser/Parser.cpp: + (JSC::::parseStrictObjectLiteral): + * parser/Parser.h: + (JSC::Scope::declareParameter): + * runtime/Identifier.cpp: + (JSC::Identifier::add): + (JSC::Identifier::add8): + (JSC::Identifier::addSlowCase): + * runtime/Identifier.h: + (JSC::Identifier::add): + (JSC::IdentifierTable::add): + * runtime/JSArray.cpp: + (JSC::SparseArrayValueMap::add): + (JSC::SparseArrayValueMap::put): + (JSC::SparseArrayValueMap::putDirect): + (JSC::JSArray::enterDictionaryMode): + (JSC::JSArray::defineOwnNumericProperty): + * runtime/JSArray.h: + (SparseArrayValueMap): + * runtime/PropertyNameArray.cpp: + (JSC::PropertyNameArray::add): + * runtime/StringRecursionChecker.h: + (JSC::StringRecursionChecker::performCheck): + * runtime/Structure.cpp: + (JSC::StructureTransitionTable::add): + * runtime/WeakGCMap.h: + (WeakGCMap): + (JSC::WeakGCMap::add): + (JSC::WeakGCMap::set): + * tools/ProfileTreeNode.h: + (JSC::ProfileTreeNode::sampleChild): + +2012-03-29 Patrick Gansterer <paroga@webkit.org> + + Build fix for !ENABLE(YARR_JIT) after r112454. + + * runtime/RegExp.cpp: + (JSC::RegExp::invalidateCode): + +2012-03-28 Filip Pizlo <fpizlo@apple.com> + + DFG object equality speculations should be simplified + https://bugs.webkit.org/show_bug.cgi?id=82557 + + Reviewed by Gavin Barraclough. + + * dfg/DFGNode.h: + (JSC::DFG::Node::shouldSpeculateFinalObject): + (JSC::DFG::Node::shouldSpeculateArray): + +2012-03-28 David Kilzer <ddkilzer@apple.com> + + minidom configurations should be based on ToolExecutable.xcconfig + <http://webkit.org/b/82513> + + Reviewed by Mark Rowe. + + Note that this patch changes minidom from being installed in + /usr/local/bin to JavaScriptCore.framework/Resources. + + * Configurations/ToolExecutable.xcconfig: Add semi-colon. + * JavaScriptCore.xcodeproj/project.pbxproj: Base minidom + configurations on ToolExecutable.xcconfig. Remove redundant + PRODUCT_NAME and SKIP_INSTALL variables. + +2012-03-28 Gavin Barraclough <barraclough@apple.com> + + Build fix - some compiles generating NORETURN related warnings. + + * yarr/YarrJIT.cpp: + (JSC::Yarr::YarrGenerator::setSubpatternStart): + (JSC::Yarr::YarrGenerator::setSubpatternEnd): + (JSC::Yarr::YarrGenerator::clearSubpatternStart): + +2012-03-28 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Unreviewed. Build fix, move WTF back into JSCore target + until issues with JSCore not linking in all WTF symbols are resolved. + + * wscript: + +2012-03-28 Gavin Barraclough <barraclough@apple.com> + + Yarr: if we're not using the output array, don't populate it! + https://bugs.webkit.org/show_bug.cgi?id=82519 + + Reviewed by Sam Weinig. + + * runtime/RegExp.cpp: + (JSC): + - Missed review comment! - didn't fully remove RegExpRepresentation. + +2012-03-28 Gavin Barraclough <barraclough@apple.com> + + Yarr: if we're not using the output array, don't populate it! + https://bugs.webkit.org/show_bug.cgi?id=82519 + + Reviewed by Sam Weinig. + + Add a new variant of the match method to RegExp that returns a MatchResult, + and modify YarrJIT to be able to compile code that doesn't use an output vector. + + This is a 3% progression on v8-regexp. + + * JavaScriptCore.xcodeproj/project.pbxproj: + - Moved MatchResult into its own header. + * assembler/AbstractMacroAssembler.h: + - Added missing include. + * runtime/MatchResult.h: Added. + (MatchResult::MatchResult): + (MatchResult): + (MatchResult::failed): + (MatchResult::operator bool): + (MatchResult::empty): + - Moved MatchResult into its own header. + * runtime/RegExp.cpp: + (JSC::RegExp::compile): + (JSC::RegExp::compileIfNecessary): + (JSC::RegExp::match): + - Changed due to execute & representation changes. + (JSC::RegExp::compileMatchOnly): + (JSC::RegExp::compileIfNecessaryMatchOnly): + - Added helper to compile MatchOnly code. + (JSC::RegExp::invalidateCode): + (JSC::RegExp::matchCompareWithInterpreter): + (JSC::RegExp::printTraceData): + - Changed due representation changes. + * runtime/RegExp.h: + (RegExp): + (JSC::RegExp::hasCode): + - Made YarrCodeBlock a member. + * runtime/RegExpConstructor.h: + (RegExpConstructor): + (JSC::RegExpConstructor::performMatch): + - Added no-ovector form. + * runtime/RegExpMatchesArray.cpp: + (JSC::RegExpMatchesArray::reifyAllProperties): + - Match now takes a reference to ovector, not a pointer. + * runtime/RegExpObject.h: + (JSC): + - Moved MatchResult into its own header. + * runtime/StringPrototype.cpp: + (JSC::stringProtoFuncSplit): + - Match now takes a reference to ovector, not a pointer. + * testRegExp.cpp: + (testOneRegExp): + - Match now takes a reference to ovector, not a pointer. + * yarr/YarrJIT.cpp: + (Yarr): + (YarrGenerator): + (JSC::Yarr::YarrGenerator::initCallFrame): + (JSC::Yarr::YarrGenerator::removeCallFrame): + (JSC::Yarr::YarrGenerator::setSubpatternStart): + (JSC::Yarr::YarrGenerator::setSubpatternEnd): + (JSC::Yarr::YarrGenerator::clearSubpatternStart): + (JSC::Yarr::YarrGenerator::setMatchStart): + (JSC::Yarr::YarrGenerator::getMatchStart): + - Added helper functions to intermediate access to output. + (JSC::Yarr::YarrGenerator::generateDotStarEnclosure): + (JSC::Yarr::YarrGenerator::generate): + (JSC::Yarr::YarrGenerator::backtrack): + (JSC::Yarr::YarrGenerator::generateEnter): + (JSC::Yarr::YarrGenerator::compile): + - Changed to use the new helpers, only generate subpatterns if IncludeSubpatterns. + (JSC::Yarr::jitCompile): + - Needs to template of MatchOnly or IncludeSubpatterns. + * yarr/YarrJIT.h: + (YarrCodeBlock): + (JSC::Yarr::YarrCodeBlock::set8BitCode): + (JSC::Yarr::YarrCodeBlock::set16BitCode): + (JSC::Yarr::YarrCodeBlock::has8BitCodeMatchOnly): + (JSC::Yarr::YarrCodeBlock::has16BitCodeMatchOnly): + (JSC::Yarr::YarrCodeBlock::set8BitCodeMatchOnly): + (JSC::Yarr::YarrCodeBlock::set16BitCodeMatchOnly): + (JSC::Yarr::YarrCodeBlock::execute): + (JSC::Yarr::YarrCodeBlock::clear): + - Added a second set of CodeRefs, so that we can compile RexExps with/without subpattern matching. + +2012-03-27 Filip Pizlo <fpizlo@apple.com> + + DFG OSR exit should not generate an exit for variables of inlinees if the + inlinees are not in scope + https://bugs.webkit.org/show_bug.cgi?id=82312 + + Reviewed by Oliver Hunt. + + * bytecode/CodeBlock.h: + (JSC::baselineCodeBlockForInlineCallFrame): + (JSC): + (JSC::baselineCodeBlockForOriginAndBaselineCodeBlock): + * dfg/DFGOSRExit.cpp: + (JSC::DFG::computeNumVariablesForCodeOrigin): + (DFG): + (JSC::DFG::OSRExit::OSRExit): + +2012-03-27 Matt Lilek <mrl@apple.com> + + Stop compiling Interpreter.cpp with -fno-var-tracking + https://bugs.webkit.org/show_bug.cgi?id=82299 + + Reviewed by Anders Carlsson. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2012-03-27 Pratik Solanki <psolanki@apple.com> + + Compiler warning when JIT is not enabled + https://bugs.webkit.org/show_bug.cgi?id=82352 + + Reviewed by Filip Pizlo. + + * runtime/JSFunction.cpp: + (JSC::JSFunction::create): + +2012-03-26 Thouraya ANDOLSI <thouraya.andolsi@st.com> + + Unaligned userspace access for SH4 platforms + https://bugs.webkit.org/show_bug.cgi?id=79104 + + Reviewed by Gavin Barraclough. + + * assembler/AbstractMacroAssembler.h: + (Jump): + (JSC::AbstractMacroAssembler::Jump::Jump): + (JSC::AbstractMacroAssembler::Jump::link): + * assembler/MacroAssemblerSH4.h: + (JSC::MacroAssemblerSH4::load16Unaligned): + (JSC::MacroAssemblerSH4::load32WithUnalignedHalfWords): + (JSC::MacroAssemblerSH4::branchDouble): + (JSC::MacroAssemblerSH4::branchTrue): + (JSC::MacroAssemblerSH4::branchFalse): + * assembler/SH4Assembler.h: + (JSC::SH4Assembler::extraInstrForBranch): + (SH4Assembler): + (JSC::SH4Assembler::bra): + (JSC::SH4Assembler::linkJump): + * jit/JIT.h: + (JIT): + * yarr/YarrJIT.cpp: + (JSC::Yarr::YarrGenerator::generatePatternCharacterOnce): + +2012-03-26 Ryosuke Niwa <rniwa@webkit.org> + + cssText should use shorthand notations + https://bugs.webkit.org/show_bug.cgi?id=81737 + + Reviewed by Enrica Casucci. + + Export symbols of BitVector on Windows. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-26 Filip Pizlo <fpizlo@apple.com> + + DFG should assert that argument value recoveries can only be + AlreadyInRegisterFile or Constant + https://bugs.webkit.org/show_bug.cgi?id=82249 + + Reviewed by Michael Saboff. + + Made the assertions that the DFG makes for argument value recoveries match + what Arguments expects. + + * bytecode/ValueRecovery.h: + (JSC::ValueRecovery::isConstant): + (ValueRecovery): + (JSC::ValueRecovery::isAlreadyInRegisterFile): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-03-26 Dan Bernstein <mitz@apple.com> + + Tried to fix the Windows build. + + * yarr/YarrPattern.cpp: + (JSC::Yarr::CharacterClassConstructor::putRange): + +2012-03-26 Gavin Barraclough <barraclough@apple.com> + + Unreviewed - speculative Windows build fix. + + * yarr/YarrCanonicalizeUCS2.h: + (JSC::Yarr::getCanonicalPair): + +2012-03-26 Dan Bernstein <mitz@apple.com> + + Fixed builds with assertions disabled. + + * yarr/YarrCanonicalizeUCS2.h: + (JSC::Yarr::areCanonicallyEquivalent): + +2012-03-26 Gavin Barraclough <barraclough@apple.com> + + Unreviewed - errk! - accidentally the whole pbxproj. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2012-03-25 Gavin Barraclough <barraclough@apple.com> + + Greek sigma is handled wrong in case independent regexp. + https://bugs.webkit.org/show_bug.cgi?id=82063 + + Reviewed by Oliver Hunt. + + The bug here is that we assume that any given codepoint has at most one additional value it + should match under a case insensitive match, and that the pair of codepoints that match (if + a codepoint does not only match itself) can be determined by calling toUpper/toLower on the + given codepoint). Life is not that simple. + + Instead, pre-calculate a set of tables mapping from a UCS2 codepoint to the set of characters + it may match, under the ES5.1 case-insensitive matching rules. Since unicode is fairly regular + we can pack this table quite nicely, and get it down to 364 entries. This means we can use a + simple binary search to find an entry in typically eight compares. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.gypi: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + * JavaScriptCore.xcodeproj/project.pbxproj: + * yarr/yarr.pri: + - Added new files to build systems. + * yarr/YarrCanonicalizeUCS2.cpp: Added. + - New - autogenerated, UCS2 canonicalized comparison tables. + * yarr/YarrCanonicalizeUCS2.h: Added. + (JSC::Yarr::rangeInfoFor): + - Look up the canonicalization info for a UCS2 character. + (JSC::Yarr::getCanonicalPair): + - For a UCS2 character with a single equivalent value, look it up. + (JSC::Yarr::isCanonicallyUnique): + - Returns true if no other UCS2 code points are canonically equal. + (JSC::Yarr::areCanonicallyEquivalent): + - Compare two values, under canonicalization rules. + * yarr/YarrCanonicalizeUCS2.js: Added. + - script used to generate YarrCanonicalizeUCS2.cpp. + * yarr/YarrInterpreter.cpp: + (JSC::Yarr::Interpreter::tryConsumeBackReference): + - Use isCanonicallyUnique, rather than Unicode toUpper/toLower. + * yarr/YarrJIT.cpp: + (JSC::Yarr::YarrGenerator::jumpIfCharNotEquals): + (JSC::Yarr::YarrGenerator::generatePatternCharacterOnce): + (JSC::Yarr::YarrGenerator::generatePatternCharacterFixed): + - Use isCanonicallyUnique, rather than Unicode toUpper/toLower. + * yarr/YarrPattern.cpp: + (JSC::Yarr::CharacterClassConstructor::putChar): + - Updated to determine canonical equivalents correctly. + (JSC::Yarr::CharacterClassConstructor::putUnicodeIgnoreCase): + - Added, used to put a non-ascii, non-unique character in a case-insensitive match. + (JSC::Yarr::CharacterClassConstructor::putRange): + - Updated to determine canonical equivalents correctly. + (JSC::Yarr::YarrPatternConstructor::atomPatternCharacter): + - Changed to call putUnicodeIgnoreCase, instead of putChar, avoid a double lookup of rangeInfo. + +2012-03-26 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Unreviewed build fix. Add the build outputs dir to the list of build dirs, + so we make sure it finds the API headers on all platforms. + + * wscript: + +2012-03-26 Patrick Gansterer <paroga@webkit.org> + + Build fix for WinCE after r112039. + + * interpreter/Register.h: + (Register): Removed inline keyword from decleration since + there is an ALWAYS_INLINE at the definition anyway. + +2012-03-26 Carlos Garcia Campos <cgarcia@igalia.com> + + Unreviewed. Fix make distcheck. + + * GNUmakefile.list.am: Add missing files. + +2012-03-25 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Unreviewed build fix. Move WTF to its own static lib build. + + * wscript: + +2012-03-25 Filip Pizlo <fpizlo@apple.com> + + DFG int-to-double conversion should be revealed to CSE + https://bugs.webkit.org/show_bug.cgi?id=82135 + + Reviewed by Oliver Hunt. + + This introduces the notion of an Int32ToDouble node, which is injected + into the graph anytime we know that we have a double use of a node that + was predicted integer. The Int32ToDouble simplifies double speculation + on integers by skipping the path that would unbox doubles, if we know + that the value is already proven to be an integer. It allows integer to + double conversions to be subjected to common subexpression elimination + (CSE) by allowing the CSE phase to see where these conversions are + occurring. Finally, it allows us to see when a constant is being used + as both a double and an integer. This is a bit odd, since it means that + sometimes a double use of a constant will not refer directly to the + constant. This should not cause problems, for now, but it may require + some canonizalization in the future if we want to support strength + reductions of double operations based on constants. + + To allow injection of nodes into the graph, this change introduces the + DFG::InsertionSet, which is a way of lazily inserting elements into a + list. This allows the FixupPhase to remain O(N) despite performing + multiple injections in a single basic block. Without the InsertionSet, + each injection would require performing an insertion into a vector, + which is O(N), leading to O(N^2) performance overall. With the + InsertionSet, each injection simply records what insertion would have + been performed, and all insertions are performed at once (via + InsertionSet::execute) after processing of a basic block is completed. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * bytecode/PredictedType.h: + (JSC::isActionableIntMutableArrayPrediction): + (JSC): + (JSC::isActionableFloatMutableArrayPrediction): + (JSC::isActionableTypedMutableArrayPrediction): + (JSC::isActionableMutableArrayPrediction): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::performNodeCSE): + * dfg/DFGCommon.h: + (JSC::DFG::useKindToString): + (DFG): + * dfg/DFGFixupPhase.cpp: + (JSC::DFG::FixupPhase::run): + (JSC::DFG::FixupPhase::fixupBlock): + (FixupPhase): + (JSC::DFG::FixupPhase::fixupNode): + (JSC::DFG::FixupPhase::fixDoubleEdge): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGInsertionSet.h: Added. + (DFG): + (Insertion): + (JSC::DFG::Insertion::Insertion): + (JSC::DFG::Insertion::index): + (JSC::DFG::Insertion::element): + (InsertionSet): + (JSC::DFG::InsertionSet::InsertionSet): + (JSC::DFG::InsertionSet::append): + (JSC::DFG::InsertionSet::execute): + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor): + (JSC::DFG::SpeculativeJIT::compileValueToInt32): + (JSC::DFG::SpeculativeJIT::compileInt32ToDouble): + (DFG): + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + (JSC::DFG::IntegerOperand::IntegerOperand): + (JSC::DFG::DoubleOperand::DoubleOperand): + (JSC::DFG::JSValueOperand::JSValueOperand): + (JSC::DFG::StorageOperand::StorageOperand): + (JSC::DFG::SpeculateIntegerOperand::SpeculateIntegerOperand): + (JSC::DFG::SpeculateStrictInt32Operand::SpeculateStrictInt32Operand): + (JSC::DFG::SpeculateDoubleOperand::SpeculateDoubleOperand): + (JSC::DFG::SpeculateCellOperand::SpeculateCellOperand): + (JSC::DFG::SpeculateBooleanOperand::SpeculateBooleanOperand): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-03-25 Filip Pizlo <fpizlo@apple.com> + + DFGOperands should be moved out of the DFG and into bytecode + https://bugs.webkit.org/show_bug.cgi?id=82151 + + Reviewed by Dan Bernstein. + + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * bytecode/Operands.h: Copied from Source/JavaScriptCore/dfg/DFGOperands.h. + * dfg/DFGBasicBlock.h: + * dfg/DFGNode.h: + * dfg/DFGOSREntry.h: + * dfg/DFGOSRExit.h: + * dfg/DFGOperands.h: Removed. + * dfg/DFGVariableAccessData.h: + +2012-03-24 Filip Pizlo <fpizlo@apple.com> + + DFG 64-bit Branch implementation should not be creating a JSValueOperand that + it isn't going to use + https://bugs.webkit.org/show_bug.cgi?id=82136 + + Reviewed by Geoff Garen. + + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::emitBranch): + +2012-03-24 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Unreviewed. Fix the build after WTF move. + + * wscript: + +2012-03-23 Filip Pizlo <fpizlo@apple.com> + + DFG double voting may be overzealous in the case of variables that end up + being used as integers + https://bugs.webkit.org/show_bug.cgi?id=82008 + + Reviewed by Oliver Hunt. + + Cleaned up propagation, making the intent more explicit in most places. + Back-propagate NodeUsedAsInt for cases where a node was used in a context + that is known to strongly prefer integers. + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::handleCall): + (JSC::DFG::ByteCodeParser::parseBlock): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dumpCodeOrigin): + (JSC::DFG::Graph::dump): + * dfg/DFGGraph.h: + (Graph): + * dfg/DFGNodeFlags.cpp: + (JSC::DFG::nodeFlagsAsString): + * dfg/DFGNodeFlags.h: + (DFG): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::run): + (JSC::DFG::PredictionPropagationPhase::propagate): + (PredictionPropagationPhase): + (JSC::DFG::PredictionPropagationPhase::mergeDefaultFlags): + (JSC::DFG::PredictionPropagationPhase::vote): + (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting): + (JSC::DFG::PredictionPropagationPhase::fixupNode): + * dfg/DFGVariableAccessData.h: + (JSC::DFG::VariableAccessData::shouldUseDoubleFormatAccordingToVote): + +2012-03-24 Filip Pizlo <fpizlo@apple.com> + + DFG::Node::shouldNotSpeculateInteger() should be eliminated + https://bugs.webkit.org/show_bug.cgi?id=82123 + + Reviewed by Geoff Garen. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGNode.h: + (Node): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compilePutByValForByteArray): + (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): + +2012-03-24 Yong Li <yoli@rim.com> + + Increase getByIdSlowCase ConstantSpace/InstructionSpace for CPU(ARM_TRADITIONAL) + https://bugs.webkit.org/show_bug.cgi?id=81521 + + Increase sequenceGetByIdSlowCaseConstantSpace and sequenceGetByIdSlowCaseInstructionSpace + for CPU(ARM_TRADITIONAL) to fit actual need. + + Reviewed by Oliver Hunt. + + * jit/JIT.h: + (JIT): + +2012-03-23 Filip Pizlo <fpizlo@apple.com> + + DFG Fixup should be able to short-circuit trivial ValueToInt32's + https://bugs.webkit.org/show_bug.cgi?id=82030 + + Reviewed by Michael Saboff. + + Takes the fixup() method of the prediction propagation phase and makes it + into its own phase. Adds the ability to short-circuit trivial ValueToInt32 + nodes, and mark pure ValueToInt32's as such. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::makeSafe): + (JSC::DFG::ByteCodeParser::handleCall): + (JSC::DFG::ByteCodeParser::parseBlock): + * dfg/DFGCommon.h: + * dfg/DFGDriver.cpp: + (JSC::DFG::compile): + * dfg/DFGFixupPhase.cpp: Added. + (DFG): + (FixupPhase): + (JSC::DFG::FixupPhase::FixupPhase): + (JSC::DFG::FixupPhase::run): + (JSC::DFG::FixupPhase::fixupNode): + (JSC::DFG::FixupPhase::fixIntEdge): + (JSC::DFG::performFixup): + * dfg/DFGFixupPhase.h: Added. + (DFG): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::run): + (PredictionPropagationPhase): + +2012-03-23 Mark Hahnenberg <mhahnenberg@apple.com> + + tryReallocate could break the zero-ed memory invariant of CopiedBlocks + https://bugs.webkit.org/show_bug.cgi?id=82087 + + Reviewed by Filip Pizlo. + + Removing this optimization turned out to be ~1% regression on kraken, so I simply + undid the modification to the current block if we fail. + + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::tryReallocate): Undid the reset in the CopiedAllocator if we fail + to reallocate from the current block. + +2012-03-23 Alexey Proskuryakov <ap@apple.com> + + [Mac] No need for platform-specific ENABLE_BLOB values + https://bugs.webkit.org/show_bug.cgi?id=82102 + + Reviewed by David Kilzer. + + * Configurations/FeatureDefines.xcconfig: + +2012-03-23 Michael Saboff <msaboff@apple.com> + + DFG::compileValueToInt32 Sometime Generates GPR to FPR reg back to GPR + https://bugs.webkit.org/show_bug.cgi?id=81805 + + Reviewed by Filip Pizlo. + + Added SpeculativeJIT::checkGeneratedType() to determine the current format + of an operand. Used that information in SpeculativeJIT::compileValueToInt32 + to generate code that will use integer and JSValue types in integer + format directly without a conversion to double. + + * JavaScriptCore.xcodeproj/project.pbxproj: + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::checkGeneratedType): + (DFG): + (JSC::DFG::SpeculativeJIT::compileValueToInt32): + * dfg/DFGSpeculativeJIT.h: + (DFG): + (SpeculativeJIT): + +2012-03-23 Steve Falkenburg <sfalken@apple.com> + + Update Apple Windows build files for WTF move + https://bugs.webkit.org/show_bug.cgi?id=82069 + + Reviewed by Jessie Berlin. + + * JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln: Removed WTF and WTFGenerated. + +2012-03-23 Dean Jackson <dino@apple.com> + + Disable CSS_SHADERS in Apple builds + https://bugs.webkit.org/show_bug.cgi?id=81996 + + Reviewed by Simon Fraser. + + Remove ENABLE_CSS_SHADERS from FeatureDefines. It's now in Platform.h. + + * Configurations/FeatureDefines.xcconfig: + +2012-03-23 Gavin Barraclough <barraclough@apple.com> + + RexExp constructor last match properties should not rely on previous ovector + https://bugs.webkit.org/show_bug.cgi?id=82077 + + Reviewed by Oliver Hunt. + + This change simplifies matching, and will enable subpattern results to be fully lazily generated in the future. + + This patch changes the scheme used to lazily generate the last match properties of the RegExp object. + Instead of relying on the results in the ovector, we can instead lazily generate the subpatters using + a RegExpMatchesArray. To do so we just need to store the input, the regexp matched, and the match + location (the MatchResult). When the match is accessed or the input is set, we reify results. We use + a special value of setting the saved result to MatchResult::failed() to indicated that we're in a + reified state. This means that next time a match is performed, the store of the result will + automatically blow away the reified value. + + * JavaScriptCore.xcodeproj/project.pbxproj: + - Added new files. + * runtime/RegExp.cpp: + (JSC::RegExpFunctionalTestCollector::outputOneTest): + - changed 'subPattern' -> 'subpattern' (there was a mix in JSC, 'subpattern' was more common). + * runtime/RegExpCachedResult.cpp: Added. + (JSC::RegExpCachedResult::visitChildren): + (JSC::RegExpCachedResult::lastResult): + (JSC::RegExpCachedResult::setInput): + - New methods, mark GC objects, lazily create the matches array, and record a user provided input (via assignment to RegExp.inupt). + * runtime/RegExpCachedResult.h: Added. + (RegExpCachedResult): + - Added new class. + (JSC::RegExpCachedResult::RegExpCachedResult): + (JSC::RegExpCachedResult::record): + (JSC::RegExpCachedResult::input): + - Initialize the object, record the result of a RegExp match, access the stored input property. + * runtime/RegExpConstructor.cpp: + (JSC::RegExpConstructor::RegExpConstructor): + - Initialize m_result/m_multiline properties. + (JSC::RegExpConstructor::visitChildren): + - Make sure the cached results (or lazy source for them) are marked. + (JSC::RegExpConstructor::getBackref): + (JSC::RegExpConstructor::getLastParen): + (JSC::RegExpConstructor::getLeftContext): + (JSC::RegExpConstructor::getRightContext): + - Moved from RegExpConstructor, moved to RegExpCachedResult, and using new caching scheme. + (JSC::regExpConstructorInput): + (JSC::setRegExpConstructorInput): + - Changed to use RegExpCachedResult. + * runtime/RegExpConstructor.h: + (JSC::RegExpConstructor::create): + (RegExpConstructor): + (JSC::RegExpConstructor::setMultiline): + (JSC::RegExpConstructor::multiline): + - Move multiline property onto the constructor object; it is not affected by the last match. + (JSC::RegExpConstructor::setInput): + (JSC::RegExpConstructor::input): + - These defer to RegExpCachedResult. + (JSC::RegExpConstructor::performMatch): + * runtime/RegExpMatchesArray.cpp: Added. + (JSC::RegExpMatchesArray::visitChildren): + - Eeeep! added missing visitChildren! + (JSC::RegExpMatchesArray::finishCreation): + (JSC::RegExpMatchesArray::reifyAllProperties): + (JSC::RegExpMatchesArray::reifyMatchProperty): + - Moved from RegExpConstructor.cpp. + (JSC::RegExpMatchesArray::leftContext): + (JSC::RegExpMatchesArray::rightContext): + - Since the match start/ + * runtime/RegExpMatchesArray.h: + (RegExpMatchesArray): + - Declare new methods & structure flags. + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::match): + - performMatch now requires the JSString input, to cache. + * runtime/StringPrototype.cpp: + (JSC::removeUsingRegExpSearch): + (JSC::replaceUsingRegExpSearch): + (JSC::stringProtoFuncMatch): + (JSC::stringProtoFuncSearch): + - performMatch now requires the JSString input, to cache. + +2012-03-23 Tony Chang <tony@chromium.org> + + [chromium] rename newwtf target back to wtf + https://bugs.webkit.org/show_bug.cgi?id=82064 + + Reviewed by Adam Barth. + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2012-03-23 Mark Hahnenberg <mhahnenberg@apple.com> + + Simplify memory usage tracking in CopiedSpace + https://bugs.webkit.org/show_bug.cgi?id=80705 + + Reviewed by Filip Pizlo. + + * heap/CopiedAllocator.h: + (CopiedAllocator): Rename currentUtilization to currentSize. + (JSC::CopiedAllocator::currentCapacity): + * heap/CopiedBlock.h: + (CopiedBlock): + (JSC::CopiedBlock::payload): Move the implementation of payload() out of the class + declaration. + (JSC): + (JSC::CopiedBlock::size): Add new function to calculate the block's size. + (JSC::CopiedBlock::capacity): Ditto for capacity. + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::CopiedSpace): Remove old bogus memory stats fields and add a new + field for the water mark. + (JSC::CopiedSpace::init): + (JSC::CopiedSpace::tryAllocateSlowCase): When we fail to allocate from the current + block, we need to update our current water mark with the size of the block. + (JSC::CopiedSpace::tryAllocateOversize): When we allocate a new oversize block, we + need to update our current water mark with the size of the used portion of the block. + (JSC::CopiedSpace::tryReallocate): We don't need to update the water mark when + reallocating because it will either get accounted for when we fill up the block later + in the case of being able to reallocate in the current block or it will get picked up + immediately because we'll have to get a new block. + (JSC::CopiedSpace::tryReallocateOversize): We do, however, need to update in when + realloc-ing an oversize block because we deallocate the old block and allocate a brand + new one. + (JSC::CopiedSpace::doneFillingBlock): Update the water mark as blocks are returned to + the CopiedSpace by the SlotVisitors. + (JSC::CopiedSpace::doneCopying): Add in any pinned blocks to the water mark. + (JSC::CopiedSpace::getFreshBlock): We use the Heap's new function to tell us whether or + not we should collect now instead of doing the calculation ourself. + (JSC::CopiedSpace::destroy): + (JSC): + (JSC::CopiedSpace::size): Manually calculate the size of the CopiedSpace, similar to how + MarkedSpace does. + (JSC::CopiedSpace::capacity): Ditto for capacity. + * heap/CopiedSpace.h: + (JSC::CopiedSpace::waterMark): + (CopiedSpace): + * heap/CopiedSpaceInlineMethods.h: + (JSC::CopiedSpace::startedCopying): Reset water mark to 0 when we start copying during a + collection. + (JSC::CopiedSpace::allocateNewBlock): + (JSC::CopiedSpace::fitsInBlock): + (JSC::CopiedSpace::allocateFromBlock): + * heap/Heap.cpp: + (JSC::Heap::size): Incorporate size of CopiedSpace into the total size of the Heap. + (JSC::Heap::capacity): Ditto for capacity. + (JSC::Heap::collect): + * heap/Heap.h: + (Heap): + (JSC::Heap::shouldCollect): New function for other sub-parts of the Heap to use to + determine whether they should initiate a collection or continue to allocate new blocks. + (JSC): + (JSC::Heap::waterMark): Now is the sum of the water marks of the two sub-parts of the + Heap (MarkedSpace and CopiedSpace). + * heap/MarkedAllocator.cpp: + (JSC::MarkedAllocator::allocateSlowCase): Changed to use the Heap's new shouldCollect() function. + +2012-03-23 Ryosuke Niwa <rniwa@webkit.org> + + BitVector::resizeOutOfLine doesn't memset when converting an inline buffer + https://bugs.webkit.org/show_bug.cgi?id=82012 + + Reviewed by Filip Pizlo. + + Initialize out-of-line buffers while extending an inline buffer. Also export symbols to be used in WebCore. + + * wtf/BitVector.cpp: + (WTF::BitVector::resizeOutOfLine): + * wtf/BitVector.h: + (BitVector): + (OutOfLineBits): + +2012-03-22 Michael Saboff <msaboff@apple.com> + + ExecutableAllocator::memoryPressureMultiplier() might can return NaN + https://bugs.webkit.org/show_bug.cgi?id=82002 + + Reviewed by Filip Pizlo. + + Guard against divide by zero and then make sure the return + value is >= 1.0. + + * jit/ExecutableAllocator.cpp: + (JSC::ExecutableAllocator::memoryPressureMultiplier): + * jit/ExecutableAllocatorFixedVMPool.cpp: + (JSC::ExecutableAllocator::memoryPressureMultiplier): + +2012-03-22 Jessie Berlin <jberlin@apple.com> + + Windows build fix after r111778. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj: + Don't include and try to build files owned by WTF. + Also, let VS have its way with the vcproj in terms of file ordering. + +2012-03-22 Raphael Kubo da Costa <rakuco@FreeBSD.org> + + [CMake] Unreviewed build fix after r111778. + + * CMakeLists.txt: Move ${WTF_DIR} after ${JAVASCRIPTCORE_DIR} in + the include paths so that the right config.h is used. + +2012-03-22 Tony Chang <tony@chromium.org> + + Unreviewed, fix chromium build after wtf move. + + Remove old wtf_config and wtf targets. + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + +2012-03-22 Martin Robinson <mrobinson@igalia.com> + + Fixed the GTK+ WTF/JavaScriptCore build after r111778. + + * GNUmakefile.list.am: Removed an extra trailing backslash. + +2012-03-22 Mark Rowe <mrowe@apple.com> + + Fix the build. + + * Configurations/JavaScriptCore.xcconfig: Tell the linker to pull in all members from static libraries + rather than only those that contain symbols that JavaScriptCore itself uses. + * JavaScriptCore.xcodeproj/project.pbxproj: Remove some bogus settings that crept in to the Xcode project. + +2012-03-22 Filip Pizlo <fpizlo@apple.com> + + DFG NodeFlags has some duplicate code and naming issues + https://bugs.webkit.org/show_bug.cgi?id=81975 + + Reviewed by Gavin Barraclough. + + Removed most references to "ArithNodeFlags" since those are now just part + of the node flags. Fixed some renaming goofs (EdgedAsNum is once again + NodeUsedAsNum). Got rid of setArithNodeFlags() and mergeArithNodeFlags() + because the former was never called and the latter did the same things as + mergeFlags(). + + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::makeSafe): + (JSC::DFG::ByteCodeParser::makeDivSafe): + (JSC::DFG::ByteCodeParser::handleIntrinsic): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGNode.h: + (JSC::DFG::Node::arithNodeFlags): + (Node): + * dfg/DFGNodeFlags.cpp: + (JSC::DFG::nodeFlagsAsString): + * dfg/DFGNodeFlags.h: + (DFG): + (JSC::DFG::nodeUsedAsNumber): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + (JSC::DFG::PredictionPropagationPhase::mergeDefaultArithFlags): + +2012-03-22 Eric Seidel <eric@webkit.org> + + Actually move WTF files to their new home + https://bugs.webkit.org/show_bug.cgi?id=81844 + + Unreviewed. The details of the port-specific changes + have been seen by contributors from those ports, but + the whole 5MB change isn't very reviewable as-is. + + * GNUmakefile.am: + * GNUmakefile.list.am: + * JSCTypedArrayStubs.h: + * JavaScriptCore.gypi: + * JavaScriptCore.xcodeproj/project.pbxproj: + * jsc.cpp: + +2012-03-22 Kevin Ollivier <kevino@theolliviers.com> + + [wx] Unreviewed. Adding Source/WTF to the build. + + * wscript: + +2012-03-22 Gavin Barraclough <barraclough@apple.com> + + Add JSValue::isFunction + https://bugs.webkit.org/show_bug.cgi?id=81935 + + Reviewed by Geoff Garen. + + This would be useful in the WebCore bindings code. + Also, remove asFunction, replace with jsCast<JSFunction*>. + + * API/JSContextRef.cpp: + * debugger/Debugger.cpp: + * debugger/DebuggerCallFrame.cpp: + (JSC::DebuggerCallFrame::functionName): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::valueOfFunctionConstant): + * dfg/DFGOperations.cpp: + * interpreter/CallFrame.cpp: + (JSC::CallFrame::isInlineCallFrameSlow): + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + * jit/JITStubs.cpp: + (JSC::DEFINE_STUB_FUNCTION): + (JSC::jitCompileFor): + (JSC::lazyLinkFor): + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::traceFunctionPrologue): + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + (JSC::LLInt::setUpCall): + * runtime/Arguments.h: + (JSC::Arguments::finishCreation): + * runtime/ArrayPrototype.cpp: + (JSC::arrayProtoFuncFilter): + (JSC::arrayProtoFuncMap): + (JSC::arrayProtoFuncEvery): + (JSC::arrayProtoFuncForEach): + (JSC::arrayProtoFuncSome): + (JSC::arrayProtoFuncReduce): + (JSC::arrayProtoFuncReduceRight): + * runtime/CommonSlowPaths.h: + (JSC::CommonSlowPaths::arityCheckFor): + * runtime/Executable.h: + (JSC::FunctionExecutable::compileFor): + (JSC::FunctionExecutable::compileOptimizedFor): + * runtime/FunctionPrototype.cpp: + (JSC::functionProtoFuncToString): + * runtime/JSArray.cpp: + (JSC::JSArray::sort): + * runtime/JSFunction.cpp: + (JSC::JSFunction::argumentsGetter): + (JSC::JSFunction::callerGetter): + (JSC::JSFunction::lengthGetter): + * runtime/JSFunction.h: + (JSC): + (JSC::asJSFunction): + (JSC::JSValue::isFunction): + * runtime/JSGlobalData.cpp: + (WTF::Recompiler::operator()): + (JSC::JSGlobalData::releaseExecutableMemory): + * runtime/JSValue.h: + * runtime/StringPrototype.cpp: + (JSC::replaceUsingRegExpSearch): + +2012-03-21 Filip Pizlo <fpizlo@apple.com> + + DFG speculation on booleans should be rationalized + https://bugs.webkit.org/show_bug.cgi?id=81840 + + Reviewed by Gavin Barraclough. + + This removes isKnownBoolean() and replaces it with AbstractState-based + optimization, and cleans up the control flow in code gen methods for + Branch and LogicalNot. Also fixes a goof in Node::shouldSpeculateNumber, + and removes isKnownNotBoolean() since that method appeared to be a + helper used solely by 32_64's speculateBooleanOperation(). + + This is performance-neutral. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGNode.h: + (JSC::DFG::Node::shouldSpeculateNumber): + * dfg/DFGSpeculativeJIT.cpp: + (DFG): + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean): + (JSC::DFG::SpeculativeJIT::compileLogicalNot): + (JSC::DFG::SpeculativeJIT::emitBranch): + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compileLogicalNot): + (JSC::DFG::SpeculativeJIT::emitBranch): + (JSC::DFG::SpeculativeJIT::compile): + +2012-03-21 Mark Rowe <mrowe@apple.com> + + Fix the build. + + * wtf/MetaAllocator.h: + (MetaAllocator): Export the destructor. + +2012-03-21 Eric Seidel <eric@webkit.org> + + Fix remaining WTF includes in JavaScriptCore in preparation for moving WTF headers out of JavaScriptCore + https://bugs.webkit.org/show_bug.cgi?id=81834 + + Reviewed by Adam Barth. + + * jsc.cpp: + * os-win32/WinMain.cpp: + * runtime/JSDateMath.cpp: + * runtime/TimeoutChecker.cpp: + * testRegExp.cpp: + * tools/CodeProfiling.cpp: + +2012-03-21 Eric Seidel <eric@webkit.org> + + WTF::MetaAllocator has a weak vtable (discovered when building wtf as a static library) + https://bugs.webkit.org/show_bug.cgi?id=81838 + + Reviewed by Geoffrey Garen. + + My understanding is that weak vtables happen when the compiler/linker cannot + determine which compilation unit should constain the vtable. In this case + because there were only pure virtual functions as well as an "inline" + virtual destructor (thus the virtual destructor was defined in many compilation + units). Since you can't actually "inline" a virtual function (it still has to + bounce through the vtable), the "inline" on this virutal destructor doesn't + actually help performance, and is only serving to confuse the compiler here. + I've moved the destructor implementation to the .cpp file, thus making + it clear to the compiler where the vtable should be stored, and solving the error. + + * wtf/MetaAllocator.cpp: + (WTF::MetaAllocator::~MetaAllocator): + (WTF): + * wtf/MetaAllocator.h: + +2012-03-20 Gavin Barraclough <barraclough@apple.com> + + RegExpMatchesArray should not copy the ovector + https://bugs.webkit.org/show_bug.cgi?id=81742 + + Reviewed by Michael Saboff. + + Currently, all RegExpMatchesArray object contain Vector<int, 32>, used to hold any sub-pattern results. + This makes allocation/construction/destruction of these objects more expensive. Instead, just store the + main match, and recreate the sub-pattern ranges only if necessary (these are often only used for grouping, + and the results never accessed). + If the main match (index 0) of the RegExpMatchesArray is accessed, reify that value alone. + + * dfg/DFGOperations.cpp: + - RegExpObject match renamed back to test (test returns a bool). + * runtime/RegExpConstructor.cpp: + (JSC): + - Removed RegExpResult, RegExpMatchesArray constructor, destroy method. + (JSC::RegExpMatchesArray::finishCreation): + - Removed RegExpConstructorPrivate parameter. + (JSC::RegExpMatchesArray::reifyAllProperties): + - (Was fillArrayInstance) Reify all properties of the RegExpMatchesArray. + If there are sub-pattern properties, the RegExp is re-run to generate their values. + (JSC::RegExpMatchesArray::reifyMatchProperty): + - Reify just the match (index 0) property of the RegExpMatchesArray. + * runtime/RegExpConstructor.h: + (RegExpConstructor): + (JSC::RegExpConstructor::performMatch): + - performMatch now returns a MatchResult, rather than using out-parameters. + * runtime/RegExpMatchesArray.h: + (JSC::RegExpMatchesArray::RegExpMatchesArray): + - Moved from .cpp, stores the input/regExp/result to use when lazily reifying properties. + (RegExpMatchesArray): + (JSC::RegExpMatchesArray::create): + - Now passed the input string matched against, the RegExp, and the MatchResult. + (JSC::RegExpMatchesArray::reifyAllPropertiesIfNecessary): + (JSC::RegExpMatchesArray::reifyMatchPropertyIfNecessary): + - Helpers to conditionally reify properties. + (JSC::RegExpMatchesArray::getOwnPropertySlot): + (JSC::RegExpMatchesArray::getOwnPropertySlotByIndex): + (JSC::RegExpMatchesArray::getOwnPropertyDescriptor): + (JSC::RegExpMatchesArray::put): + (JSC::RegExpMatchesArray::putByIndex): + (JSC::RegExpMatchesArray::deleteProperty): + (JSC::RegExpMatchesArray::deletePropertyByIndex): + (JSC::RegExpMatchesArray::getOwnPropertyNames): + (JSC::RegExpMatchesArray::defineOwnProperty): + - Changed to use reifyAllPropertiesIfNecessary/reifyMatchPropertyIfNecessary + (getOwnPropertySlotByIndex calls reifyMatchPropertyIfNecessary if index is 0). + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::exec): + (JSC::RegExpObject::match): + - match now returns a MatchResult. + * runtime/RegExpObject.h: + (JSC::MatchResult::MatchResult): + - Added the result of a match is a start & end tuple. + (JSC::MatchResult::failed): + - A failure is indicated by (notFound, 0). + (JSC::MatchResult::operator bool): + - Evaluates to false if the match failed. + (JSC::MatchResult::empty): + - Evaluates to true if the match succeeded with length 0. + (JSC::RegExpObject::test): + - Now returns a bool. + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncTest): + - RegExpObject match renamed back to test (test returns a bool). + * runtime/StringPrototype.cpp: + (JSC::removeUsingRegExpSearch): + (JSC::replaceUsingRegExpSearch): + (JSC::stringProtoFuncMatch): + (JSC::stringProtoFuncSearch): + - performMatch now returns a MatchResult, rather than using out-parameters. + +2012-03-21 Hojong Han <hojong.han@samsung.com> + + Fix out of memory by allowing overcommit + https://bugs.webkit.org/show_bug.cgi?id=81743 + + Reviewed by Geoffrey Garen. + + Garbage collection is not triggered and new blocks are added + because overcommit is allowed by MAP_NORESERVE flag when high water mark is big enough. + + * wtf/OSAllocatorPosix.cpp: + (WTF::OSAllocator::reserveAndCommit): + +2012-03-21 Jessie Berlin <jberlin@apple.com> + + More Windows build fixing. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + Fix the order of the include directories to look in include/private first before looking + in include/private/JavaScriptCore. + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops: + Look in the Production output directory (where the wtf headers will be). This is the same + thing that is done for jsc and testRegExp in ReleasePGO. + +2012-03-21 Jessie Berlin <jberlin@apple.com> + + WTF headers should be in $(ConfigurationBuildDir)\include\private\wtf, not + $(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf. + https://bugs.webkit.org/show_bug.cgi?id=81739 + + Reviewed by Dan Bernstein. + + * JavaScriptCore.vcproj/jsc/jsc.vcproj: + Look for AtomicString.cpp, StringBuilder.cpp, StringImpl.cpp, and WTFString.cpp in the wtf + subdirectory of the build output, not the JavaScriptCore/wtf subdirectory. + * JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj: + Ditto. + + * JavaScriptCore.vcproj/testRegExp/testRegExpReleasePGO.vsprops: + Get the headers for those 4 files from the wtf subdirectory of the build output, not the + JavaScriptCore/wtf subdirectory. + * JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops: + Ditto. + +2012-03-20 Eric Seidel <eric@webkit.org> + + Move wtf/Platform.h from JavaScriptCore to Source/WTF/wtf + https://bugs.webkit.org/show_bug.cgi?id=80911 + + Reviewed by Adam Barth. + + Update the various build systems to depend on Source/WTF headers + as well as remove references to Platform.h (since it's now moved). + + * CMakeLists.txt: + * JavaScriptCore.pri: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops: + * JavaScriptCore.xcodeproj/project.pbxproj: + * wtf/CMakeLists.txt: + +2012-03-20 Filip Pizlo <fpizlo@apple.com> + + op_mod fails on many interesting corner cases + https://bugs.webkit.org/show_bug.cgi?id=81648 + + Reviewed by Oliver Hunt. + + Removed most strength reduction for op_mod, and fixed the integer handling + to do the right thing for corner cases. Oddly, this revealed bugs in OSR, + which this patch also fixes. + + This patch is performance neutral on all of the major benchmarks we track. + + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: + * dfg/DFGSpeculativeJIT.cpp: + (DFG): + (JSC::DFG::SpeculativeJIT::compileSoftModulo): + (JSC::DFG::SpeculativeJIT::compileArithMod): + * jit/JIT.h: + (JIT): + * jit/JITArithmetic.cpp: + (JSC): + (JSC::JIT::emit_op_mod): + (JSC::JIT::emitSlow_op_mod): + * jit/JITArithmetic32_64.cpp: + (JSC::JIT::emit_op_mod): + (JSC::JIT::emitSlow_op_mod): + * jit/JITOpcodes32_64.cpp: + (JSC::JIT::privateCompileCTIMachineTrampolines): + (JSC): + * jit/JITStubs.h: + (TrampolineStructure): + (JSC::JITThunks::ctiNativeConstruct): + * llint/LowLevelInterpreter64.asm: + * wtf/Platform.h: + * wtf/SimpleStats.h: + (WTF::SimpleStats::variance): + +2012-03-20 Steve Falkenburg <sfalken@apple.com> + + Windows (make based) build fix. + <rdar://problem/11069015> + + * JavaScriptCore.vcproj/JavaScriptCore.make: devenv /rebuild doesn't work with JavaScriptCore.vcproj. Use /clean and /build instead. + +2012-03-20 Steve Falkenburg <sfalken@apple.com> + + Move WTF-related Windows project files out of JavaScriptCore + https://bugs.webkit.org/show_bug.cgi?id=80680 + + This change only moves the vcproj and related files from JavaScriptCore/JavaScriptCore.vcproj/WTF. + It does not move any source code. This is in preparation for the WTF source move out of + JavaScriptCore. + + Reviewed by Jessie Berlin. + + * JavaScriptCore.vcproj/JavaScriptCore.sln: + * JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln: + * JavaScriptCore.vcproj/WTF: Removed. + * JavaScriptCore.vcproj/WTF/WTF.vcproj: Removed. + * JavaScriptCore.vcproj/WTF/WTFCommon.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFDebug.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFDebugAll.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFDebugCairoCFLite.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFGenerated.make: Removed. + * JavaScriptCore.vcproj/WTF/WTFGenerated.vcproj: Removed. + * JavaScriptCore.vcproj/WTF/WTFGeneratedCommon.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFGeneratedDebug.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFGeneratedDebugAll.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFGeneratedDebugCairoCFLite.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFGeneratedProduction.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFGeneratedRelease.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFGeneratedReleaseCairoCFLite.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFPostBuild.cmd: Removed. + * JavaScriptCore.vcproj/WTF/WTFPreBuild.cmd: Removed. + * JavaScriptCore.vcproj/WTF/WTFProduction.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFRelease.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/WTFReleaseCairoCFLite.vsprops: Removed. + * JavaScriptCore.vcproj/WTF/build-generated-files.sh: Removed. + * JavaScriptCore.vcproj/WTF/copy-files.cmd: Removed. + * JavaScriptCore.vcproj/WTF/work-around-vs-dependency-tracking-bugs.py: Removed. + +2012-03-20 Benjamin Poulain <bpoulain@apple.com> + + Cache the type string of JavaScript object + https://bugs.webkit.org/show_bug.cgi?id=81446 + + Reviewed by Geoffrey Garen. + + Instead of creating the JSString every time, we create + lazily the strings in JSGlobalData. + + This avoid the construction of the StringImpl and of the JSString, + which gives some performance improvements. + + * runtime/CommonIdentifiers.h: + * runtime/JSValue.cpp: + (JSC::JSValue::toStringSlowCase): + * runtime/Operations.cpp: + (JSC::jsTypeStringForValue): + * runtime/SmallStrings.cpp: + (JSC::SmallStrings::SmallStrings): + (JSC::SmallStrings::finalizeSmallStrings): + (JSC::SmallStrings::initialize): + (JSC): + * runtime/SmallStrings.h: + (SmallStrings): + +2012-03-20 Oliver Hunt <oliver@apple.com> + + Allow LLINT to work even when executable allocation fails. + https://bugs.webkit.org/show_bug.cgi?id=81693 + + Reviewed by Gavin Barraclough. + + Don't crash if executable allocation fails if we can fall back on LLINT + + * jit/ExecutableAllocatorFixedVMPool.cpp: + (JSC::FixedVMPoolExecutableAllocator::FixedVMPoolExecutableAllocator): + * wtf/OSAllocatorPosix.cpp: + (WTF::OSAllocator::reserveAndCommit): + +2012-03-20 Csaba Osztrogonác <ossy@webkit.org> + + Division optimizations fail to infer cases of truncated division and mishandle -2147483648/-1 + https://bugs.webkit.org/show_bug.cgi?id=81428 + + 32 bit buildfix after r111355. + + 2147483648 (2^31) isn't valid int literal in ISO C90, because 2147483647 (2^31-1) is the biggest int. + The smallest int is -2147483648 (-2^31) == -2147483647 - 1 == -INT32_MAX-1 == INT32_MIN (stdint.h). + + Reviewed by Zoltan Herczeg. + + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileIntegerArithDivForX86): + +2012-03-19 Jochen Eisinger <jochen@chromium.org> + + Split WTFReportBacktrace into WTFReportBacktrace and WTFPrintBacktrace + https://bugs.webkit.org/show_bug.cgi?id=80983 + + Reviewed by Darin Adler. + + This allows printing a backtrace acquired by an earlier WTFGetBacktrace + call which is useful for local debugging. + + * wtf/Assertions.cpp: + * wtf/Assertions.h: + +2012-03-19 Benjamin Poulain <benjamin@webkit.org> + + Do not copy the script source in the SourceProvider, just reference the existing string + https://bugs.webkit.org/show_bug.cgi?id=81466 + + Reviewed by Geoffrey Garen. + + * parser/SourceCode.h: Remove the unused, and incorrect, function data(). + * parser/SourceProvider.h: Add OVERRIDE for clarity. + +2012-03-19 Filip Pizlo <fpizlo@apple.com> + + Division optimizations fail to infer cases of truncated division and + mishandle -2147483648/-1 + https://bugs.webkit.org/show_bug.cgi?id=81428 + <rdar://problem/11067382> + + Reviewed by Oliver Hunt. + + If you're a division over integers and you're only used as an integer, then you're + an integer division and remainder checks become unnecessary. If you're dividing + -2147483648 by -1, don't crash. + + * assembler/MacroAssemblerX86Common.h: + (MacroAssemblerX86Common): + (JSC::MacroAssemblerX86Common::add32): + * dfg/DFGSpeculativeJIT.cpp: + (DFG): + (JSC::DFG::SpeculativeJIT::compileIntegerArithDivForX86): + * dfg/DFGSpeculativeJIT.h: + (SpeculativeJIT): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * llint/LowLevelInterpreter64.asm: + +2012-03-19 Benjamin Poulain <bpoulain@apple.com> + + Simplify SmallStrings + https://bugs.webkit.org/show_bug.cgi?id=81445 + + Reviewed by Gavin Barraclough. + + SmallStrings had two methods that should not be public: count() and clear(). + + The method clear() is effectively replaced by finalizeSmallStrings(). The body + of the method was moved to the constructor since the code is obvious. + + The method count() is unused. + + * runtime/SmallStrings.cpp: + (JSC::SmallStrings::SmallStrings): + * runtime/SmallStrings.h: + (SmallStrings): + +2012-03-19 Filip Pizlo <fpizlo@apple.com> + + DFG can no longer compile V8-v4/regexp in debug mode + https://bugs.webkit.org/show_bug.cgi?id=81592 + + Reviewed by Gavin Barraclough. + + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + +2012-03-19 Filip Pizlo <fpizlo@apple.com> + + Prediction propagation for UInt32ToNumber incorrectly assumes that outs outcome does not + change throughout the fixpoint + https://bugs.webkit.org/show_bug.cgi?id=81583 + + Reviewed by Michael Saboff. + + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + +2012-03-19 Filip Pizlo <fpizlo@apple.com> + + GC should not attempt to clear LLInt instruction inline caches for code blocks that are in + the process of being generated + https://bugs.webkit.org/show_bug.cgi?id=81565 + + Reviewed by Oliver Hunt. + + * bytecode/CodeBlock.cpp: + (JSC::CodeBlock::finalizeUnconditionally): + +2012-03-19 Eric Seidel <eric@webkit.org> + + Fix WTF header include discipline in Chromium WebKit + https://bugs.webkit.org/show_bug.cgi?id=81281 + + Reviewed by James Robinson. + + * JavaScriptCore.gyp/JavaScriptCore.gyp: + * wtf/unicode/icu/CollatorICU.cpp: + +2012-03-19 Filip Pizlo <fpizlo@apple.com> + + DFG NodeUse should be called Edge and NodeReferenceBlob should be called AdjacencyList + https://bugs.webkit.org/show_bug.cgi?id=81556 + + Rubber stamped by Gavin Barraclough. + + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * dfg/DFGAbstractState.h: + (JSC::DFG::AbstractState::forNode): + * dfg/DFGAdjacencyList.h: Copied from Source/JavaScriptCore/dfg/DFGNodeReferenceBlob.h. + (JSC::DFG::AdjacencyList::AdjacencyList): + (JSC::DFG::AdjacencyList::child): + (JSC::DFG::AdjacencyList::setChild): + (JSC::DFG::AdjacencyList::child1): + (JSC::DFG::AdjacencyList::child2): + (JSC::DFG::AdjacencyList::child3): + (JSC::DFG::AdjacencyList::setChild1): + (JSC::DFG::AdjacencyList::setChild2): + (JSC::DFG::AdjacencyList::setChild3): + (JSC::DFG::AdjacencyList::child1Unchecked): + (JSC::DFG::AdjacencyList::initialize): + (AdjacencyList): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::addVarArgChild): + (JSC::DFG::ByteCodeParser::processPhiStack): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::canonicalize): + (JSC::DFG::CSEPhase::performSubstitution): + * dfg/DFGEdge.h: Copied from Source/JavaScriptCore/dfg/DFGNodeUse.h. + (DFG): + (JSC::DFG::Edge::Edge): + (JSC::DFG::Edge::operator==): + (JSC::DFG::Edge::operator!=): + (Edge): + (JSC::DFG::operator==): + (JSC::DFG::operator!=): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::operator[]): + (JSC::DFG::Graph::at): + (JSC::DFG::Graph::ref): + (JSC::DFG::Graph::deref): + (JSC::DFG::Graph::clearAndDerefChild1): + (JSC::DFG::Graph::clearAndDerefChild2): + (JSC::DFG::Graph::clearAndDerefChild3): + (Graph): + * dfg/DFGJITCompiler.h: + (JSC::DFG::JITCompiler::getPrediction): + * dfg/DFGNode.h: + (JSC::DFG::Node::Node): + (JSC::DFG::Node::child1): + (JSC::DFG::Node::child1Unchecked): + (JSC::DFG::Node::child2): + (JSC::DFG::Node::child3): + (Node): + * dfg/DFGNodeFlags.cpp: + (JSC::DFG::arithNodeFlagsAsString): + * dfg/DFGNodeFlags.h: + (DFG): + (JSC::DFG::nodeUsedAsNumber): + * dfg/DFGNodeReferenceBlob.h: Removed. + * dfg/DFGNodeUse.h: Removed. + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + (JSC::DFG::PredictionPropagationPhase::mergeDefaultArithFlags): + (JSC::DFG::PredictionPropagationPhase::vote): + (JSC::DFG::PredictionPropagationPhase::fixupNode): + * dfg/DFGScoreBoard.h: + (JSC::DFG::ScoreBoard::use): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::useChildren): + (JSC::DFG::SpeculativeJIT::writeBarrier): + (JSC::DFG::SpeculativeJIT::compilePutByValForByteArray): + (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray): + (JSC::DFG::SpeculativeJIT::compilePutByValForFloatTypedArray): + (JSC::DFG::SpeculativeJIT::compileStrictEqForConstant): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::at): + (JSC::DFG::SpeculativeJIT::canReuse): + (JSC::DFG::SpeculativeJIT::use): + (SpeculativeJIT): + (JSC::DFG::SpeculativeJIT::speculationCheck): + (JSC::DFG::SpeculativeJIT::terminateSpeculativeExecution): + (JSC::DFG::IntegerOperand::IntegerOperand): + (JSC::DFG::DoubleOperand::DoubleOperand): + (JSC::DFG::JSValueOperand::JSValueOperand): + (JSC::DFG::StorageOperand::StorageOperand): + (JSC::DFG::SpeculateIntegerOperand::SpeculateIntegerOperand): + (JSC::DFG::SpeculateStrictInt32Operand::SpeculateStrictInt32Operand): + (JSC::DFG::SpeculateDoubleOperand::SpeculateDoubleOperand): + (JSC::DFG::SpeculateCellOperand::SpeculateCellOperand): + (JSC::DFG::SpeculateBooleanOperand::SpeculateBooleanOperand): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::cachedPutById): + (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull): + (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull): + (JSC::DFG::SpeculativeJIT::nonSpeculativeCompareNull): + (JSC::DFG::SpeculativeJIT::emitCall): + (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot): + (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::cachedPutById): + (JSC::DFG::SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull): + (JSC::DFG::SpeculativeJIT::nonSpeculativePeepholeBranchNull): + (JSC::DFG::SpeculativeJIT::nonSpeculativeCompareNull): + (JSC::DFG::SpeculativeJIT::emitCall): + (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot): + (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch): + +2012-03-19 Gavin Barraclough <barraclough@apple.com> + + Object.freeze broken on latest Nightly + https://bugs.webkit.org/show_bug.cgi?id=80577 + + Reviewed by Oliver Hunt. + + * runtime/Arguments.cpp: + (JSC::Arguments::defineOwnProperty): + - defineOwnProperty was checking for correct behaviour, provided that length/callee hadn't + been overrridden. instead, just reify length/callee & rely on JSObject::defineOwnProperty. + * runtime/JSFunction.cpp: + (JSC::JSFunction::defineOwnProperty): + - for arguments/caller/length properties, defineOwnProperty was incorrectly asserting that + the object must be extensible; this is incorrect since these properties should already exist + on the object. In addition, it was asserting that the arguments/caller values must match the + corresponding magic data properties, but for strict mode function this is incorrect. Instead, + just reify the arguments/caller accessor & defer to JSObject::defineOwnProperty. + +2012-03-19 Filip Pizlo <fpizlo@apple.com> + + LLInt get_by_pname slow path incorrectly assumes that the operands are not constants + https://bugs.webkit.org/show_bug.cgi?id=81559 + + Reviewed by Michael Saboff. + + * llint/LLIntSlowPaths.cpp: + (JSC::LLInt::LLINT_SLOW_PATH_DECL): + +2012-03-19 Yong Li <yoli@rim.com> + + [BlackBerry] Implement OSAllocator::commit/decommit in the correct way + https://bugs.webkit.org/show_bug.cgi?id=77013 + + We should use mmap(PROT_NONE, MAP_LAZY) instead of posix_madvise() to + implement memory decommitting for QNX. + + Reviewed by Rob Buis. + + * wtf/OSAllocatorPosix.cpp: + (WTF::OSAllocator::reserveUncommitted): + (WTF::OSAllocator::commit): + (WTF::OSAllocator::decommit): + +2012-03-19 Gavin Barraclough <barraclough@apple.com> + + Unreviewed - revent a couple of files accidentally committed. + + * runtime/Arguments.cpp: + (JSC::Arguments::defineOwnProperty): + * runtime/JSFunction.cpp: + (JSC::JSFunction::defineOwnProperty): + +2012-03-19 Jessie Berlin <jberlin@apple.com> + + Another Windows build fix after r111129. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-19 Raphael Kubo da Costa <rakuco@FreeBSD.org> + + Cross-platform processor core counter: fix build on FreeBSD. + https://bugs.webkit.org/show_bug.cgi?id=81482 + + Reviewed by Zoltan Herczeg. + + The documentation of sysctl(3) shows that <sys/types.h> should be + included before <sys/sysctl.h> (sys/types.h tends to be the first + included header in general). + + This should fix the build on FreeBSD and other systems where + sysctl.h really depends on types defined in types.h. + + * wtf/NumberOfCores.cpp: + +2012-03-19 Jessie Berlin <jberlin@apple.com> + + Windows build fix after r111129. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-19 Gavin Barraclough <barraclough@apple.com> + + JSCallbackFunction::toStringCallback/valueOfCallback do not handle 0 return value from convertToType + https://bugs.webkit.org/show_bug.cgi?id=81468 <rdar://problem/11034745> + + Reviewed by Oliver Hunt. + + The API specifies that convertToType may opt not to handle a conversion: + "@result The objects's converted value, or NULL if the object was not converted." + In which case, it would propagate first up the JSClass hierarchy, calling its superclass's + conversion functions, and failing that call the JSObject::defaultValue function. + + Unfortunately this behaviour was removed in bug#69677/bug#69858, and instead we now rely on + the toStringCallback/valueOfCallback function introduced in bug#69156. Even after a fix in + bug#73368, these will return the result from the first convertToType they find, regardless + of whether this result is null, and if no convertToType method is found in the api class + hierarchy (possible if toStringCallback/valueOfCallback was accessed off the prototype + chain), they will also return a null pointer. This is unsafe. + + It would be easy to make the approach based around toStringCallback/valueOfCallback continue + to walk the api class hierarchy, but making the fallback to defaultValue would be problematic + (since defaultValue calls toStringCallback/valueOfCallback, this would infinitely recurse). + Making the fallback work with toString/valueOf methods attached to api objects is probably + not the right thing to do – instead, we should just implement the defaultValue trap for api + objects. + + In addition, this bug highlights that fact that JSCallbackFunction::call will allow a hard + null to be returned from C to JavaScript - this is not okay. Handle with an exception. + + * API/JSCallbackFunction.cpp: + (JSC::JSCallbackFunction::call): + - Should be null checking the return value. + (JSC): + - Remove toStringCallback/valueOfCallback. + * API/JSCallbackFunction.h: + (JSCallbackFunction): + - Remove toStringCallback/valueOfCallback. + * API/JSCallbackObject.h: + (JSCallbackObject): + - Add defaultValue mthods to JSCallbackObject. + * API/JSCallbackObjectFunctions.h: + (JSC::::defaultValue): + - Add defaultValue mthods to JSCallbackObject. + * API/JSClassRef.cpp: + (OpaqueJSClass::prototype): + - Remove toStringCallback/valueOfCallback. + * API/tests/testapi.js: + - Revert this test, now we no longer artificially introduce a toString method onto the api object. + +2012-03-18 Raphael Kubo da Costa <rakuco@FreeBSD.org> + + [EFL] Include ICU_INCLUDE_DIRS when building. + https://bugs.webkit.org/show_bug.cgi?id=81483 + + Reviewed by Daniel Bates. + + So far, only the ICU libraries were being included when building + JavaScriptCore, however the include path is also needed, otherwise the + build will fail when ICU is installed into a non-standard location. + + * PlatformEfl.cmake: Include ${ICU_INCLUDE_DIRS}. + +2012-03-17 Gavin Barraclough <barraclough@apple.com> + + Strength reduction, RegExp.exec -> RegExp.test + https://bugs.webkit.org/show_bug.cgi?id=81459 + + Reviewed by Sam Weinig. + + RegExp.prototype.exec & RegExp.prototype.test can both be used to test a regular + expression for a match against a string - however exec is more expensive, since + it allocates a matches array object. In cases where the result is consumed in a + boolean context the allocation of the matches array can be trivially elided. + + For example: + function f() + { + for (i =0; i < 10000000; ++i) + if(!/a/.exec("a")) + err = true; + } + + This is a 2.5x speedup on this example microbenchmark loop. + + In a more advanced form of this optimization, we may be able to avoid allocating + the array where access to the array can be observed. + + * create_hash_table: + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::handleIntrinsic): + * dfg/DFGNode.h: + (JSC::DFG::Node::hasHeapPrediction): + * dfg/DFGNodeType.h: + (DFG): + * dfg/DFGOperations.cpp: + * dfg/DFGOperations.h: + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileRegExpExec): + (DFG): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::callOperation): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::compile): + * jsc.cpp: + (GlobalObject::addConstructableFunction): + * runtime/Intrinsic.h: + * runtime/JSFunction.cpp: + (JSC::JSFunction::create): + (JSC): + * runtime/JSFunction.h: + (JSFunction): + * runtime/Lookup.cpp: + (JSC::setUpStaticFunctionSlot): + * runtime/RegExpObject.cpp: + (JSC::RegExpObject::exec): + (JSC::RegExpObject::match): + * runtime/RegExpObject.h: + (RegExpObject): + * runtime/RegExpPrototype.cpp: + (JSC::regExpProtoFuncTest): + (JSC::regExpProtoFuncExec): + +2012-03-16 Michael Saboff <msaboff@apple.com> + + Improve diagnostic benefit of JSGlobalData::m_isInitializingObject + https://bugs.webkit.org/show_bug.cgi?id=81244 + + Rubber stamped by Filip Pizlo. + + Changed type and name of JSGlobalData::m_isInitializingObject to + ClassInfo* and m_initializingObjectClass. + Changed JSGlobalData::setInitializingObject to + JSGlobalData::setInitializingObjectClass. This pointer can be used within + the debugger to determine what type of object is being initialized. + + * runtime/JSCell.h: + (JSC::JSCell::finishCreation): + (JSC::allocateCell): + * runtime/JSGlobalData.cpp: + (JSC::JSGlobalData::JSGlobalData): + * runtime/JSGlobalData.h: + (JSGlobalData): + (JSC::JSGlobalData::isInitializingObject): + (JSC::JSGlobalData::setInitializingObjectClass): + * runtime/Structure.h: + (JSC::JSCell::finishCreation): + +2012-03-16 Mark Rowe <mrowe@apple.com> + + Build fix. Do not preserve owner and group information when installing the WTF headers. + + * JavaScriptCore.xcodeproj/project.pbxproj: + +2012-03-15 David Dorwin <ddorwin@chromium.org> + + Make the array pointer parameters in the Typed Array create() methods const. + https://bugs.webkit.org/show_bug.cgi?id=81147 + + Reviewed by Kenneth Russell. + + This allows const arrays to be passed to these methods. + They use PassRefPtr<Subclass> create(), which already has a const parameter. + + * wtf/Int16Array.h: + (Int16Array): + (WTF::Int16Array::create): + * wtf/Int32Array.h: + (Int32Array): + (WTF::Int32Array::create): + * wtf/Int8Array.h: + (Int8Array): + (WTF::Int8Array::create): + * wtf/Uint16Array.h: + (Uint16Array): + (WTF::Uint16Array::create): + * wtf/Uint32Array.h: + (Uint32Array): + (WTF::Uint32Array::create): + * wtf/Uint8Array.h: + (Uint8Array): + (WTF::Uint8Array::create): + * wtf/Uint8ClampedArray.h: + (Uint8ClampedArray): + (WTF::Uint8ClampedArray::create): + +2012-03-15 Myles Maxfield <mmaxfield@google.com> + + CopiedSpace::tryAllocateOversize assumes system page size + https://bugs.webkit.org/show_bug.cgi?id=80615 + + Reviewed by Geoffrey Garen. + + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::tryAllocateOversize): + * heap/CopiedSpace.h: + (CopiedSpace): + * heap/CopiedSpaceInlineMethods.h: + (JSC::CopiedSpace::oversizeBlockFor): + * wtf/BumpPointerAllocator.h: + (WTF::BumpPointerPool::create): + * wtf/StdLibExtras.h: + (WTF::roundUpToMultipleOf): + +2012-03-15 Mark Hahnenberg <mhahnenberg@apple.com> + + Fixing Windows build breakage + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-15 Patrick Gansterer <paroga@webkit.org> + + [EFL] Make zlib a general build requirement + https://bugs.webkit.org/show_bug.cgi?id=80153 + + Reviewed by Hajime Morita. + + After r109538 WebSocket module needs zlib to support deflate-frame extension. + + * wtf/Platform.h: + +2012-03-15 Benjamin Poulain <bpoulain@apple.com> + + NumericStrings should be inlined + https://bugs.webkit.org/show_bug.cgi?id=81183 + + Reviewed by Gavin Barraclough. + + NumericStrings is not always inlined. When it is not, the class is not faster + than using UString::number() directly. + + * runtime/NumericStrings.h: + (JSC::NumericStrings::add): + (JSC::NumericStrings::lookupSmallString): + +2012-03-15 Andras Becsi <andras.becsi@nokia.com> + + Fix ARM build after r110792. + + Unreviewed build fix. + + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::cacheFlush): + Remove superfluous curly brackets. + +2012-03-15 Gavin Barraclough <barraclough@apple.com> + + ARMv7: prefer vmov(gpr,gpr->double) over vmov(gpr->single) + https://bugs.webkit.org/show_bug.cgi?id=81256 + + Reviewed by Oliver Hunt. + + This is a 0.5% sunspider progression. + + * assembler/MacroAssemblerARMv7.h: + (JSC::MacroAssemblerARMv7::convertInt32ToDouble): + - switch which form of vmov we use. + +2012-03-15 YoungTaeck Song <youngtaeck.song@samsung.com> + + [EFL] Add OwnPtr specialization for Ecore_Timer. + https://bugs.webkit.org/show_bug.cgi?id=80119 + + Reviewed by Hajime Morita. + + Add an overload for deleteOwnedPtr(Ecore_Timer*) on EFL port. + + * wtf/OwnPtrCommon.h: + (WTF): + * wtf/efl/OwnPtrEfl.cpp: + (WTF::deleteOwnedPtr): + (WTF): + +2012-03-15 Hojong Han <hojong.han@samsung.com> + + Linux has madvise enough to support OSAllocator::commit/decommit + https://bugs.webkit.org/show_bug.cgi?id=80505 + + Reviewed by Geoffrey Garen. + + * wtf/OSAllocatorPosix.cpp: + (WTF::OSAllocator::reserveUncommitted): + (WTF::OSAllocator::commit): + (WTF::OSAllocator::decommit): + +2012-03-15 Steve Falkenburg <sfalken@apple.com> + + Windows build fix. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops: + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops: + * JavaScriptCore.vcproj/WTF/copy-files.cmd: + * JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops: + +2012-03-15 Steve Falkenburg <sfalken@apple.com> + + Windows build fix. + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj: + +2012-03-15 Kevin Ollivier <kevino@theolliviers.com> + + Move wx port to using export macros + https://bugs.webkit.org/show_bug.cgi?id=77279 + + Reviewed by Hajime Morita. + + * wscript: + * wtf/Platform.h: + +2012-03-14 Benjamin Poulain <bpoulain@apple.com> + + Avoid StringImpl::getData16SlowCase() when sorting array + https://bugs.webkit.org/show_bug.cgi?id=81070 + + Reviewed by Geoffrey Garen. + + The function codePointCompare() is used intensively when sorting strings. + This patch improves its performance by: + -Avoiding character conversion. + -Inlining the function. + + This makes Peacekeeper's arrayCombined test 30% faster. + + * wtf/text/StringImpl.cpp: + * wtf/text/StringImpl.h: + (WTF): + (WTF::codePointCompare): + (WTF::codePointCompare8): + (WTF::codePointCompare16): + (WTF::codePointCompare8To16): + +2012-03-14 Hojong Han <hojong.han@samsung.com> + + Fix memory allocation failed by fastmalloc + https://bugs.webkit.org/show_bug.cgi?id=79614 + + Reviewed by Geoffrey Garen. + + Memory allocation failed even if the heap grows successfully. + It is wrong to get the span only from the large list after the heap grows, + because new span could be added in the normal list. + + * wtf/FastMalloc.cpp: + (WTF::TCMalloc_PageHeap::New): + +2012-03-14 Hojong Han <hojong.han@samsung.com> + + Run cacheFlush page by page to assure of flushing all the requested ranges + https://bugs.webkit.org/show_bug.cgi?id=77712 + + Reviewed by Geoffrey Garen. + + Current MetaAllocator concept, always coalesces adjacent free spaces, + doesn't meet memory management of Linux kernel. + In a certain case Linux kernel doesn't regard contiguous virtual memory areas as one but two. + Therefore cacheFlush page by page guarantees a flush-requested range. + + * jit/ExecutableAllocator.h: + (JSC::ExecutableAllocator::cacheFlush): + +2012-03-14 Oliver Hunt <oliver@apple.com> + + Make ARMv7 work again + https://bugs.webkit.org/show_bug.cgi?id=81157 + + Reviewed by Geoffrey Garen. + + We were trying to use the ARMv7 dataRegister as a scratch register in a scenario + where we the ARMv7MacroAssembler would also try to use dataRegister for its own + nefarious purposes. + + * assembler/MacroAssembler.h: + (JSC::MacroAssembler::store32): + * assembler/MacroAssemblerARMv7.h: + (MacroAssemblerARMv7): + +2012-03-14 Mark Hahnenberg <mhahnenberg@apple.com> + + Heap::destroy leaks CopiedSpace + https://bugs.webkit.org/show_bug.cgi?id=81055 + + Reviewed by Geoffrey Garen. + + Added a destroy() function to CopiedSpace that moves all normal size + CopiedBlocks from the CopiedSpace to the Heap's list of free blocks + as well as deallocates all of the oversize blocks in the CopiedSpace. + This function is now called in Heap::destroy(). + + * heap/CopiedSpace.cpp: + (JSC::CopiedSpace::destroy): + (JSC): + * heap/CopiedSpace.h: + (CopiedSpace): + * heap/Heap.cpp: + (JSC::Heap::destroy): + +2012-03-14 Andrew Lo <anlo@rim.com> + + [BlackBerry] Implement REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR using AnimationFrameRateController + https://bugs.webkit.org/show_bug.cgi?id=81000 + + Enable WTF_USE_REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR for BlackBerry. + + Reviewed by Antonio Gomes. + + * wtf/Platform.h: + +2012-03-13 Filip Pizlo <fpizlo@apple.com> + + ValueToInt32 speculation will cause OSR exits even when it does not have to + https://bugs.webkit.org/show_bug.cgi?id=81068 + <rdar://problem/11043926> + + Reviewed by Anders Carlsson. + + Two related changes: + 1) ValueToInt32 will now always just defer to the non-speculative path, instead + of exiting, if it doesn't know what speculations to perform. + 2) ValueToInt32 will speculate boolean if it sees this to be profitable. + + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGNode.h: + (JSC::DFG::Node::shouldSpeculateBoolean): + (Node): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileValueToInt32): + +2012-03-13 Mark Hahnenberg <mhahnenberg@apple.com> + + More Windows build fixing + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-13 Mark Hahnenberg <mhahnenberg@apple.com> + + Windows build fix + + * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def: + +2012-03-13 Mark Hahnenberg <mhahnenberg@apple.com> + + Type conversion of exponential part failed + https://bugs.webkit.org/show_bug.cgi?id=80673 + + Reviewed by Geoffrey Garen. + + * parser/Lexer.cpp: + (JSC::::lex): + * runtime/JSGlobalObjectFunctions.cpp: + (JSC::parseInt): + (JSC): + (JSC::jsStrDecimalLiteral): Added another template argument that exposes whether or not + we accept trailing junk to clients of jsStrDecimalLiteral. Also added additional template + parameter for strtod to allow trailing spaces. + (JSC::toDouble): + (JSC::parseFloat): Accept trailing junk, as per the ECMA 262 spec (15.1.2.3). + * runtime/LiteralParser.cpp: + (JSC::::Lexer::lexNumber): + * tests/mozilla/expected.html: Update the expected page for run-javascriptcore-tests so that + we will run ecma/TypeConversion/9.3.1-3.js as a regression test now. + * wtf/dtoa.cpp: + (WTF): + (WTF::strtod): We also needed to sometimes accept trailing spaces to pass a few other tests that were + broken by changing the default allowance of trailing junk in jsStrDecimalLiteral. + * wtf/dtoa.h: + * wtf/dtoa/double-conversion.cc: When the AdvanceToNonspace function was lifted out of the + Chromium codebase, the person porting it only thought to check for spaces when skipping whitespace. + A few of our JSC tests check for other types of trailing whitespace, so I've added checks for those + here to cover those cases (horizontal tab, vertical tab, carriage return, form feed, and line feed). + * wtf/text/WTFString.cpp: + (WTF::toDoubleType): Disallow trailing spaces, as this breaks form input verification stuff. + +2012-03-13 Filip Pizlo <fpizlo@apple.com> + + Unreviewed, build fix since is_pod<> includes some header that I didn't know about. + Removing the assert for now. + + * dfg/DFGOperations.h: + * llint/LLIntSlowPaths.h: + +2012-03-13 Filip Pizlo <fpizlo@apple.com> + + Functions with C linkage should return POD types + https://bugs.webkit.org/show_bug.cgi?id=81061 + + Reviewed by Mark Rowe. + + * dfg/DFGOperations.h: + * llint/LLIntSlowPaths.h: + (LLInt): + (SlowPathReturnType): + (JSC::LLInt::encodeResult): + +2012-03-13 Filip Pizlo <fpizlo@apple.com> + + Loads from UInt32Arrays should not result in a double up-convert if it isn't necessary + https://bugs.webkit.org/show_bug.cgi?id=80979 + <rdar://problem/11036848> + + Reviewed by Oliver Hunt. + + Also improved DFG IR dumping to include type information in a somewhat more + intuitive way. + + * bytecode/PredictedType.cpp: + (JSC::predictionToAbbreviatedString): + (JSC): + * bytecode/PredictedType.h: + (JSC): + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::execute): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::compileUInt32ToNumber): + (JSC::DFG::SpeculativeJIT::compileGetByValOnIntTypedArray): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::forwardSpeculationCheck): + +2012-03-13 George Staikos <staikos@webkit.org> + + The callback is only used if SA_RESTART is defined. Compile it out + otherwise to avoid a warning. + https://bugs.webkit.org/show_bug.cgi?id=80926 + + Reviewed by Alexey Proskuryakov. + + * heap/MachineStackMarker.cpp: + (JSC): + +2012-03-13 Hojong Han <hojong.han@samsung.com> + + Dump the generated code for ARM_TRADITIONAL + https://bugs.webkit.org/show_bug.cgi?id=80975 + + Reviewed by Gavin Barraclough. + + * assembler/LinkBuffer.h: + (JSC::LinkBuffer::dumpCode): + +2012-03-13 Adam Barth <abarth@webkit.org> && Benjamin Poulain <bpoulain@apple.com> + + Always enable ENABLE(CLIENT_BASED_GEOLOCATION) + https://bugs.webkit.org/show_bug.cgi?id=78853 + + Reviewed by Adam Barth. + + * Configurations/FeatureDefines.xcconfig: + * wtf/Platform.h: + +2012-03-13 Kwonjin Jeong <gram@company100.net> + + Remove SlotVisitor::copy() method. + https://bugs.webkit.org/show_bug.cgi?id=80973 + + Reviewed by Geoffrey Garen. + + SlotVisitor::copy() method isn't called anywhere. + + * heap/MarkStack.cpp: Remove definition of SlotVisitor::copy() method. + * heap/SlotVisitor.h: Remove declaration of SlotVisitor::copy() method. + +2012-03-12 Hojong Han <hojong.han@samsung.com> + + Fix test cases for RegExp multiline + https://bugs.webkit.org/show_bug.cgi?id=80822 + + Reviewed by Gavin Barraclough. + + * tests/mozilla/js1_2/regexp/RegExp_multiline.js: + * tests/mozilla/js1_2/regexp/RegExp_multiline_as_array.js: + * tests/mozilla/js1_2/regexp/beginLine.js: + * tests/mozilla/js1_2/regexp/endLine.js: + +2012-03-12 Filip Pizlo <fpizlo@apple.com> + + Arithmetic use inference should be procedure-global and should run in tandem + with type propagation + https://bugs.webkit.org/show_bug.cgi?id=80819 + <rdar://problem/11034006> + + Reviewed by Gavin Barraclough. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * dfg/DFGArithNodeFlagsInferencePhase.cpp: Removed. + * dfg/DFGArithNodeFlagsInferencePhase.h: Removed. + * dfg/DFGDriver.cpp: + (JSC::DFG::compile): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::isNotNegZero): + (PredictionPropagationPhase): + (JSC::DFG::PredictionPropagationPhase::isNotZero): + (JSC::DFG::PredictionPropagationPhase::propagate): + (JSC::DFG::PredictionPropagationPhase::mergeDefaultArithFlags): + * dfg/DFGVariableAccessData.h: + (JSC::DFG::VariableAccessData::VariableAccessData): + (JSC::DFG::VariableAccessData::flags): + (VariableAccessData): + (JSC::DFG::VariableAccessData::mergeFlags): + +2012-03-12 Filip Pizlo <fpizlo@apple.com> + + Node::op and Node::flags should be private + https://bugs.webkit.org/show_bug.cgi?id=80824 + <rdar://problem/11033435> + + Reviewed by Gavin Barraclough. + + * CMakeLists.txt: + * GNUmakefile.list.am: + * JavaScriptCore.xcodeproj/project.pbxproj: + * Target.pri: + * dfg/DFGAbstractState.cpp: + (JSC::DFG::AbstractState::initialize): + (JSC::DFG::AbstractState::execute): + (JSC::DFG::AbstractState::mergeStateAtTail): + (JSC::DFG::AbstractState::mergeToSuccessors): + * dfg/DFGArithNodeFlagsInferencePhase.cpp: + (JSC::DFG::ArithNodeFlagsInferencePhase::propagate): + * dfg/DFGByteCodeParser.cpp: + (JSC::DFG::ByteCodeParser::injectLazyOperandPrediction): + (JSC::DFG::ByteCodeParser::getLocal): + (JSC::DFG::ByteCodeParser::getArgument): + (JSC::DFG::ByteCodeParser::flushArgument): + (JSC::DFG::ByteCodeParser::toInt32): + (JSC::DFG::ByteCodeParser::isJSConstant): + (JSC::DFG::ByteCodeParser::makeSafe): + (JSC::DFG::ByteCodeParser::makeDivSafe): + (JSC::DFG::ByteCodeParser::handleInlining): + (JSC::DFG::ByteCodeParser::parseBlock): + (JSC::DFG::ByteCodeParser::processPhiStack): + (JSC::DFG::ByteCodeParser::linkBlock): + * dfg/DFGCFAPhase.cpp: + (JSC::DFG::CFAPhase::performBlockCFA): + * dfg/DFGCSEPhase.cpp: + (JSC::DFG::CSEPhase::canonicalize): + (JSC::DFG::CSEPhase::endIndexForPureCSE): + (JSC::DFG::CSEPhase::pureCSE): + (JSC::DFG::CSEPhase::byValIsPure): + (JSC::DFG::CSEPhase::clobbersWorld): + (JSC::DFG::CSEPhase::impureCSE): + (JSC::DFG::CSEPhase::globalVarLoadElimination): + (JSC::DFG::CSEPhase::getByValLoadElimination): + (JSC::DFG::CSEPhase::checkFunctionElimination): + (JSC::DFG::CSEPhase::checkStructureLoadElimination): + (JSC::DFG::CSEPhase::getByOffsetLoadElimination): + (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination): + (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination): + (JSC::DFG::CSEPhase::getScopeChainLoadElimination): + (JSC::DFG::CSEPhase::performNodeCSE): + * dfg/DFGGraph.cpp: + (JSC::DFG::Graph::dump): + (DFG): + * dfg/DFGGraph.h: + (JSC::DFG::Graph::addShouldSpeculateInteger): + (JSC::DFG::Graph::negateShouldSpeculateInteger): + (JSC::DFG::Graph::methodOfGettingAValueProfileFor): + * dfg/DFGNode.cpp: Removed. + * dfg/DFGNode.h: + (DFG): + (JSC::DFG::Node::Node): + (Node): + (JSC::DFG::Node::op): + (JSC::DFG::Node::flags): + (JSC::DFG::Node::setOp): + (JSC::DFG::Node::setFlags): + (JSC::DFG::Node::mergeFlags): + (JSC::DFG::Node::filterFlags): + (JSC::DFG::Node::clearFlags): + (JSC::DFG::Node::setOpAndDefaultFlags): + (JSC::DFG::Node::mustGenerate): + (JSC::DFG::Node::isConstant): + (JSC::DFG::Node::isWeakConstant): + (JSC::DFG::Node::valueOfJSConstant): + (JSC::DFG::Node::hasVariableAccessData): + (JSC::DFG::Node::hasIdentifier): + (JSC::DFG::Node::resolveGlobalDataIndex): + (JSC::DFG::Node::hasArithNodeFlags): + (JSC::DFG::Node::arithNodeFlags): + (JSC::DFG::Node::setArithNodeFlag): + (JSC::DFG::Node::mergeArithNodeFlags): + (JSC::DFG::Node::hasConstantBuffer): + (JSC::DFG::Node::hasRegexpIndex): + (JSC::DFG::Node::hasVarNumber): + (JSC::DFG::Node::hasScopeChainDepth): + (JSC::DFG::Node::hasResult): + (JSC::DFG::Node::hasInt32Result): + (JSC::DFG::Node::hasNumberResult): + (JSC::DFG::Node::hasJSResult): + (JSC::DFG::Node::hasBooleanResult): + (JSC::DFG::Node::isJump): + (JSC::DFG::Node::isBranch): + (JSC::DFG::Node::isTerminal): + (JSC::DFG::Node::hasHeapPrediction): + (JSC::DFG::Node::hasFunctionCheckData): + (JSC::DFG::Node::hasStructureTransitionData): + (JSC::DFG::Node::hasStructureSet): + (JSC::DFG::Node::hasStorageAccessData): + (JSC::DFG::Node::hasFunctionDeclIndex): + (JSC::DFG::Node::hasFunctionExprIndex): + (JSC::DFG::Node::child1): + (JSC::DFG::Node::child2): + (JSC::DFG::Node::child3): + (JSC::DFG::Node::firstChild): + (JSC::DFG::Node::numChildren): + * dfg/DFGNodeFlags.cpp: Copied from Source/JavaScriptCore/dfg/DFGNode.cpp. + * dfg/DFGNodeFlags.h: Added. + (DFG): + (JSC::DFG::nodeUsedAsNumber): + (JSC::DFG::nodeCanTruncateInteger): + (JSC::DFG::nodeCanIgnoreNegativeZero): + (JSC::DFG::nodeMayOverflow): + (JSC::DFG::nodeCanSpeculateInteger): + * dfg/DFGNodeType.h: Added. + (DFG): + (JSC::DFG::defaultFlags): + * dfg/DFGPredictionPropagationPhase.cpp: + (JSC::DFG::PredictionPropagationPhase::propagate): + (JSC::DFG::PredictionPropagationPhase::vote): + (JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting): + (JSC::DFG::PredictionPropagationPhase::fixupNode): + * dfg/DFGRedundantPhiEliminationPhase.cpp: + (JSC::DFG::RedundantPhiEliminationPhase::run): + (JSC::DFG::RedundantPhiEliminationPhase::replacePhiChild): + (JSC::DFG::RedundantPhiEliminationPhase::updateBlockVariableInformation): + * dfg/DFGSpeculativeJIT.cpp: + (JSC::DFG::SpeculativeJIT::useChildren): + (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch): + (JSC::DFG::SpeculativeJIT::compileMovHint): + (JSC::DFG::SpeculativeJIT::compile): + (JSC::DFG::SpeculativeJIT::checkArgumentTypes): + (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor): + (JSC::DFG::SpeculativeJIT::compileUInt32ToNumber): + (JSC::DFG::SpeculativeJIT::compileAdd): + (JSC::DFG::SpeculativeJIT::compare): + * dfg/DFGSpeculativeJIT.h: + (JSC::DFG::SpeculativeJIT::detectPeepHoleBranch): + * dfg/DFGSpeculativeJIT32_64.cpp: + (JSC::DFG::SpeculativeJIT::emitCall): + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGSpeculativeJIT64.cpp: + (JSC::DFG::SpeculativeJIT::emitCall): + (JSC::DFG::SpeculativeJIT::compile): + * dfg/DFGVirtualRegisterAllocationPhase.cpp: + (JSC::DFG::VirtualRegisterAllocationPhase::run): + +2012-03-12 Laszlo Gombos <laszlo.1.gombos@nokia.com> + + Minor DataLog fixes + https://bugs.webkit.org/show_bug.cgi?id=80826 + + Reviewed by Andreas Kling. + + * bytecode/ExecutionCounter.cpp: + Do not include DataLog.h, it is not used. + + * jit/ExecutableAllocator.cpp: + Ditto. + + * wtf/DataLog.cpp: + (WTF::initializeLogFileOnce): + Add missing semi-colon to the code path where DATA_LOG_FILENAME is defined. + + * wtf/HashTable.cpp: + Include DataLog as it is used. + +2012-03-12 SangGyu Lee <sg5.lee@samsung.com> + + Integer overflow check code in arithmetic operation in classic interpreter + https://bugs.webkit.org/show_bug.cgi?id=80465 + + Reviewed by Gavin Barraclough. + + * interpreter/Interpreter.cpp: + (JSC::Interpreter::privateExecute): + +2012-03-12 Zeno Albisser <zeno@webkit.org> + + [Qt][Mac] Build fails after enabling LLINT when JIT is disabled (r109863) + https://bugs.webkit.org/show_bug.cgi?id=80827 + + Qt on Mac uses OS(DARWIN) as well, but we do not want to enable LLINT. + + Reviewed by Simon Hausmann. + + * wtf/Platform.h: + +2012-03-12 Simon Hausmann <simon.hausmann@nokia.com> + + Unreviewed prospective Qt/Mac build fix + + * runtime/JSGlobalData.cpp: use #USE(CF) instead of PLATFORM(MAC) to determine + whether to include CoreFoundation headers, used for JIT configuration in JSGlobalData + constructor. + 2012-03-12 Filip Pizlo <fpizlo@apple.com> All DFG nodes should have a mutable set of flags diff --git a/Source/JavaScriptCore/Configurations/Base.xcconfig b/Source/JavaScriptCore/Configurations/Base.xcconfig index e4d3617fd..96e9a356f 100644 --- a/Source/JavaScriptCore/Configurations/Base.xcconfig +++ b/Source/JavaScriptCore/Configurations/Base.xcconfig @@ -27,7 +27,7 @@ COMPILER_SPECIFIC_WARNING_CFLAGS = $(COMPILER_SPECIFIC_WARNING_CFLAGS_$(TARGET_G COMPILER_SPECIFIC_WARNING_CFLAGS_LLVM_COMPILER = -Wglobal-constructors -Wexit-time-destructors; CLANG_WARN_CXX0X_EXTENSIONS = NO; -DEBUG_INFORMATION_FORMAT = dwarf; +DEBUG_INFORMATION_FORMAT = dwarf-with-dsym; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DEBUGGING_SYMBOLS = default; GCC_DYNAMIC_NO_PIC = NO; diff --git a/Source/JavaScriptCore/Configurations/DebugRelease.xcconfig b/Source/JavaScriptCore/Configurations/DebugRelease.xcconfig index 2b2cff7e5..5fb574367 100644 --- a/Source/JavaScriptCore/Configurations/DebugRelease.xcconfig +++ b/Source/JavaScriptCore/Configurations/DebugRelease.xcconfig @@ -46,5 +46,6 @@ MACOSX_DEPLOYMENT_TARGET_macosx_1080 = 10.8; MACOSX_DEPLOYMENT_TARGET_macosx_1090 = 10.9; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = YES; +DEBUG_INFORMATION_FORMAT = dwarf; SECTORDER_FLAGS = ; diff --git a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig index 58a02f521..2dc145f36 100644 --- a/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig +++ b/Source/JavaScriptCore/Configurations/FeatureDefines.xcconfig @@ -31,24 +31,32 @@ // Set any ENABLE_FEATURE_NAME macro to an empty string to disable that feature. -ENABLE_BLOB = $(ENABLE_BLOB_$(REAL_PLATFORM_NAME)); -ENABLE_BLOB_macosx = ENABLE_BLOB; - -ENABLE_CLIENT_BASED_GEOLOCATION = $(ENABLE_CLIENT_BASED_GEOLOCATION_$(REAL_PLATFORM_NAME)); -ENABLE_CLIENT_BASED_GEOLOCATION_macosx = ENABLE_CLIENT_BASED_GEOLOCATION; - +ENABLE_3D_RENDERING = ENABLE_3D_RENDERING; +ENABLE_ACCELERATED_2D_CANVAS = ; +ENABLE_ANIMATION_API = ; +ENABLE_BLOB = ENABLE_BLOB; +ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING; +ENABLE_CSS_FILTERS = ENABLE_CSS_FILTERS; +ENABLE_CSS_GRID_LAYOUT = ENABLE_CSS_GRID_LAYOUT; ENABLE_DASHBOARD_SUPPORT = $(ENABLE_DASHBOARD_SUPPORT_$(REAL_PLATFORM_NAME)); ENABLE_DASHBOARD_SUPPORT_macosx = ENABLE_DASHBOARD_SUPPORT; - -ENABLE_DATALIST = $(ENABLE_DATALIST_$(REAL_PLATFORM_NAME)); -ENABLE_DATALIST_macosx = ENABLE_DATALIST; - +ENABLE_DATALIST = ; +ENABLE_DATA_TRANSFER_ITEMS = ; +ENABLE_DETAILS = ENABLE_DETAILS; +ENABLE_DEVICE_ORIENTATION = ; +ENABLE_DIRECTORY_UPLOAD = ; +ENABLE_FILE_SYSTEM = ; ENABLE_FILTERS = $(ENABLE_FILTERS_$(REAL_PLATFORM_NAME)); ENABLE_FILTERS_macosx = ENABLE_FILTERS; - +ENABLE_FULLSCREEN_API = ENABLE_FULLSCREEN_API; +ENABLE_GAMEPAD = ; +ENABLE_GEOLOCATION = ENABLE_GEOLOCATION; +ENABLE_HIGH_DPI_CANVAS = ENABLE_HIGH_DPI_CANVAS; ENABLE_ICONDATABASE = $(ENABLE_ICONDATABASE_$(REAL_PLATFORM_NAME)); ENABLE_ICONDATABASE_macosx = ENABLE_ICONDATABASE; - +ENABLE_INDEXED_DATABASE = ; +ENABLE_INPUT_SPEECH = ; +ENABLE_INPUT_TYPE_COLOR = ; ENABLE_INPUT_TYPE_DATE = $(ENABLE_INPUT_TYPE_DATE_$(REAL_PLATFORM_NAME)); ENABLE_INPUT_TYPE_DATE_iphoneos = ENABLE_INPUT_TYPE_DATE; ENABLE_INPUT_TYPE_DATE_iphonesimulator = ENABLE_INPUT_TYPE_DATE; @@ -67,31 +75,14 @@ ENABLE_INPUT_TYPE_TIME_iphonesimulator = ENABLE_INPUT_TYPE_TIME; ENABLE_INPUT_TYPE_WEEK = $(ENABLE_INPUT_TYPE_WEEK_$(REAL_PLATFORM_NAME)); ENABLE_INPUT_TYPE_WEEK_iphoneos = ENABLE_INPUT_TYPE_WEEK; ENABLE_INPUT_TYPE_WEEK_iphonesimulator = ENABLE_INPUT_TYPE_WEEK; - -ENABLE_SVG_DOM_OBJC_BINDINGS = $(ENABLE_SVG_DOM_OBJC_BINDINGS_$(REAL_PLATFORM_NAME)); -ENABLE_SVG_DOM_OBJC_BINDINGS_macosx = ENABLE_SVG_DOM_OBJC_BINDINGS; - -ENABLE_3D_RENDERING = ENABLE_3D_RENDERING; -ENABLE_ACCELERATED_2D_CANVAS = ; -ENABLE_ANIMATION_API = ; -ENABLE_CHANNEL_MESSAGING = ENABLE_CHANNEL_MESSAGING; -ENABLE_CSS_FILTERS = ENABLE_CSS_FILTERS; -ENABLE_CSS_GRID_LAYOUT = ENABLE_CSS_GRID_LAYOUT; -ENABLE_CSS_SHADERS = ENABLE_CSS_SHADERS; -ENABLE_DATA_TRANSFER_ITEMS = ; -ENABLE_DETAILS = ENABLE_DETAILS; -ENABLE_DEVICE_ORIENTATION = ; -ENABLE_DIRECTORY_UPLOAD = ; -ENABLE_FILE_SYSTEM = ; -ENABLE_FULLSCREEN_API = ENABLE_FULLSCREEN_API; -ENABLE_GAMEPAD = ; -ENABLE_GEOLOCATION = ENABLE_GEOLOCATION; -ENABLE_INDEXED_DATABASE = ; -ENABLE_INPUT_COLOR = ; -ENABLE_INPUT_SPEECH = ; ENABLE_JAVASCRIPT_DEBUGGER = ENABLE_JAVASCRIPT_DEBUGGER; -ENABLE_LEGACY_NOTIFICATIONS = ENABLE_LEGACY_NOTIFICATIONS; +ENABLE_LEGACY_NOTIFICATIONS = $(ENABLE_LEGACY_NOTIFICATIONS_$(REAL_PLATFORM_NAME)); +ENABLE_LEGACY_NOTIFICATIONS_macosx = $(ENABLE_LEGACY_NOTIFICATIONS_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)); +ENABLE_LEGACY_NOTIFICATIONS_macosx_1070 = ; +ENABLE_LEGACY_NOTIFICATIONS_macosx_1080 = ENABLE_LEGACY_NOTIFICATIONS; +ENABLE_LEGACY_NOTIFICATIONS_macosx_1090 = ENABLE_LEGACY_NOTIFICATIONS; ENABLE_LINK_PREFETCH = ; +ENABLE_LINK_PRERENDER = ; ENABLE_MATHML = ENABLE_MATHML; ENABLE_MEDIA_SOURCE = ; ENABLE_MEDIA_STATISTICS = ; @@ -99,13 +90,11 @@ ENABLE_METER_TAG = ENABLE_METER_TAG; ENABLE_MHTML = ; ENABLE_MICRODATA = ; ENABLE_MUTATION_OBSERVERS = ENABLE_MUTATION_OBSERVERS; - ENABLE_NOTIFICATIONS = $(ENABLE_NOTIFICATIONS_$(REAL_PLATFORM_NAME)); ENABLE_NOTIFICATIONS_macosx = $(ENABLE_NOTIFICATIONS_macosx_$(TARGET_MAC_OS_X_VERSION_MAJOR)); -ENABLE_NOTIFICATIONS_macosx_1070 = ENABLE_NOTIFICATIONS; +ENABLE_NOTIFICATIONS_macosx_1070 = ; ENABLE_NOTIFICATIONS_macosx_1080 = ENABLE_NOTIFICATIONS; ENABLE_NOTIFICATIONS_macosx_1090 = ENABLE_NOTIFICATIONS; - ENABLE_PAGE_VISIBILITY_API = ; ENABLE_PROGRESS_TAG = ENABLE_PROGRESS_TAG; ENABLE_QUOTA = ; @@ -117,14 +106,14 @@ ENABLE_SHARED_WORKERS = ENABLE_SHARED_WORKERS; ENABLE_SQL_DATABASE = ENABLE_SQL_DATABASE; ENABLE_STYLE_SCOPED = ; ENABLE_SVG = ENABLE_SVG; +ENABLE_SVG_DOM_OBJC_BINDINGS = $(ENABLE_SVG_DOM_OBJC_BINDINGS_$(REAL_PLATFORM_NAME)); +ENABLE_SVG_DOM_OBJC_BINDINGS_macosx = ENABLE_SVG_DOM_OBJC_BINDINGS; ENABLE_SVG_FONTS = ENABLE_SVG_FONTS; ENABLE_TEXT_NOTIFICATIONS_ONLY = ENABLE_TEXT_NOTIFICATIONS_ONLY; ENABLE_TOUCH_ICON_LOADING = ; ENABLE_VIDEO = ENABLE_VIDEO; - ENABLE_VIDEO_TRACK = $(ENABLE_VIDEO_TRACK_$(REAL_PLATFORM_NAME)); ENABLE_VIDEO_TRACK_macosx = ENABLE_VIDEO_TRACK; - ENABLE_WEBGL = ENABLE_WEBGL; ENABLE_WEB_AUDIO = ENABLE_WEB_AUDIO; ENABLE_WEB_SOCKETS = ENABLE_WEB_SOCKETS; @@ -132,4 +121,4 @@ ENABLE_WEB_TIMING = ; ENABLE_WORKERS = ENABLE_WORKERS; ENABLE_XSLT = ENABLE_XSLT; -FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CLIENT_BASED_GEOLOCATION) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_SHADERS) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_COLOR) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT); +FEATURE_DEFINES = $(ENABLE_3D_RENDERING) $(ENABLE_ACCELERATED_2D_CANVAS) $(ENABLE_ANIMATION_API) $(ENABLE_BLOB) $(ENABLE_CHANNEL_MESSAGING) $(ENABLE_CSS_FILTERS) $(ENABLE_CSS_GRID_LAYOUT) $(ENABLE_CSS_SHADERS) $(ENABLE_DASHBOARD_SUPPORT) $(ENABLE_DATALIST) $(ENABLE_DATA_TRANSFER_ITEMS) $(ENABLE_DETAILS) $(ENABLE_DEVICE_ORIENTATION) $(ENABLE_DIRECTORY_UPLOAD) $(ENABLE_FILE_SYSTEM) $(ENABLE_FILTERS) $(ENABLE_FULLSCREEN_API) $(ENABLE_GAMEPAD) $(ENABLE_GEOLOCATION) $(ENABLE_HIGH_DPI_CANVAS) $(ENABLE_ICONDATABASE) $(ENABLE_INDEXED_DATABASE) $(ENABLE_INPUT_TYPE_COLOR) $(ENABLE_INPUT_SPEECH) $(ENABLE_INPUT_TYPE_DATE) $(ENABLE_INPUT_TYPE_DATETIME) $(ENABLE_INPUT_TYPE_DATETIMELOCAL) $(ENABLE_INPUT_TYPE_MONTH) $(ENABLE_INPUT_TYPE_TIME) $(ENABLE_INPUT_TYPE_WEEK) $(ENABLE_JAVASCRIPT_DEBUGGER) $(ENABLE_LEGACY_NOTIFICATIONS) $(ENABLE_LINK_PREFETCH) $(ENABLE_LINK_PRERENDER) $(ENABLE_MATHML) $(ENABLE_MEDIA_SOURCE) $(ENABLE_MEDIA_STATISTICS) $(ENABLE_METER_TAG) $(ENABLE_MICRODATA) $(ENABLE_MUTATION_OBSERVERS) $(ENABLE_NOTIFICATIONS) $(ENABLE_PAGE_VISIBILITY_API) $(ENABLE_PROGRESS_TAG) $(ENABLE_QUOTA) $(ENABLE_REGISTER_PROTOCOL_HANDLER) $(ENABLE_REQUEST_ANIMATION_FRAME) $(ENABLE_SCRIPTED_SPEECH) $(ENABLE_SHADOW_DOM) $(ENABLE_SHARED_WORKERS) $(ENABLE_SQL_DATABASE) $(ENABLE_STYLE_SCOPED) $(ENABLE_SVG) $(ENABLE_SVG_DOM_OBJC_BINDINGS) $(ENABLE_SVG_FONTS) $(ENABLE_TEXT_NOTIFICATIONS_ONLY) $(ENABLE_TOUCH_ICON_LOADING) $(ENABLE_VIDEO) $(ENABLE_VIDEO_TRACK) $(ENABLE_WEBGL) $(ENABLE_WEB_AUDIO) $(ENABLE_WEB_SOCKETS) $(ENABLE_WEB_TIMING) $(ENABLE_WORKERS) $(ENABLE_XSLT); diff --git a/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig b/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig index fcef7550c..28ce60770 100644 --- a/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig +++ b/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig @@ -34,7 +34,7 @@ JSVALUE_MODEL_ppc64 = 64; JSVALUE_MODEL_x86_64 = 64; // Prevent C++ standard library operator new, delete and their related exception types from being exported as weak symbols. -OTHER_LDFLAGS_HIDE_SYMBOLS = -Wl,-unexported_symbol -Wl,__ZTISt9bad_alloc -Wl,-unexported_symbol -Wl,__ZTISt9exception -Wl,-unexported_symbol -Wl,__ZTSSt9bad_alloc -Wl,-unexported_symbol -Wl,__ZTSSt9exception -Wl,-unexported_symbol -Wl,__ZdlPvS_ -Wl,-unexported_symbol -Wl,__ZnwmPv; +OTHER_LDFLAGS_HIDE_SYMBOLS = -Wl,-unexported_symbol -Wl,__ZTISt9bad_alloc -Wl,-unexported_symbol -Wl,__ZTISt9exception -Wl,-unexported_symbol -Wl,__ZTSSt9bad_alloc -Wl,-unexported_symbol -Wl,__ZTSSt9exception -Wl,-unexported_symbol -Wl,__ZdlPvS_ -Wl,-unexported_symbol -Wl,__ZnwmPv -Wl,-all_load; OTHER_LDFLAGS_BASE = -lobjc -Wl,-Y,3 $(OTHER_LDFLAGS_HIDE_SYMBOLS); OTHER_LDFLAGS = $(OTHER_LDFLAGS_$(REAL_PLATFORM_NAME)); OTHER_LDFLAGS_iphoneos = $(OTHER_LDFLAGS_BASE); diff --git a/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig b/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig index 194c240fa..65f9ad5ac 100644 --- a/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig +++ b/Source/JavaScriptCore/Configurations/ToolExecutable.xcconfig @@ -1,4 +1,4 @@ -// Copyright (C) 2011 Apple Inc. All rights reserved. +// Copyright (C) 2011, 2012 Apple Inc. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions @@ -21,7 +21,10 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -INSTALL_PATH = $(JAVASCRIPTCORE_FRAMEWORKS_DIR)/JavaScriptCore.framework/Resources +INSTALL_PATH = $(INSTALL_PATH_$(REAL_PLATFORM_NAME)); +INSTALL_PATH_iphoneos = $(JAVASCRIPTCORE_FRAMEWORKS_DIR)/JavaScriptCore.framework/Resources; +INSTALL_PATH_iphonesimulator = $(INSTALL_PATH_iphoneos); +INSTALL_PATH_macosx = $(JAVASCRIPTCORE_FRAMEWORKS_DIR)/JavaScriptCore.framework/Versions/A/Resources; PRODUCT_NAME = $(TARGET_NAME); SKIP_INSTALL = $(SKIP_INSTALL_$(FORCE_TOOL_INSTALL)); diff --git a/Source/JavaScriptCore/Configurations/Version.xcconfig b/Source/JavaScriptCore/Configurations/Version.xcconfig index 7477f4b74..d7e12df22 100644 --- a/Source/JavaScriptCore/Configurations/Version.xcconfig +++ b/Source/JavaScriptCore/Configurations/Version.xcconfig @@ -22,7 +22,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. MAJOR_VERSION = 536; -MINOR_VERSION = 3; +MINOR_VERSION = 11; TINY_VERSION = 0; FULL_VERSION = $(MAJOR_VERSION).$(MINOR_VERSION); diff --git a/Source/JavaScriptCore/GNUmakefile.am b/Source/JavaScriptCore/GNUmakefile.am index 8d6d252d4..e84528763 100644 --- a/Source/JavaScriptCore/GNUmakefile.am +++ b/Source/JavaScriptCore/GNUmakefile.am @@ -62,12 +62,6 @@ javascriptcore_cppflags += \ -I$(srcdir)/Source/JavaScriptCore/profiler \ -I$(srcdir)/Source/JavaScriptCore/runtime \ -I$(srcdir)/Source/JavaScriptCore/tools \ - -I$(srcdir)/Source/JavaScriptCore/wtf \ - -I$(srcdir)/Source/JavaScriptCore/wtf \ - -I$(srcdir)/Source/JavaScriptCore/wtf/gobject \ - -I$(srcdir)/Source/JavaScriptCore/wtf/gtk \ - -I$(srcdir)/Source/JavaScriptCore/wtf/text \ - -I$(srcdir)/Source/JavaScriptCore/wtf/unicode \ -I$(srcdir)/Source/JavaScriptCore/yarr \ -I$(top_builddir)/DerivedSources/JavaScriptCore diff --git a/Source/JavaScriptCore/GNUmakefile.list.am b/Source/JavaScriptCore/GNUmakefile.list.am index 430b564c0..1b59db10c 100644 --- a/Source/JavaScriptCore/GNUmakefile.list.am +++ b/Source/JavaScriptCore/GNUmakefile.list.am @@ -117,11 +117,11 @@ javascriptcore_sources += \ Source/JavaScriptCore/bytecode/MethodOfGettingAValueProfile.h \ Source/JavaScriptCore/bytecode/Opcode.cpp \ Source/JavaScriptCore/bytecode/Opcode.h \ + Source/JavaScriptCore/bytecode/Operands.h \ Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.cpp \ Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h \ Source/JavaScriptCore/bytecode/PredictedType.cpp \ Source/JavaScriptCore/bytecode/PredictedType.h \ - Source/JavaScriptCore/bytecode/PredictionTracker.h \ Source/JavaScriptCore/bytecode/PutByIdStatus.cpp \ Source/JavaScriptCore/bytecode/PutByIdStatus.h \ Source/JavaScriptCore/bytecode/PutKind.h \ @@ -142,8 +142,7 @@ javascriptcore_sources += \ Source/JavaScriptCore/dfg/DFGAbstractState.cpp \ Source/JavaScriptCore/dfg/DFGAbstractState.h \ Source/JavaScriptCore/dfg/DFGAbstractValue.h \ - Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.cpp \ - Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.h \ + Source/JavaScriptCore/dfg/DFGArgumentPosition.h \ Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp \ Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h \ Source/JavaScriptCore/dfg/DFGBasicBlock.h \ @@ -160,20 +159,25 @@ javascriptcore_sources += \ Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h \ Source/JavaScriptCore/dfg/DFGCSEPhase.cpp \ Source/JavaScriptCore/dfg/DFGCSEPhase.h \ + Source/JavaScriptCore/dfg/DFGDoubleFormatState.h \ Source/JavaScriptCore/dfg/DFGDriver.cpp \ Source/JavaScriptCore/dfg/DFGDriver.h \ Source/JavaScriptCore/dfg/DFGFPRInfo.h \ + Source/JavaScriptCore/dfg/DFGFixupPhase.cpp \ + Source/JavaScriptCore/dfg/DFGFixupPhase.h \ Source/JavaScriptCore/dfg/DFGGenerationInfo.h \ Source/JavaScriptCore/dfg/DFGGPRInfo.h \ Source/JavaScriptCore/dfg/DFGGraph.cpp \ Source/JavaScriptCore/dfg/DFGGraph.h \ + Source/JavaScriptCore/dfg/DFGInsertionSet.h \ Source/JavaScriptCore/dfg/DFGJITCompiler.cpp \ Source/JavaScriptCore/dfg/DFGJITCompiler.h \ - Source/JavaScriptCore/dfg/DFGNode.cpp \ Source/JavaScriptCore/dfg/DFGNode.h \ - Source/JavaScriptCore/dfg/DFGNodeReferenceBlob.h \ - Source/JavaScriptCore/dfg/DFGNodeUse.h \ - Source/JavaScriptCore/dfg/DFGOperands.h \ + Source/JavaScriptCore/dfg/DFGNodeFlags.cpp \ + Source/JavaScriptCore/dfg/DFGNodeFlags.h \ + Source/JavaScriptCore/dfg/DFGAdjacencyList.h \ + Source/JavaScriptCore/dfg/DFGNodeType.h \ + Source/JavaScriptCore/dfg/DFGEdge.h \ Source/JavaScriptCore/dfg/DFGOperations.cpp \ Source/JavaScriptCore/dfg/DFGOperations.h \ Source/JavaScriptCore/dfg/DFGOSREntry.cpp \ @@ -215,13 +219,15 @@ javascriptcore_sources += \ Source/JavaScriptCore/heap/DFGCodeBlocks.h \ Source/JavaScriptCore/heap/GCAssertions.h \ Source/JavaScriptCore/heap/Handle.h \ - Source/JavaScriptCore/heap/HandleHeap.cpp \ - Source/JavaScriptCore/heap/HandleHeap.h \ + Source/JavaScriptCore/heap/HandleSet.cpp \ + Source/JavaScriptCore/heap/HandleSet.h \ Source/JavaScriptCore/heap/HeapBlock.h \ Source/JavaScriptCore/heap/SlotVisitor.h \ Source/JavaScriptCore/heap/HandleStack.cpp \ Source/JavaScriptCore/heap/HandleStack.h \ Source/JavaScriptCore/heap/HandleTypes.h \ + Source/JavaScriptCore/heap/BlockAllocator.cpp \ + Source/JavaScriptCore/heap/BlockAllocator.h \ Source/JavaScriptCore/heap/Heap.cpp \ Source/JavaScriptCore/heap/Heap.h \ Source/JavaScriptCore/heap/ListableHandler.h \ @@ -247,6 +253,14 @@ javascriptcore_sources += \ Source/JavaScriptCore/heap/VTableSpectrum.cpp \ Source/JavaScriptCore/heap/VTableSpectrum.h \ Source/JavaScriptCore/heap/Weak.h \ + Source/JavaScriptCore/heap/WeakBlock.cpp \ + Source/JavaScriptCore/heap/WeakBlock.h \ + Source/JavaScriptCore/heap/WeakHandleOwner.cpp \ + Source/JavaScriptCore/heap/WeakHandleOwner.h \ + Source/JavaScriptCore/heap/WeakImpl.h \ + Source/JavaScriptCore/heap/WeakSet.cpp \ + Source/JavaScriptCore/heap/WeakSet.h \ + Source/JavaScriptCore/heap/WeakSetInlines.h \ Source/JavaScriptCore/heap/WeakReferenceHarvester.h \ Source/JavaScriptCore/heap/WriteBarrierSupport.cpp \ Source/JavaScriptCore/heap/WriteBarrierSupport.h \ @@ -439,8 +453,6 @@ javascriptcore_sources += \ Source/JavaScriptCore/runtime/JSAPIValueWrapper.h \ Source/JavaScriptCore/runtime/JSArray.cpp \ Source/JavaScriptCore/runtime/JSArray.h \ - Source/JavaScriptCore/runtime/JSByteArray.cpp \ - Source/JavaScriptCore/runtime/JSByteArray.h \ Source/JavaScriptCore/runtime/JSCell.cpp \ Source/JavaScriptCore/runtime/JSCell.h \ Source/JavaScriptCore/runtime/JSDateMath.cpp \ @@ -471,6 +483,8 @@ javascriptcore_sources += \ Source/JavaScriptCore/runtime/JSStaticScopeObject.cpp \ Source/JavaScriptCore/runtime/JSStaticScopeObject.h \ Source/JavaScriptCore/runtime/JSStringBuilder.h \ + Source/JavaScriptCore/runtime/JSStringJoiner.cpp \ + Source/JavaScriptCore/runtime/JSStringJoiner.h \ Source/JavaScriptCore/runtime/JSString.cpp \ Source/JavaScriptCore/runtime/JSString.h \ Source/JavaScriptCore/runtime/JSType.h \ @@ -486,6 +500,7 @@ javascriptcore_sources += \ Source/JavaScriptCore/runtime/LiteralParser.h \ Source/JavaScriptCore/runtime/Lookup.cpp \ Source/JavaScriptCore/runtime/Lookup.h \ + Source/JavaScriptCore/runtime/MatchResult.h \ Source/JavaScriptCore/runtime/MathObject.cpp \ Source/JavaScriptCore/runtime/MathObject.h \ Source/JavaScriptCore/runtime/MemoryStatistics.h \ @@ -524,7 +539,10 @@ javascriptcore_sources += \ Source/JavaScriptCore/runtime/RegExp.cpp \ Source/JavaScriptCore/runtime/RegExp.h \ Source/JavaScriptCore/runtime/RegExpKey.h \ + Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp \ Source/JavaScriptCore/runtime/RegExpMatchesArray.h \ + Source/JavaScriptCore/runtime/RegExpCachedResult.cpp \ + Source/JavaScriptCore/runtime/RegExpCachedResult.h \ Source/JavaScriptCore/runtime/RegExpObject.cpp \ Source/JavaScriptCore/runtime/RegExpObject.h \ Source/JavaScriptCore/runtime/RegExpPrototype.cpp \ @@ -571,224 +589,9 @@ javascriptcore_sources += \ Source/JavaScriptCore/tools/CodeProfiling.h \ Source/JavaScriptCore/tools/ProfileTreeNode.h \ Source/JavaScriptCore/tools/TieredMMapArray.h \ - Source/JavaScriptCore/wtf/Alignment.h \ - Source/JavaScriptCore/wtf/AlwaysInline.h \ - Source/JavaScriptCore/wtf/ArrayBuffer.cpp \ - Source/JavaScriptCore/wtf/ArrayBuffer.h \ - Source/JavaScriptCore/wtf/ArrayBufferView.cpp \ - Source/JavaScriptCore/wtf/ArrayBufferView.h \ - Source/JavaScriptCore/wtf/ASCIICType.h \ - Source/JavaScriptCore/wtf/Assertions.cpp \ - Source/JavaScriptCore/wtf/Assertions.h \ - Source/JavaScriptCore/wtf/Atomics.h \ - Source/JavaScriptCore/wtf/AVLTree.h \ - Source/JavaScriptCore/wtf/Bitmap.h \ - Source/JavaScriptCore/wtf/BitVector.cpp \ - Source/JavaScriptCore/wtf/BitVector.h \ - Source/JavaScriptCore/wtf/BlockStack.h \ - Source/JavaScriptCore/wtf/BloomFilter.h \ - Source/JavaScriptCore/wtf/BoundsCheckedPointer.h \ - Source/JavaScriptCore/wtf/BumpPointerAllocator.h \ - Source/JavaScriptCore/wtf/ByteArray.cpp \ - Source/JavaScriptCore/wtf/ByteArray.h \ - Source/JavaScriptCore/wtf/CheckedArithmetic.h \ - Source/JavaScriptCore/wtf/CheckedBoolean.h \ - Source/JavaScriptCore/wtf/RefCountedArray.h \ - Source/JavaScriptCore/wtf/Compiler.h \ - Source/JavaScriptCore/wtf/Complex.h \ - Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.cpp \ - Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h \ - Source/JavaScriptCore/wtf/CurrentTime.cpp \ - Source/JavaScriptCore/wtf/CurrentTime.h \ - Source/JavaScriptCore/wtf/DateMath.cpp \ - Source/JavaScriptCore/wtf/DateMath.h \ - Source/JavaScriptCore/wtf/DataLog.cpp \ - Source/JavaScriptCore/wtf/DataLog.h \ - Source/JavaScriptCore/wtf/DecimalNumber.cpp \ - Source/JavaScriptCore/wtf/DecimalNumber.h \ - Source/JavaScriptCore/wtf/Decoder.h \ - Source/JavaScriptCore/wtf/Deque.h \ - Source/JavaScriptCore/wtf/DisallowCType.h \ - Source/JavaScriptCore/wtf/DoublyLinkedList.h \ - Source/JavaScriptCore/wtf/ExportMacros.h \ - Source/JavaScriptCore/wtf/dtoa.cpp \ - Source/JavaScriptCore/wtf/dtoa.h \ - Source/JavaScriptCore/wtf/dtoa/bignum-dtoa.cc \ - Source/JavaScriptCore/wtf/dtoa/bignum-dtoa.h \ - Source/JavaScriptCore/wtf/dtoa/bignum.cc \ - Source/JavaScriptCore/wtf/dtoa/bignum.h \ - Source/JavaScriptCore/wtf/dtoa/cached-powers.cc \ - Source/JavaScriptCore/wtf/dtoa/cached-powers.h \ - Source/JavaScriptCore/wtf/dtoa/diy-fp.cc \ - Source/JavaScriptCore/wtf/dtoa/diy-fp.h \ - Source/JavaScriptCore/wtf/dtoa/double-conversion.cc \ - Source/JavaScriptCore/wtf/dtoa/double-conversion.h \ - Source/JavaScriptCore/wtf/dtoa/double.h \ - Source/JavaScriptCore/wtf/dtoa/fast-dtoa.cc \ - Source/JavaScriptCore/wtf/dtoa/fast-dtoa.h \ - Source/JavaScriptCore/wtf/dtoa/fixed-dtoa.cc \ - Source/JavaScriptCore/wtf/dtoa/fixed-dtoa.h \ - Source/JavaScriptCore/wtf/dtoa/strtod.cc \ - Source/JavaScriptCore/wtf/dtoa/strtod.h \ - Source/JavaScriptCore/wtf/dtoa/utils.h \ - Source/JavaScriptCore/wtf/DynamicAnnotations.cpp \ - Source/JavaScriptCore/wtf/DynamicAnnotations.h \ - Source/JavaScriptCore/wtf/Encoder.h \ - Source/JavaScriptCore/wtf/FastAllocBase.h \ - Source/JavaScriptCore/wtf/FastMalloc.cpp \ - Source/JavaScriptCore/wtf/FastMalloc.h \ - Source/JavaScriptCore/wtf/FixedArray.h \ - Source/JavaScriptCore/wtf/Float32Array.h \ - Source/JavaScriptCore/wtf/Float64Array.h \ - Source/JavaScriptCore/wtf/Forward.h \ - Source/JavaScriptCore/wtf/Functional.h \ - Source/JavaScriptCore/wtf/GetPtr.h \ - Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp \ - Source/JavaScriptCore/wtf/gobject/GOwnPtr.h \ - Source/JavaScriptCore/wtf/gobject/GRefPtr.cpp \ - Source/JavaScriptCore/wtf/gobject/GRefPtr.h \ - Source/JavaScriptCore/wtf/gobject/GTypedefs.h \ - Source/JavaScriptCore/wtf/gobject/GlibUtilities.cpp \ - Source/JavaScriptCore/wtf/gobject/GlibUtilities.h \ - Source/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp \ - Source/JavaScriptCore/wtf/HashCountedSet.h \ - Source/JavaScriptCore/wtf/HashFunctions.h \ - Source/JavaScriptCore/wtf/HashIterators.h \ - Source/JavaScriptCore/wtf/HashMap.h \ - Source/JavaScriptCore/wtf/HashSet.h \ - Source/JavaScriptCore/wtf/HashTable.cpp \ - Source/JavaScriptCore/wtf/HashTable.h \ - Source/JavaScriptCore/wtf/HashTraits.h \ - Source/JavaScriptCore/wtf/HexNumber.h \ - Source/JavaScriptCore/wtf/InlineASM.h \ - Source/JavaScriptCore/wtf/Int16Array.h \ - Source/JavaScriptCore/wtf/Int32Array.h \ - Source/JavaScriptCore/wtf/Int8Array.h \ - Source/JavaScriptCore/wtf/IntegralTypedArrayBase.h \ - Source/JavaScriptCore/wtf/ListHashSet.h \ - Source/JavaScriptCore/wtf/ListRefPtr.h \ - Source/JavaScriptCore/wtf/Locker.h \ - Source/JavaScriptCore/wtf/MainThread.cpp \ - Source/JavaScriptCore/wtf/MainThread.h \ - Source/JavaScriptCore/wtf/MallocZoneSupport.h \ - Source/JavaScriptCore/wtf/MathExtras.h \ - Source/JavaScriptCore/wtf/MD5.cpp \ - Source/JavaScriptCore/wtf/MD5.h \ - Source/JavaScriptCore/wtf/MessageQueue.h \ - Source/JavaScriptCore/wtf/MetaAllocator.cpp \ - Source/JavaScriptCore/wtf/MetaAllocator.h \ - Source/JavaScriptCore/wtf/MetaAllocatorHandle.h \ - Source/JavaScriptCore/wtf/Noncopyable.h \ - Source/JavaScriptCore/wtf/NonCopyingSort.h \ - Source/JavaScriptCore/wtf/NotFound.h \ - Source/JavaScriptCore/wtf/NullPtr.h \ - Source/JavaScriptCore/wtf/NumberOfCores.cpp \ - Source/JavaScriptCore/wtf/NumberOfCores.h \ - Source/JavaScriptCore/wtf/OSAllocator.h \ - Source/JavaScriptCore/wtf/OSRandomSource.cpp \ - Source/JavaScriptCore/wtf/OSRandomSource.h \ - Source/JavaScriptCore/wtf/OwnArrayPtr.h \ - Source/JavaScriptCore/wtf/OwnPtr.h \ - Source/JavaScriptCore/wtf/OwnPtrCommon.h \ - Source/JavaScriptCore/wtf/PackedIntVector.h \ - Source/JavaScriptCore/wtf/PageAllocation.h \ - Source/JavaScriptCore/wtf/PageAllocationAligned.cpp \ - Source/JavaScriptCore/wtf/PageAllocationAligned.h \ - Source/JavaScriptCore/wtf/PageBlock.cpp \ - Source/JavaScriptCore/wtf/PageBlock.h \ - Source/JavaScriptCore/wtf/PageReservation.h \ - Source/JavaScriptCore/wtf/ParallelJobs.h \ - Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp \ - Source/JavaScriptCore/wtf/ParallelJobsGeneric.h \ - Source/JavaScriptCore/wtf/ParallelJobsLibdispatch.h \ - Source/JavaScriptCore/wtf/ParallelJobsOpenMP.h \ - Source/JavaScriptCore/wtf/PassOwnArrayPtr.h \ - Source/JavaScriptCore/wtf/PassOwnPtr.h \ - Source/JavaScriptCore/wtf/PassRefPtr.h \ - Source/JavaScriptCore/wtf/PassTraits.h \ - Source/JavaScriptCore/wtf/Platform.h \ - Source/JavaScriptCore/wtf/PossiblyNull.h \ - Source/JavaScriptCore/wtf/RandomNumber.cpp \ - Source/JavaScriptCore/wtf/RandomNumber.h \ - Source/JavaScriptCore/wtf/RandomNumberSeed.h \ - Source/JavaScriptCore/wtf/RedBlackTree.h \ - Source/JavaScriptCore/wtf/RefCounted.h \ - Source/JavaScriptCore/wtf/RefCountedLeakCounter.cpp \ - Source/JavaScriptCore/wtf/RefCountedLeakCounter.h \ - Source/JavaScriptCore/wtf/RefPtr.h \ - Source/JavaScriptCore/wtf/RefPtrHashMap.h \ - Source/JavaScriptCore/wtf/RetainPtr.h \ - Source/JavaScriptCore/wtf/SegmentedVector.h \ - Source/JavaScriptCore/wtf/SentinelLinkedList.h \ - Source/JavaScriptCore/wtf/SHA1.cpp \ - Source/JavaScriptCore/wtf/SHA1.h \ - Source/JavaScriptCore/wtf/SimpleStats.h \ - Source/JavaScriptCore/wtf/SinglyLinkedList.h \ - Source/JavaScriptCore/wtf/Spectrum.h \ - Source/JavaScriptCore/wtf/StackBounds.cpp \ - Source/JavaScriptCore/wtf/StackBounds.h \ - Source/JavaScriptCore/wtf/StaticConstructors.h \ - Source/JavaScriptCore/wtf/StdLibExtras.h \ - Source/JavaScriptCore/wtf/StringExtras.h \ - Source/JavaScriptCore/wtf/StringHasher.h \ - Source/JavaScriptCore/wtf/TCPackedCache.h \ - Source/JavaScriptCore/wtf/TCPageMap.h \ - Source/JavaScriptCore/wtf/TCSpinLock.h \ - Source/JavaScriptCore/wtf/TCSystemAlloc.cpp \ - Source/JavaScriptCore/wtf/TCSystemAlloc.h \ - Source/JavaScriptCore/wtf/TemporaryChange.h \ - Source/JavaScriptCore/wtf/text/ASCIIFastPath.h \ - Source/JavaScriptCore/wtf/text/AtomicString.cpp \ - Source/JavaScriptCore/wtf/text/AtomicString.h \ - Source/JavaScriptCore/wtf/text/AtomicStringHash.h \ - Source/JavaScriptCore/wtf/text/AtomicStringImpl.h \ - Source/JavaScriptCore/wtf/text/CString.cpp \ - Source/JavaScriptCore/wtf/text/CString.h \ - Source/JavaScriptCore/wtf/text/StringBuffer.h \ - Source/JavaScriptCore/wtf/text/StringBuilder.cpp \ - Source/JavaScriptCore/wtf/text/StringBuilder.h \ - Source/JavaScriptCore/wtf/text/StringConcatenate.h \ - Source/JavaScriptCore/wtf/text/StringHash.h \ - Source/JavaScriptCore/wtf/text/StringImpl.cpp \ - Source/JavaScriptCore/wtf/text/StringImpl.h \ - Source/JavaScriptCore/wtf/text/StringOperators.h \ - Source/JavaScriptCore/wtf/text/StringStatics.cpp \ - Source/JavaScriptCore/wtf/text/TextPosition.h \ - Source/JavaScriptCore/wtf/text/WTFString.cpp \ - Source/JavaScriptCore/wtf/text/WTFString.h \ - Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp \ - Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h \ - Source/JavaScriptCore/wtf/Threading.cpp \ - Source/JavaScriptCore/wtf/Threading.h \ - Source/JavaScriptCore/wtf/ThreadingPrimitives.h \ - Source/JavaScriptCore/wtf/ThreadingPthreads.cpp \ - Source/JavaScriptCore/wtf/ThreadRestrictionVerifier.h \ - Source/JavaScriptCore/wtf/threads/BinarySemaphore.cpp \ - Source/JavaScriptCore/wtf/threads/BinarySemaphore.h \ - Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h \ - Source/JavaScriptCore/wtf/ThreadSpecific.h \ - Source/JavaScriptCore/wtf/TypedArrayBase.h \ - Source/JavaScriptCore/wtf/TypeTraits.cpp \ - Source/JavaScriptCore/wtf/TypeTraits.h \ - Source/JavaScriptCore/wtf/Uint16Array.h \ - Source/JavaScriptCore/wtf/Uint32Array.h \ - Source/JavaScriptCore/wtf/Uint8Array.h \ - Source/JavaScriptCore/wtf/Uint8ClampedArray.h \ - Source/JavaScriptCore/wtf/unicode/CharacterNames.h \ - Source/JavaScriptCore/wtf/unicode/Collator.h \ - Source/JavaScriptCore/wtf/unicode/CollatorDefault.cpp \ - Source/JavaScriptCore/wtf/unicode/Unicode.h \ - Source/JavaScriptCore/wtf/unicode/UTF8.cpp \ - Source/JavaScriptCore/wtf/unicode/UTF8.h \ - Source/JavaScriptCore/wtf/UnionFind.h \ - Source/JavaScriptCore/wtf/UnusedParam.h \ - Source/JavaScriptCore/wtf/ValueCheck.h \ - Source/JavaScriptCore/wtf/Vector.h \ - Source/JavaScriptCore/wtf/VectorTraits.h \ - Source/JavaScriptCore/wtf/VMTags.h \ - Source/JavaScriptCore/wtf/WTFThreadData.cpp \ - Source/JavaScriptCore/wtf/WTFThreadData.h \ Source/JavaScriptCore/yarr/Yarr.h \ + Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.cpp \ + Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.h \ Source/JavaScriptCore/yarr/YarrInterpreter.cpp \ Source/JavaScriptCore/yarr/YarrInterpreter.h \ Source/JavaScriptCore/yarr/YarrJIT.cpp \ @@ -800,37 +603,11 @@ javascriptcore_sources += \ Source/JavaScriptCore/yarr/YarrSyntaxChecker.h if TARGET_WIN32 -javascriptcore_sources += \ - Source/JavaScriptCore/wtf/OSAllocatorWin.cpp \ - Source/JavaScriptCore/wtf/ThreadFunctionInvocation.h \ - Source/JavaScriptCore/wtf/ThreadingWin.cpp \ - Source/JavaScriptCore/wtf/ThreadSpecificWin.cpp else javascriptcore_sources += \ - Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp \ - Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp + Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp endif -# ---- -# icu unicode backend -# ---- -if USE_ICU_UNICODE -javascriptcore_sources += \ - Source/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp \ - Source/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h -endif # USE_ICU_UNICODE - -# ---- -# glib unicode backend -# ---- -if USE_GLIB_UNICODE -javascriptcore_sources += \ - Source/JavaScriptCore/wtf/unicode/UnicodeMacrosFromICU.h \ - Source/JavaScriptCore/wtf/unicode/ScriptCodesFromICU.h \ - Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h \ - Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp -endif # USE_GLIB_UNICODE - # minidom Programs_minidom_SOURCES = \ Source/JavaScriptCore/API/tests/JSNode.c \ diff --git a/Source/JavaScriptCore/JSCTypedArrayStubs.h b/Source/JavaScriptCore/JSCTypedArrayStubs.h index e3546ee65..ca4030186 100644 --- a/Source/JavaScriptCore/JSCTypedArrayStubs.h +++ b/Source/JavaScriptCore/JSCTypedArrayStubs.h @@ -26,19 +26,21 @@ #ifndef JSCTypedArrayStubs_h #define JSCTypedArrayStubs_h -#include "Float32Array.h" -#include "Float64Array.h" -#include "Int16Array.h" -#include "Int32Array.h" -#include "Int8Array.h" #include "JSObject.h" #include "ObjectPrototype.h" -#include "Uint16Array.h" -#include "Uint32Array.h" -#include "Uint8Array.h" +#include <wtf/Float32Array.h> +#include <wtf/Float64Array.h> +#include <wtf/Forward.h> +#include <wtf/Int16Array.h> +#include <wtf/Int32Array.h> +#include <wtf/Int8Array.h> +#include <wtf/Uint16Array.h> +#include <wtf/Uint32Array.h> +#include <wtf/Uint8Array.h> +#include <wtf/Uint8ClampedArray.h> namespace JSC { - + #define TYPED_ARRAY(name, type) \ class JS##name##Array : public JSNonFinalObject { \ public: \ @@ -54,7 +56,7 @@ public: \ static bool getOwnPropertyDescriptor(JSC::JSObject*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertyDescriptor&);\ static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);\ static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&);\ - static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue);\ + static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool);\ static const JSC::ClassInfo s_info;\ \ static JSC::Structure* createStructure(JSC::JSGlobalData& globalData, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)\ @@ -186,8 +188,8 @@ static EncodedJSValue JSC_HOST_CALL constructJS##name##Array(ExecState* callFram return JSValue::encode(JS##name##Array::create(structure, callFrame->lexicalGlobalObject(), name##Array::create(length)));\ } -#if ENABLE(COMMANDLINE_TYPEDARRAYS) TYPED_ARRAY(Uint8, uint8_t); +TYPED_ARRAY(Uint8Clamped, uint8_t); TYPED_ARRAY(Uint16, uint16_t); TYPED_ARRAY(Uint32, uint32_t); TYPED_ARRAY(Int8, int8_t); @@ -195,7 +197,6 @@ TYPED_ARRAY(Int16, int16_t); TYPED_ARRAY(Int32, int32_t); TYPED_ARRAY(Float32, float); TYPED_ARRAY(Float64, double); -#endif } diff --git a/Source/JavaScriptCore/JavaScriptCore.gyp/.gitignore b/Source/JavaScriptCore/JavaScriptCore.gyp/.gitignore new file mode 100644 index 000000000..9b06f58bf --- /dev/null +++ b/Source/JavaScriptCore/JavaScriptCore.gyp/.gitignore @@ -0,0 +1,5 @@ +*.Makefile +*.mk +*.sln +*.vcproj* +JavaScriptCore.xcodeproj diff --git a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp index 34b4e08e5..f0de2f073 100644 --- a/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp +++ b/Source/JavaScriptCore/JavaScriptCore.gyp/JavaScriptCore.gyp @@ -57,146 +57,10 @@ ], 'targets': [ { - # This target sets up defines and includes that are required by WTF and - # its dependents. - 'target_name': 'wtf_config', - 'type': 'none', - 'direct_dependent_settings': { - 'defines': [ - # Import features_defines from features.gypi - '<@(feature_defines)', - - # Turns on #if PLATFORM(CHROMIUM) - 'BUILDING_CHROMIUM__=1', - # Controls wtf/FastMalloc - # FIXME: consider moving into config.h - 'USE_SYSTEM_MALLOC=1', - ], - 'conditions': [ - ['OS=="win"', { - 'defines': [ - '__STD_C', - '_CRT_SECURE_NO_DEPRECATE', - '_SCL_SECURE_NO_DEPRECATE', - 'CRASH=__debugbreak', - ], - 'include_dirs': [ - '../os-win32', - ], - }], - ['OS=="mac"', { - 'defines': [ - # Use USE_NEW_THEME on Mac. - 'WTF_USE_NEW_THEME=1', - ], - }], - ['os_posix == 1 and OS != "mac"', { - 'defines': [ - 'WTF_USE_PTHREADS=1', - ], - }], - ], - } - }, - { - 'target_name': 'wtf', - 'type': 'static_library', - 'variables': { 'optimize': 'max' }, - 'dependencies': [ - 'wtf_config', - '<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n', - '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc', - ], - 'include_dirs': [ - '../', - '../wtf', - '../wtf/unicode', - ], - 'sources': [ - '<@(javascriptcore_publicheader_files)', - '<@(javascriptcore_privateheader_files)', - '<@(javascriptcore_files)', - ], - 'sources/': [ - # First exclude everything ... - ['exclude', '../'], - # ... Then include what we want. - ['include', '../wtf/'], - # FIXME: This is clearly not sustainable. - ['exclude', '../wtf/efl'], - ['exclude', '../wtf/gobject'], - ['exclude', '../wtf/gtk'], - ['exclude', '../wtf/mac'], - ['exclude', '../wtf/qt'], - ['exclude', '../wtf/url'], - ['exclude', '../wtf/wince'], - ['exclude', '../wtf/wx'], - ['exclude', '../wtf/unicode/wince'], - ['exclude', '../wtf/unicode/glib'], - ['exclude', '../wtf/unicode/qt4'], - # GLib/GTK, even though its name doesn't really indicate. - ['exclude', '/(gtk|glib|gobject)/.*\\.(cpp|h)$'], - ['exclude', '(Default|Gtk|Mac|None|Qt|Win|Wx|Efl|Symbian)\\.(cpp|mm)$'], - ['exclude', 'wtf/CurrentTime\\.cpp$'], - ['exclude', 'wtf/OSRandomSource\\.cpp$'], - ['exclude', 'wtf/MainThread.cpp$'], - ['exclude', 'wtf/TC.*\\.(cpp|h)$'], - ], - 'direct_dependent_settings': { - 'include_dirs': [ - '../', - '../wtf', - ], - # Some warnings occur in JSC headers, so they must also be disabled - # in targets that use JSC. - 'msvs_disabled_warnings': [ - # Don't complain about calling specific versions of templatized - # functions (e.g. in RefPtrHashMap.h). - 4344, - # Don't complain about using "this" in an initializer list - # (e.g. in StringImpl.h). - 4355, - ], - }, - 'export_dependent_settings': [ - 'wtf_config', - '<(chromium_src_dir)/third_party/icu/icu.gyp:icui18n', - '<(chromium_src_dir)/third_party/icu/icu.gyp:icuuc', - ], - 'msvs_disabled_warnings': [4127, 4355, 4510, 4512, 4610, 4706], - 'conditions': [ - ['OS=="win"', { - 'sources/': [ - ['exclude', 'ThreadIdentifierDataPthreads\\.(h|cpp)$'], - ['exclude', 'ThreadingPthreads\\.cpp$'], - ['include', 'Thread(ing|Specific)Win\\.cpp$'], - ['exclude', 'OSAllocatorPosix\\.cpp$'], - ['include', 'OSAllocatorWin\\.cpp$'], - ['include', 'win/OwnPtrWin\\.cpp$'], - ], - 'include_dirs!': [ - '<(SHARED_INTERMEDIATE_DIR)/webkit', - ], - 'conditions': [ - ['inside_chromium_build==1 and component=="shared_library"', { - # Chromium windows multi-dll build enables c++ exception and this - # causes wtf generates 4291 warning due to operator new/delete - # implementations. Disable the warning for chromium windows - # multi-dll build. - 'msvs_disabled_warnings': [4291], - 'direct_dependent_settings': { - 'msvs_disabled_warnings': [4291], - }, - }], - ], - }], - ], - }, - { 'target_name': 'yarr', 'type': 'static_library', 'dependencies': [ - 'wtf', + '../../WTF/WTF.gyp/WTF.gyp:wtf', ], 'variables': { 'optimize': 'max' }, 'actions': [ @@ -216,6 +80,7 @@ ], 'include_dirs': [ '<(INTERMEDIATE_DIR)', + '..', '../runtime', ], 'sources': [ @@ -230,7 +95,7 @@ ['exclude', '../yarr/YarrJIT\\.(h|cpp)$'], ], 'export_dependent_settings': [ - 'wtf', + '../../WTF/WTF.gyp/WTF.gyp:wtf', ], }, ], # targets diff --git a/Source/JavaScriptCore/JavaScriptCore.gypi b/Source/JavaScriptCore/JavaScriptCore.gypi index e19dfb67a..4a03be893 100644 --- a/Source/JavaScriptCore/JavaScriptCore.gypi +++ b/Source/JavaScriptCore/JavaScriptCore.gypi @@ -3,114 +3,285 @@ 'project_dir': ['.'], # These headers are part of JavaScriptCore's public API in the Apple Mac build. 'javascriptcore_publicheader_files': [ + 'API/APICast.h', + 'API/APIShims.h', 'API/JSBase.h', 'API/JSContextRef.h', + 'API/JSContextRefPrivate.h', 'API/JSObjectRef.h', + 'API/JSObjectRefPrivate.h', + 'API/JSRetainPtr.h', 'API/JSStringRef.h', + 'API/JSStringRefBSTR.h', 'API/JSStringRefCF.h', 'API/JSValueRef.h', + 'API/JSWeakObjectMapRefInternal.h', + 'API/JSWeakObjectMapRefPrivate.h', 'API/JavaScript.h', 'API/JavaScriptCore.h', + 'API/OpaqueJSString.h', 'API/WebKitAvailability.h', ], # These headers are part of JavaScriptCore's private API in the Apple Mac build. 'javascriptcore_privateheader_files': [ - 'API/APICast.h', - 'API/APIShims.h', - 'API/JSBasePrivate.h', - 'API/JSContextRefPrivate.h', - 'API/JSObjectRefPrivate.h', - 'API/JSProfilerPrivate.h', - 'API/JSRetainPtr.h', - 'API/JSWeakObjectMapRefInternal.h', - 'API/JSWeakObjectMapRefPrivate.h', - 'API/OpaqueJSString.h', + 'assembler/AbstractMacroAssembler.h', + 'assembler/ARMAssembler.h', + 'assembler/ARMv7Assembler.h', + 'assembler/AssemblerBuffer.h', + 'assembler/AssemblerBufferWithConstantPool.h', + 'assembler/CodeLocation.h', + 'assembler/LinkBuffer.h', + 'assembler/MacroAssembler.h', + 'assembler/MacroAssemblerARM.h', + 'assembler/MacroAssemblerARMv7.h', 'assembler/MacroAssemblerCodeRef.h', + 'assembler/MacroAssemblerMIPS.h', + 'assembler/MacroAssemblerSH4.h', + 'assembler/MacroAssemblerX86.h', + 'assembler/MacroAssemblerX86Common.h', + 'assembler/MacroAssemblerX86_64.h', + 'assembler/MIPSAssembler.h', + 'assembler/RepatchBuffer.h', + 'assembler/SH4Assembler.h', + 'assembler/X86Assembler.h', + 'bytecode/BytecodeConventions.h', + 'bytecode/CallLinkInfo.h', + 'bytecode/CallLinkStatus.h', + 'bytecode/CallReturnOffsetToBytecodeOffset.h', + 'bytecode/CodeBlock.h', + 'bytecode/CodeOrigin.h', + 'bytecode/CodeType.h', + 'bytecode/DataFormat.h', + 'bytecode/DFGExitProfile.h', + 'bytecode/EvalCodeCache.h', + 'bytecode/ExecutionCounter.h', + 'bytecode/ExpressionRangeInfo.h', + 'bytecode/GetByIdStatus.h', + 'bytecode/GlobalResolveInfo.h', + 'bytecode/HandlerInfo.h', + 'bytecode/Instruction.h', + 'bytecode/JumpTable.h', + 'bytecode/LazyOperandValueProfile.h', + 'bytecode/LineInfo.h', + 'bytecode/LLIntCallLinkInfo.h', + 'bytecode/MethodCallLinkInfo.h', + 'bytecode/MethodCallLinkStatus.h', + 'bytecode/MethodOfGettingAValueProfile.h', 'bytecode/Opcode.h', + 'bytecode/Operands.h', + 'bytecode/PolymorphicPutByIdList.h', + 'bytecode/PredictedType.h', + 'bytecode/PredictionTracker.h', + 'bytecode/PutByIdStatus.h', + 'bytecode/PutKind.h', + 'bytecode/SamplingTool.h', + 'bytecode/StructureSet.h', + 'bytecode/StructureStubInfo.h', + 'bytecode/ValueProfile.h', + 'bytecode/ValueRecovery.h', + 'bytecode/VirtualRegister.h', + 'dfg/DFGAbstractState.h', + 'dfg/DFGAbstractValue.h', + 'dfg/DFGAdjacencyList.h', + 'dfg/DFGAssemblyHelpers.h', + 'dfg/DFGBasicBlock.h', + 'dfg/DFGByteCodeCache.h', + 'dfg/DFGByteCodeParser.h', + 'dfg/DFGCapabilities.h', + 'dfg/DFGCCallHelpers.h', + 'dfg/DFGCFAPhase.h', + 'dfg/DFGCommon.h', + 'dfg/DFGCorrectableJumpPoint.h', + 'dfg/DFGCSEPhase.h', + 'dfg/DFGDriver.h', + 'dfg/DFGEdge.h', + 'dfg/DFGFixupPhase.h', + 'dfg/DFGFPRInfo.h', + 'dfg/DFGGenerationInfo.h', + 'dfg/DFGGPRInfo.h', + 'dfg/DFGGraph.h', + 'dfg/DFGInsertionSet.h', + 'dfg/DFGJITCompiler.h', + 'dfg/DFGNode.h', + 'dfg/DFGNodeFlags.h', + 'dfg/DFGNodeType.h', + 'dfg/DFGOperations.h', + 'dfg/DFGOSREntry.h', + 'dfg/DFGOSRExit.h', + 'dfg/DFGOSRExitCompiler.h', + 'dfg/DFGPhase.h', + 'dfg/DFGPredictionPropagationPhase.h', + 'dfg/DFGRedundantPhiEliminationPhase.h', + 'dfg/DFGRegisterBank.h', + 'dfg/DFGRepatch.h', + 'dfg/DFGScoreBoard.h', + 'dfg/DFGSpeculativeJIT.h', + 'dfg/DFGThunks.h', + 'dfg/DFGVariableAccessData.h', + 'dfg/DFGVirtualRegisterAllocationPhase.h', + 'heap/CardSet.h', + 'heap/ConservativeRoots.h', 'heap/CopiedAllocator.h', 'heap/CopiedBlock.h', 'heap/CopiedSpace.h', 'heap/CopiedSpaceInlineMethods.h', - 'heap/ConservativeRoots.h', + 'heap/DFGCodeBlocks.h', 'heap/GCAssertions.h', 'heap/Handle.h', - 'heap/HandleHeap.h', - 'heap/HeapBlock.h', - 'heap/SlotVisitor.h', + 'heap/HandleSet.h', 'heap/HandleStack.h', 'heap/HandleTypes.h', 'heap/Heap.h', + 'heap/HeapBlock.h', + 'heap/HeapRootVisitor.h', + 'heap/ListableHandler.h', 'heap/Local.h', 'heap/LocalScope.h', + 'heap/MachineStackMarker.h', + 'heap/MarkedAllocator.h', + 'heap/MarkedBlock.h', + 'heap/MarkedBlockSet.h', + 'heap/MarkedSpace.h', + 'heap/MarkStack.h', + 'heap/PassWeak.h', + 'heap/SlotVisitor.h', 'heap/Strong.h', 'heap/StrongInlines.h', + 'heap/TinyBloomFilter.h', + 'heap/UnconditionalFinalizer.h', + 'heap/VTableSpectrum.h', 'heap/Weak.h', - 'config.h', + 'heap/WeakBlock.h', + 'heap/WeakHandleOwner.h', + 'heap/WeakImpl.h', + 'heap/WeakReferenceHarvester.h', + 'heap/WeakSet.h', + 'heap/WeakSetInlines.h', + 'heap/WriteBarrierSupport.h', 'debugger/Debugger.h', 'debugger/DebuggerActivation.h', 'debugger/DebuggerCallFrame.h', + 'interpreter/AbstractPC.h', + 'interpreter/CachedCall.h', 'interpreter/CallFrame.h', + 'interpreter/CallFrameClosure.h', 'interpreter/Interpreter.h', 'interpreter/Register.h', 'interpreter/RegisterFile.h', + 'jit/CompactJITCodeMap.h', 'jit/ExecutableAllocator.h', + 'jit/HostCallReturnValue.h', + 'jit/JIT.h', 'jit/JITCode.h', + 'jit/JITCompilationEffort.h', + 'jit/JITDriver.h', + 'jit/JITExceptions.h', + 'jit/JITInlineMethods.h', + 'jit/JITStubCall.h', 'jit/JITStubs.h', + 'jit/JITWriteBarrier.h', + 'jit/JSInterfaceJIT.h', + 'jit/SpecializedThunkJIT.h', 'jit/ThunkGenerators.h', + 'parser/ASTBuilder.h', + 'parser/Lexer.h', + 'parser/NodeConstructors.h', + 'parser/NodeInfo.h', + 'parser/Nodes.h', + 'parser/Parser.h', + 'parser/ParserArena.h', + 'parser/ParserTokens.h', 'parser/ResultType.h', 'parser/SourceCode.h', 'parser/SourceProvider.h', 'parser/SourceProviderCache.h', + 'parser/SourceProviderCacheItem.h', + 'parser/SyntaxChecker.h', 'profiler/CallIdentifier.h', 'profiler/Profile.h', + 'profiler/ProfileGenerator.h', 'profiler/ProfileNode.h', 'profiler/Profiler.h', 'runtime/ArgList.h', + 'runtime/Arguments.h', + 'runtime/ArrayConstructor.h', 'runtime/ArrayPrototype.h', + 'runtime/BatchedTransitionOptimizer.h', + 'runtime/BigInteger.h', + 'runtime/BooleanConstructor.h', 'runtime/BooleanObject.h', + 'runtime/BooleanPrototype.h', 'runtime/CachedTranscendentalFunction.h', 'runtime/CallData.h', 'runtime/ClassInfo.h', + 'runtime/CodeSpecializationKind.h', 'runtime/CommonIdentifiers.h', + 'runtime/CommonSlowPaths.h', 'runtime/Completion.h', 'runtime/ConstructData.h', + 'runtime/DateConstructor.h', + 'runtime/DateConversion.h', 'runtime/DateInstance.h', 'runtime/DateInstanceCache.h', + 'runtime/DatePrototype.h', 'runtime/Error.h', + 'runtime/ErrorConstructor.h', + 'runtime/ErrorInstance.h', + 'runtime/ErrorPrototype.h', 'runtime/ExceptionHelpers.h', + 'runtime/Executable.h', + 'runtime/ExecutionHarness.h', 'runtime/FunctionConstructor.h', 'runtime/FunctionPrototype.h', 'runtime/GCActivityCallback.h', + 'runtime/GetterSetter.h', 'runtime/Identifier.h', 'runtime/InitializeThreading.h', 'runtime/InternalFunction.h', + 'runtime/Intrinsic.h', + 'runtime/JSActivation.h', 'runtime/JSAPIValueWrapper.h', 'runtime/JSArray.h', - 'runtime/JSByteArray.h', + 'runtime/JSBoundFunction.h', 'runtime/JSCell.h', + 'runtime/JSChunk.h', 'runtime/JSDateMath.h', + 'runtime/JSExportMacros.h', 'runtime/JSFunction.h', - 'runtime/JSBoundFunction.h', 'runtime/JSGlobalData.h', 'runtime/JSGlobalObject.h', + 'runtime/JSGlobalObjectFunctions.h', 'runtime/JSGlobalThis.h', 'runtime/JSLock.h', + 'runtime/JSNotAnObject.h', 'runtime/JSObject.h', + 'runtime/JSONObject.h', + 'runtime/JSPropertyNameIterator.h', + 'runtime/JSStaticScopeObject.h', 'runtime/JSString.h', + 'runtime/JSStringBuilder.h', + 'runtime/JSStringJoiner.h', 'runtime/JSType.h', 'runtime/JSTypeInfo.h', 'runtime/JSValue.h', 'runtime/JSValueInlineMethods.h', 'runtime/JSVariableObject.h', 'runtime/JSWrapperObject.h', + 'runtime/LiteralParser.h', 'runtime/Lookup.h', + 'runtime/MatchResult.h', 'runtime/MathObject.h', 'runtime/MemoryStatistics.h', + 'runtime/NativeErrorConstructor.h', + 'runtime/NativeErrorPrototype.h', + 'runtime/NumberConstructor.h', 'runtime/NumberObject.h', 'runtime/NumberPrototype.h', 'runtime/NumericStrings.h', + 'runtime/ObjectConstructor.h', 'runtime/ObjectPrototype.h', 'runtime/Operations.h', + 'runtime/Options.h', 'runtime/PropertyDescriptor.h', 'runtime/PropertyMapHashTable.h', 'runtime/PropertyNameArray.h', @@ -118,558 +289,252 @@ 'runtime/Protect.h', 'runtime/PutPropertySlot.h', 'runtime/RegExp.h', - 'runtime/RegExpKey.h', 'runtime/RegExpCache.h', + 'runtime/RegExpCachedResult.h', + 'runtime/RegExpConstructor.h', + 'runtime/RegExpKey.h', + 'runtime/RegExpMatchesArray.h', 'runtime/RegExpObject.h', + 'runtime/RegExpPrototype.h', + 'runtime/SamplingCounter.h', 'runtime/ScopeChain.h', + 'runtime/ScopeChainMark.h', 'runtime/SmallStrings.h', 'runtime/StorageBarrier.h', + 'runtime/StrictEvalActivation.h', + 'runtime/StringConstructor.h', 'runtime/StringObject.h', 'runtime/StringPrototype.h', + 'runtime/StringRecursionChecker.h', 'runtime/Structure.h', 'runtime/StructureChain.h', 'runtime/StructureTransitionTable.h', 'runtime/SymbolTable.h', 'runtime/Terminator.h', 'runtime/TimeoutChecker.h', + 'runtime/Tracing.h', + 'runtime/Uint16WithFraction.h', 'runtime/UString.h', 'runtime/UStringBuilder.h', + 'runtime/UStringConcatenate.h', 'runtime/WeakGCMap.h', 'runtime/WeakRandom.h', 'runtime/WriteBarrier.h', - 'wtf/ASCIICType.h', - 'wtf/AVLTree.h', - 'wtf/Alignment.h', - 'wtf/AlwaysInline.h', - 'wtf/Assertions.h', - 'wtf/Atomics.h', - 'wtf/Bitmap.h', - 'wtf/BlockStack.h', - 'wtf/BloomFilter.h', - 'wtf/BumpPointerAllocator.h', - 'wtf/ByteArray.h', - 'wtf/CheckedArithmetic.h', - 'wtf/CheckedBoolean.h', - 'wtf/Compiler.h', - 'wtf/Complex.h', - 'wtf/CryptographicallyRandomNumber.h', - 'wtf/CurrentTime.h', - 'wtf/DateMath.h', - 'wtf/DecimalNumber.h', - 'wtf/Decoder.h', - 'wtf/DataLog.h', - 'wtf/Deque.h', - 'wtf/DisallowCType.h', - 'wtf/DoublyLinkedList.h', - 'wtf/Encoder.h', - 'wtf/FastAllocBase.h', - 'wtf/FastMalloc.h', - 'wtf/FixedArray.h', - 'wtf/Forward.h', - 'wtf/Functional.h', - 'wtf/GetPtr.h', - 'wtf/HashCountedSet.h', - 'wtf/HashFunctions.h', - 'wtf/HashIterators.h', - 'wtf/HashMap.h', - 'wtf/HashSet.h', - 'wtf/HashTable.h', - 'wtf/HashTraits.h', - 'wtf/HexNumber.h', - 'wtf/ListHashSet.h', - 'wtf/ListRefPtr.h', - 'wtf/Locker.h', - 'wtf/MD5.h', - 'wtf/MainThread.h', - 'wtf/MathExtras.h', - 'wtf/MessageQueue.h', - 'wtf/NonCopyingSort.h', - 'wtf/Noncopyable.h', - 'wtf/NotFound.h', - 'wtf/NullPtr.h', - 'wtf/OSAllocator.h', - 'wtf/OwnArrayPtr.h', - 'wtf/OwnPtr.h', - 'wtf/OwnPtrCommon.h', - 'wtf/PageAllocation.h', - 'wtf/PageAllocationAligned.h', - 'wtf/PageBlock.h', - 'wtf/PageReservation.h', - 'wtf/PassOwnArrayPtr.h', - 'wtf/PassOwnPtr.h', - 'wtf/PassRefPtr.h', - 'wtf/PassTraits.h', - 'wtf/Platform.h', - 'wtf/PossiblyNull.h', - 'wtf/RandomNumber.h', - 'wtf/RefCounted.h', - 'wtf/RefCountedLeakCounter.h', - 'wtf/RefPtr.h', - 'wtf/RefPtrHashMap.h', - 'wtf/RetainPtr.h', - 'wtf/SentinelLinkedList.h', - 'wtf/SinglyLinkedList.h', - 'wtf/StackBounds.h', - 'wtf/StaticConstructors.h', - 'wtf/StdLibExtras.h', - 'wtf/StringExtras.h', - 'wtf/StringHasher.h', - 'wtf/TemporaryChange.h', - 'wtf/ThreadSafeRefCounted.h', - 'wtf/ThreadSpecific.h', - 'wtf/ThreadRestrictionVerifier.h', - 'wtf/Threading.h', - 'wtf/ThreadingPrimitives.h', - 'wtf/TypeTraits.h', - 'wtf/UnusedParam.h', - 'wtf/VMTags.h', - 'wtf/ValueCheck.h', - 'wtf/Vector.h', - 'wtf/VectorTraits.h', - 'wtf/WTFThreadData.h', - 'wtf/dtoa.h', - 'wtf/dtoa/bignum-dtoa.h', - 'wtf/dtoa/bignum.h', - 'wtf/dtoa/cached-powers.h', - 'wtf/dtoa/diy-fp.h', - 'wtf/dtoa/double-conversion.h', - 'wtf/dtoa/double.h', - 'wtf/dtoa/fast-dtoa.h', - 'wtf/dtoa/fixed-dtoa.h', - 'wtf/dtoa/strtod.h', - 'wtf/dtoa/utils.h', - 'wtf/text/ASCIIFastPath.h', - 'wtf/text/AtomicString.h', - 'wtf/text/AtomicStringHash.h', - 'wtf/text/AtomicStringImpl.h', - 'wtf/text/CString.h', - 'wtf/text/StringBuffer.h', - 'wtf/text/StringBuilder.h', - 'wtf/text/StringConcatenate.h', - 'wtf/text/StringHash.h', - 'wtf/text/StringImpl.h', - 'wtf/text/StringOperators.h', - 'wtf/text/TextPosition.h', - 'wtf/text/WTFString.h', - 'wtf/threads/BinarySemaphore.h', - 'wtf/unicode/CharacterNames.h', - 'wtf/unicode/Collator.h', - 'wtf/unicode/UTF8.h', - 'wtf/unicode/Unicode.h', - 'wtf/unicode/icu/UnicodeIcu.h', 'yarr/Yarr.h', + 'yarr/YarrCanonicalizeUCS2.h', 'yarr/YarrInterpreter.h', + 'yarr/YarrJIT.h', + 'yarr/YarrParser.h', 'yarr/YarrPattern.h', + 'yarr/YarrSyntaxChecker.h', ], 'javascriptcore_files': [ - 'API/APIShims.h', 'API/JSBase.cpp', 'API/JSCallbackConstructor.cpp', - 'API/JSCallbackConstructor.h', 'API/JSCallbackFunction.cpp', - 'API/JSCallbackFunction.h', 'API/JSCallbackObject.cpp', - 'API/JSCallbackObject.h', - 'API/JSCallbackObjectFunctions.h', 'API/JSClassRef.cpp', - 'API/JSClassRef.h', 'API/JSContextRef.cpp', 'API/JSObjectRef.cpp', 'API/JSProfilerPrivate.cpp', 'API/JSStringRef.cpp', 'API/JSStringRefBSTR.cpp', - 'API/JSStringRefBSTR.h', 'API/JSStringRefCF.cpp', 'API/JSValueRef.cpp', 'API/JSWeakObjectMapRefPrivate.cpp', 'API/OpaqueJSString.cpp', - 'AllInOneFile.cpp', - 'ForwardingHeaders/JavaScriptCore/APICast.h', - 'ForwardingHeaders/JavaScriptCore/APIShims.h', - 'ForwardingHeaders/JavaScriptCore/JSBase.h', - 'ForwardingHeaders/JavaScriptCore/JSContextRef.h', - 'ForwardingHeaders/JavaScriptCore/JSObjectRef.h', - 'ForwardingHeaders/JavaScriptCore/JSRetainPtr.h', - 'ForwardingHeaders/JavaScriptCore/JSStringRef.h', - 'ForwardingHeaders/JavaScriptCore/JSStringRefCF.h', - 'ForwardingHeaders/JavaScriptCore/JSValueRef.h', - 'ForwardingHeaders/JavaScriptCore/JavaScript.h', - 'ForwardingHeaders/JavaScriptCore/JavaScriptCore.h', - 'ForwardingHeaders/JavaScriptCore/OpaqueJSString.h', - 'ForwardingHeaders/JavaScriptCore/WebKitAvailability.h', - 'JavaScriptCorePrefix.h', 'assembler/ARMAssembler.cpp', - 'assembler/ARMAssembler.h', 'assembler/ARMv7Assembler.cpp', - '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.cpp', - 'assembler/MacroAssemblerARM.h', - 'assembler/MacroAssemblerARMv7.h', - 'assembler/MacroAssemblerMIPS.h', - 'assembler/MacroAssemblerX86.h', - 'assembler/MacroAssemblerX86Common.h', - 'assembler/MacroAssemblerX86_64.h', - 'assembler/RepatchBuffer.h', - 'assembler/X86Assembler.h', + 'assembler/MacroAssemblerSH4.cpp', + 'bytecode/CallLinkInfo.cpp', + 'bytecode/CallLinkStatus.cpp', 'bytecode/CodeBlock.cpp', - 'bytecode/CodeBlock.h', - 'bytecode/EvalCodeCache.h', - 'bytecode/Instruction.h', + 'bytecode/DFGExitProfile.cpp', + 'bytecode/ExecutionCounter.cpp', + 'bytecode/GetByIdStatus.cpp', 'bytecode/JumpTable.cpp', - 'bytecode/JumpTable.h', + 'bytecode/LazyOperandValueProfile.cpp', + 'bytecode/MethodCallLinkInfo.cpp', + 'bytecode/MethodCallLinkStatus.cpp', + 'bytecode/MethodOfGettingAValueProfile.cpp', 'bytecode/Opcode.cpp', + 'bytecode/PolymorphicPutByIdList.cpp', + 'bytecode/PredictedType.cpp', + 'bytecode/PutByIdStatus.cpp', 'bytecode/SamplingTool.cpp', - 'bytecode/SamplingTool.h', 'bytecode/StructureStubInfo.cpp', - 'bytecode/StructureStubInfo.h', 'bytecompiler/BytecodeGenerator.cpp', - 'bytecompiler/BytecodeGenerator.h', - 'bytecompiler/Label.h', - 'bytecompiler/LabelScope.h', 'bytecompiler/NodesCodegen.cpp', - 'bytecompiler/RegisterID.h', - 'heap/ConservativeRoots.cpp', - 'heap/HandleHeap.cpp', - 'heap/HandleStack.cpp', - 'heap/Heap.cpp', - 'heap/MachineStackMarker.cpp', - 'heap/MachineStackMarker.h', - 'heap/MarkStack.cpp', - 'heap/MarkStack.h', - 'heap/HeapRootVisitor.h', - 'heap/MarkedBlock.cpp', - 'heap/MarkedBlock.h', - 'heap/MarkedBlockSet.h', - 'heap/TinyBloomFilter.h', - 'heap/MarkedSpace.cpp', - 'heap/MarkedSpace.h', 'debugger/Debugger.cpp', 'debugger/DebuggerActivation.cpp', 'debugger/DebuggerCallFrame.cpp', + 'dfg/DFGAbstractState.cpp', + 'dfg/DFGAssemblyHelpers.cpp', 'dfg/DFGByteCodeParser.cpp', - 'dfg/DFGByteCodeParser.h', - 'dfg/DFGGenerationInfo.h', + 'dfg/DFGCapabilities.cpp', + 'dfg/DFGCFAPhase.cpp', + 'dfg/DFGCorrectableJumpPoint.cpp', + 'dfg/DFGCSEPhase.cpp', + 'dfg/DFGDriver.cpp', + 'dfg/DFGFixupPhase.cpp', 'dfg/DFGGraph.cpp', - 'dfg/DFGGraph.h', 'dfg/DFGJITCompiler.cpp', - 'dfg/DFGJITCompiler.h', - 'dfg/DFGNode.h', + 'dfg/DFGNodeFlags.cpp', 'dfg/DFGOperations.cpp', - 'dfg/DFGOperations.h', - 'dfg/DFGRegisterBank.h', - 'dfg/DFGScoreBoard.h', + 'dfg/DFGOSREntry.cpp', + 'dfg/DFGOSRExit.cpp', + 'dfg/DFGOSRExitCompiler.cpp', + 'dfg/DFGOSRExitCompiler32_64.cpp', + 'dfg/DFGOSRExitCompiler64.cpp', + 'dfg/DFGPhase.cpp', + 'dfg/DFGPredictionPropagationPhase.cpp', + 'dfg/DFGRedundantPhiEliminationPhase.cpp', + 'dfg/DFGRepatch.cpp', 'dfg/DFGSpeculativeJIT.cpp', - 'dfg/DFGSpeculativeJIT.h', - 'icu/unicode/parseerr.h', - 'icu/unicode/platform.h', - 'icu/unicode/putil.h', - 'icu/unicode/uchar.h', - 'icu/unicode/ucnv.h', - 'icu/unicode/ucnv_err.h', - 'icu/unicode/ucol.h', - 'icu/unicode/uconfig.h', - 'icu/unicode/uenum.h', - 'icu/unicode/uiter.h', - 'icu/unicode/uloc.h', - 'icu/unicode/umachine.h', - 'icu/unicode/unorm.h', - 'icu/unicode/urename.h', - 'icu/unicode/uscript.h', - 'icu/unicode/uset.h', - 'icu/unicode/ustring.h', - 'icu/unicode/utf.h', - 'icu/unicode/utf16.h', - 'icu/unicode/utf8.h', - 'icu/unicode/utf_old.h', - 'icu/unicode/utypes.h', - 'icu/unicode/uversion.h', - 'interpreter/CachedCall.h', + 'dfg/DFGSpeculativeJIT32_64.cpp', + 'dfg/DFGSpeculativeJIT64.cpp', + 'dfg/DFGThunks.cpp', + 'dfg/DFGVirtualRegisterAllocationPhase.cpp', + 'heap/ConservativeRoots.cpp', + 'heap/CopiedSpace.cpp', + 'heap/DFGCodeBlocks.cpp', + 'heap/HandleSet.cpp', + 'heap/HandleStack.cpp', + 'heap/BlockAllocator.cpp', + 'heap/Heap.cpp', + 'heap/MachineStackMarker.cpp', + 'heap/MarkedAllocator.cpp', + 'heap/MarkedBlock.cpp', + 'heap/MarkedSpace.cpp', + 'heap/MarkStack.cpp', + 'heap/VTableSpectrum.cpp', + 'heap/WeakBlock.cpp', + 'heap/WeakHandleOwner.cpp', + 'heap/WeakSet.cpp', + 'heap/WriteBarrierSupport.cpp', + 'interpreter/AbstractPC.cpp', 'interpreter/CallFrame.cpp', - 'interpreter/CallFrameClosure.h', 'interpreter/Interpreter.cpp', 'interpreter/RegisterFile.cpp', 'jit/ExecutableAllocator.cpp', 'jit/ExecutableAllocatorFixedVMPool.cpp', + 'jit/HostCallReturnValue.cpp', 'jit/JIT.cpp', - 'jit/JIT.h', 'jit/JITArithmetic.cpp', 'jit/JITArithmetic32_64.cpp', 'jit/JITCall.cpp', 'jit/JITCall32_64.cpp', - 'jit/JITInlineMethods.h', + 'jit/JITExceptions.cpp', 'jit/JITOpcodes.cpp', 'jit/JITOpcodes32_64.cpp', 'jit/JITPropertyAccess.cpp', 'jit/JITPropertyAccess32_64.cpp', - 'jit/JITStubCall.h', 'jit/JITStubs.cpp', - 'jit/JSInterfaceJIT.h', - 'jit/SpecializedThunkJIT.h', 'jit/ThunkGenerators.cpp', - 'os-win32/WinMain.cpp', - 'os-win32/inttypes.h', - 'os-win32/stdbool.h', - 'os-win32/stdint.h', - 'parser/ASTBuilder.h', 'parser/Lexer.cpp', - 'parser/Lexer.h', - 'parser/NodeConstructors.h', - 'parser/NodeInfo.h', 'parser/Nodes.cpp', - 'parser/Nodes.h', 'parser/Parser.cpp', - 'parser/Parser.h', 'parser/ParserArena.cpp', - 'parser/ParserArena.h', 'parser/SourceProviderCache.cpp', - 'parser/SourceProviderCacheItem.h', - 'parser/SyntaxChecker.h', 'profiler/Profile.cpp', 'profiler/ProfileGenerator.cpp', - 'profiler/ProfileGenerator.h', 'profiler/ProfileNode.cpp', 'profiler/Profiler.cpp', 'runtime/ArgList.cpp', 'runtime/Arguments.cpp', - 'runtime/Arguments.h', 'runtime/ArrayConstructor.cpp', - 'runtime/ArrayConstructor.h', 'runtime/ArrayPrototype.cpp', - 'runtime/BatchedTransitionOptimizer.h', 'runtime/BooleanConstructor.cpp', - 'runtime/BooleanConstructor.h', 'runtime/BooleanObject.cpp', 'runtime/BooleanPrototype.cpp', - 'runtime/BooleanPrototype.h', 'runtime/CallData.cpp', 'runtime/CommonIdentifiers.cpp', 'runtime/Completion.cpp', 'runtime/ConstructData.cpp', 'runtime/DateConstructor.cpp', - 'runtime/DateConstructor.h', 'runtime/DateConversion.cpp', - 'runtime/DateConversion.h', 'runtime/DateInstance.cpp', 'runtime/DatePrototype.cpp', - 'runtime/DatePrototype.h', 'runtime/Error.cpp', 'runtime/ErrorConstructor.cpp', - 'runtime/ErrorConstructor.h', 'runtime/ErrorInstance.cpp', - 'runtime/ErrorInstance.h', 'runtime/ErrorPrototype.cpp', - 'runtime/ErrorPrototype.h', 'runtime/ExceptionHelpers.cpp', 'runtime/Executable.cpp', - 'runtime/Executable.h', 'runtime/FunctionConstructor.cpp', 'runtime/FunctionPrototype.cpp', 'runtime/GCActivityCallback.cpp', 'runtime/GCActivityCallbackCF.cpp', 'runtime/GetterSetter.cpp', - 'runtime/GetterSetter.h', 'runtime/Identifier.cpp', 'runtime/InitializeThreading.cpp', 'runtime/InternalFunction.cpp', - 'runtime/JSAPIValueWrapper.cpp', 'runtime/JSActivation.cpp', - 'runtime/JSActivation.h', + 'runtime/JSAPIValueWrapper.cpp', 'runtime/JSArray.cpp', - 'runtime/JSByteArray.cpp', + 'runtime/JSBoundFunction.cpp', 'runtime/JSCell.cpp', + 'runtime/JSChunk.cpp', 'runtime/JSDateMath.cpp', 'runtime/JSFunction.cpp', - 'runtime/JSBoundFunction.cpp', 'runtime/JSGlobalData.cpp', 'runtime/JSGlobalObject.cpp', 'runtime/JSGlobalObjectFunctions.cpp', - 'runtime/JSGlobalObjectFunctions.h', 'runtime/JSGlobalThis.cpp', 'runtime/JSLock.cpp', 'runtime/JSNotAnObject.cpp', - 'runtime/JSNotAnObject.h', - 'runtime/JSONObject.cpp', - 'runtime/JSONObject.h', 'runtime/JSObject.cpp', + 'runtime/JSONObject.cpp', 'runtime/JSPropertyNameIterator.cpp', - 'runtime/JSPropertyNameIterator.h', 'runtime/JSStaticScopeObject.cpp', - 'runtime/JSStaticScopeObject.h', 'runtime/JSString.cpp', - 'runtime/JSStringBuilder.h', + 'runtime/JSStringJoiner.cpp', 'runtime/JSValue.cpp', 'runtime/JSVariableObject.cpp', 'runtime/JSWrapperObject.cpp', 'runtime/LiteralParser.cpp', - 'runtime/LiteralParser.h', 'runtime/Lookup.cpp', 'runtime/MathObject.cpp', 'runtime/MemoryStatistics.cpp', 'runtime/NativeErrorConstructor.cpp', - 'runtime/NativeErrorConstructor.h', 'runtime/NativeErrorPrototype.cpp', - 'runtime/NativeErrorPrototype.h', 'runtime/NumberConstructor.cpp', - 'runtime/NumberConstructor.h', 'runtime/NumberObject.cpp', 'runtime/NumberPrototype.cpp', 'runtime/ObjectConstructor.cpp', - 'runtime/ObjectConstructor.h', 'runtime/ObjectPrototype.cpp', 'runtime/Operations.cpp', + 'runtime/Options.cpp', 'runtime/PropertyDescriptor.cpp', 'runtime/PropertyNameArray.cpp', 'runtime/PropertySlot.cpp', 'runtime/RegExp.cpp', 'runtime/RegExpCache.cpp', + 'runtime/RegExpCachedResult.cpp', 'runtime/RegExpConstructor.cpp', - 'runtime/RegExpConstructor.h', - 'runtime/RegExpMatchesArray.h', + 'runtime/RegExpMatchesArray.cpp', 'runtime/RegExpObject.cpp', 'runtime/RegExpPrototype.cpp', - 'runtime/RegExpPrototype.h', + 'runtime/SamplingCounter.cpp', 'runtime/ScopeChain.cpp', - 'runtime/ScopeChainMark.h', 'runtime/SmallStrings.cpp', 'runtime/StrictEvalActivation.cpp', - 'runtime/StrictEvalActivation.h', 'runtime/StringConstructor.cpp', - 'runtime/StringConstructor.h', 'runtime/StringObject.cpp', 'runtime/StringPrototype.cpp', 'runtime/StringRecursionChecker.cpp', - 'runtime/StringRecursionChecker.h', 'runtime/Structure.cpp', 'runtime/StructureChain.cpp', 'runtime/TimeoutChecker.cpp', - 'runtime/Tracing.d', - 'runtime/Tracing.h', 'runtime/UString.cpp', - 'runtime/UStringConcatenate.h', - 'wtf/ArrayBuffer.cpp', - 'wtf/ArrayBuffer.h', - 'wtf/ArrayBufferView.cpp', - 'wtf/ArrayBufferView.h', - 'wtf/Assertions.cpp', - 'wtf/ByteArray.cpp', - 'wtf/CryptographicallyRandomNumber.cpp', - 'wtf/CurrentTime.cpp', - 'wtf/DateMath.cpp', - 'wtf/DecimalNumber.cpp', - 'wtf/DataLog.cpp', - 'wtf/DynamicAnnotations.cpp', - 'wtf/DynamicAnnotations.h', - 'wtf/FastMalloc.cpp', - 'wtf/Float32Array.h', - 'wtf/Float64Array.h', - 'wtf/HashTable.cpp', - 'wtf/Int16Array.h', - 'wtf/Int32Array.h', - 'wtf/Int8Array.h', - 'wtf/IntegralTypedArrayBase.h', - 'wtf/MD5.cpp', - 'wtf/MainThread.cpp', - 'wtf/MallocZoneSupport.h', - 'wtf/NullPtr.cpp', - 'wtf/NumberOfCores.cpp', - 'wtf/NumberOfCores.h', - 'wtf/OSAllocatorPosix.cpp', - 'wtf/OSAllocatorWin.cpp', - 'wtf/OSRandomSource.cpp', - 'wtf/OSRandomSource.h', - 'wtf/PageAllocationAligned.cpp', - 'wtf/PageBlock.cpp', - 'wtf/ParallelJobs.h', - 'wtf/ParallelJobsGeneric.cpp', - 'wtf/ParallelJobsGeneric.h', - 'wtf/ParallelJobsLibdispatch.h', - 'wtf/ParallelJobsOpenMP.h', - 'wtf/RandomNumber.cpp', - 'wtf/RandomNumberSeed.h', - 'wtf/RefCountedLeakCounter.cpp', - 'wtf/SHA1.cpp', - 'wtf/SHA1.h', - 'wtf/SegmentedVector.h', - 'wtf/SizeLimits.cpp', - 'wtf/StackBounds.cpp', - 'wtf/StringExtras.cpp', - 'wtf/TCPackedCache.h', - 'wtf/TCPageMap.h', - 'wtf/TCSpinLock.h', - 'wtf/TCSystemAlloc.cpp', - 'wtf/TCSystemAlloc.h', - 'wtf/ThreadFunctionInvocation.h', - 'wtf/ThreadIdentifierDataPthreads.cpp', - 'wtf/ThreadIdentifierDataPthreads.h', - 'wtf/ThreadSpecificWin.cpp', - 'wtf/Threading.cpp', - 'wtf/ThreadingPthreads.cpp', - 'wtf/ThreadingWin.cpp', - 'wtf/TypeTraits.cpp', - 'wtf/TypedArrayBase.h', - 'wtf/WTFThreadData.cpp', - 'wtf/Uint16Array.h', - 'wtf/Uint32Array.h', - 'wtf/Uint8Array.h', - 'wtf/chromium/ChromiumThreading.h', - 'wtf/chromium/MainThreadChromium.cpp', - 'wtf/dtoa.cpp', - 'wtf/dtoa/bignum-dtoa.cc', - 'wtf/dtoa/bignum.cc', - 'wtf/dtoa/cached-powers.cc', - 'wtf/dtoa/diy-fp.cc', - 'wtf/dtoa/double-conversion.cc', - 'wtf/dtoa/fast-dtoa.cc', - 'wtf/dtoa/fixed-dtoa.cc', - 'wtf/dtoa/strtod.cc', - 'wtf/efl/MainThreadEfl.cpp', - 'wtf/gobject/GOwnPtr.cpp', - 'wtf/gobject/GOwnPtr.h', - 'wtf/gobject/GRefPtr.cpp', - 'wtf/gobject/GRefPtr.h', - 'wtf/gobject/GTypedefs.h', - 'wtf/gtk/MainThreadGtk.cpp', - 'wtf/mac/MainThreadMac.mm', - 'wtf/qt/MainThreadQt.cpp', - 'wtf/qt/StringQt.cpp', - 'wtf/text/AtomicString.cpp', - 'wtf/text/CString.cpp', - 'wtf/text/StringBuilder.cpp', - 'wtf/text/StringImpl.cpp', - 'wtf/text/StringStatics.cpp', - 'wtf/text/WTFString.cpp', - 'wtf/threads/BinarySemaphore.cpp', - 'wtf/unicode/CollatorDefault.cpp', - 'wtf/unicode/ScriptCodesFromICU.h', - 'wtf/unicode/UTF8.cpp', - 'wtf/unicode/UnicodeMacrosFromICU.h', - 'wtf/unicode/glib/UnicodeGLib.cpp', - 'wtf/unicode/glib/UnicodeGLib.h', - 'wtf/unicode/icu/CollatorICU.cpp', - 'wtf/unicode/qt4/UnicodeQt4.h', - 'wtf/unicode/wince/UnicodeWinCE.cpp', - 'wtf/unicode/wince/UnicodeWinCE.h', - 'wtf/win/MainThreadWin.cpp', - 'wtf/win/OwnPtrWin.cpp', - 'wtf/wince/FastMallocWinCE.h', - 'wtf/wince/MemoryManager.cpp', - 'wtf/wince/MemoryManager.h', - 'wtf/wx/MainThreadWx.cpp', - 'wtf/wx/StringWx.cpp', + 'tools/CodeProfile.cpp', + 'tools/CodeProfiling.cpp', + 'yarr/YarrCanonicalizeUCS2.cpp', 'yarr/YarrInterpreter.cpp', 'yarr/YarrJIT.cpp', - 'yarr/YarrJIT.h', - 'yarr/YarrParser.h', 'yarr/YarrPattern.cpp', 'yarr/YarrSyntaxChecker.cpp', - 'yarr/YarrSyntaxChecker.h', ], 'javascriptcore_derived_source_files': [ '<(PRODUCT_DIR)/DerivedSources/JavaScriptCore/Lexer.lut.h', diff --git a/Source/JavaScriptCore/JavaScriptCore.order b/Source/JavaScriptCore/JavaScriptCore.order index e1e1f231a..3a450075a 100644 --- a/Source/JavaScriptCore/JavaScriptCore.order +++ b/Source/JavaScriptCore/JavaScriptCore.order @@ -268,7 +268,6 @@ __ZN3JSC12X86Assembler7addl_irEiNS_12X86Registers10RegisterIDE __ZN3JSC14MacroAssembler4jumpENS_22AbstractMacroAssemblerINS_12X86AssemblerEE5LabelE __ZN3WTF15deleteAllValuesIPN3JSC4Yarr18PatternDisjunctionELm4EEEvRKNS_6VectorIT_XT0_EEE __ZN3WTF15deleteAllValuesIPN3JSC4Yarr14CharacterClassELm0EEEvRKNS_6VectorIT_XT0_EEE -__ZN3JSC12RegExpObjectC2EPNS_14JSGlobalObjectEPNS_9StructureEN3WTF17NonNullPassRefPtrINS_6RegExpEEE __ZN3JSC14ErrorPrototypeC1EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE __ZN3JSC14ErrorPrototypeC2EPNS_9ExecStateEPNS_14JSGlobalObjectEPNS_9StructureE __ZN3JSC13ErrorInstanceC2EPNS_12JSGlobalDataEPNS_9StructureE @@ -1035,7 +1034,6 @@ __ZNK3JSC14ExpressionNode10isSubtractEv __ZN3JSC3JIT18emit_op_new_regexpEPNS_11InstructionE __ZN3JSC8JSString18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE _cti_op_new_regexp -__ZN3JSC12RegExpObjectC1EPNS_14JSGlobalObjectEPNS_9StructureEN3WTF17NonNullPassRefPtrINS_6RegExpEEE __ZN3JSCL22stringProtoFuncReplaceEPNS_9ExecStateE __ZNK3JSC7JSValue14toThisJSStringEPNS_9ExecStateE __ZN3JSC9ExecState8argumentEi @@ -1274,12 +1272,6 @@ __ZN3JSC3JIT21emitSlow_op_nstricteqEPNS_11InstructionERPNS_13SlowCaseEntryE _cti_op_nstricteq __ZN3JSC14LogicalNotNode30emitBytecodeInConditionContextERNS_17BytecodeGeneratorEPNS_5LabelES4_b __ZN3JSC3JIT18emit_op_jmp_scopesEPNS_11InstructionE -__ZN3WTF9ByteArray6createEm -__ZN3JSC11JSByteArray15createStructureERNS_12JSGlobalDataENS_7JSValueEPKNS_9ClassInfoE -__ZN3JSC11JSByteArrayC1EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE -__ZN3JSC11JSByteArrayC2EPNS_9ExecStateEPNS_9StructureEPN3WTF9ByteArrayE -__ZN3JSC11JSByteArrayD1Ev -_cti_op_get_by_val_byte_array _cti_op_negate __ZN3JSCL16mathProtoFuncMaxEPNS_9ExecStateE __ZN3WTF15ThreadConditionD1Ev @@ -1337,7 +1329,6 @@ __ZN3JSC4Yarr13YarrGenerator17BacktrackingState6linkToENS_22AbstractMacroAssembl __ZN3JSC4Yarr22YarrPatternConstructor23setupDisjunctionOffsetsEPNS0_18PatternDisjunctionEjj __ZN3JSC4Yarr13YarrGenerator17BacktrackingState24takeBacktracksToJumpListERNS_22AbstractMacroAssemblerINS_12X86AssemblerEE8JumpListEPNS_14MacroAssemblerE __ZNK3JSC11BooleanNode6isPureERNS_17BytecodeGeneratorE -__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateERKNS_10IdentifierERNS_12PropertySlotE _cti_timeout_check __ZN3JSC14TimeoutChecker10didTimeOutEPNS_9ExecStateE __ZN3JSC22createNotAnObjectErrorEPNS_9ExecStateENS_7JSValueE @@ -1356,8 +1347,6 @@ __ZN3JSC6JSCell16getConstructDataERNS_13ConstructDataE __ZN3JSC26createNotAConstructorErrorEPNS_9ExecStateENS_7JSValueE __ZN3JSC23objectProtoFuncToStringEPNS_9ExecStateE __ZNK3JSC8JSObject9classNameEv -__ZN3JSC11JSByteArray3putEPNS_9ExecStateEjNS_7JSValueE -_cti_op_put_by_val_byte_array __ZNK3JSC14ExpressionNode11isCommaNodeEv __ZN3JSC9CommaNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE __ZN3JSC9CommaNodeD1Ev @@ -2203,8 +2192,6 @@ __ZN3JSCL21arrayProtoFuncIndexOfEPNS_9ExecStateE __ZN3JSC12StringObject18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE __ZN3JSC8JSObject14deletePropertyEPNS_9ExecStateEj __ZN3JSCL25arrayProtoFuncLastIndexOfEPNS_9ExecStateE -__ZN3JSC11JSByteArray3putEPNS_9ExecStateERKNS_10IdentifierENS_7JSValueERNS_15PutPropertySlotE -__ZN3JSC11JSByteArray18getOwnPropertySlotEPNS_9ExecStateEjRNS_12PropertySlotE __ZN3WTF20equalIgnoringNullityEPNS_10StringImplES1_ _cti_op_get_by_id_array_fail __ZN3JSC17PrefixBracketNode12emitBytecodeERNS_17BytecodeGeneratorEPNS_10RegisterIDE @@ -2243,7 +2230,6 @@ __ZN3JSCL24dateProtoFuncToISOStringEPNS_9ExecStateE _cti_op_get_by_id_string_fail __ZN3JSC22StringRecursionChecker11emptyStringEv __ZN3JSC22StringRecursionChecker23throwStackOverflowErrorEv -__ZN3JSC11JSByteArray19getOwnPropertyNamesEPNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE __ZN3JSC9ExecState9jsonTableEPS0_ __ZN3JSC10JSFunction12callerGetterEPNS_9ExecStateENS_7JSValueERKNS_10IdentifierE __ZNK3JSC11Interpreter14retrieveCallerEPNS_9ExecStateEPNS_10JSFunctionE @@ -2343,7 +2329,6 @@ __ZN3JSC17NumberConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10Iden __ZN3JSC17RegExpConstructor24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE __ZN3JSC10MathObject24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE __ZN3JSC18RegExpMatchesArray24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE -__ZN3JSC11JSByteArray24getOwnPropertyDescriptorEPNS_9ExecStateERKNS_10IdentifierERNS_18PropertyDescriptorE __ZN3JSCL8callDateEPNS_9ExecStateE __ZN3JSCL26callNativeErrorConstructorEPNS_9ExecStateE __ZN3JSC17BytecodeGenerator35emitThrowExpressionTooDeepExceptionEv diff --git a/Source/JavaScriptCore/JavaScriptCore.pri b/Source/JavaScriptCore/JavaScriptCore.pri index eeace1764..4a8ecd42f 100644 --- a/Source/JavaScriptCore/JavaScriptCore.pri +++ b/Source/JavaScriptCore/JavaScriptCore.pri @@ -12,6 +12,7 @@ JAVASCRIPTCORE_GENERATED_SOURCES_DIR = $${ROOT_BUILD_DIR}/Source/JavaScriptCore/ INCLUDEPATH += \ $$SOURCE_DIR \ $$SOURCE_DIR/.. \ + $$SOURCE_DIR/../WTF \ $$SOURCE_DIR/assembler \ $$SOURCE_DIR/bytecode \ $$SOURCE_DIR/bytecompiler \ diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make index bd4753093..a87ecc9dd 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.make @@ -10,8 +10,11 @@ install: set WebKitOutputDir=$(OBJROOT) set ConfigurationBuildDir=$(OBJROOT)\$(BUILDSTYLE) set WebKitVSPropsRedirectionDir=$(SRCROOT)\AppleInternal\tools\vsprops\OpenSource\1\2\3\4\ + -mkdir "%ConfigurationBuildDir%\include\private" + xcopy "%WebKitLibrariesDir%\include\private\*" "%ConfigurationBuildDir%\include\private" /e/v/i/h/y !IF "$(BUILDSTYLE)"=="Release_PGO" - devenv "JavaScriptCoreSubmit.sln" /rebuild $(BUILDSTYLE) + devenv "JavaScriptCoreSubmit.sln" /clean $(BUILDSTYLE) + devenv "JavaScriptCoreSubmit.sln" /build $(BUILDSTYLE) set PATH=$(SYSTEMDRIVE)\cygwin\bin;$(PATH) xcopy "$(SRCROOT)\AppleInternal\tests\SunSpider\*" "%ConfigurationBuildDir%\tests\SunSpider" /e/v/i/h/y cd "%ConfigurationBuildDir%\tests\SunSpider" @@ -20,7 +23,8 @@ install: cd "$(SRCROOT)\JavaScriptCore.vcproj" devenv "JavaScriptCoreSubmit.sln" /build Release_PGO_Optimize !ELSE - devenv "JavaScriptCoreSubmit.sln" /rebuild $(BUILDSTYLE) + devenv "JavaScriptCoreSubmit.sln" /clean $(BUILDSTYLE) + devenv "JavaScriptCoreSubmit.sln" /build $(BUILDSTYLE) !ENDIF -xcopy "%ConfigurationBuildDir%\bin\JavaScriptCore.dll" "$(DSTROOT)\AppleInternal\bin\" /e/v/i/h/y -xcopy "%ConfigurationBuildDir%\bin\JavaScriptCore_debug.dll" "$(DSTROOT)\AppleInternal\bin\" /e/v/i/h/y diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln index 0834a3fe8..84d5e16a6 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore.sln @@ -11,7 +11,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsc", "jsc\jsc.vcproj", "{C {011D10F1-B656-4A1B-A0C3-3842F02122C5} = {011D10F1-B656-4A1B-A0C3-3842F02122C5} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTF", "WTF\WTF.vcproj", "{AA8A5A85-592B-4357-BC60-E0E91E026AF6}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTF", "..\..\WTF\WTF.vcproj\WTF.vcproj", "{AA8A5A85-592B-4357-BC60-E0E91E026AF6}" ProjectSection(ProjectDependencies) = postProject {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} = {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} EndProjectSection @@ -26,7 +26,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testRegExp", "testRegExp\te {C59E5129-B453-49B7-A52B-1E104715F76E} = {C59E5129-B453-49B7-A52B-1E104715F76E} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTFGenerated", "WTF\WTFGenerated.vcproj", "{5AE5F5E4-782D-4F63-B4D7-3977B52B9950}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTFGenerated", "..\..\WTF\WTF.vcproj\WTFGenerated.vcproj", "{5AE5F5E4-782D-4F63-B4D7-3977B52B9950}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def index c50a4252b..bae50e204 100644..100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.def @@ -1,7 +1,5 @@ EXPORTS - ??$strtod@$00@WTF@@YANPBDPAPAD@Z - ??$strtod@$0A@@WTF@@YANPBDPAPAD@Z ??0ArrayBufferView@WTF@@IAE@V?$PassRefPtr@VArrayBuffer@WTF@@@1@I@Z ??0CString@WTF@@QAE@PBD@Z ??0CString@WTF@@QAE@PBDI@Z @@ -11,8 +9,6 @@ EXPORTS ??0DropAllLocks@JSLock@JSC@@QAE@W4JSLockBehavior@2@@Z ??0DynamicGlobalObjectScope@JSC@@QAE@AAVJSGlobalData@1@PAVJSGlobalObject@1@@Z ??0InternalFunction@JSC@@IAE@PAVJSGlobalObject@1@PAVStructure@1@@Z - ??0JSArray@JSC@@IAE@AAVJSGlobalData@1@PAVStructure@1@@Z - ??0JSByteArray@JSC@@AAE@PAVExecState@1@PAVStructure@1@PAVByteArray@WTF@@@Z ??0JSLock@JSC@@QAE@PAVExecState@1@@Z ??0MD5@WTF@@QAE@XZ ??0Mutex@WTF@@QAE@XZ @@ -45,6 +41,7 @@ EXPORTS ??8JSC@@YA_NABVUString@0@0@Z ??8WTF@@YA_NABVCString@0@0@Z ?EcmaScriptConverter@DoubleToStringConverter@double_conversion@WTF@@SAABV123@XZ + ?StringToDouble@StringToDoubleConverter@double_conversion@WTF@@SANPBDIPAI@Z ?ToExponential@DoubleToStringConverter@double_conversion@WTF@@QBE_NNHPAVStringBuilder@23@@Z ?ToFixed@DoubleToStringConverter@double_conversion@WTF@@QBE_NNHPAVStringBuilder@23@@Z ?ToPrecision@DoubleToStringConverter@double_conversion@WTF@@QBE_NNHPAVStringBuilder@23@@Z @@ -65,7 +62,6 @@ EXPORTS ?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVExecState@2@PAVStringImpl@4@@Z ?addSlowCase@Identifier@JSC@@CA?AV?$PassRefPtr@VStringImpl@WTF@@@WTF@@PAVJSGlobalData@2@PAVStringImpl@4@@Z ?addStaticGlobals@JSGlobalObject@JSC@@IAEXPAUGlobalPropertyInfo@12@H@Z - ?allocatePropertyStorage@JSObject@JSC@@QAEXAAVJSGlobalData@2@II@Z ?allocateSlowCase@MarkedAllocator@JSC@@AAEPAXXZ ?append@StringBuilder@WTF@@QAEXPBEI@Z ?append@StringBuilder@WTF@@QAEXPB_WI@Z @@ -93,7 +89,6 @@ EXPORTS ?checksum@MD5@WTF@@QAEXAAV?$Vector@E$0BA@@2@@Z ?className@JSObject@JSC@@SA?AVUString@2@PBV12@@Z ?clear@SourceProviderCache@JSC@@QAEXXZ - ?clearBuiltinStructures@JSGlobalData@JSC@@QAEXXZ ?clearRareData@JSGlobalObject@JSC@@CAXPAVJSCell@2@@Z ?collate@Collator@WTF@@QBE?AW4Result@12@PB_WI0I@Z ?collectAllGarbage@Heap@JSC@@QAEXXZ @@ -106,8 +101,7 @@ EXPORTS ?convertLatin1ToUTF8@Unicode@WTF@@YA?AW4ConversionResult@12@PAPBEPBEPAPADPAD@Z ?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@JSFunction@JSC@@SAPAV12@PAVExecState@2@PAVJSGlobalObject@2@HABVIdentifier@2@P6I_J0@Z3@Z + ?create@JSFunction@JSC@@SAPAV12@PAVExecState@2@PAVJSGlobalObject@2@HABVIdentifier@2@P6I_J0@ZW4Intrinsic@2@3@Z ?create@JSGlobalData@JSC@@SA?AV?$PassRefPtr@VJSGlobalData@JSC@@@WTF@@W4ThreadStackType@2@W4HeapSize@2@@Z ?create@OpaqueJSString@@SA?AV?$PassRefPtr@UOpaqueJSString@@@WTF@@ABVUString@JSC@@@Z ?create@RegExp@JSC@@SAPAV12@AAVJSGlobalData@2@ABVUString@2@W4RegExpFlags@2@@Z @@ -119,13 +113,13 @@ EXPORTS ?createReferenceError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z ?createSingleCharacterString@SmallStrings@JSC@@AAEXPAVJSGlobalData@2@E@Z ?createStackOverflowError@JSC@@YAPAVJSObject@1@PAVExecState@1@@Z - ?createStructure@JSByteArray@JSC@@SAPAVStructure@2@AAVJSGlobalData@2@PAVJSGlobalObject@2@VJSValue@2@PBUClassInfo@2@@Z ?createSyntaxError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z ?createTable@HashTable@JSC@@ABEXPAVJSGlobalData@2@@Z ?createThread@WTF@@YAIP6APAXPAX@Z0@Z ?createThread@WTF@@YAIP6APAXPAX@Z0PBD@Z ?createThread@WTF@@YAIP6AXPAX@Z0PBD@Z ?createTypeError@JSC@@YAPAVJSObject@1@PAVExecState@1@ABVUString@1@@Z + ?createNotEnoughArgumentsError@JSC@@YAPAVJSObject@1@PAVExecState@1@@Z ?cryptographicallyRandomNumber@WTF@@YAIXZ ?cryptographicallyRandomValues@WTF@@YAXPAXI@Z ?currentThread@WTF@@YAIXZ @@ -151,13 +145,13 @@ EXPORTS ?deleteTable@HashTable@JSC@@QBEXXZ ?despecifyDictionaryFunction@Structure@JSC@@QAEXAAVJSGlobalData@2@ABVIdentifier@2@@Z ?despecifyFunctionTransition@Structure@JSC@@SAPAV12@AAVJSGlobalData@2@PAV12@ABVIdentifier@2@@Z - ?destroy@Heap@JSC@@QAEXXZ - ?destroy@JSByteArray@JSC@@SAXPAVJSCell@2@@Z ?destroy@JSCell@JSC@@KAXPAV12@@Z ?destroy@JSGlobalObject@JSC@@SAXPAVJSCell@2@@Z + ?destroy@OutOfLineBits@BitVector@WTF@@SAXPAV123@@Z ?detach@Debugger@JSC@@UAEXPAVJSGlobalObject@2@@Z ?detachThread@WTF@@YAXI@Z ?didTimeOut@TimeoutChecker@JSC@@QAE_NPAVExecState@2@@Z + ?discardAllCompiledCode@Heap@JSC@@QAEXXZ ?displayName@JSFunction@JSC@@QAE?BVUString@2@PAVExecState@2@@Z ?dtoa@WTF@@YAXQADNAA_NAAHAAI@Z ?dumpSampleData@JSGlobalData@JSC@@QAEXPAVExecState@2@@Z @@ -180,6 +174,7 @@ EXPORTS ?fastZeroedMalloc@WTF@@YAPAXI@Z ?fillGetterPropertySlot@JSObject@JSC@@AAEXAAVPropertySlot@2@PAV?$WriteBarrierBase@W4Unknown@JSC@@@2@@Z ?finalize@WeakHandleOwner@JSC@@UAEXV?$Handle@W4Unknown@JSC@@@2@PAX@Z + ?findAllocator@WeakSet@JSC@@AAEPAUFreeCell@WeakBlock@2@XZ ?finishCreation@DateInstance@JSC@@IAEXAAVJSGlobalData@2@N@Z ?finishCreation@InternalFunction@JSC@@IAEXAAVJSGlobalData@2@ABVIdentifier@2@@Z ?finishCreation@JSArray@JSC@@IAEXAAVJSGlobalData@2@I@Z @@ -195,28 +190,26 @@ EXPORTS ?getCalculatedDisplayName@JSC@@YA?AVUString@1@PAVExecState@1@PAVJSObject@1@@Z ?getCallData@JSCell@JSC@@SA?AW4CallType@2@PAV12@AATCallData@2@@Z ?getConstructData@JSCell@JSC@@SA?AW4ConstructType@2@PAV12@AATConstructData@2@@Z + ?getCurrentLocalTime@WTF@@YAXPAUtm@@@Z ?getObject@JSCell@JSC@@QAEPAVJSObject@2@XZ - ?getOwnPropertyDescriptor@JSByteArray@JSC@@SA_NPAVJSObject@2@PAVExecState@2@ABVIdentifier@2@AAVPropertyDescriptor@2@@Z ?getOwnPropertyDescriptor@JSGlobalObject@JSC@@SA_NPAVJSObject@2@PAVExecState@2@ABVIdentifier@2@AAVPropertyDescriptor@2@@Z ?getOwnPropertyDescriptor@JSObject@JSC@@SA_NPAV12@PAVExecState@2@ABVIdentifier@2@AAVPropertyDescriptor@2@@Z - ?getOwnPropertyNames@JSByteArray@JSC@@SAXPAVJSObject@2@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z ?getOwnPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z ?getOwnPropertyNames@JSVariableObject@JSC@@SAXPAVJSObject@2@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z - ?getOwnPropertySlot@JSByteArray@JSC@@SA_NPAVJSCell@2@PAVExecState@2@ABVIdentifier@2@AAVPropertySlot@2@@Z ?getOwnPropertySlot@JSGlobalObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@ABVIdentifier@2@AAVPropertySlot@2@@Z ?getOwnPropertySlotByIndex@JSArray@JSC@@SA_NPAVJSCell@2@PAVExecState@2@IAAVPropertySlot@2@@Z - ?getOwnPropertySlotByIndex@JSByteArray@JSC@@SA_NPAVJSCell@2@PAVExecState@2@IAAVPropertySlot@2@@Z ?getOwnPropertySlotByIndex@JSObject@JSC@@SA_NPAVJSCell@2@PAVExecState@2@IAAVPropertySlot@2@@Z ?getPropertyDescriptor@JSObject@JSC@@QAE_NPAVExecState@2@ABVIdentifier@2@AAVPropertyDescriptor@2@@Z ?getPropertyNames@JSObject@JSC@@SAXPAV12@PAVExecState@2@AAVPropertyNameArray@2@W4EnumerationMode@2@@Z ?getSlice@ArgList@JSC@@QBEXHAAV12@@Z - ?getStackTrace@Interpreter@JSC@@SAXPAVJSGlobalData@2@HAAV?$Vector@UStackFrame@JSC@@$0A@@WTF@@@Z + ?getStackTrace@Interpreter@JSC@@SAXPAVJSGlobalData@2@AAV?$Vector@UStackFrame@JSC@@$0A@@WTF@@@Z ?getString@JSCell@JSC@@QBE?AVUString@2@PAVExecState@2@@Z ?getString@JSCell@JSC@@QBE_NPAVExecState@2@AAVUString@2@@Z ?getter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ ?globalExec@JSGlobalObject@JSC@@QAEPAVExecState@2@XZ ?globalObjectCount@Heap@JSC@@QAEIXZ - ?grow@HandleHeap@JSC@@AAEXXZ + ?grow@HandleSet@JSC@@AAEXXZ + ?growPropertyStorage@JSObject@JSC@@QAEPAV?$WriteBarrierBase@W4Unknown@JSC@@@2@AAVJSGlobalData@2@II@Z ?hasInstance@JSObject@JSC@@SA_NPAV12@PAVExecState@2@VJSValue@2@2@Z ?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@ABVIdentifier@2@@Z ?hasProperty@JSObject@JSC@@QBE_NPAVExecState@2@I@Z @@ -229,7 +222,7 @@ EXPORTS ?initializeMainThread@WTF@@YAXXZ ?initializeThreading@JSC@@YAXXZ ?initializeThreading@WTF@@YAXXZ - ?interpret@Yarr@JSC@@YAIPAUBytecodePattern@12@ABVUString@2@IIPAI@Z + ?interpret@Yarr@JSC@@YAIPAUBytecodePattern@12@ABVUString@2@IPAI@Z ?isAccessorDescriptor@PropertyDescriptor@JSC@@QBE_NXZ ?isBusy@Heap@JSC@@QAE_NXZ ?isDataDescriptor@PropertyDescriptor@JSC@@QBE_NXZ @@ -246,7 +239,7 @@ EXPORTS ?lock@Mutex@WTF@@QAEXXZ ?lockAtomicallyInitializedStaticMutex@WTF@@YAXXZ ?lockCount@JSLock@JSC@@SAHXZ - ?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@IPAV?$Vector@H$0CA@@WTF@@@Z + ?match@RegExp@JSC@@QAEHAAVJSGlobalData@2@ABVUString@2@IAAV?$Vector@H$0CA@@WTF@@@Z ?materializePropertyMap@Structure@JSC@@AAEXAAVJSGlobalData@2@@Z ?monotonicallyIncreasingTime@WTF@@YANXZ ?monthFromDayInYear@WTF@@YAHH_N@Z @@ -267,12 +260,12 @@ EXPORTS ?objectProtoFuncToString@JSC@@YI_JPAVExecState@1@@Z ?objectTypeCounts@Heap@JSC@@QAE?AV?$PassOwnPtr@V?$HashCountedSet@PBDU?$PtrHash@PBD@WTF@@U?$HashTraits@PBD@2@@WTF@@@WTF@@XZ ?parseDateFromNullTerminatedCharacters@WTF@@YANPBD@Z + ?parseDoubleFromLongString@Internal@WTF@@YANPB_WIAAI@Z ?profiler@Profiler@JSC@@SAPAV12@XZ ?protect@Heap@JSC@@QAEXVJSValue@2@@Z ?protectedGlobalObjectCount@Heap@JSC@@QAEIXZ ?protectedObjectCount@Heap@JSC@@QAEIXZ ?protectedObjectTypeCounts@Heap@JSC@@QAE?AV?$PassOwnPtr@V?$HashCountedSet@PBDU?$PtrHash@PBD@WTF@@U?$HashTraits@PBD@2@@WTF@@@WTF@@XZ - ?put@JSByteArray@JSC@@SAXPAVJSCell@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@AAVPutPropertySlot@2@@Z ?put@JSGlobalObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@AAVPutPropertySlot@2@@Z ?put@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@ABVIdentifier@2@VJSValue@2@AAVPutPropertySlot@2@@Z ?putByIndex@JSObject@JSC@@SAXPAVJSCell@2@PAVExecState@2@IVJSValue@2@_N@Z @@ -286,6 +279,7 @@ EXPORTS ?releaseDecommitted@OSAllocator@WTF@@SAXPAXI@Z ?releaseExecutableMemory@JSGlobalData@JSC@@QAEXXZ ?removeBlock@MarkedAllocator@JSC@@QAEXPAVMarkedBlock@2@@Z + ?reportAbandonedObjectGraph@Heap@JSC@@QAEXXZ ?reportExtraMemoryCostSlowCase@Heap@JSC@@AAEXI@Z ?reserveAndCommit@OSAllocator@WTF@@SAPAXIW4Usage@12@_N11@Z ?reserveCapacity@StringBuilder@WTF@@QAEXI@Z @@ -293,7 +287,8 @@ EXPORTS ?reset@TimeoutChecker@JSC@@QAEXXZ ?resetDateCache@JSGlobalData@JSC@@QAEXXZ ?resize@StringBuilder@WTF@@QAEXI@Z - ?resolveRope@JSString@JSC@@ABEXPAVExecState@2@@Z + ?resizeOutOfLine@BitVector@WTF@@AAEXI@Z + ?resolveRope@JSRopeString@JSC@@ABEXPAVExecState@2@@Z ?restoreAll@Profile@JSC@@QAEXXZ ?retrieveCallerFromVMCode@Interpreter@JSC@@QBE?AVJSValue@2@PAVExecState@2@PAVJSFunction@2@@Z ?retrieveLastCaller@Interpreter@JSC@@QBEXPAVExecState@2@AAH1AAVUString@2@AAVJSValue@2@@Z @@ -308,6 +303,7 @@ EXPORTS ?setPrototype@JSObject@JSC@@QAEXAAVJSGlobalData@2@VJSValue@2@@Z ?setSetter@PropertyDescriptor@JSC@@QAEXVJSValue@2@@Z ?setUndefined@PropertyDescriptor@JSC@@QAEXXZ + ?setUnwrappedObject@JSGlobalThis@JSC@@IAEXAAVJSGlobalData@2@PAVJSGlobalObject@2@@Z ?setUpStaticFunctionSlot@JSC@@YA_NPAVExecState@1@PBVHashEntry@1@PAVJSObject@1@ABVIdentifier@1@AAVPropertySlot@1@@Z ?setWritable@PropertyDescriptor@JSC@@QAEX_N@Z ?setter@PropertyDescriptor@JSC@@QBE?AVJSValue@2@XZ @@ -324,6 +320,7 @@ EXPORTS ?stopProfiling@Profiler@JSC@@QAE?AV?$PassRefPtr@VProfile@JSC@@@WTF@@PAVExecState@2@ABVUString@2@@Z ?stopSampling@JSGlobalData@JSC@@QAEXXZ ?substringSharingImpl@UString@JSC@@QBE?AV12@II@Z + ?suggestedNewPropertyStorageSize@Structure@JSC@@QAEIXZ ?symbolTableGet@JSVariableObject@JSC@@IAE_NABVIdentifier@2@AAVPropertyDescriptor@2@@Z ?synthesizePrototype@JSValue@JSC@@QBEPAVJSObject@2@PAVExecState@2@@Z ?thisObject@DebuggerCallFrame@JSC@@QBEPAVJSObject@2@XZ @@ -368,11 +365,12 @@ EXPORTS ?waitForThreadCompletion@WTF@@YAHI@Z ?waitForThreadCompletion@WTF@@YAHIPAPAX@Z ?writable@PropertyDescriptor@JSC@@QBE_NXZ - ?writeBarrier@HandleHeap@JSC@@QAEXPAVJSValue@2@ABV32@@Z + ?writeBarrier@HandleSet@JSC@@QAEXPAVJSValue@2@ABV32@@Z ?yield@WTF@@YAXXZ WTFGetBacktrace WTFInvokeCrashHook WTFLog + WTFLogAlways WTFLogVerbose WTFReportArgumentAssertionFailure WTFReportAssertionFailure diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj index 8599dedb8..e71b433e0 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj @@ -642,14 +642,6 @@ > </File> <File - RelativePath="..\..\wtf\DateMath.cpp" - > - </File> - <File - RelativePath="..\..\wtf\DateMath.h" - > - </File> - <File RelativePath="..\..\runtime\DatePrototype.cpp" > </File> @@ -778,11 +770,11 @@ > </File> <File - RelativePath="..\..\runtime\JSByteArray.cpp" + RelativePath="..\..\runtime\JSBoundFunction.cpp" > </File> <File - RelativePath="..\..\runtime\JSByteArray.h" + RelativePath="..\..\runtime\JSBoundFunction.h" > </File> <File @@ -810,14 +802,6 @@ > </File> <File - RelativePath="..\..\runtime\JSBoundFunction.cpp" - > - </File> - <File - RelativePath="..\..\runtime\JSBoundFunction.h" - > - </File> - <File RelativePath="..\..\runtime\JSGlobalData.cpp" > </File> @@ -905,6 +889,14 @@ RelativePath="..\..\runtime\JSString.h" > </File> + <File + RelativePath="..\..\runtime\JSStringJoiner.cpp" + > + </File> + <File + RelativePath="..\..\runtime\JSStringJoiner.h" + > + </File> <File RelativePath="..\..\runtime\JSType.h" > @@ -1098,10 +1090,22 @@ > </File> <File + RelativePath="..\..\runtime\RegExpCachedResult.cpp" + > + </File> + <File + RelativePath="..\..\runtime\RegExpCachedResult.h" + > + </File> + <File RelativePath="..\..\runtime\RegExpKey.h" > </File> <File + RelativePath="..\..\runtime\RegExpMatchesArray.cpp" + > + </File> + <File RelativePath="..\..\runtime\RegExpMatchesArray.h" > </File> @@ -1122,6 +1126,14 @@ > </File> <File + RelativePath="..\..\runtime\SamplingCounter.cpp" + > + </File> + <File + RelativePath="..\..\runtime\SamplingCounter.h" + > + </File> + <File RelativePath="..\..\runtime\ScopeChain.cpp" > </File> @@ -1133,14 +1145,6 @@ RelativePath="..\..\runtime\ScopeChainMark.h" > </File> - <File - RelativePath="..\..\runtime\SamplingCounter.cpp" - > - </File> - <File - RelativePath="..\..\runtime\SamplingCounter.h" - > - </File> <File RelativePath="..\..\runtime\SmallStrings.cpp" > @@ -1478,143 +1482,143 @@ Name="bytecode" > <File - RelativePath="..\..\bytecode\ExecutionCounter.cpp" + RelativePath="..\..\bytecode\CallLinkInfo.cpp" > </File> <File - RelativePath="..\..\bytecode\MethodOfGettingAValueProfile.cpp" + RelativePath="..\..\bytecode\CallLinkInfo.h" > </File> <File - RelativePath="..\..\bytecode\MethodOfGettingAValueProfile.h" + RelativePath="..\..\bytecode\CallLinkStatus.cpp" > </File> <File - RelativePath="..\..\bytecode\LazyOperandValueProfile.cpp" + RelativePath="..\..\bytecode\CallLinkStatus.h" > </File> <File - RelativePath="..\..\bytecode\LazyOperandValueProfile.h" + RelativePath="..\..\bytecode\CallReturnOffsetToBytecodeOffset.h" > </File> <File - RelativePath="..\..\bytecode\GetByIdStatus.h" + RelativePath="..\..\bytecode\CodeBlock.cpp" > </File> <File - RelativePath="..\..\bytecode\PutByIdStatus.h" + RelativePath="..\..\bytecode\CodeBlock.h" > </File> <File - RelativePath="..\..\bytecode\CallLinkStatus.h" + RelativePath="..\..\bytecode\CodeOrigin.h" > </File> <File - RelativePath="..\..\bytecode\MethodCallLinkStatus.h" + RelativePath="..\..\bytecode\CodeType.h" > </File> <File - RelativePath="..\..\bytecode\GetByIdStatus.cpp" + RelativePath="..\..\bytecode\EvalCodeCache.h" > </File> <File - RelativePath="..\..\bytecode\PutByIdStatus.cpp" + RelativePath="..\..\bytecode\ExecutionCounter.cpp" > </File> <File - RelativePath="..\..\bytecode\CallLinkStatus.cpp" + RelativePath="..\..\bytecode\ExpressionRangeInfo.h" > </File> <File - RelativePath="..\..\bytecode\MethodCallLinkStatus.cpp" + RelativePath="..\..\bytecode\GetByIdStatus.cpp" > </File> <File - RelativePath="..\..\bytecode\HandlerInfo.h" + RelativePath="..\..\bytecode\GetByIdStatus.h" > </File> <File - RelativePath="..\..\bytecode\CallLinkInfo.cpp" + RelativePath="..\..\bytecode\GlobalResolveInfo.h" > </File> <File - RelativePath="..\..\bytecode\LineInfo.h" + RelativePath="..\..\bytecode\HandlerInfo.h" > </File> <File - RelativePath="..\..\bytecode\MethodCallLinkInfo.h" + RelativePath="..\..\bytecode\Instruction.h" > </File> <File - RelativePath="..\..\bytecode\CallReturnOffsetToBytecodeOffset.h" + RelativePath="..\..\bytecode\JumpTable.cpp" > </File> <File - RelativePath="..\..\bytecode\CodeType.h" + RelativePath="..\..\bytecode\JumpTable.h" > </File> <File - RelativePath="..\..\bytecode\ExpressionRangeInfo.h" + RelativePath="..\..\bytecode\LazyOperandValueProfile.cpp" > </File> <File - RelativePath="..\..\bytecode\MethodCallLinkInfo.cpp" + RelativePath="..\..\bytecode\LazyOperandValueProfile.h" > </File> <File - RelativePath="..\..\bytecode\CallLinkInfo.h" + RelativePath="..\..\bytecode\LineInfo.h" > </File> <File - RelativePath="..\..\bytecode\GlobalResolveInfo.h" + RelativePath="..\..\bytecode\MethodCallLinkInfo.cpp" > </File> <File - RelativePath="..\..\bytecode\CodeBlock.cpp" + RelativePath="..\..\bytecode\MethodCallLinkInfo.h" > </File> <File - RelativePath="..\..\bytecode\CodeBlock.h" + RelativePath="..\..\bytecode\MethodCallLinkStatus.cpp" > </File> <File - RelativePath="..\..\bytecode\CodeOrigin.h" + RelativePath="..\..\bytecode\MethodCallLinkStatus.h" > </File> <File - RelativePath="..\..\bytecode\EvalCodeCache.h" + RelativePath="..\..\bytecode\MethodOfGettingAValueProfile.cpp" > </File> <File - RelativePath="..\..\bytecode\Instruction.h" + RelativePath="..\..\bytecode\MethodOfGettingAValueProfile.h" > </File> <File - RelativePath="..\..\bytecode\JumpTable.cpp" + RelativePath="..\..\bytecode\Opcode.cpp" > </File> <File - RelativePath="..\..\bytecode\JumpTable.h" + RelativePath="..\..\bytecode\Opcode.h" > </File> <File - RelativePath="..\..\bytecode\Opcode.cpp" + RelativePath="..\..\bytecode\PolymorphicPutByIdList.cpp" > </File> <File - RelativePath="..\..\bytecode\Opcode.h" + RelativePath="..\..\bytecode\PredictedType.cpp" > </File> <File - RelativePath="..\..\bytecode\PolymorphicPutByIdList.cpp" + RelativePath="..\..\bytecode\PredictedType.h" > </File> <File - RelativePath="..\..\bytecode\PredictedType.cpp" + RelativePath="..\..\bytecode\PutByIdStatus.cpp" > </File> <File - RelativePath="..\..\bytecode\PredictedType.h" + RelativePath="..\..\bytecode\PutByIdStatus.h" > </File> <File @@ -1706,22 +1710,22 @@ > </File> </Filter> - <Filter - Name="dfg" - > - <File - RelativePath="..\..\dfg\DFGDriver.h" - > - </File> - <File - RelativePath="..\..\dfg\DFGIntrinsic.h" - > - </File> - <File - RelativePath="..\..\dfg\DFGOSREntry.h" - > - </File> - </Filter> + <Filter + Name="dfg" + > + <File + RelativePath="..\..\dfg\DFGDriver.h" + > + </File> + <File + RelativePath="..\..\dfg\DFGIntrinsic.h" + > + </File> + <File + RelativePath="..\..\dfg\DFGOSREntry.h" + > + </File> + </Filter> <Filter Name="yarr" > @@ -1730,6 +1734,14 @@ > </File> <File + RelativePath="..\..\yarr\YarrCanonicalizeUCS2.cpp" + > + </File> + <File + RelativePath="..\..\yarr\YarrCanonicalizeUCS2.h" + > + </File> + <File RelativePath="..\..\yarr\YarrInterpreter.cpp" > </File> @@ -1810,35 +1822,35 @@ > </File> <File - RelativePath="..\..\jit\JITInlineMethods.h" + RelativePath="..\..\jit\JITExceptions.cpp" > </File> <File - RelativePath="..\..\jit\JITOpcodes.cpp" + RelativePath="..\..\jit\JITExceptions.h" > </File> <File - RelativePath="..\..\jit\JITOpcodes32_64.cpp" + RelativePath="..\..\jit\JITInlineMethods.h" > </File> <File - RelativePath="..\..\jit\JITPropertyAccess.cpp" + RelativePath="..\..\jit\JITOpcodes.cpp" > </File> <File - RelativePath="..\..\jit\JITPropertyAccess32_64.cpp" + RelativePath="..\..\jit\JITOpcodes32_64.cpp" > </File> <File - RelativePath="..\..\jit\JITStubCall.h" + RelativePath="..\..\jit\JITPropertyAccess.cpp" > </File> <File - RelativePath="..\..\jit\JITExceptions.cpp" + RelativePath="..\..\jit\JITPropertyAccess32_64.cpp" > </File> <File - RelativePath="..\..\jit\JITExceptions.h" + RelativePath="..\..\jit\JITStubCall.h" > </File> <File @@ -2065,158 +2077,198 @@ <Filter Name="heap" > - <File - RelativePath="..\..\heap\CopiedAllocator.h" - > - </File> - <File - RelativePath="..\..\heap\CopiedBlock.h" - > - </File> - <File - RelativePath="..\..\heap\CopiedSpace.cpp" - > - </File> - <File - RelativePath="..\..\heap\CopiedSpace.h" - > - </File> - <File - RelativePath="..\..\heap\CopiedSpaceInlineMethods.h" - > - </File> - <File - RelativePath="..\..\heap\ConservativeRoots.cpp" - > - </File> - <File - RelativePath="..\..\heap\ConservativeRoots.h" - > - </File> - <File - RelativePath="..\..\heap\GCAssertions.h" - > - </File> - <File - RelativePath="..\..\heap\MachineStackMarker.cpp" - > - </File> - <File - RelativePath="..\..\heap\MachineStackMarker.h" - > - </File> - <File - RelativePath="..\..\heap\MarkedAllocator.cpp" - > - </File> - <File - RelativePath="..\..\heap\MarkedAllocator.h" - > - </File> - <File - RelativePath="..\..\heap\MarkedBlock.cpp" - > - </File> - <File - RelativePath="..\..\heap\MarkedBlock.h" - > - </File> - <File - RelativePath="..\..\heap\MarkedSpace.cpp" - > - </File> - <File - RelativePath="..\..\heap\MarkedSpace.h" - > - </File> - <File - RelativePath="..\..\heap\MarkStack.cpp" - > - </File> - <File - RelativePath="..\..\heap\MarkStack.h" - > - </File> - <File - RelativePath="..\..\heap\HeapRootVisitor.h" - > - </File> - <File - RelativePath="..\..\heap\Heap.cpp" - > - </File> - <File - RelativePath="..\..\heap\Heap.h" - > - </File> - <File - RelativePath="..\..\heap\HeapBlock.h" - > - </File> - <File - RelativePath="..\..\heap\Strong.h" - > - </File> - <File - RelativePath="..\..\heap\StrongInlines.h" - > - </File> - <File - RelativePath="..\..\heap\Handle.h" - > - </File> - <File - RelativePath="..\..\heap\HandleHeap.cpp" - > - </File> - <File - RelativePath="..\..\heap\HandleHeap.h" - > - </File> - <File - RelativePath="..\..\heap\HandleStack.cpp" - > - </File> - <File - RelativePath="..\..\heap\HandleStack.h" - > - </File> - <File - RelativePath="..\..\heap\DFGCodeBlocks.cpp" - > - </File> - <File - RelativePath="..\..\heap\DFGCodeBlocks.h" - > - </File> - <File - RelativePath="..\..\heap\Local.h" - > - </File> - <File - RelativePath="..\..\heap\LocalScope.h" - > - </File> - <File - RelativePath="..\..\heap\VTableSpectrum.h" - > - </File> - <File - RelativePath="..\..\heap\VTableSpectrum.cpp" - > - </File> - <File - RelativePath="..\..\heap\Weak.h" - > - </File> - <File - RelativePath="..\..\heap\WriteBarrierSupport.cpp" - > - </File> - <File - RelativePath="..\..\heap\WriteBarrierSupport.h" - > - </File> + <File + RelativePath="..\..\heap\ConservativeRoots.cpp" + > + </File> + <File + RelativePath="..\..\heap\ConservativeRoots.h" + > + </File> + <File + RelativePath="..\..\heap\CopiedAllocator.h" + > + </File> + <File + RelativePath="..\..\heap\CopiedBlock.h" + > + </File> + <File + RelativePath="..\..\heap\CopiedSpace.cpp" + > + </File> + <File + RelativePath="..\..\heap\CopiedSpace.h" + > + </File> + <File + RelativePath="..\..\heap\CopiedSpaceInlineMethods.h" + > + </File> + <File + RelativePath="..\..\heap\DFGCodeBlocks.cpp" + > + </File> + <File + RelativePath="..\..\heap\DFGCodeBlocks.h" + > + </File> + <File + RelativePath="..\..\heap\GCAssertions.h" + > + </File> + <File + RelativePath="..\..\heap\Handle.h" + > + </File> + <File + RelativePath="..\..\heap\HandleSet.cpp" + > + </File> + <File + RelativePath="..\..\heap\HandleSet.h" + > + </File> + <File + RelativePath="..\..\heap\WeakBlock.cpp" + > + </File> + <File + RelativePath="..\..\heap\WeakBlock.h" + > + </File> + <File + RelativePath="..\..\heap\WeakSet.cpp" + > + </File> + <File + RelativePath="..\..\heap\WeakSet.h" + > + </File> + <File + RelativePath="..\..\heap\WeakSetInlines.h" + > + </File> + <File + RelativePath="..\..\heap\WeakImpl.h" + > + </File> + <File + RelativePath="..\..\heap\WeakHandleOwner.cpp" + > + </File> + <File + RelativePath="..\..\heap\WeakHandleOwner.h" + > + </File> + <File + RelativePath="..\..\heap\HandleStack.cpp" + > + </File> + <File + RelativePath="..\..\heap\HandleStack.h" + > + </File> + <File + RelativePath="..\..\heap\BlockAllocator.cpp" + > + </File> + <File + RelativePath="..\..\heap\BlockAllocator.h" + > + </File> + <File + RelativePath="..\..\heap\Heap.cpp" + > + </File> + <File + RelativePath="..\..\heap\Heap.h" + > + </File> + <File + RelativePath="..\..\heap\HeapBlock.h" + > + </File> + <File + RelativePath="..\..\heap\HeapRootVisitor.h" + > + </File> + <File + RelativePath="..\..\heap\Local.h" + > + </File> + <File + RelativePath="..\..\heap\LocalScope.h" + > + </File> + <File + RelativePath="..\..\heap\MachineStackMarker.cpp" + > + </File> + <File + RelativePath="..\..\heap\MachineStackMarker.h" + > + </File> + <File + RelativePath="..\..\heap\MarkedAllocator.cpp" + > + </File> + <File + RelativePath="..\..\heap\MarkedAllocator.h" + > + </File> + <File + RelativePath="..\..\heap\MarkedBlock.cpp" + > + </File> + <File + RelativePath="..\..\heap\MarkedBlock.h" + > + </File> + <File + RelativePath="..\..\heap\MarkedSpace.cpp" + > + </File> + <File + RelativePath="..\..\heap\MarkedSpace.h" + > + </File> + <File + RelativePath="..\..\heap\MarkStack.cpp" + > + </File> + <File + RelativePath="..\..\heap\MarkStack.h" + > + </File> + <File + RelativePath="..\..\heap\Strong.h" + > + </File> + <File + RelativePath="..\..\heap\StrongInlines.h" + > + </File> + <File + RelativePath="..\..\heap\VTableSpectrum.cpp" + > + </File> + <File + RelativePath="..\..\heap\VTableSpectrum.h" + > + </File> + <File + RelativePath="..\..\heap\Weak.h" + > + </File> + <File + RelativePath="..\..\heap\WriteBarrierSupport.cpp" + > + </File> + <File + RelativePath="..\..\heap\WriteBarrierSupport.h" + > + </File> </Filter> <File RelativePath="..\..\config.h" diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops index b0b45d38d..fac0af564 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreCommon.vsprops @@ -6,7 +6,7 @@ > <Tool Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../llint/;../../runtime/;../../tools/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(ConfigurationBuildDir)\include";"$(ConfigurationBuildDir)\include\JavaScriptCore";"$(ConfigurationBuildDir)\include\private";"$(WebKitLibrariesDir)\include\pthreads"" + AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\";../../;../../API/;../../parser/;../../bytecompiler/;../../dfg/;../../jit/;../../llint/;../../runtime/;../../tools/;../../bytecode/;../../interpreter/;../../wtf/;../../profiler;../../assembler/;../../debugger/;../../heap/;"$(WebKitLibrariesDir)\include";"$(WebKitLibrariesDir)\include\private";"$(ConfigurationBuildDir)\include";"$(ConfigurationBuildDir)\include\JavaScriptCore";"$(ConfigurationBuildDir)\include\private";"$(ConfigurationBuildDir)\include\private\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads"" PreprocessorDefinitions="__STD_C" ForcedIncludeFiles="ICUVersion.h" /> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj index 5e91b148b..9ab7648e3 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreGenerated.vcproj @@ -69,6 +69,15 @@ Name="VCNMakeTool" /> </Configuration> + <Configuration + Name="Release_PGO|Win32" + ConfigurationType="0" + InheritedPropertySheets=".\JavaScriptCoreGeneratedReleasePGO.vsprops" + > + <Tool + Name="VCNMakeTool" + /> + </Configuration> </Configurations> <References> </References> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops index c64bfc30a..79eca08ea 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGO.vsprops @@ -5,4 +5,12 @@ Name="JavaScriptCoreReleasePGO" InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCF.vsprops" > + <Tool + Name="VCLinkerTool" + AdditionalLibraryDirectories=""$(ConfigurationBuildDir)\..\Production\lib"" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\..\Production\include\private"" + /> </VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops index b38b28556..e8faef70b 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCoreReleasePGOOptimize.vsprops @@ -5,4 +5,8 @@ Name="JavaScriptCoreReleasePGOOptimize" InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\JavaScriptCoreCommon.vsprops;.\JavaScriptCoreCF.vsprops;.\JavaScriptCorePGOOptimize.vsprops" > + <Tool + Name="VCLinkerTool" + AdditionalLibraryDirectories=""$(ConfigurationBuildDir)\..\Production\lib"" + /> </VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln index 2ff339fb1..f2ccebe6f 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCoreSubmit.sln @@ -7,22 +7,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JavaScriptCore", "JavaScrip EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JavaScriptCoreGenerated", "JavaScriptCore\JavaScriptCoreGenerated.vcproj", "{4FF5BA11-59EC-4C24-8F52-F235C2E7D43A}" - ProjectSection(ProjectDependencies) = postProject - {AA8A5A85-592B-4357-BC60-E0E91E026AF6} = {AA8A5A85-592B-4357-BC60-E0E91E026AF6} - EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jsc", "jsc\jsc.vcproj", "{C59E5129-B453-49B7-A52B-1E104715F76E}" ProjectSection(ProjectDependencies) = postProject {011D10F1-B656-4A1B-A0C3-3842F02122C5} = {011D10F1-B656-4A1B-A0C3-3842F02122C5} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTF", "WTF\WTF.vcproj", "{AA8A5A85-592B-4357-BC60-E0E91E026AF6}" - ProjectSection(ProjectDependencies) = postProject - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} = {5AE5F5E4-782D-4F63-B4D7-3977B52B9950} - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WTFGenerated", "WTF\WTFGenerated.vcproj", "{5AE5F5E4-782D-4F63-B4D7-3977B52B9950}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug_All|Win32 = Debug_All|Win32 @@ -83,38 +73,6 @@ Global {C59E5129-B453-49B7-A52B-1E104715F76E}.Release_PGO|Win32.Build.0 = Release_PGO|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release|Win32.ActiveCfg = Release|Win32 {C59E5129-B453-49B7-A52B-1E104715F76E}.Release|Win32.Build.0 = Release|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.ActiveCfg = Debug|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Debug|Win32.Build.0 = Debug|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.ActiveCfg = Production|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Production|Win32.Build.0 = Production|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.ActiveCfg = Production|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO_Optimize|Win32.Build.0 = Production|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.ActiveCfg = Production|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release_PGO|Win32.Build.0 = Production|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release|Win32.ActiveCfg = Release|Win32 - {AA8A5A85-592B-4357-BC60-E0E91E026AF6}.Release|Win32.Build.0 = Release|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_All|Win32.ActiveCfg = Debug_All|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_All|Win32.Build.0 = Debug_All|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_Cairo_CFLite|Win32.ActiveCfg = Debug_Cairo_CFLite|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug_Cairo_CFLite|Win32.Build.0 = Debug_Cairo_CFLite|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug|Win32.ActiveCfg = Debug|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Debug|Win32.Build.0 = Debug|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Production|Win32.ActiveCfg = Production|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Production|Win32.Build.0 = Production|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_Cairo_CFLite|Win32.ActiveCfg = Release_Cairo_CFLite|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_Cairo_CFLite|Win32.Build.0 = Release_Cairo_CFLite|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO_Optimize|Win32.ActiveCfg = Production|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO_Optimize|Win32.Build.0 = Production|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO|Win32.ActiveCfg = Production|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release_PGO|Win32.Build.0 = Production|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release|Win32.ActiveCfg = Release|Win32 - {5AE5F5E4-782D-4F63-B4D7-3977B52B9950}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj deleted file mode 100644 index 3bf7817f3..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj +++ /dev/null @@ -1,1210 +0,0 @@ -<?xml version="1.0" encoding="windows-1251"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="WTF" - ProjectGUID="{AA8A5A85-592B-4357-BC60-E0E91E026AF6}" - RootNamespace="WTF" - Keyword="Win32Proj" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\WTFDebug.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\WTFRelease.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug_All|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\WTFDebugAll.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Production|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\WTFProduction.vsprops" - CharacterSet="1" - WholeProgramOptimization="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Release_Cairo_CFLite|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\WTFReleaseCairoCFLite.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - <Configuration - Name="Debug_Cairo_CFLite|Win32" - ConfigurationType="4" - InheritedPropertySheets=".\WTFDebugCairoCFLite.vsprops" - CharacterSet="1" - > - <Tool - Name="VCPreBuildEventTool" - /> - <Tool - Name="VCCustomBuildTool" - /> - <Tool - Name="VCXMLDataGeneratorTool" - /> - <Tool - Name="VCWebServiceProxyGeneratorTool" - /> - <Tool - Name="VCMIDLTool" - /> - <Tool - Name="VCCLCompilerTool" - /> - <Tool - Name="VCManagedResourceCompilerTool" - /> - <Tool - Name="VCResourceCompilerTool" - /> - <Tool - Name="VCPreLinkEventTool" - /> - <Tool - Name="VCLibrarianTool" - /> - <Tool - Name="VCALinkTool" - /> - <Tool - Name="VCXDCMakeTool" - /> - <Tool - Name="VCBscMakeTool" - /> - <Tool - Name="VCFxCopTool" - /> - <Tool - Name="VCPostBuildEventTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <Filter - Name="win" - > - <File - RelativePath="..\..\wtf\win\MainThreadWin.cpp" - > - </File> - <File - RelativePath="..\..\wtf\win\OwnPtrWin.cpp" - > - </File> - </Filter> - <Filter - Name="unicode" - > - <File - RelativePath="..\..\wtf\unicode\CharacterNames.h" - > - </File> - <File - RelativePath="..\..\wtf\unicode\Collator.h" - > - </File> - <File - RelativePath="..\..\wtf\unicode\Unicode.h" - > - </File> - <File - RelativePath="..\..\wtf\unicode\UnicodeMacrosFromICU.h" - > - </File> - <File - RelativePath="..\..\wtf\unicode\UTF8.cpp" - > - </File> - <File - RelativePath="..\..\wtf\unicode\UTF8.h" - > - </File> - <Filter - Name="icu" - > - <File - RelativePath="..\..\wtf\unicode\icu\CollatorICU.cpp" - > - </File> - <File - RelativePath="..\..\wtf\unicode\icu\UnicodeIcu.h" - > - </File> - </Filter> - </Filter> - <Filter - Name="text" - > - <File - RelativePath="..\..\wtf\text\ASCIIFastPath.h" - > - </File> - <File - RelativePath="..\..\wtf\text\AtomicString.cpp" - > - </File> - <File - RelativePath="..\..\wtf\text\AtomicString.h" - > - </File> - <File - RelativePath="..\..\wtf\text\AtomicStringHash.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\StringBuffer.h" - > - </File> - <File - RelativePath="..\..\wtf\text\StringBuilder.cpp" - > - </File> - <File - RelativePath="..\..\wtf\text\StringBuilder.h" - > - </File> - <File - RelativePath="..\..\wtf\text\StringConcatenate.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\StringOperators.h" - > - </File> - <File - RelativePath="..\..\wtf\text\StringStatics.cpp" - > - </File> - <File - RelativePath="..\..\wtf\text\WTFString.cpp" - > - </File> - <File - RelativePath="..\..\wtf\text\WTFString.h" - > - </File> - </Filter> - <Filter - Name="dtoa" - > - <File - RelativePath="..\..\wtf\dtoa\bignum-dtoa.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\bignum-dtoa.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\bignum.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\bignum.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\cached-powers.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\cached-powers.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\diy-fp.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\diy-fp.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\double-conversion.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\double-conversion.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\double.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\fast-dtoa.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\fast-dtoa.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\fixed-dtoa.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\fixed-dtoa.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\strtod.cc" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\strtod.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa\utils.h" - > - </File> - </Filter> - <Filter - Name="threads" - > - <File - RelativePath="..\..\wtf\threads\BinarySemaphore.cpp" - > - </File> - <File - RelativePath="..\..\wtf\threads\BinarySemaphore.h" - > - </File> - <Filter - Name="win" - > - <File - RelativePath="..\..\wtf\threads\win\BinarySemaphoreWin.cpp" - > - </File> - </Filter> - </Filter> - <File - RelativePath="..\..\wtf\Alignment.h" - > - </File> - <File - RelativePath="..\..\wtf\AlwaysInline.h" - > - </File> - <File - RelativePath="..\..\wtf\ArrayBuffer.cpp" - > - </File> - <File - RelativePath="..\..\wtf\ArrayBuffer.h" - > - </File> - <File - RelativePath="..\..\wtf\ArrayBufferView.cpp" - > - </File> - <File - RelativePath="..\..\wtf\ArrayBufferView.h" - > - </File> - <File - RelativePath="..\..\wtf\ASCIICType.h" - > - </File> - <File - RelativePath="..\..\wtf\Assertions.cpp" - > - </File> - <File - RelativePath="..\..\wtf\Assertions.h" - > - </File> - <File - RelativePath="..\..\wtf\Atomics.h" - > - </File> - <File - RelativePath="..\..\wtf\AVLTree.h" - > - </File> - <File - RelativePath="..\..\wtf\Bitmap.h" - > - </File> - <File - RelativePath="..\..\wtf\BitVector.cpp" - > - </File> - <File - RelativePath="..\..\wtf\BitVector.h" - > - </File> - <File - RelativePath="..\..\wtf\BlockStack.h" - > - </File> - <File - RelativePath="..\..\wtf\BloomFilter.h" - > - </File> - <File - RelativePath="..\..\wtf\BoundsCheckedPointer.h" - > - </File> - <File - RelativePath="..\..\wtf\BumpPointerAllocator.h" - > - </File> - <File - RelativePath="..\..\wtf\ByteArray.cpp" - > - </File> - <File - RelativePath="..\..\wtf\ByteArray.h" - > - </File> - <File - RelativePath="..\..\wtf\CheckedArithmetic.h" - > - </File> - <File - RelativePath="..\..\wtf\CheckedBoolean.h" - > - </File> - <File - RelativePath="..\..\wtf\Compiler.h" - > - </File> - <File - RelativePath="..\..\wtf\Complex.h" - > - </File> - <File - RelativePath="..\..\wtf\CryptographicallyRandomNumber.cpp" - > - </File> - <File - RelativePath="..\..\wtf\CryptographicallyRandomNumber.h" - > - </File> - <File - RelativePath="..\..\wtf\CurrentTime.cpp" - > - </File> - <File - RelativePath="..\..\wtf\CurrentTime.h" - > - </File> - <File - RelativePath="..\..\wtf\DataLog.cpp" - > - </File> - <File - RelativePath="..\..\wtf\DataLog.h" - > - </File> - <File - RelativePath="..\..\wtf\DecimalNumber.cpp" - > - </File> - <File - RelativePath="..\..\wtf\DecimalNumber.h" - > - </File> - <File - RelativePath="..\..\wtf\Decoder.h" - > - </File> - <File - RelativePath="..\..\wtf\Deque.h" - > - </File> - <File - RelativePath="..\..\wtf\DisallowCType.h" - > - </File> - <File - RelativePath="..\..\wtf\DoublyLinkedList.h" - > - </File> - <File - RelativePath="..\..\wtf\dtoa.cpp" - > - </File> - <File - RelativePath="..\..\wtf\dtoa.h" - > - </File> - <File - RelativePath="..\..\wtf\DynamicAnnotations.cpp" - > - </File> - <File - RelativePath="..\..\wtf\DynamicAnnotations.h" - > - </File> - <File - RelativePath="..\..\wtf\Encoder.h" - > - </File> - <File - RelativePath="..\..\wtf\FastAllocBase.h" - > - </File> - <File - RelativePath="..\..\wtf\FastMalloc.cpp" - > - <FileConfiguration - Name="Release|Win32" - > - <Tool - Name="VCCLCompilerTool" - DisableSpecificWarnings="4702" - /> - </FileConfiguration> - <FileConfiguration - Name="Production|Win32" - > - <Tool - Name="VCCLCompilerTool" - DisableSpecificWarnings="4702" - /> - </FileConfiguration> - <FileConfiguration - Name="Release_Cairo_CFLite|Win32" - > - <Tool - Name="VCCLCompilerTool" - DisableSpecificWarnings="4702" - /> - </FileConfiguration> - </File> - <File - RelativePath="..\..\wtf\FastMalloc.h" - > - </File> - <File - RelativePath="..\..\wtf\FixedArray.h" - > - </File> - <File - RelativePath="..\..\wtf\Float32Array.h" - > - </File> - <File - RelativePath="..\..\wtf\Float64Array.h" - > - </File> - <File - RelativePath="..\..\wtf\Forward.h" - > - </File> - <File - RelativePath="..\..\wtf\Functional.h" - > - </File> - <File - RelativePath="..\..\wtf\GetPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\HashCountedSet.h" - > - </File> - <File - RelativePath="..\..\wtf\HashFunctions.h" - > - </File> - <File - RelativePath="..\..\wtf\HashIterators.h" - > - </File> - <File - RelativePath="..\..\wtf\HashMap.h" - > - </File> - <File - RelativePath="..\..\wtf\HashSet.h" - > - </File> - <File - RelativePath="..\..\wtf\HashTable.cpp" - > - </File> - <File - RelativePath="..\..\wtf\HashTable.h" - > - </File> - <File - RelativePath="..\..\wtf\HashTraits.h" - > - </File> - <File - RelativePath="..\..\wtf\HexNumber.h" - > - </File> - <File - RelativePath="..\..\wtf\Int16Array.h" - > - </File> - <File - RelativePath="..\..\wtf\Int32Array.h" - > - </File> - <File - RelativePath="..\..\wtf\Int8Array.h" - > - </File> - <File - RelativePath="..\..\wtf\ListHashSet.h" - > - </File> - <File - RelativePath="..\..\wtf\ListRefPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\Locker.h" - > - </File> - <File - RelativePath="..\..\wtf\MainThread.cpp" - > - </File> - <File - RelativePath="..\..\wtf\MainThread.h" - > - </File> - <File - RelativePath="..\..\wtf\MallocZoneSupport.h" - > - </File> - <File - RelativePath="..\..\wtf\MathExtras.h" - > - </File> - <File - RelativePath="..\..\wtf\MD5.cpp" - > - </File> - <File - RelativePath="..\..\wtf\MD5.h" - > - </File> - <File - RelativePath="..\..\wtf\MessageQueue.h" - > - </File> - <File - RelativePath="..\..\wtf\MetaAllocator.cpp" - > - </File> - <File - RelativePath="..\..\wtf\MetaAllocator.h" - > - </File> - <File - RelativePath="..\..\wtf\MetaAllocatorHandle.h" - > - </File> - <File - RelativePath="..\..\wtf\Noncopyable.h" - > - </File> - <File - RelativePath="..\..\wtf\NonCopyingSort.h" - > - </File> - <File - RelativePath="..\..\wtf\NotFound.h" - > - </File> - <File - RelativePath="..\..\wtf\NullPtr.cpp" - > - </File> - <File - RelativePath="..\..\wtf\NullPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\NumberOfCores.cpp" - > - </File> - <File - RelativePath="..\..\wtf\NumberOfCores.h" - > - </File> - <File - RelativePath="..\..\wtf\OSAllocatorWin.cpp" - > - </File> - <File - RelativePath="..\..\wtf\OSRandomSource.cpp" - > - </File> - <File - RelativePath="..\..\wtf\OSRandomSource.h" - > - </File> - <File - RelativePath="..\..\wtf\OwnArrayPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\OwnPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\OwnPtrCommon.h" - > - </File> - <File - RelativePath="..\..\wtf\PackedIntVector.h" - > - </File> - <File - RelativePath="..\..\wtf\PageAllocation.h" - > - </File> - <File - RelativePath="..\..\wtf\PageAllocationAligned.cpp" - > - </File> - <File - RelativePath="..\..\wtf\PageAllocationAligned.h" - > - </File> - <File - RelativePath="..\..\wtf\PageBlock.cpp" - > - </File> - <File - RelativePath="..\..\wtf\PageBlock.h" - > - </File> - <File - RelativePath="..\..\wtf\PageReservation.h" - > - </File> - <File - RelativePath="..\..\wtf\ParallelJobs.h" - > - </File> - <File - RelativePath="..\..\wtf\ParallelJobsGeneric.cpp" - > - </File> - <File - RelativePath="..\..\wtf\ParallelJobsGeneric.h" - > - </File> - <File - RelativePath="..\..\wtf\ParallelJobsLibdispatch.h" - > - </File> - <File - RelativePath="..\..\wtf\ParallelJobsOpenMP.h" - > - </File> - <File - RelativePath="..\..\wtf\PassOwnArrayPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\PassOwnPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\PassRefPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\PassTraits.h" - > - </File> - <File - RelativePath="..\..\wtf\Platform.h" - > - </File> - <File - RelativePath="..\..\wtf\PossiblyNull.h" - > - </File> - <File - RelativePath="..\..\wtf\RandomNumber.cpp" - > - </File> - <File - RelativePath="..\..\wtf\RandomNumber.h" - > - </File> - <File - RelativePath="..\..\wtf\RandomNumberSeed.h" - > - </File> - <File - RelativePath="..\..\wtf\RedBlackTree.h" - > - </File> - <File - RelativePath="..\..\wtf\RefCounted.h" - > - </File> - <File - RelativePath="..\..\wtf\RefCountedLeakCounter.cpp" - > - </File> - <File - RelativePath="..\..\wtf\RefCountedLeakCounter.h" - > - </File> - <File - RelativePath="..\..\wtf\RefPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\RefPtrHashMap.h" - > - </File> - <File - RelativePath="..\..\wtf\RetainPtr.h" - > - </File> - <File - RelativePath="..\..\wtf\SegmentedVector.h" - > - </File> - <File - RelativePath="..\..\wtf\SentinelLinkedList.h" - > - </File> - <File - RelativePath="..\..\wtf\SHA1.cpp" - > - </File> - <File - RelativePath="..\..\wtf\SHA1.h" - > - </File> - <File - RelativePath="..\..\wtf\SinglyLinkedList.h" - > - </File> - <File - RelativePath="..\..\wtf\SizeLimits.cpp" - > - </File> - <File - RelativePath="..\..\wtf\StackBounds.cpp" - > - </File> - <File - RelativePath="..\..\wtf\StackBounds.h" - > - </File> - <File - RelativePath="..\..\wtf\StaticConstructors.h" - > - </File> - <File - RelativePath="..\..\wtf\StdLibExtras.h" - > - </File> - <File - RelativePath="..\..\wtf\StringExtras.cpp" - > - </File> - <File - RelativePath="..\..\wtf\StringExtras.h" - > - </File> - <File - RelativePath="..\..\wtf\StringHasher.h" - > - </File> - <File - RelativePath="..\..\wtf\TCPackedCache.h" - > - </File> - <File - RelativePath="..\..\wtf\TCPageMap.h" - > - </File> - <File - RelativePath="..\..\wtf\TCSpinLock.h" - > - </File> - <File - RelativePath="..\..\wtf\TCSystemAlloc.cpp" - > - </File> - <File - RelativePath="..\..\wtf\TCSystemAlloc.h" - > - </File> - <File - RelativePath="..\..\wtf\TemporaryChange.h" - > - </File> - <File - RelativePath="..\..\wtf\Threading.cpp" - > - </File> - <File - RelativePath="..\..\wtf\Threading.h" - > - </File> - <File - RelativePath="..\..\wtf\ThreadingPrimitives.h" - > - </File> - <File - RelativePath="..\..\wtf\ThreadingWin.cpp" - > - </File> - <File - RelativePath="..\..\wtf\ThreadRestrictionVerifier.h" - > - </File> - <File - RelativePath="..\..\wtf\ThreadSafeRefCounted.h" - > - </File> - <File - RelativePath="..\..\wtf\ThreadSpecific.h" - > - </File> - <File - RelativePath="..\..\wtf\ThreadSpecificWin.cpp" - > - </File> - <File - RelativePath="..\..\wtf\TypeTraits.cpp" - > - </File> - <File - RelativePath="..\..\wtf\TypeTraits.h" - > - </File> - <File - RelativePath="..\..\wtf\UInt16Array.h" - > - </File> - <File - RelativePath="..\..\wtf\UInt32Array.h" - > - </File> - <File - RelativePath="..\..\wtf\UInt8Array.h" - > - </File> - <File - RelativePath="..\..\wtf\UnusedParam.h" - > - </File> - <File - RelativePath="..\..\wtf\ValueCheck.h" - > - </File> - <File - RelativePath="..\..\wtf\Vector.h" - > - </File> - <File - RelativePath="..\..\wtf\Vector3.h" - > - </File> - <File - RelativePath="..\..\wtf\VectorTraits.h" - > - </File> - <File - RelativePath="..\..\wtf\VMTags.h" - > - </File> - <File - RelativePath="..\..\wtf\WTFThreadData.cpp" - > - </File> - <File - RelativePath="..\..\wtf\WTFThreadData.h" - > - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFCommon.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFCommon.vsprops deleted file mode 100644 index ed682216b..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFCommon.vsprops +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFCommon" - OutputDirectory="$(ConfigurationBuildDir)\lib" - > - <Tool - Name="VCCLCompilerTool" - AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\obj\JavaScriptCore\DerivedSources\";../../;"../../os-win32/";../../parser/;../../wtf/;../../wtf/threads;../../wtf/unicode/;"$(ConfigurationBuildDir)\include\private";"$(WebKitLibrariesDir)\include";../../../icu/include;../../bindings;../../bindings/c;../../bindings/jni;"$(ConfigurationBuildDir)\include\JavaScriptCore";"$(WebKitLibrariesDir)\include\pthreads"" - PreprocessorDefinitions="__STD_C" - ForcedIncludeFiles="ICUVersion.h" - ProgramDataBaseFileName="$(OutDir)\$(TargetName).vc80.pdb" - /> - <Tool - Name="VCLibrarianTool" - AdditionalDependencies="user32.lib" - OutputFile="$(OutDir)\$(ProjectName)$(WebKitConfigSuffix).lib" - /> -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebug.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebug.vsprops deleted file mode 100644 index ecad463ee..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebug.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFDebug" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\WTFCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugAll.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugAll.vsprops deleted file mode 100644 index 511618ff5..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugAll.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFDebugAll" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\WTFCommon.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugCairoCFLite.vsprops deleted file mode 100644 index 3ef5c6c93..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFDebugCairoCFLite.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFDebugCairoCFLite" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;.\WTFCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.make b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.make deleted file mode 100644 index e7896fdfb..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.make +++ /dev/null @@ -1,13 +0,0 @@ -all: - touch "%ConfigurationBuildDir%\buildfailed" - bash build-generated-files.sh "%ConfigurationBuildDir%" "$(WEBKITLIBRARIESDIR)" -!IF "$(OFFICIAL_BUILD)"!="1" - bash -c "python work-around-vs-dependency-tracking-bugs.py" -!ENDIF - copy-files.cmd - - -del "%ConfigurationBuildDir%\buildfailed" - -clean: - -del "%ConfigurationBuildDir%\buildfailed" - copy-files.cmd clean diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.vcproj deleted file mode 100644 index 3cb825062..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGenerated.vcproj +++ /dev/null @@ -1,95 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioProject - ProjectType="Visual C++" - Version="8.00" - Name="WTFGenerated" - ProjectGUID="{5AE5F5E4-782D-4F63-B4D7-3977B52B9950}" - RootNamespace="WTFGenerated" - Keyword="MakeFileProj" - > - <Platforms> - <Platform - Name="Win32" - /> - </Platforms> - <ToolFiles> - </ToolFiles> - <Configurations> - <Configuration - Name="Debug|Win32" - ConfigurationType="0" - InheritedPropertySheets=".\WTFGeneratedDebug.vsprops" - > - <Tool - Name="VCNMakeTool" - /> - </Configuration> - <Configuration - Name="Debug_All|Win32" - ConfigurationType="0" - InheritedPropertySheets=".\WTFGeneratedDebugAll.vsprops" - > - <Tool - Name="VCNMakeTool" - /> - </Configuration> - <Configuration - Name="Release|Win32" - ConfigurationType="0" - InheritedPropertySheets=".\WTFGeneratedRelease.vsprops" - > - <Tool - Name="VCNMakeTool" - /> - </Configuration> - <Configuration - Name="Production|Win32" - ConfigurationType="0" - InheritedPropertySheets=".\WTFGeneratedProduction.vsprops" - > - <Tool - Name="VCNMakeTool" - /> - </Configuration> - <Configuration - Name="Release_Cairo_CFLite|Win32" - ConfigurationType="0" - InheritedPropertySheets=".\WTFGeneratedReleaseCairoCFLite.vsprops" - > - <Tool - Name="VCNMakeTool" - /> - </Configuration> - <Configuration - Name="Debug_Cairo_CFLite|Win32" - ConfigurationType="0" - InheritedPropertySheets=".\WTFGeneratedDebugCairoCFLite.vsprops" - > - <Tool - Name="VCNMakeTool" - /> - </Configuration> - </Configurations> - <References> - </References> - <Files> - <File - RelativePath=".\build-generated-files.sh" - > - </File> - <File - RelativePath=".\copy-files.cmd" - > - </File> - <File - RelativePath=".\work-around-vs-dependency-tracking-bugs.py" - > - </File> - <File - RelativePath=".\WTFGenerated.make" - > - </File> - </Files> - <Globals> - </Globals> -</VisualStudioProject> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedCommon.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedCommon.vsprops deleted file mode 100644 index 5173df8ef..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedCommon.vsprops +++ /dev/null @@ -1,14 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFGeneratedCommon" - OutputDirectory="$(ConfigurationBuildDir)\lib" - > - <Tool - Name="VCNMakeTool" - BuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f WTFGenerated.make" - ReBuildCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f WTFGenerated.make clean
nmake -f WTFGenerated.make" - CleanCommandLine="%SystemDrive%\cygwin\bin\which.exe bash
if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH%
cmd /c

set CONFIGURATIONBUILDDIR=$(WebKitOutputDir)\$(ConfigurationName)
set PRODUCTION=$(PRODUCTION)
nmake /nologo -f WTFGenerated.make clean" - /> -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebug.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebug.vsprops deleted file mode 100644 index bc16aca94..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebug.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFGeneratedDebug" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;.\WTFGeneratedCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugAll.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugAll.vsprops deleted file mode 100644 index cacea402c..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugAll.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFGeneratedDebugAll" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_all.vsprops;.\WTFGeneratedCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugCairoCFLite.vsprops deleted file mode 100644 index fbc371372..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedDebugCairoCFLite.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFGeneratedDebugCairoCFLite" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\debug_wincairo.vsprops;.\WTFGeneratedCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedProduction.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedProduction.vsprops deleted file mode 100644 index 3e49ed6ea..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedProduction.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFGeneratedProduction" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\WTFGeneratedCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedRelease.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedRelease.vsprops deleted file mode 100644 index 74a4debaa..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedRelease.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFGeneratedRelease" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\WTFGeneratedCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedReleaseCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedReleaseCairoCFLite.vsprops deleted file mode 100644 index 730d71941..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFGeneratedReleaseCairoCFLite.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFGeneratedReleaseCairoCFLite" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;.\WTFGeneratedCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFPostBuild.cmd b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFPostBuild.cmd deleted file mode 100644 index 26707cac6..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFPostBuild.cmd +++ /dev/null @@ -1 +0,0 @@ -if exist "%CONFIGURATIONBUILDDIR%\buildfailed" del "%CONFIGURATIONBUILDDIR%\buildfailed" diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFPreBuild.cmd b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFPreBuild.cmd deleted file mode 100644 index a77077674..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFPreBuild.cmd +++ /dev/null @@ -1,6 +0,0 @@ -%SystemDrive%\cygwin\bin\which.exe bash -if errorlevel 1 set PATH=%SystemDrive%\cygwin\bin;%PATH% -cmd /c -if exist "%CONFIGURATIONBUILDDIR%\buildfailed" grep XX%PROJECTNAME%XX "%CONFIGURATIONBUILDDIR%\buildfailed" -if errorlevel 1 exit 1 -echo XX%PROJECTNAME%XX > "%CONFIGURATIONBUILDDIR%\buildfailed" diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFProduction.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFProduction.vsprops deleted file mode 100644 index 7e8904b00..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFProduction.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFProduction" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\WTFCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFRelease.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFRelease.vsprops deleted file mode 100644 index b0af34238..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFRelease.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFRelease" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefines.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;.\WTFCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleaseCairoCFLite.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleaseCairoCFLite.vsprops deleted file mode 100644 index c39ae128d..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTFReleaseCairoCFLite.vsprops +++ /dev/null @@ -1,8 +0,0 @@ -<?xml version="1.0" encoding="Windows-1252"?> -<VisualStudioPropertySheet - ProjectType="Visual C++" - Version="8.00" - Name="WTFReleaseCairoCFLite" - InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\FeatureDefinesCairo.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\release.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\WinCairo.vsprops;.\WTFCommon.vsprops" - > -</VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/build-generated-files.sh b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/build-generated-files.sh deleted file mode 100755 index d1a4e560f..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/build-generated-files.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/bash - -# Determine whether we have the versioned ICU 4.0 or the unversioned ICU 4.4 -UNVERSIONED_ICU_LIB_PATH=$(cygpath -u "${WEBKITLIBRARIESDIR}/lib/libicuuc.lib") -ICUVERSION_H_PATH=$(cygpath -u "${CONFIGURATIONBUILDDIR}/include/private/ICUVersion.h") -if test \( ! -f "${ICUVERSION_H_PATH}" \) -o \( -f "${UNVERSIONED_ICU_LIB_PATH}" -a \( "${UNVERSIONED_ICU_LIB_PATH}" -nt "${ICUVERSION_H_PATH}" \) \) -then - mkdir -p "$(dirname "${ICUVERSION_H_PATH}")" - test ! -f "${UNVERSIONED_ICU_LIB_PATH}" - echo "#define U_DISABLE_RENAMING $?" > "${ICUVERSION_H_PATH}" -fi diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/copy-files.cmd b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/copy-files.cmd deleted file mode 100755 index 3160e5cc1..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/copy-files.cmd +++ /dev/null @@ -1,37 +0,0 @@ -@echo off
-
-set PrivateHeadersDirectory=%CONFIGURATIONBUILDDIR%\include\private\JavaScriptCore
-
-if "%1" EQU "clean" goto :clean
-if "%1" EQU "rebuild" call :clean
-
-echo Copying WTF headers...
-for %%d in (
- wtf
- wtf\dtoa
- wtf\text
- wtf\threads
- wtf\unicode
- wtf\unicode\icu
-) do (
- mkdir "%PrivateHeadersDirectory%\%%d" 2>NUL
- xcopy /y /d ..\..\%%d\*.h "%PrivateHeadersDirectory%\%%d" >NUL
-)
-
-echo Copying other files...
-for %%f in (
- create_hash_table
- wtf\text\AtomicString.cpp
- wtf\text\StringBuilder.cpp
- wtf\text\StringImpl.cpp
- wtf\text\WTFString.cpp
-) do (
- echo F | xcopy /y /d ..\..\%%f "%PrivateHeadersDirectory%\%%f" >NUL
-)
-
-goto :EOF
-
-:clean
-
-echo Deleting copied files...
-if exist "%PrivateHeadersDirectory%" rmdir /s /q "%PrivateHeadersDirectory%" >NUL
diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/work-around-vs-dependency-tracking-bugs.py b/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/work-around-vs-dependency-tracking-bugs.py deleted file mode 100644 index 5060f69c4..000000000 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/work-around-vs-dependency-tracking-bugs.py +++ /dev/null @@ -1,66 +0,0 @@ -#!/usr/bin/env python - -import glob -import os -import re -import sys - - -# It's fragile to rely on the location of this script to find the top-level -# source directory. -TOP_LEVEL_DIRECTORY = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))) - - -def main(): - react_to_vsprops_changes() - react_to_webkit1_interface_changes() - - -def react_to_vsprops_changes(): - vsprops_directory = os.path.join(TOP_LEVEL_DIRECTORY, 'WebKitLibraries', 'win', 'tools', 'vsprops') - newest_vsprops_time = mtime_of_newest_file_matching_glob(os.path.join(vsprops_directory, '*.vsprops')) - - obj_directory = os.path.join(os.environ['CONFIGURATIONBUILDDIR'], 'obj') - - # Visual Studio isn't smart enough to figure out it needs to rebuild these file types when - # .vsprops files change (even if we touch wtf/Platform.h below), so we delete them to force them - # to be rebuilt. - for extension in ('dep', 'manifest', 'pch', 'res'): - for filepath in glob.iglob(os.path.join(obj_directory, '*', '*.%s' % extension)): - delete_if_older_than(filepath, newest_vsprops_time) - - # Touch wtf/Platform.h so all files will be recompiled. This is necessary - # to pick up changes to preprocessor macros (e.g., ENABLE_*). - wtf_platform_h = os.path.join(TOP_LEVEL_DIRECTORY, 'Source', 'JavaScriptCore', 'wtf', 'Platform.h') - touch_if_older_than(wtf_platform_h, newest_vsprops_time) - - -def react_to_webkit1_interface_changes(): - interfaces_directory = os.path.join(TOP_LEVEL_DIRECTORY, 'Source', 'WebKit', 'win', 'Interfaces') - newest_idl_time = mtime_of_newest_file_matching_glob(os.path.join(interfaces_directory, '*.idl')) - # WebKit.idl includes all the other IDL files, so needs to be rebuilt if any IDL file changes. - # But Visual Studio isn't smart enough to figure this out, so we touch WebKit.idl to ensure that - # it gets rebuilt. - touch_if_older_than(os.path.join(interfaces_directory, 'WebKit.idl'), newest_idl_time) - - -def mtime_of_newest_file_matching_glob(glob_pattern): - files = glob.glob(glob_pattern) - assert len(files), "Couldn't find any files matching glob %s" % glob_pattern - return max(map(os.path.getmtime, files)) - - -def delete_if_older_than(path, reference_time): - if os.path.getmtime(path) < reference_time: - print 'Deleting %s' % path - os.remove(path) - - -def touch_if_older_than(path, reference_time): - if os.path.getmtime(path) < reference_time: - print 'Touching %s' % path - os.utime(path, None) - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj index 21f13fc47..9e04fee9c 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jsc.vcproj @@ -448,7 +448,7 @@ </References> <Files> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\AtomicString.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\wtf\text\AtomicString.cpp" > </File> <File @@ -456,15 +456,15 @@ > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\StringBuilder.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\wtf\text\StringBuilder.cpp" > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\StringImpl.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\wtf\text\StringImpl.cpp" > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\WTFString.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\wtf\text\WTFString.cpp" > </File> </Files> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops index 72789b98c..0e4fb8459 100644 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/jsc/jscReleasePGO.vsprops @@ -5,4 +5,8 @@ Name="jscReleasePGO" InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\jscCommon.vsprops" > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\..\Production\include\private";"$(ConfigurationBuildDir)\..\Production\include\private\wtf\text"" + /> </VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj b/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj index 6d44dce91..b7053908d 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExp.vcproj @@ -448,15 +448,15 @@ </References> <Files> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\AtomicString.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\wtf\text\AtomicString.cpp" > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\StringBuilder.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\wtf\text\StringBuilder.cpp" > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\StringImpl.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\wtf\text\StringImpl.cpp" > </File> <File @@ -464,7 +464,7 @@ > </File> <File - RelativePath="$(ConfigurationBuildDir)\include\private\JavaScriptCore\wtf\text\WTFString.cpp" + RelativePath="$(ConfigurationBuildDir)\include\private\wtf\text\WTFString.cpp" > </File> </Files> diff --git a/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExpReleasePGO.vsprops b/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExpReleasePGO.vsprops index e226c42e6..079224b2b 100755 --- a/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExpReleasePGO.vsprops +++ b/Source/JavaScriptCore/JavaScriptCore.vcproj/testRegExp/testRegExpReleasePGO.vsprops @@ -5,4 +5,8 @@ Name="testRegExpReleasePGO" InheritedPropertySheets="$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\common.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\releaseproduction.vsprops;$(WebKitVSPropsRedirectionDir)..\..\..\..\WebKitLibraries\win\tools\vsprops\production.vsprops;.\testRegExpCommon.vsprops" > + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories=""$(ConfigurationBuildDir)\..\Production\include\private";"$(ConfigurationBuildDir)\..\Production\include\private\wtf\text"" + /> </VisualStudioPropertySheet> diff --git a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj index a72046e2c..d5cf8dedc 100644 --- a/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj +++ b/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj @@ -16,6 +16,19 @@ name = "LLInt Offsets"; productName = "Derived Sources"; }; + 5D6B2A47152B9E17005231DE /* Test Tools */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 5D6B2A4C152B9E17005231DE /* Build configuration list for PBXAggregateTarget "Test Tools" */; + buildPhases = ( + ); + dependencies = ( + 5D6B2A4F152B9E23005231DE /* PBXTargetDependency */, + 5D6B2A51152B9E23005231DE /* PBXTargetDependency */, + 5D6B2A55152B9E23005231DE /* PBXTargetDependency */, + ); + name = "Test Tools"; + productName = "Test Tools"; + }; 65FB3F6609D11E9100F49DEB /* Derived Sources */ = { isa = PBXAggregateTarget; buildConfigurationList = 65FB3F7709D11EBD00F49DEB /* Build configuration list for PBXAggregateTarget "Derived Sources" */; @@ -36,10 +49,8 @@ ); dependencies = ( 932F5BE70822A1C700736975 /* PBXTargetDependency */, - 141214BF0A49190E00480255 /* PBXTargetDependency */, - 932F5BE90822A1C700736975 /* PBXTargetDependency */, - 14BD59C70A3E8FA400BAF59C /* PBXTargetDependency */, - 651123091404768B002B101D /* PBXTargetDependency */, + 5D69E912152BE5470028D720 /* PBXTargetDependency */, + 5D6B2A57152B9E2E005231DE /* PBXTargetDependency */, ); name = All; productName = All; @@ -47,14 +58,9 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ - 06D358B30DAADAA4003B174E /* MainThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06D358A20DAAD9C4003B174E /* MainThread.cpp */; }; - 06D358B40DAADAAA003B174E /* MainThreadMac.mm in Sources */ = {isa = PBXBuildFile; fileRef = 06D358A10DAAD9C4003B174E /* MainThreadMac.mm */; }; - 088FA5BB0EF76D4300578E6F /* RandomNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 088FA5B90EF76D4300578E6F /* RandomNumber.cpp */; }; 08DDA5C11264631700751732 /* UStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 08DDA5BB12645F1D00751732 /* UStringBuilder.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0A4337BB1506218800991C95 /* DFGRedundantPhiEliminationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0A4337BA1506218800991C95 /* DFGRedundantPhiEliminationPhase.cpp */; }; 0A4337BE1506219B00991C95 /* DFGRedundantPhiEliminationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A4337BD1506219B00991C95 /* DFGRedundantPhiEliminationPhase.h */; }; - 0B330C270F38C62300692DE3 /* TypeTraits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0B330C260F38C62300692DE3 /* TypeTraits.cpp */; }; - 0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */; }; 0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F0B839A14BCF45D00885B4F /* LLIntEntrypoints.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */; }; 0F0B839B14BCF46000885B4F /* LLIntEntrypoints.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -72,13 +78,17 @@ 0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F0FC45A14BD15F500B81154 /* LLIntCallLinkInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F15F15F14B7A73E005DE37D /* CommonSlowPaths.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; }; - 0F1D0861150C5A860074D109 /* DFGNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F1D085F150C5A800074D109 /* DFGNode.cpp */; }; + 0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F21C26814BE5F6800ADC64B /* JITDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C26614BE5F5E00ADC64B /* JITDriver.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F21C27C14BE727600ADC64B /* ExecutionHarness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F21C27F14BEAA8200ADC64B /* BytecodeConventions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */; }; + 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0F2BDC21151E803B00CD8910 /* DFGInsertionSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2BDC2B151FDE8B00CD8910 /* Operands.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F2C556F14738F3100121E4F /* DFGCodeBlocks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F2C557014738F3500121E4F /* DFGCodeBlocks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */; }; 0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A451460CBAB00131F8F /* ValueRecovery.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -105,13 +115,12 @@ 0F56A1D515001CF4002992B1 /* ExecutionCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */; }; 0F5F08CF146C7633000472A9 /* UnconditionalFinalizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0F620175143FCD370068B77C /* DFGOperands.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620171143FCD2F0068B77C /* DFGOperands.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */; }; - 0F66E16B14DF3F1600B7B2E4 /* DFGNodeReferenceBlob.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGNodeReferenceBlob.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0F66E16C14DF3F1600B7B2E4 /* DFGNodeUse.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGNodeUse.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; }; 0F7B294A14C3CD29007C3DB1 /* DFGCCallHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -126,12 +135,13 @@ 0F9332A314CA7DD70085F3C6 /* PutByIdStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */; }; 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F93329B14CA7DC10085F3C6 /* StructureSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0F963B2C13F853EC0002D9B2 /* MetaAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; }; 0F963B3813FC6FE90002D9B2 /* ValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */; }; 0F9FC8C414E1B60000D52AE0 /* PolymorphicPutByIdList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0F9FC8D014E612D800D52AE0 /* DataLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F9FC8CD14E612D500D52AE0 /* DataLog.cpp */; }; + 0FA581BA150E952C00B9A2D9 /* DFGNodeFlags.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA581B7150E952A00B9A2D9 /* DFGNodeFlags.cpp */; }; + 0FA581BB150E953000B9A2D9 /* DFGNodeFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 0FA581BC150E953000B9A2D9 /* DFGNodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FB5467914F5C46B002C2989 /* LazyOperandValueProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */; }; 0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -160,15 +170,12 @@ 0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */; }; 0FD82E39141AB14D00179C94 /* CompactJITCodeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FD82E54141DAEEE00179C94 /* PredictedType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E4F141DAEA100179C94 /* PredictedType.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 0FD82E55141DAEEE00179C94 /* PredictionTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E50141DAEA100179C94 /* PredictionTracker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FD82E56141DAF0800179C94 /* DFGOSREntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */; }; 0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FD82E86141F3FF100179C94 /* PredictedType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E84141F3FDA00179C94 /* PredictedType.cpp */; }; 0FE228ED1436AB2700196C48 /* Options.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FE228EB1436AB2300196C48 /* Options.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE228EA1436AB2300196C48 /* Options.cpp */; }; 0FF922D414F46B410041A24E /* LLIntOffsetsExtractor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F4680A114BA7F8200BFE272 /* LLIntOffsetsExtractor.cpp */; }; - 0FFFC95514EF909A00C72532 /* DFGArithNodeFlagsInferencePhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94914EF909500C72532 /* DFGArithNodeFlagsInferencePhase.cpp */; }; - 0FFFC95614EF909C00C72532 /* DFGArithNodeFlagsInferencePhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94A14EF909500C72532 /* DFGArithNodeFlagsInferencePhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */; }; 0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC94D14EF909500C72532 /* DFGCSEPhase.cpp */; }; @@ -179,7 +186,6 @@ 0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC95214EF909500C72532 /* DFGPredictionPropagationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; 0FFFC95F14EF90BB00C72532 /* DFGVirtualRegisterAllocationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFFC95314EF909500C72532 /* DFGVirtualRegisterAllocationPhase.cpp */; }; 0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFFC95414EF909500C72532 /* DFGVirtualRegisterAllocationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */; }; 140566C4107EC255005DBC8D /* JSAPIValueWrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC0894D50FAFBA2D00001865 /* JSAPIValueWrapper.cpp */; }; 140566D1107EC267005DBC8D /* JSStaticScopeObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7E42C190E3938830065A544 /* JSStaticScopeObject.cpp */; }; 140566D6107EC271005DBC8D /* JSFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A85E0255597D01FF60F7 /* JSFunction.cpp */; }; @@ -189,6 +195,7 @@ 141211340A48795800480255 /* minidom.c in Sources */ = {isa = PBXBuildFile; fileRef = 141211020A48780900480255 /* minidom.c */; }; 141448CB13A176EC00F5BA1A /* MarkedBlockSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 141448CA13A176EC00F5BA1A /* MarkedBlockSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; 141448CD13A1783700F5BA1A /* TinyBloomFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 14150133154BB13F005D8C98 /* WeakSetInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 14150132154BB13F005D8C98 /* WeakSetInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1420BE7B10AA6DDB00F455D2 /* WeakRandom.h in Headers */ = {isa = PBXBuildFile; fileRef = 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1421359A0A677F4F00A8195E /* JSBase.cpp */; }; 14280823107EC02C0013E7B2 /* Debugger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8580255597D01FF60F7 /* Debugger.cpp */; }; @@ -207,7 +214,7 @@ 14280870107EC1340013E7B2 /* JSWrapperObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65C7A1710A8EAACB00FA37EA /* JSWrapperObject.cpp */; }; 14280875107EC13E0013E7B2 /* JSLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65EA4C99092AF9E20093D800 /* JSLock.cpp */; }; 1429D77C0ED20D7300B89619 /* Interpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429D77B0ED20D7300B89619 /* Interpreter.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429D7D30ED2128200B89619 /* Interpreter.cpp */; settings = {COMPILER_FLAGS = "-fno-var-tracking"; }; }; + 1429D7D40ED2128200B89619 /* Interpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429D7D30ED2128200B89619 /* Interpreter.cpp */; }; 1429D8780ED21ACD00B89619 /* ExceptionHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */; }; 1429D8850ED21C3D00B89619 /* SamplingTool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1429D8830ED21C3D00B89619 /* SamplingTool.cpp */; }; 1429D8860ED21C3D00B89619 /* SamplingTool.h in Headers */ = {isa = PBXBuildFile; fileRef = 1429D8840ED21C3D00B89619 /* SamplingTool.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -221,8 +228,8 @@ 142D6F1113539A4100B02E86 /* MarkStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 142D6F0E13539A4100B02E86 /* MarkStack.cpp */; }; 142D6F1213539A4100B02E86 /* MarkStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 142D6F0F13539A4100B02E86 /* MarkStack.h */; settings = {ATTRIBUTES = (Private, ); }; }; 142E3134134FF0A600AFADB5 /* Handle.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E312B134FF0A600AFADB5 /* Handle.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 142E3135134FF0A600AFADB5 /* HandleHeap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 142E312C134FF0A600AFADB5 /* HandleHeap.cpp */; }; - 142E3136134FF0A600AFADB5 /* HandleHeap.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E312D134FF0A600AFADB5 /* HandleHeap.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 142E3135134FF0A600AFADB5 /* HandleSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 142E312C134FF0A600AFADB5 /* HandleSet.cpp */; }; + 142E3136134FF0A600AFADB5 /* HandleSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E312D134FF0A600AFADB5 /* HandleSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; 142E3137134FF0A600AFADB5 /* HandleStack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 142E312E134FF0A600AFADB5 /* HandleStack.cpp */; }; 142E3138134FF0A600AFADB5 /* HandleStack.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E312F134FF0A600AFADB5 /* HandleStack.h */; settings = {ATTRIBUTES = (Private, ); }; }; 142E3139134FF0A600AFADB5 /* Local.h in Headers */ = {isa = PBXBuildFile; fileRef = 142E3130134FF0A600AFADB5 /* Local.h */; }; @@ -242,7 +249,6 @@ 1440F8920A508B100005F061 /* JSCallbackFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1440F8900A508B100005F061 /* JSCallbackFunction.cpp */; }; 1440F8AF0A508D200005F061 /* JSCallbackConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1440F8AD0A508D200005F061 /* JSCallbackConstructor.cpp */; }; 1440FCE40A51E46B0005F061 /* JSClassRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1440FCE20A51E46B0005F061 /* JSClassRef.cpp */; }; - 14469DD7107EC79E00650446 /* dtoa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 651F6412039D5B5F0078395C /* dtoa.cpp */; }; 14469DDE107EC7E700650446 /* Lookup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8680255597D01FF60F7 /* Lookup.cpp */; }; 14469DDF107EC7E700650446 /* MathObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A86A0255597D01FF60F7 /* MathObject.cpp */; }; 14469DE0107EC7E700650446 /* NativeErrorConstructor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC02E9080E1839DB000F9297 /* NativeErrorConstructor.cpp */; }; @@ -292,6 +298,8 @@ 147F39D5107EC37600427A48 /* JSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC02E9B60E1842FA000F9297 /* JSString.cpp */; }; 147F39D6107EC37600427A48 /* JSValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F692A8870255597D01FF60F7 /* JSValue.cpp */; }; 147F39D7107EC37600427A48 /* JSVariableObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC22A39A0E16E14800AF21C8 /* JSVariableObject.cpp */; }; + 14816E1B154CC56C00B8054C /* BlockAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14816E19154CC56C00B8054C /* BlockAllocator.cpp */; }; + 14816E1C154CC56C00B8054C /* BlockAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = 14816E1A154CC56C00B8054C /* BlockAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1482B74E0A43032800517CFC /* JSStringRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1482B74C0A43032800517CFC /* JSStringRef.cpp */; }; 1482B7E40A43076000517CFC /* JSObjectRef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1482B7E20A43076000517CFC /* JSObjectRef.cpp */; }; 148CD1D8108CF902008163C6 /* JSContextRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 148CD1D7108CF902008163C6 /* JSContextRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -306,7 +314,6 @@ 14A42E3F0F4F60EE00599099 /* TimeoutChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14A42E3D0F4F60EE00599099 /* TimeoutChecker.cpp */; }; 14A42E400F4F60EE00599099 /* TimeoutChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A42E3E0F4F60EE00599099 /* TimeoutChecker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14ABDF5E0A437FEF00ECCA01 /* JSCallbackObject.cpp */; }; - 14B3EF0612BC24DD00D29EFF /* PageBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14B3EF0412BC24DD00D29EFF /* PageBlock.cpp */; }; 14B723B212D7DA46003BD5ED /* MachineStackMarker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */; }; 14B723B812D7DA6F003BD5ED /* MachineStackMarker.h in Headers */ = {isa = PBXBuildFile; fileRef = 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14B8EC720A5652090062BE54 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; }; @@ -320,26 +327,21 @@ 14C5242B0F5355E900BA3D04 /* JITStubs.h in Headers */ = {isa = PBXBuildFile; fileRef = 14A6581A0F4E36F4000150FD /* JITStubs.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14D2F3DA139F4BE200491031 /* MarkedSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14D2F3D8139F4BE200491031 /* MarkedSpace.cpp */; }; 14D2F3DB139F4BE200491031 /* MarkedSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = 14D2F3D9139F4BE200491031 /* MarkedSpace.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 14E84F9E14EE1ACC00D6D5D4 /* WeakBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14E84F9914EE1ACC00D6D5D4 /* WeakBlock.cpp */; }; + 14E84F9F14EE1ACC00D6D5D4 /* WeakBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E84F9A14EE1ACC00D6D5D4 /* WeakBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 14E84FA014EE1ACC00D6D5D4 /* WeakSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14E84F9B14EE1ACC00D6D5D4 /* WeakSet.cpp */; }; + 14E84FA114EE1ACC00D6D5D4 /* WeakSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E84F9C14EE1ACC00D6D5D4 /* WeakSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = 14E84F9D14EE1ACC00D6D5D4 /* WeakImpl.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14E9D17B107EC469004DDA21 /* JSGlobalObjectFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */; }; - 14F8BA3E107EC886009892DC /* FastMalloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 65E217B908E7EECC0023E5F6 /* FastMalloc.cpp */; }; - 14F8BA43107EC88C009892DC /* TCSystemAlloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 6541BD7008E80A17002CBEE7 /* TCSystemAlloc.cpp */; }; + 14F7256514EE265E00B1652B /* WeakHandleOwner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14F7256314EE265E00B1652B /* WeakHandleOwner.cpp */; }; + 14F7256614EE265E00B1652B /* WeakHandleOwner.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F7256414EE265E00B1652B /* WeakHandleOwner.h */; settings = {ATTRIBUTES = (Private, ); }; }; 14F97447138C853E00DA1C67 /* HeapRootVisitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 14F97446138C853E00DA1C67 /* HeapRootVisitor.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 14FFF98C12BFFF7500795BB8 /* PageAllocationAligned.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 14FFF98A12BFFF7500795BB8 /* PageAllocationAligned.cpp */; }; - 180B9BFE0F16E94D009BDBC5 /* CurrentTime.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 180B9AEF0F16C569009BDBC5 /* CurrentTime.cpp */; }; - 18BAB55310DAE054000D945B /* ThreadIdentifierDataPthreads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18BAB52710DADFCD000D945B /* ThreadIdentifierDataPthreads.cpp */; }; - 1A082779142168D70090CCAC /* BinarySemaphore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A082777142168D70090CCAC /* BinarySemaphore.cpp */; }; - 1A08277A142168D70090CCAC /* BinarySemaphore.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A082778142168D70090CCAC /* BinarySemaphore.h */; }; - 2684B2D314D4A9B20072C0B6 /* ParsedURL.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2684B2C414D4A9B20072C0B6 /* ParsedURL.cpp */; }; - 2684B2D814D4A9B20072C0B6 /* URLCharacterTypes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2684B2CA14D4A9B20072C0B6 /* URLCharacterTypes.cpp */; }; - 2684B2DB14D4A9B20072C0B6 /* URLEscape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2684B2CD14D4A9B20072C0B6 /* URLEscape.cpp */; }; - 2684B2DF14D4A9B20072C0B6 /* URLSegments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2684B2D114D4A9B20072C0B6 /* URLSegments.cpp */; }; + 2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */; }; + 2600B5A7152BAAA70091EE5F /* JSStringJoiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */; }; 41359CF30FDD89AD00206180 /* DateConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateConversion.h */; }; - 41359CF60FDD89CB00206180 /* DateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41359CF40FDD89CB00206180 /* DateMath.cpp */; }; 451539B912DC994500EF7AC4 /* Yarr.h in Headers */ = {isa = PBXBuildFile; fileRef = 451539B812DC994500EF7AC4 /* Yarr.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 511FC4C9117EE28700425272 /* MD5.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 511FC4C7117EE23D00425272 /* MD5.cpp */; }; 5D53726F0E1C54880021E549 /* Tracing.h in Headers */ = {isa = PBXBuildFile; fileRef = 5D53726E0E1C54880021E549 /* Tracing.h */; }; 5D5D8AD10E0D0EBE00F9C692 /* libedit.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */; }; - 5D6A566B0F05995500266145 /* Threading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5D6A566A0F05995500266145 /* Threading.cpp */; }; 5DBB151B131D0B310056AD36 /* testapi.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 14D857740A4696C80032146C /* testapi.js */; }; 5DBB1525131D0BD70056AD36 /* minidom.js in Copy Support Script */ = {isa = PBXBuildFile; fileRef = 1412110D0A48788700480255 /* minidom.js */; }; 5DE6E5B30E1728EC00180407 /* create_hash_table in Headers */ = {isa = PBXBuildFile; fileRef = F692A8540255597D01FF60F7 /* create_hash_table */; settings = {ATTRIBUTES = (); }; }; @@ -349,10 +351,6 @@ 6511230714046B0A002B101D /* testRegExp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 651122E5140469BA002B101D /* testRegExp.cpp */; }; 65303D641447B9E100D3F904 /* ParserTokens.h in Headers */ = {isa = PBXBuildFile; fileRef = 65303D631447B9E100D3F904 /* ParserTokens.h */; settings = {ATTRIBUTES = (Private, ); }; }; 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 */; }; - 76FB9F1112E851960051A2EB /* SHA1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 76FB9F1012E851960051A2EB /* SHA1.cpp */; }; - 7934BB7C1361979400CB99A1 /* ParallelJobsGeneric.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7934BB771361979300CB99A1 /* ParallelJobsGeneric.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 */; }; @@ -363,10 +361,11 @@ 860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */; }; 8604F505143CE1C200B295F5 /* JSGlobalThis.h in Headers */ = {isa = PBXBuildFile; fileRef = 8604F503143CE1C100B295F5 /* JSGlobalThis.h */; settings = {ATTRIBUTES = (Private, ); }; }; 860BD801148EA6F200112B2F /* Intrinsic.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BF642A148DB2B5004DE36A /* Intrinsic.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 8626BECF11928E3900782FAB /* StringStatics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 8626BECE11928E3900782FAB /* StringStatics.cpp */; }; + 8612E4CD152389EC00C836BE /* MatchResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 8612E4CB1522918400C836BE /* MatchResult.h */; settings = {ATTRIBUTES = (Private, ); }; }; 863B23E00FC6118900703AA4 /* MacroAssemblerCodeRef.h in Headers */ = {isa = PBXBuildFile; fileRef = 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 86438FC41265503E00E0DFCA /* StringBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86438FC31265503E00E0DFCA /* StringBuilder.cpp */; }; - 86565742115BE3DA00291F40 /* CString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86565740115BE3DA00291F40 /* CString.cpp */; }; + 863C6D9C1521111A00585E4E /* YarrCanonicalizeUCS2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 863C6D981521111200585E4E /* YarrCanonicalizeUCS2.cpp */; }; + 8642C510151C06A90046D4EF /* RegExpCachedResult.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86F75EFB151C062F007C9BA3 /* RegExpCachedResult.cpp */; }; + 8642C512151C083D0046D4EF /* RegExpMatchesArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86F75EFD151C062F007C9BA3 /* RegExpMatchesArray.cpp */; }; 865A30F1135007E100CDB49E /* JSValueInlineMethods.h in Headers */ = {isa = PBXBuildFile; fileRef = 865A30F0135007E100CDB49E /* JSValueInlineMethods.h */; settings = {ATTRIBUTES = (Private, ); }; }; 865F408810E7D56300947361 /* APIShims.h in Headers */ = {isa = PBXBuildFile; fileRef = 865F408710E7D56300947361 /* APIShims.h */; settings = {ATTRIBUTES = (Private, ); }; }; 866739D213BFDE710023D87C /* BigInteger.h in Headers */ = {isa = PBXBuildFile; fileRef = 866739D013BFDE710023D87C /* BigInteger.h */; }; @@ -376,15 +375,12 @@ 86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */; }; 86704B8512DBA33700A9FE7B /* YarrInterpreter.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B7F12DBA33700A9FE7B /* YarrJIT.cpp */; }; - 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8012DBA33700A9FE7B /* YarrJIT.h */; settings = {ATTRIBUTES = (); }; }; + 86704B8712DBA33700A9FE7B /* YarrJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8012DBA33700A9FE7B /* YarrJIT.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86704B8812DBA33700A9FE7B /* YarrParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8112DBA33700A9FE7B /* YarrParser.h */; settings = {ATTRIBUTES = (); }; }; 86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86704B8212DBA33700A9FE7B /* YarrPattern.cpp */; }; 86704B8A12DBA33700A9FE7B /* YarrPattern.h in Headers */ = {isa = PBXBuildFile; fileRef = 86704B8312DBA33700A9FE7B /* YarrPattern.h */; settings = {ATTRIBUTES = (Private, ); }; }; 86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */; }; 86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */; }; - 868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA00117CEFD100B908B1 /* AtomicString.cpp */; }; - 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA06117CEFD100B908B1 /* StringImpl.cpp */; }; - 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 868BFA15117CF19900B908B1 /* WTFString.cpp */; }; 869D04AF1193B54D00803475 /* CachedTranscendentalFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */; settings = {ATTRIBUTES = (Private, ); }; }; 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 */; }; @@ -409,14 +405,12 @@ 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 */; }; 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 */; }; 86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */; }; 86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C110159D7F002865E7 /* LinkBuffer.h */; }; 86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */; }; - 86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D87DA512BC4B14008E73A1 /* StackBounds.cpp */; }; 86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; }; 86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; }; 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; }; @@ -438,7 +432,6 @@ 86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */; }; 90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */; }; 90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */ = {isa = PBXBuildFile; fileRef = 90213E3C123A40C200D422F3 /* MemoryStatistics.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */; }; 93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93052C320FB792190048FDC3 /* ParserArena.cpp */; }; 93052C350FB792190048FDC3 /* ParserArena.h in Headers */ = {isa = PBXBuildFile; fileRef = 93052C330FB792190048FDC3 /* ParserArena.h */; settings = {ATTRIBUTES = (Private, ); }; }; 932F5BD30822A1C700736975 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */; }; @@ -449,7 +442,6 @@ 933040040E6A749400786E6A /* SmallStrings.h in Headers */ = {isa = PBXBuildFile; fileRef = 93303FEA0E6A72C000786E6A /* SmallStrings.h */; settings = {ATTRIBUTES = (Private, ); }; }; 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93303FE80E6A72B500786E6A /* SmallStrings.cpp */; }; 9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93345A8712D838C400302BE3 /* StringRecursionChecker.cpp */; }; - 93854A9A12C93D3B00DAAF77 /* NullPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93854A9912C93D3B00DAAF77 /* NullPtr.cpp */; }; 9534AAFB0E5B7A9600B8A45B /* JSProfilerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 952C63AC0E4777D600C13936 /* JSProfilerPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 95742F650DD11F5A000917FB /* Profile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95742F630DD11F5A000917FB /* Profile.cpp */; }; 95AB83420DA4322500BC83F3 /* Profiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 95AB832E0DA42CAD00BC83F3 /* Profiler.cpp */; }; @@ -474,8 +466,6 @@ 971EDEA61169E0D3005E4262 /* Terminator.h in Headers */ = {isa = PBXBuildFile; fileRef = 97F6903A1169DF7F00A6BB46 /* Terminator.h */; settings = {ATTRIBUTES = (Private, ); }; }; 978801401471AD920041B016 /* JSDateMath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */; }; 978801411471AD920041B016 /* JSDateMath.h in Headers */ = {isa = PBXBuildFile; fileRef = 9788FC231471AD0C0068CE2D /* JSDateMath.h */; settings = {ATTRIBUTES = (Private, ); }; }; - 97941A5713029AAB004A3447 /* OSRandomSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97941A3F130299DB004A3447 /* OSRandomSource.cpp */; }; - 97941A7E1302A098004A3447 /* CryptographicallyRandomNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 97941A7C1302A098004A3447 /* CryptographicallyRandomNumber.cpp */; }; A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A1712B3A11C7B212007A5315 /* RegExpCache.cpp */; }; A1712B3F11C7B228007A5315 /* RegExpCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B3E11C7B228007A5315 /* RegExpCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; A1712B4111C7B235007A5315 /* RegExpKey.h in Headers */ = {isa = PBXBuildFile; fileRef = A1712B4011C7B235007A5315 /* RegExpKey.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -491,8 +481,6 @@ A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386551118697B400540279 /* SpecializedThunkJIT.h */; }; A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7386552118697B400540279 /* ThunkGenerators.cpp */; }; A7386556118697B400540279 /* ThunkGenerators.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386553118697B400540279 /* ThunkGenerators.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A73BE168148420520091204B /* ArrayBuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A73BE154148420520091204B /* ArrayBuffer.cpp */; }; - A73BE16A148420520091204B /* ArrayBufferView.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A73BE156148420520091204B /* ArrayBufferView.cpp */; }; 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, ); }; }; @@ -500,14 +488,11 @@ A7521E131429169A003C8D0C /* CardSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A7521E121429169A003C8D0C /* CardSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; A75706DE118A2BCF0057F88F /* JITArithmetic32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A75706DD118A2BCF0057F88F /* JITArithmetic32_64.cpp */; }; A766B44F0EE8DCD1009518CA /* ExecutableAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A76C51741182748D00715B05 /* JSInterfaceJIT.h */; }; + A76C51761182748D00715B05 /* JSInterfaceJIT.h in Headers */ = {isa = PBXBuildFile; fileRef = A76C51741182748D00715B05 /* JSInterfaceJIT.h */; settings = {ATTRIBUTES = (Private, ); }; }; A76F54A313B28AAB00EF2BCE /* JITWriteBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */; }; A781E359141970C700094D90 /* StorageBarrier.h in Headers */ = {isa = PBXBuildFile; fileRef = A781E358141970C700094D90 /* StorageBarrier.h */; settings = {ATTRIBUTES = (Private, ); }; }; A784A26111D16622005776AC /* ASTBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */; }; A784A26411D16622005776AC /* SyntaxChecker.h in Headers */ = {isa = PBXBuildFile; fileRef = A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */; }; - A791EF280F11E07900AE1F68 /* JSByteArray.h in Headers */ = {isa = PBXBuildFile; fileRef = A791EF260F11E07900AE1F68 /* JSByteArray.h */; settings = {ATTRIBUTES = (Private, ); }; }; - A791EF290F11E07900AE1F68 /* JSByteArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A791EF270F11E07900AE1F68 /* JSByteArray.cpp */; }; - A7A1F7AC0F252B3C00E184E2 /* ByteArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */; }; A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */; }; A7B4ACAF1484C9CE00B38A36 /* JSExportMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A7B4ACAE1484C9CE00B38A36 /* JSExportMacros.h */; settings = {ATTRIBUTES = (Private, ); }; }; A7C1E8E4112E72EF00A37F98 /* JITPropertyAccess32_64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */; }; @@ -518,6 +503,7 @@ A7F993600FD7325100A0B2D0 /* JSONObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */; }; A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7FB60A3103F7DC20017A286 /* PropertyDescriptor.cpp */; }; A7FB61001040C38B0017A286 /* PropertyDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */; settings = {ATTRIBUTES = (Private, ); }; }; + A8A4748E151A8306004123FF /* libWTF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A8A4748D151A8306004123FF /* libWTF.a */; }; BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9050E1839DB000F9297 /* ErrorConstructor.h */; }; BC02E90F0E1839DB000F9297 /* ErrorPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9070E1839DB000F9297 /* ErrorPrototype.h */; }; BC02E9110E1839DB000F9297 /* NativeErrorConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BC02E9090E1839DB000F9297 /* NativeErrorConstructor.h */; }; @@ -631,14 +617,6 @@ BCFD8C920EEB2EE700283848 /* JumpTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCFD8C900EEB2EE700283848 /* JumpTable.cpp */; }; BCFD8C930EEB2EE700283848 /* JumpTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BCFD8C910EEB2EE700283848 /* JumpTable.h */; }; C22B31B9140577D700DB475A /* SamplingCounter.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F77008E1402FDD60078EB39 /* SamplingCounter.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C22C52F113FAF6EF00B7DC0D /* bignum-dtoa.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529013FAF6EF00B7DC0D /* bignum-dtoa.cc */; }; - C22C52F313FAF6EF00B7DC0D /* bignum.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529213FAF6EF00B7DC0D /* bignum.cc */; }; - C22C52F513FAF6EF00B7DC0D /* cached-powers.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529413FAF6EF00B7DC0D /* cached-powers.cc */; }; - C22C52F713FAF6EF00B7DC0D /* diy-fp.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529713FAF6EF00B7DC0D /* diy-fp.cc */; }; - C22C52F913FAF6EF00B7DC0D /* double-conversion.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529913FAF6EF00B7DC0D /* double-conversion.cc */; }; - C22C52FC13FAF6EF00B7DC0D /* fast-dtoa.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529C13FAF6EF00B7DC0D /* fast-dtoa.cc */; }; - C22C52FE13FAF6EF00B7DC0D /* fixed-dtoa.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C529E13FAF6EF00B7DC0D /* fixed-dtoa.cc */; }; - C22C531313FAF6EF00B7DC0D /* strtod.cc in Sources */ = {isa = PBXBuildFile; fileRef = C22C52B913FAF6EF00B7DC0D /* strtod.cc */; }; C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C240305314B404C90079EB64 /* CopiedSpace.cpp */; }; C2B916C214DA014E00CBAC86 /* MarkedAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = C2B916C114DA014E00CBAC86 /* MarkedAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; C2B916C514DA040C00CBAC86 /* MarkedAllocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2B916C414DA040C00CBAC86 /* MarkedAllocator.cpp */; }; @@ -647,21 +625,15 @@ C2C8D03114A3CEFC00578E65 /* HeapBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */; settings = {ATTRIBUTES = (Private, ); }; }; C2EAA3FA149A835E00FCE112 /* CopiedSpace.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EAA3F8149A830800FCE112 /* CopiedSpace.h */; settings = {ATTRIBUTES = (Private, ); }; }; C2EAD2FC14F0249800A4B159 /* CopiedAllocator.h in Headers */ = {isa = PBXBuildFile; fileRef = C2EAD2FB14F0249800A4B159 /* CopiedAllocator.h */; settings = {ATTRIBUTES = (Private, ); }; }; - C2EE59A113FC9768009CEAFE /* DecimalNumber.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C2EE599D13FC972A009CEAFE /* DecimalNumber.cpp */; }; DDF7ABD411F60ED200108E36 /* GCActivityCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */; settings = {ATTRIBUTES = (Private, ); }; }; DDF7ABD511F60ED200108E36 /* GCActivityCallbackCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */; }; E124A8F70E555775003091F1 /* OpaqueJSString.h in Headers */ = {isa = PBXBuildFile; fileRef = E124A8F50E555775003091F1 /* OpaqueJSString.h */; settings = {ATTRIBUTES = (Private, ); }; }; E124A8F80E555775003091F1 /* OpaqueJSString.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E124A8F60E555775003091F1 /* OpaqueJSString.cpp */; }; E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */; }; E18E3A590DF9278C00D90B34 /* JSGlobalData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E18E3A570DF9278C00D90B34 /* JSGlobalData.cpp */; }; - E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */; settings = {COMPILER_FLAGS = "-fno-strict-aliasing"; }; }; - E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */; }; - E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */; }; - E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E1EF79A80CE97BA60088D500 /* UTF8.cpp */; }; E49DC16B12EF293E00184A1F /* SourceProviderCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E49DC15512EF277200184A1F /* SourceProviderCache.cpp */; }; E49DC16C12EF294E00184A1F /* SourceProviderCache.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC15112EF272200184A1F /* SourceProviderCache.h */; settings = {ATTRIBUTES = (Private, ); }; }; E49DC16D12EF295300184A1F /* SourceProviderCacheItem.h in Headers */ = {isa = PBXBuildFile; fileRef = E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */; settings = {ATTRIBUTES = (Private, ); }; }; - F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F69E86C114C6E551002C2C62 /* NumberOfCores.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -679,27 +651,41 @@ remoteGlobalIDString = 0FF922C314F46B130041A24E; remoteInfo = JSCLLIntOffsetsExtractor; }; - 141214BE0A49190E00480255 /* PBXContainerItemProxy */ = { + 5D69E911152BE5470028D720 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 932F5BDA0822A1C700736975; + remoteInfo = jsc; + }; + 5D6B2A4E152B9E23005231DE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 1412111F0A48793C00480255; remoteInfo = minidom; }; - 14BD59C60A3E8FA400BAF59C /* PBXContainerItemProxy */ = { + 5D6B2A50152B9E23005231DE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 14BD59BE0A3E8F9000BAF59C; remoteInfo = testapi; }; - 651123081404768B002B101D /* PBXContainerItemProxy */ = { + 5D6B2A54152B9E23005231DE /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; proxyType = 1; remoteGlobalIDString = 651122F714046A4C002B101D; remoteInfo = testRegExp; }; + 5D6B2A56152B9E2E005231DE /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 5D6B2A47152B9E17005231DE; + remoteInfo = "Test Tools"; + }; 65FB3F7D09D11EF300F49DEB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; @@ -714,13 +700,6 @@ remoteGlobalIDString = 932F5B3E0822A1C700736975; remoteInfo = "JavaScriptCore (Upgraded)"; }; - 932F5BE80822A1C700736975 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 0867D690FE84028FC02AAC07 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 932F5BDA0822A1C700736975; - remoteInfo = "jsc (Upgraded)"; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -749,23 +728,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 06D358A10DAAD9C4003B174E /* MainThreadMac.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MainThreadMac.mm; sourceTree = "<group>"; }; - 06D358A20DAAD9C4003B174E /* MainThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MainThread.cpp; sourceTree = "<group>"; }; - 06D358A30DAAD9C4003B174E /* MainThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MainThread.h; sourceTree = "<group>"; }; - 081469481264375E00DFF935 /* StringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringBuilder.h; path = text/StringBuilder.h; sourceTree = "<group>"; }; - 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>"; }; 0896C29B1265AAF600B1CDD3 /* UStringConcatenate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UStringConcatenate.h; sourceTree = "<group>"; }; - 0896C29E1265AB0900B1CDD3 /* StringConcatenate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringConcatenate.h; path = text/StringConcatenate.h; sourceTree = "<group>"; }; 08DDA5BB12645F1D00751732 /* UStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UStringBuilder.h; sourceTree = "<group>"; }; - 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RandomNumberSeed.h; sourceTree = "<group>"; }; 0A4337BA1506218800991C95 /* DFGRedundantPhiEliminationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGRedundantPhiEliminationPhase.cpp; path = dfg/DFGRedundantPhiEliminationPhase.cpp; sourceTree = "<group>"; }; 0A4337BD1506219B00991C95 /* DFGRedundantPhiEliminationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRedundantPhiEliminationPhase.h; path = dfg/DFGRedundantPhiEliminationPhase.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>"; }; - 0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadRestrictionVerifier.h; sourceTree = "<group>"; }; - 0BCD83541485841200EA2003 /* TemporaryChange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TemporaryChange.h; sourceTree = "<group>"; }; - 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SizeLimits.cpp; sourceTree = "<group>"; }; 0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; }; 0F0B839514BCF45A00885B4F /* LLIntEntrypoints.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntEntrypoints.cpp; path = llint/LLIntEntrypoints.cpp; sourceTree = "<group>"; }; 0F0B839614BCF45A00885B4F /* LLIntEntrypoints.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntEntrypoints.h; path = llint/LLIntEntrypoints.h; sourceTree = "<group>"; }; @@ -783,16 +749,19 @@ 0F0B83B814BCF95B00885B4F /* CallReturnOffsetToBytecodeOffset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallReturnOffsetToBytecodeOffset.h; sourceTree = "<group>"; }; 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntCallLinkInfo.h; sourceTree = "<group>"; }; 0F15F15D14B7A73A005DE37D /* CommonSlowPaths.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommonSlowPaths.h; sourceTree = "<group>"; }; - 0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; }; - 0F1D085F150C5A800074D109 /* DFGNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNode.cpp; path = dfg/DFGNode.cpp; sourceTree = "<group>"; }; + 0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArgumentPosition.h; path = dfg/DFGArgumentPosition.h; sourceTree = "<group>"; }; + 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDoubleFormatState.h; path = dfg/DFGDoubleFormatState.h; sourceTree = "<group>"; }; 0F21C26614BE5F5E00ADC64B /* JITDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITDriver.h; sourceTree = "<group>"; }; 0F21C27914BE727300ADC64B /* CodeSpecializationKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeSpecializationKind.h; sourceTree = "<group>"; }; 0F21C27A14BE727300ADC64B /* ExecutionHarness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionHarness.h; sourceTree = "<group>"; }; 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeConventions.h; sourceTree = "<group>"; }; 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; }; + 0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGFixupPhase.cpp; path = dfg/DFGFixupPhase.cpp; sourceTree = "<group>"; }; + 0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFixupPhase.h; path = dfg/DFGFixupPhase.h; sourceTree = "<group>"; }; + 0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInsertionSet.h; path = dfg/DFGInsertionSet.h; sourceTree = "<group>"; }; + 0F2BDC2B151FDE8B00CD8910 /* Operands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Operands.h; sourceTree = "<group>"; }; 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGCodeBlocks.cpp; sourceTree = "<group>"; }; 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGCodeBlocks.h; sourceTree = "<group>"; }; - 0F2E5BF5146357D2003EB2EB /* Spectrum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Spectrum.h; sourceTree = "<group>"; }; 0F426A451460CBAB00131F8F /* ValueRecovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueRecovery.h; sourceTree = "<group>"; }; 0F426A461460CBAB00131F8F /* VirtualRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VirtualRegister.h; sourceTree = "<group>"; }; 0F426A4A1460CD6B00131F8F /* DataFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataFormat.h; sourceTree = "<group>"; }; @@ -816,18 +785,15 @@ 0F55F0F214D1063600AC7649 /* AbstractPC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractPC.h; sourceTree = "<group>"; }; 0F56A1D115000F31002992B1 /* ExecutionCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutionCounter.h; sourceTree = "<group>"; }; 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutionCounter.cpp; sourceTree = "<group>"; }; - 0F56A1D6150028B9002992B1 /* SimpleStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleStats.h; sourceTree = "<group>"; }; 0F5F08CC146BE602000472A9 /* DFGByteCodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGByteCodeCache.h; path = dfg/DFGByteCodeCache.h; sourceTree = "<group>"; }; 0F5F08CE146C762F000472A9 /* UnconditionalFinalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnconditionalFinalizer.h; sourceTree = "<group>"; }; 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractState.cpp; path = dfg/DFGAbstractState.cpp; sourceTree = "<group>"; }; 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractState.h; path = dfg/DFGAbstractState.h; sourceTree = "<group>"; }; 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValue.h; path = dfg/DFGAbstractValue.h; sourceTree = "<group>"; }; 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlock.h; path = dfg/DFGBasicBlock.h; sourceTree = "<group>"; }; - 0F620171143FCD2F0068B77C /* DFGOperands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOperands.h; path = dfg/DFGOperands.h; sourceTree = "<group>"; }; 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; }; - 0F636D9F142D27D200B2E66A /* PackedIntVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PackedIntVector.h; sourceTree = "<group>"; }; - 0F66E16814DF3F1300B7B2E4 /* DFGNodeReferenceBlob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeReferenceBlob.h; path = dfg/DFGNodeReferenceBlob.h; sourceTree = "<group>"; }; - 0F66E16914DF3F1300B7B2E4 /* DFGNodeUse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeUse.h; path = dfg/DFGNodeUse.h; sourceTree = "<group>"; }; + 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = "<group>"; }; + 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = "<group>"; }; 0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; }; 0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; }; 0F7B294814C3CD23007C3DB1 /* DFGCCallHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCCallHelpers.h; path = dfg/DFGCCallHelpers.h; sourceTree = "<group>"; }; @@ -840,21 +806,17 @@ 0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PutByIdStatus.cpp; sourceTree = "<group>"; }; 0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutByIdStatus.h; sourceTree = "<group>"; }; 0F93329B14CA7DC10085F3C6 /* StructureSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureSet.h; sourceTree = "<group>"; }; - 0F963B2613F753990002D9B2 /* RedBlackTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RedBlackTree.h; sourceTree = "<group>"; }; - 0F963B2A13F853BD0002D9B2 /* MetaAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetaAllocator.h; sourceTree = "<group>"; }; - 0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MetaAllocator.cpp; sourceTree = "<group>"; }; - 0F963B2E13FC66AE0002D9B2 /* MetaAllocatorHandle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MetaAllocatorHandle.h; sourceTree = "<group>"; }; 0F963B3613FC6FDE0002D9B2 /* ValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueProfile.h; sourceTree = "<group>"; }; 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PolymorphicPutByIdList.cpp; sourceTree = "<group>"; }; 0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicPutByIdList.h; sourceTree = "<group>"; }; 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutKind.h; sourceTree = "<group>"; }; - 0F9FC8CD14E612D500D52AE0 /* DataLog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DataLog.cpp; sourceTree = "<group>"; }; - 0F9FC8CE14E612D500D52AE0 /* DataLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataLog.h; sourceTree = "<group>"; }; + 0FA581B7150E952A00B9A2D9 /* DFGNodeFlags.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGNodeFlags.cpp; path = dfg/DFGNodeFlags.cpp; sourceTree = "<group>"; }; + 0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeFlags.h; path = dfg/DFGNodeFlags.h; sourceTree = "<group>"; }; + 0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeType.h; path = dfg/DFGNodeType.h; sourceTree = "<group>"; }; 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LazyOperandValueProfile.h; sourceTree = "<group>"; }; 0FB5467814F5C468002C2989 /* LazyOperandValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LazyOperandValueProfile.cpp; sourceTree = "<group>"; }; 0FB5467A14F5C7D4002C2989 /* MethodOfGettingAValueProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MethodOfGettingAValueProfile.h; sourceTree = "<group>"; }; 0FB5467C14F5CFD3002C2989 /* MethodOfGettingAValueProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MethodOfGettingAValueProfile.cpp; sourceTree = "<group>"; }; - 0FB5468E14FADA6F002C2989 /* RefCountedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCountedArray.h; sourceTree = "<group>"; }; 0FBC0AE41496C7C100D4FBDD /* DFGExitProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DFGExitProfile.cpp; sourceTree = "<group>"; }; 0FBC0AE51496C7C100D4FBDD /* DFGExitProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DFGExitProfile.h; sourceTree = "<group>"; }; 0FBD7E671447998F00481315 /* CodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeOrigin.h; sourceTree = "<group>"; }; @@ -877,22 +839,16 @@ 0FC815141405118D00CFA603 /* VTableSpectrum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VTableSpectrum.h; sourceTree = "<group>"; }; 0FD3C82014115CF800FD81CB /* DFGDriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDriver.cpp; path = dfg/DFGDriver.cpp; sourceTree = "<group>"; }; 0FD3C82214115D0E00FD81CB /* DFGDriver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDriver.h; path = dfg/DFGDriver.h; sourceTree = "<group>"; }; - 0FD52AAC1430359D0026DC9F /* UnionFind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnionFind.h; sourceTree = "<group>"; }; 0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCapabilities.cpp; path = dfg/DFGCapabilities.cpp; sourceTree = "<group>"; }; 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCapabilities.h; path = dfg/DFGCapabilities.h; sourceTree = "<group>"; }; 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompactJITCodeMap.h; sourceTree = "<group>"; }; 0FD82E4F141DAEA100179C94 /* PredictedType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PredictedType.h; sourceTree = "<group>"; }; - 0FD82E50141DAEA100179C94 /* PredictionTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PredictionTracker.h; sourceTree = "<group>"; }; 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSREntry.cpp; path = dfg/DFGOSREntry.cpp; sourceTree = "<group>"; }; 0FD82E53141DAEDE00179C94 /* DFGOSREntry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSREntry.h; path = dfg/DFGOSREntry.h; sourceTree = "<group>"; }; - 0FD82E82141F3FC900179C94 /* BoundsCheckedPointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BoundsCheckedPointer.h; sourceTree = "<group>"; }; 0FD82E84141F3FDA00179C94 /* PredictedType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PredictedType.cpp; sourceTree = "<group>"; }; - 0FD82F491428069200179C94 /* BitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BitVector.h; sourceTree = "<group>"; }; 0FE228EA1436AB2300196C48 /* Options.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Options.cpp; sourceTree = "<group>"; }; 0FE228EB1436AB2300196C48 /* Options.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Options.h; sourceTree = "<group>"; }; 0FF922CF14F46B130041A24E /* JSCLLIntOffsetsExtractor */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = JSCLLIntOffsetsExtractor; sourceTree = BUILT_PRODUCTS_DIR; }; - 0FFFC94914EF909500C72532 /* DFGArithNodeFlagsInferencePhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGArithNodeFlagsInferencePhase.cpp; path = dfg/DFGArithNodeFlagsInferencePhase.cpp; sourceTree = "<group>"; }; - 0FFFC94A14EF909500C72532 /* DFGArithNodeFlagsInferencePhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArithNodeFlagsInferencePhase.h; path = dfg/DFGArithNodeFlagsInferencePhase.h; sourceTree = "<group>"; }; 0FFFC94B14EF909500C72532 /* DFGCFAPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCFAPhase.cpp; path = dfg/DFGCFAPhase.cpp; sourceTree = "<group>"; }; 0FFFC94C14EF909500C72532 /* DFGCFAPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFAPhase.h; path = dfg/DFGCFAPhase.h; sourceTree = "<group>"; }; 0FFFC94D14EF909500C72532 /* DFGCSEPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCSEPhase.cpp; path = dfg/DFGCSEPhase.cpp; sourceTree = "<group>"; }; @@ -903,15 +859,13 @@ 0FFFC95214EF909500C72532 /* DFGPredictionPropagationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPredictionPropagationPhase.h; path = dfg/DFGPredictionPropagationPhase.h; sourceTree = "<group>"; }; 0FFFC95314EF909500C72532 /* DFGVirtualRegisterAllocationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVirtualRegisterAllocationPhase.cpp; path = dfg/DFGVirtualRegisterAllocationPhase.cpp; sourceTree = "<group>"; }; 0FFFC95414EF909500C72532 /* DFGVirtualRegisterAllocationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVirtualRegisterAllocationPhase.h; path = dfg/DFGVirtualRegisterAllocationPhase.h; sourceTree = "<group>"; }; - 1400067612A6F7830064D123 /* OSAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSAllocator.h; sourceTree = "<group>"; }; - 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSAllocatorPosix.cpp; sourceTree = "<group>"; }; 140D17D60E8AD4A9000CD17D /* JSBasePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBasePrivate.h; sourceTree = "<group>"; }; 141211020A48780900480255 /* minidom.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = minidom.c; path = tests/minidom.c; sourceTree = "<group>"; }; 1412110D0A48788700480255 /* minidom.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = minidom.js; path = tests/minidom.js; sourceTree = "<group>"; }; 141211200A48793C00480255 /* minidom */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = minidom; sourceTree = BUILT_PRODUCTS_DIR; }; 141448CA13A176EC00F5BA1A /* MarkedBlockSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedBlockSet.h; sourceTree = "<group>"; }; 141448CC13A1783700F5BA1A /* TinyBloomFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TinyBloomFilter.h; sourceTree = "<group>"; }; - 1419D32C0CEA7CDE00FF507A /* RefCounted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCounted.h; sourceTree = "<group>"; }; + 14150132154BB13F005D8C98 /* WeakSetInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakSetInlines.h; sourceTree = "<group>"; }; 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakRandom.h; sourceTree = "<group>"; }; 1421359A0A677F4F00A8195E /* JSBase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBase.cpp; sourceTree = "<group>"; }; 142711380A460BBB0080EEEA /* JSBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBase.h; sourceTree = "<group>"; }; @@ -931,8 +885,8 @@ 142D6F0E13539A4100B02E86 /* MarkStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkStack.cpp; sourceTree = "<group>"; }; 142D6F0F13539A4100B02E86 /* MarkStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkStack.h; sourceTree = "<group>"; }; 142E312B134FF0A600AFADB5 /* Handle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Handle.h; sourceTree = "<group>"; }; - 142E312C134FF0A600AFADB5 /* HandleHeap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HandleHeap.cpp; sourceTree = "<group>"; }; - 142E312D134FF0A600AFADB5 /* HandleHeap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandleHeap.h; sourceTree = "<group>"; }; + 142E312C134FF0A600AFADB5 /* HandleSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HandleSet.cpp; sourceTree = "<group>"; }; + 142E312D134FF0A600AFADB5 /* HandleSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandleSet.h; sourceTree = "<group>"; }; 142E312E134FF0A600AFADB5 /* HandleStack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HandleStack.cpp; sourceTree = "<group>"; }; 142E312F134FF0A600AFADB5 /* HandleStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HandleStack.h; sourceTree = "<group>"; }; 142E3130134FF0A600AFADB5 /* Local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Local.h; sourceTree = "<group>"; }; @@ -953,7 +907,6 @@ 1440F8AD0A508D200005F061 /* JSCallbackConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCallbackConstructor.cpp; sourceTree = "<group>"; }; 1440FCE10A51E46B0005F061 /* JSClassRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSClassRef.h; sourceTree = "<group>"; }; 1440FCE20A51E46B0005F061 /* JSClassRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSClassRef.cpp; sourceTree = "<group>"; }; - 14456A311314657800212CA3 /* DoublyLinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoublyLinkedList.h; sourceTree = "<group>"; }; 145722851437E140005FDE26 /* StrongInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StrongInlines.h; sourceTree = "<group>"; }; 145C507F0D9DF63B0088F6B9 /* CallData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallData.h; sourceTree = "<group>"; }; 146AAB2A0B66A84900E55F16 /* JSStringRefCF.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSStringRefCF.h; sourceTree = "<group>"; }; @@ -964,14 +917,14 @@ 147B83AA0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BatchedTransitionOptimizer.h; sourceTree = "<group>"; }; 147B84620E6DE6B1004775A4 /* PutPropertySlot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PutPropertySlot.h; sourceTree = "<group>"; }; 1480DB9B0DDC227F003CFDF2 /* DebuggerCallFrame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerCallFrame.h; sourceTree = "<group>"; }; + 14816E19154CC56C00B8054C /* BlockAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BlockAllocator.cpp; sourceTree = "<group>"; }; + 14816E1A154CC56C00B8054C /* BlockAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockAllocator.h; sourceTree = "<group>"; }; 1482B6EA0A4300B300517CFC /* JSValueRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSValueRef.h; sourceTree = "<group>"; }; 1482B74B0A43032800517CFC /* JSStringRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringRef.h; sourceTree = "<group>"; }; 1482B74C0A43032800517CFC /* JSStringRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringRef.cpp; sourceTree = "<group>"; }; 1482B78A0A4305AB00517CFC /* APICast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APICast.h; sourceTree = "<group>"; }; 1482B7E10A43076000517CFC /* JSObjectRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSObjectRef.h; sourceTree = "<group>"; }; 1482B7E20A43076000517CFC /* JSObjectRef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSObjectRef.cpp; sourceTree = "<group>"; }; - 148A1626095D16BB00666D0D /* ListRefPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ListRefPtr.h; sourceTree = "<group>"; }; - 148A1ECD0D10C23B0069A47C /* RefPtrHashMap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefPtrHashMap.h; sourceTree = "<group>"; }; 148CD1D7108CF902008163C6 /* JSContextRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSContextRefPrivate.h; sourceTree = "<group>"; }; 149559ED0DDCDDF700648087 /* DebuggerCallFrame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerCallFrame.cpp; sourceTree = "<group>"; }; 1497209014EB831500FEB1B7 /* PassWeak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassWeak.h; sourceTree = "<group>"; }; @@ -987,8 +940,6 @@ 14ABB454099C2A0F00E2A24F /* JSType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSType.h; sourceTree = "<group>"; }; 14ABDF5D0A437FEF00ECCA01 /* JSCallbackObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObject.h; sourceTree = "<group>"; }; 14ABDF5E0A437FEF00ECCA01 /* JSCallbackObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSCallbackObject.cpp; sourceTree = "<group>"; }; - 14B3EF0312BC24DD00D29EFF /* PageBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageBlock.h; sourceTree = "<group>"; }; - 14B3EF0412BC24DD00D29EFF /* PageBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageBlock.cpp; sourceTree = "<group>"; }; 14B7233F12D7D0DA003BD5ED /* MachineStackMarker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MachineStackMarker.cpp; sourceTree = "<group>"; }; 14B7234012D7D0DA003BD5ED /* MachineStackMarker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MachineStackMarker.h; sourceTree = "<group>"; }; 14BA78F013AAB88F005B7C2C /* SlotVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotVisitor.h; sourceTree = "<group>"; }; @@ -1007,104 +958,48 @@ 14DA818E0D99FD2000B0A4FB /* JSActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSActivation.h; sourceTree = "<group>"; }; 14DA818F0D99FD2000B0A4FB /* JSActivation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSActivation.cpp; sourceTree = "<group>"; }; 14DE0D680D02431400AACCA2 /* JSGlobalObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalObject.cpp; sourceTree = "<group>"; }; + 14E84F9914EE1ACC00D6D5D4 /* WeakBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakBlock.cpp; sourceTree = "<group>"; }; + 14E84F9A14EE1ACC00D6D5D4 /* WeakBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakBlock.h; sourceTree = "<group>"; }; + 14E84F9B14EE1ACC00D6D5D4 /* WeakSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakSet.cpp; sourceTree = "<group>"; }; + 14E84F9C14EE1ACC00D6D5D4 /* WeakSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakSet.h; sourceTree = "<group>"; }; + 14E84F9D14EE1ACC00D6D5D4 /* WeakImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakImpl.h; sourceTree = "<group>"; }; 14F252560D08DD8D004ECFFF /* JSVariableObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSVariableObject.h; sourceTree = "<group>"; }; + 14F7256314EE265E00B1652B /* WeakHandleOwner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WeakHandleOwner.cpp; sourceTree = "<group>"; }; + 14F7256414EE265E00B1652B /* WeakHandleOwner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakHandleOwner.h; sourceTree = "<group>"; }; 14F97446138C853E00DA1C67 /* HeapRootVisitor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapRootVisitor.h; sourceTree = "<group>"; }; - 14FFF98A12BFFF7500795BB8 /* PageAllocationAligned.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PageAllocationAligned.cpp; sourceTree = "<group>"; }; - 14FFF98B12BFFF7500795BB8 /* PageAllocationAligned.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageAllocationAligned.h; sourceTree = "<group>"; }; - 180B9AEF0F16C569009BDBC5 /* CurrentTime.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CurrentTime.cpp; sourceTree = "<group>"; }; - 180B9AF00F16C569009BDBC5 /* CurrentTime.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CurrentTime.h; sourceTree = "<group>"; }; - 18BAB52710DADFCD000D945B /* ThreadIdentifierDataPthreads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadIdentifierDataPthreads.cpp; sourceTree = "<group>"; }; - 18BAB52810DADFCD000D945B /* ThreadIdentifierDataPthreads.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadIdentifierDataPthreads.h; sourceTree = "<group>"; }; - 1A082777142168D70090CCAC /* BinarySemaphore.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BinarySemaphore.cpp; sourceTree = "<group>"; }; - 1A082778142168D70090CCAC /* BinarySemaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BinarySemaphore.h; sourceTree = "<group>"; }; - 1AA9E5501498093500001A8A /* Functional.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Functional.h; sourceTree = "<group>"; }; 1C9051420BA9E8A70081E9D0 /* Version.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = "<group>"; }; 1C9051430BA9E8A70081E9D0 /* JavaScriptCore.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = JavaScriptCore.xcconfig; sourceTree = "<group>"; }; 1C9051440BA9E8A70081E9D0 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; }; 1C9051450BA9E8A70081E9D0 /* Base.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; }; 1CAA8B4A0D32C39A0041BCFF /* JavaScript.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScript.h; sourceTree = "<group>"; }; 1CAA8B4B0D32C39A0041BCFF /* JavaScriptCore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptCore.h; sourceTree = "<group>"; }; - 2684B2C414D4A9B20072C0B6 /* ParsedURL.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParsedURL.cpp; sourceTree = "<group>"; }; - 2684B2C514D4A9B20072C0B6 /* ParsedURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParsedURL.h; sourceTree = "<group>"; }; - 2684B2C614D4A9B20072C0B6 /* URLString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLString.h; sourceTree = "<group>"; }; - 2684B2C814D4A9B20072C0B6 /* RawURLBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RawURLBuffer.h; sourceTree = "<group>"; }; - 2684B2C914D4A9B20072C0B6 /* URLBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLBuffer.h; sourceTree = "<group>"; }; - 2684B2CA14D4A9B20072C0B6 /* URLCharacterTypes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLCharacterTypes.cpp; sourceTree = "<group>"; }; - 2684B2CB14D4A9B20072C0B6 /* URLCharacterTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLCharacterTypes.h; sourceTree = "<group>"; }; - 2684B2CC14D4A9B20072C0B6 /* URLComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLComponent.h; sourceTree = "<group>"; }; - 2684B2CD14D4A9B20072C0B6 /* URLEscape.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLEscape.cpp; sourceTree = "<group>"; }; - 2684B2CE14D4A9B20072C0B6 /* URLEscape.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLEscape.h; sourceTree = "<group>"; }; - 2684B2CF14D4A9B20072C0B6 /* URLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLParser.h; sourceTree = "<group>"; }; - 2684B2D014D4A9B20072C0B6 /* URLQueryCanonicalizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLQueryCanonicalizer.h; sourceTree = "<group>"; }; - 2684B2D114D4A9B20072C0B6 /* URLSegments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = URLSegments.cpp; sourceTree = "<group>"; }; - 2684B2D214D4A9B20072C0B6 /* URLSegments.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = URLSegments.h; sourceTree = "<group>"; }; - 2CFC5B7A12F44714004914E2 /* CharacterNames.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CharacterNames.h; sourceTree = "<group>"; }; - 41359CF40FDD89CB00206180 /* DateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DateMath.cpp; sourceTree = "<group>"; }; - 41359CF50FDD89CB00206180 /* DateMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateMath.h; sourceTree = "<group>"; }; - 434A8E7014956A50009126F7 /* ASCIIFastPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ASCIIFastPath.h; path = text/ASCIIFastPath.h; sourceTree = "<group>"; }; - 440B7AED0FAF7FCB0073323E /* OwnPtrCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnPtrCommon.h; sourceTree = "<group>"; }; + 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringJoiner.cpp; sourceTree = "<group>"; }; + 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringJoiner.h; sourceTree = "<group>"; }; 449097EE0F8F81B50076A327 /* FeatureDefines.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = FeatureDefines.xcconfig; sourceTree = "<group>"; }; - 44DD48520FAEA85000D6B4EB /* PassOwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassOwnPtr.h; sourceTree = "<group>"; }; 451539B812DC994500EF7AC4 /* Yarr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Yarr.h; path = yarr/Yarr.h; sourceTree = "<group>"; }; 45E12D8806A49B0F00E9DF84 /* jsc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = jsc.cpp; sourceTree = "<group>"; tabWidth = 4; }; - 511FC4C7117EE23D00425272 /* MD5.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MD5.cpp; sourceTree = "<group>"; }; - 511FC4CA117EE2A800425272 /* MD5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MD5.h; sourceTree = "<group>"; }; - 5135FAD512D26856003C083B /* Decoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Decoder.h; sourceTree = "<group>"; }; - 5135FAD612D26856003C083B /* Encoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Encoder.h; sourceTree = "<group>"; }; - 5186111D0CC824830081412B /* Deque.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Deque.h; sourceTree = "<group>"; }; 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; }; 51F0EC0705C86C9A00E6DF1B /* libobjc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libobjc.dylib; path = /usr/lib/libobjc.dylib; sourceTree = "<absolute>"; }; - 51F648D60BB4E2CA0033D760 /* RetainPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = RetainPtr.h; sourceTree = "<group>"; }; 5D53726D0E1C546B0021E549 /* Tracing.d */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Tracing.d; sourceTree = "<group>"; }; 5D53726E0E1C54880021E549 /* Tracing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Tracing.h; sourceTree = "<group>"; }; 5D53727D0E1C55EC0021E549 /* TracingDtrace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TracingDtrace.h; sourceTree = "<group>"; }; 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libedit.dylib; path = /usr/lib/libedit.dylib; sourceTree = "<absolute>"; }; - 5D63E9AC10F2BD6E00FC8AE9 /* StringHasher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringHasher.h; sourceTree = "<group>"; }; - 5D6A566A0F05995500266145 /* Threading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Threading.cpp; sourceTree = "<group>"; }; - 5DA479650CFBCF56009328A0 /* TCPackedCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TCPackedCache.h; sourceTree = "<group>"; }; 5DAFD6CB146B686300FBEFB4 /* JSC.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = JSC.xcconfig; sourceTree = "<group>"; }; - 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MallocZoneSupport.h; sourceTree = "<group>"; }; 5DDDF44614FEE72200B4FB4D /* LLIntDesiredOffsets.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntDesiredOffsets.h; path = LLIntOffsets/LLIntDesiredOffsets.h; sourceTree = BUILT_PRODUCTS_DIR; }; 5DE3D0F40DD8DDFB00468714 /* WebKitAvailability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitAvailability.h; sourceTree = "<group>"; }; 6507D2970E871E4A00D7D896 /* JSTypeInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSTypeInfo.h; sourceTree = "<group>"; }; 651122E5140469BA002B101D /* testRegExp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = testRegExp.cpp; sourceTree = "<group>"; }; 6511230514046A4C002B101D /* testRegExp */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = testRegExp; sourceTree = BUILT_PRODUCTS_DIR; }; - 651DCA02136A6FAB00F74194 /* PassTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassTraits.h; sourceTree = "<group>"; }; - 651F6412039D5B5F0078395C /* dtoa.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dtoa.cpp; sourceTree = "<group>"; tabWidth = 8; }; - 651F6413039D5B5F0078395C /* dtoa.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = dtoa.h; sourceTree = "<group>"; tabWidth = 8; }; - 652246A40C8D7A0E007BDAF7 /* HashIterators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HashIterators.h; sourceTree = "<group>"; }; 65303D631447B9E100D3F904 /* ParserTokens.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParserTokens.h; sourceTree = "<group>"; }; 65400C0F0A69BAF200509887 /* PropertyNameArray.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyNameArray.cpp; sourceTree = "<group>"; }; 65400C100A69BAF200509887 /* PropertyNameArray.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = PropertyNameArray.h; sourceTree = "<group>"; }; - 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = TCPageMap.h; sourceTree = "<group>"; tabWidth = 8; }; - 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = TCSpinLock.h; sourceTree = "<group>"; tabWidth = 8; }; - 6541BD7008E80A17002CBEE7 /* TCSystemAlloc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TCSystemAlloc.cpp; sourceTree = "<group>"; tabWidth = 8; }; - 6541BD7108E80A17002CBEE7 /* TCSystemAlloc.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = TCSystemAlloc.h; sourceTree = "<group>"; tabWidth = 8; }; 655EB29A10CE2581001A990E /* NodesCodegen.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NodesCodegen.cpp; sourceTree = "<group>"; }; 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; }; 65621E6B089E859700760F35 /* PropertySlot.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertySlot.cpp; sourceTree = "<group>"; tabWidth = 8; }; 65621E6C089E859700760F35 /* PropertySlot.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = PropertySlot.h; sourceTree = "<group>"; tabWidth = 8; }; - 657EB7450B708F540063461B /* ListHashSet.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ListHashSet.h; sourceTree = "<group>"; }; - 657EEBBF094E445E008C9C7B /* HashCountedSet.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HashCountedSet.h; sourceTree = "<group>"; tabWidth = 8; }; - 6580F795094070560082C219 /* PassRefPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = PassRefPtr.h; sourceTree = "<group>"; tabWidth = 8; }; - 6592C316098B7DE10003D4F6 /* Vector.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Vector.h; sourceTree = "<group>"; }; - 6592C317098B7DE10003D4F6 /* VectorTraits.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = VectorTraits.h; sourceTree = "<group>"; }; 65C02FBB0637462A003E7EE6 /* Protect.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Protect.h; sourceTree = "<group>"; tabWidth = 8; }; - 65C647B3093EF8D60022C380 /* RefPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = RefPtr.h; sourceTree = "<group>"; tabWidth = 8; }; 65C7A1710A8EAACB00FA37EA /* JSWrapperObject.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = JSWrapperObject.cpp; sourceTree = "<group>"; }; 65C7A1720A8EAACB00FA37EA /* JSWrapperObject.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = JSWrapperObject.h; sourceTree = "<group>"; }; - 65D6D87E09B5A32E0002E4D7 /* Platform.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = Platform.h; sourceTree = "<group>"; }; - 65DFC92A08EA173A00F7300B /* HashFunctions.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HashFunctions.h; sourceTree = "<group>"; tabWidth = 8; }; - 65DFC92B08EA173A00F7300B /* HashMap.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HashMap.h; sourceTree = "<group>"; tabWidth = 8; }; - 65DFC92C08EA173A00F7300B /* HashSet.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HashSet.h; sourceTree = "<group>"; tabWidth = 8; }; - 65DFC92D08EA173A00F7300B /* HashTable.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HashTable.cpp; sourceTree = "<group>"; tabWidth = 8; }; - 65DFC92E08EA173A00F7300B /* HashTable.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HashTable.h; sourceTree = "<group>"; tabWidth = 8; }; - 65DFC92F08EA173A00F7300B /* HashTraits.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = HashTraits.h; sourceTree = "<group>"; tabWidth = 8; }; - 65E1A2F4122B880D00B26097 /* NonCopyingSort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NonCopyingSort.h; sourceTree = "<group>"; }; - 65E217B708E7EECC0023E5F6 /* Assertions.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Assertions.h; sourceTree = "<group>"; tabWidth = 8; }; - 65E217B808E7EECC0023E5F6 /* Assertions.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Assertions.cpp; sourceTree = "<group>"; tabWidth = 8; }; - 65E217B908E7EECC0023E5F6 /* FastMalloc.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FastMalloc.cpp; sourceTree = "<group>"; tabWidth = 8; }; - 65E217BA08E7EECC0023E5F6 /* FastMalloc.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = FastMalloc.h; sourceTree = "<group>"; tabWidth = 8; }; 65E866ED0DD59AFA00A2B2A1 /* SourceProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceProvider.h; sourceTree = "<group>"; }; 65E866EE0DD59AFA00A2B2A1 /* SourceCode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceCode.h; sourceTree = "<group>"; }; 65EA4C99092AF9E20093D800 /* JSLock.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSLock.cpp; sourceTree = "<group>"; tabWidth = 8; }; @@ -1112,15 +1007,6 @@ 65EA73620BAE35D1001BB560 /* CommonIdentifiers.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CommonIdentifiers.cpp; sourceTree = "<group>"; }; 65EA73630BAE35D1001BB560 /* CommonIdentifiers.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CommonIdentifiers.h; sourceTree = "<group>"; }; 704FD35305697E6D003DBED9 /* BooleanObject.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = BooleanObject.h; sourceTree = "<group>"; tabWidth = 8; }; - 7186A6E813100B57004479E1 /* HexNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HexNumber.h; sourceTree = "<group>"; }; - 718A8482134F3A1200B87529 /* StringOperators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringOperators.h; path = text/StringOperators.h; sourceTree = "<group>"; }; - 76FB9F0E12E851860051A2EB /* SHA1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SHA1.h; sourceTree = "<group>"; }; - 76FB9F1012E851960051A2EB /* SHA1.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SHA1.cpp; sourceTree = "<group>"; }; - 7934BB761361979300CB99A1 /* ParallelJobs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelJobs.h; sourceTree = "<group>"; }; - 7934BB771361979300CB99A1 /* ParallelJobsGeneric.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParallelJobsGeneric.cpp; sourceTree = "<group>"; }; - 7934BB781361979300CB99A1 /* ParallelJobsGeneric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelJobsGeneric.h; sourceTree = "<group>"; }; - 7934BB791361979300CB99A1 /* ParallelJobsLibdispatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelJobsLibdispatch.h; sourceTree = "<group>"; }; - 7934BB7A1361979300CB99A1 /* ParallelJobsOpenMP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParallelJobsOpenMP.h; 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>"; }; @@ -1133,17 +1019,15 @@ 8603CEF314C7546400AE59E3 /* CodeProfiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeProfiling.h; sourceTree = "<group>"; }; 8604F4F2143A6C4400B295F5 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; }; 8604F503143CE1C100B295F5 /* JSGlobalThis.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalThis.h; sourceTree = "<group>"; }; - 8626BECE11928E3900782FAB /* StringStatics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringStatics.cpp; path = text/StringStatics.cpp; sourceTree = "<group>"; }; - 8627E5EA11F1281900A313B5 /* PageAllocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageAllocation.h; sourceTree = "<group>"; }; + 8612E4CB1522918400C836BE /* MatchResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MatchResult.h; sourceTree = "<group>"; }; 863B23DF0FC60E6200703AA4 /* MacroAssemblerCodeRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerCodeRef.h; sourceTree = "<group>"; }; - 86438FC31265503E00E0DFCA /* StringBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StringBuilder.cpp; path = text/StringBuilder.cpp; 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>"; }; + 863C6D981521111200585E4E /* YarrCanonicalizeUCS2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrCanonicalizeUCS2.cpp; path = yarr/YarrCanonicalizeUCS2.cpp; sourceTree = "<group>"; }; + 863C6D991521111200585E4E /* YarrCanonicalizeUCS2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrCanonicalizeUCS2.h; path = yarr/YarrCanonicalizeUCS2.h; sourceTree = "<group>"; }; + 863C6D9A1521111200585E4E /* YarrCanonicalizeUCS2.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; name = YarrCanonicalizeUCS2.js; path = yarr/YarrCanonicalizeUCS2.js; sourceTree = "<group>"; }; 865A30F0135007E100CDB49E /* JSValueInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSValueInlineMethods.h; sourceTree = "<group>"; }; 865F408710E7D56300947361 /* APIShims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIShims.h; sourceTree = "<group>"; }; 866739D013BFDE710023D87C /* BigInteger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BigInteger.h; sourceTree = "<group>"; }; 866739D113BFDE710023D87C /* Uint16WithFraction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uint16WithFraction.h; sourceTree = "<group>"; }; - 86676D4D11FED55D004B6863 /* BumpPointerAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BumpPointerAllocator.h; sourceTree = "<group>"; }; 86704B4012DB8A8100A9FE7B /* YarrSyntaxChecker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrSyntaxChecker.cpp; path = yarr/YarrSyntaxChecker.cpp; sourceTree = "<group>"; }; 86704B4112DB8A8100A9FE7B /* YarrSyntaxChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrSyntaxChecker.h; path = yarr/YarrSyntaxChecker.h; sourceTree = "<group>"; }; 86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = YarrInterpreter.cpp; path = yarr/YarrInterpreter.cpp; sourceTree = "<group>"; }; @@ -1155,17 +1039,6 @@ 86704B8312DBA33700A9FE7B /* YarrPattern.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = YarrPattern.h; path = yarr/YarrPattern.h; sourceTree = "<group>"; }; 86880F1B14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSpeculativeJIT32_64.cpp; path = dfg/DFGSpeculativeJIT32_64.cpp; sourceTree = "<group>"; }; 86880F4C14353B2100B08D42 /* DFGSpeculativeJIT64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGSpeculativeJIT64.cpp; path = dfg/DFGSpeculativeJIT64.cpp; 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>"; }; - 8690231412092D5C00630AF9 /* PageReservation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageReservation.h; sourceTree = "<group>"; }; - 8699AA60146A0E2B00E23A73 /* InlineASM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InlineASM.h; sourceTree = "<group>"; }; 869D04AE1193B54D00803475 /* CachedTranscendentalFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedTranscendentalFunction.h; 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>"; }; @@ -1180,7 +1053,6 @@ 86B5822E14D2373B00A9C306 /* CodeProfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeProfile.cpp; sourceTree = "<group>"; }; 86B5822F14D2373B00A9C306 /* CodeProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeProfile.h; sourceTree = "<group>"; }; 86B5826A14D35D5100A9C306 /* TieredMMapArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TieredMMapArray.h; sourceTree = "<group>"; }; - 86B99AE1117E578100DF5A90 /* StringBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StringBuffer.h; path = text/StringBuffer.h; sourceTree = "<group>"; }; 86BB09BE138E381B0056702F /* DFGRepatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGRepatch.cpp; path = dfg/DFGRepatch.cpp; sourceTree = "<group>"; }; 86BB09BF138E381B0056702F /* DFGRepatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGRepatch.h; path = dfg/DFGRepatch.h; sourceTree = "<group>"; }; 86BF642A148DB2B5004DE36A /* Intrinsic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Intrinsic.h; sourceTree = "<group>"; }; @@ -1194,16 +1066,12 @@ 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>"; }; 86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARM.h; sourceTree = "<group>"; }; 86D3B3C110159D7F002865E7 /* LinkBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkBuffer.h; sourceTree = "<group>"; }; 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RepatchBuffer.h; sourceTree = "<group>"; }; - 86D87DA512BC4B14008E73A1 /* StackBounds.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackBounds.cpp; sourceTree = "<group>"; }; - 86D87DA612BC4B14008E73A1 /* StackBounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackBounds.h; sourceTree = "<group>"; }; 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorFixedVMPool.cpp; sourceTree = "<group>"; }; 86E116B00FE75AC800B512BC /* CodeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeLocation.h; sourceTree = "<group>"; }; 86E85538111B9968001AF51E /* JSStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringBuilder.h; sourceTree = "<group>"; }; @@ -1221,17 +1089,13 @@ 86EC9DC31328DF82002B2AD7 /* DFGSpeculativeJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSpeculativeJIT.h; path = dfg/DFGSpeculativeJIT.h; sourceTree = "<group>"; }; 86ECA3E9132DEF1C002B2AD7 /* DFGNode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNode.h; path = dfg/DFGNode.h; sourceTree = "<group>"; }; 86ECA3F9132DF25A002B2AD7 /* DFGScoreBoard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGScoreBoard.h; path = dfg/DFGScoreBoard.h; sourceTree = "<group>"; }; - 86F38858121130CA007A7CE3 /* AtomicStringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AtomicStringHash.h; path = text/AtomicStringHash.h; sourceTree = "<group>"; }; + 86F75EFB151C062F007C9BA3 /* RegExpCachedResult.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpCachedResult.cpp; sourceTree = "<group>"; }; + 86F75EFC151C062F007C9BA3 /* RegExpCachedResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCachedResult.h; sourceTree = "<group>"; }; + 86F75EFD151C062F007C9BA3 /* RegExpMatchesArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpMatchesArray.cpp; sourceTree = "<group>"; }; 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBoundFunction.cpp; sourceTree = "<group>"; }; 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBoundFunction.h; sourceTree = "<group>"; }; 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MemoryStatistics.cpp; sourceTree = "<group>"; }; 90213E3C123A40C200D422F3 /* MemoryStatistics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MemoryStatistics.h; sourceTree = "<group>"; }; - 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RefCountedLeakCounter.cpp; sourceTree = "<group>"; }; - 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RefCountedLeakCounter.h; sourceTree = "<group>"; }; - 91A3905514C0F47200F67901 /* Uint8ClampedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uint8ClampedArray.h; sourceTree = "<group>"; }; - 9303F567099118FA00AD71B8 /* OwnPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnPtr.h; sourceTree = "<group>"; }; - 9303F5690991190000AD71B8 /* Noncopyable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Noncopyable.h; sourceTree = "<group>"; }; - 9303F5A409911A5800AD71B8 /* OwnArrayPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OwnArrayPtr.h; sourceTree = "<group>"; }; 93052C320FB792190048FDC3 /* ParserArena.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ParserArena.cpp; sourceTree = "<group>"; }; 93052C330FB792190048FDC3 /* ParserArena.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParserArena.h; sourceTree = "<group>"; }; 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NodeConstructors.h; sourceTree = "<group>"; }; @@ -1245,19 +1109,11 @@ 93345A8812D838C400302BE3 /* StringRecursionChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringRecursionChecker.h; sourceTree = "<group>"; }; 933A349A038AE7C6008635CE /* Identifier.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Identifier.h; sourceTree = "<group>"; tabWidth = 8; }; 933A349D038AE80F008635CE /* Identifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Identifier.cpp; sourceTree = "<group>"; tabWidth = 8; }; - 933F5CDB126922690049191E /* NullPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NullPtr.h; sourceTree = "<group>"; }; - 935AF46909E9D9DB00ACD1D8 /* Forward.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Forward.h; sourceTree = "<group>"; }; - 935AF46B09E9D9DB00ACD1D8 /* UnusedParam.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnusedParam.h; sourceTree = "<group>"; }; 9374D3A7038D9D74008635CE /* ScopeChain.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ScopeChain.h; sourceTree = "<group>"; tabWidth = 8; }; 9374D3A8038D9D74008635CE /* ScopeChain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ScopeChain.cpp; sourceTree = "<group>"; tabWidth = 8; }; 937B63CC09E766D200A671DD /* DerivedSources.make */ = {isa = PBXFileReference; explicitFileType = sourcecode.make; fileEncoding = 4; path = DerivedSources.make; sourceTree = "<group>"; usesTabs = 1; }; - 93854A9912C93D3B00DAAF77 /* NullPtr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NullPtr.cpp; path = ./wtf/NullPtr.cpp; sourceTree = SOURCE_ROOT; }; 938772E5038BFE19008635CE /* JSArray.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = JSArray.h; sourceTree = "<group>"; tabWidth = 8; }; - 938C4F690CA06BC700D9310A /* ASCIICType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASCIICType.h; sourceTree = "<group>"; }; - 938C4F6B0CA06BCE00D9310A /* DisallowCType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DisallowCType.h; sourceTree = "<group>"; }; - 93AA4F770957251F0084B3A7 /* AlwaysInline.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = AlwaysInline.h; sourceTree = "<group>"; tabWidth = 8; }; 93ADFCE60CCBD7AC00D30B08 /* JSArray.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSArray.cpp; sourceTree = "<group>"; }; - 93B6A0DE0AA64DA40076DE27 /* GetPtr.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GetPtr.h; sourceTree = "<group>"; }; 93CEDDFB0EA91EE600258EBE /* RegExpMatchesArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpMatchesArray.h; sourceTree = "<group>"; }; 93F0B3A909BB4DC00068FCE3 /* Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Parser.cpp; sourceTree = "<group>"; }; 93F0B3AA09BB4DC00068FCE3 /* Parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Parser.h; sourceTree = "<group>"; }; @@ -1282,7 +1138,6 @@ 969A07210ED1CE3300F1F681 /* BytecodeGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BytecodeGenerator.h; sourceTree = "<group>"; }; 969A07270ED1CE6900F1F681 /* Label.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Label.h; sourceTree = "<group>"; }; 969A07280ED1CE6900F1F681 /* RegisterID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegisterID.h; sourceTree = "<group>"; }; - 969A07290ED1CE6900F1F681 /* SegmentedVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SegmentedVector.h; sourceTree = "<group>"; }; 969A07900ED1D3AE00F1F681 /* CodeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlock.cpp; sourceTree = "<group>"; }; 969A07910ED1D3AE00F1F681 /* CodeBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlock.h; sourceTree = "<group>"; }; 969A07920ED1D3AE00F1F681 /* EvalCodeCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EvalCodeCache.h; sourceTree = "<group>"; }; @@ -1290,18 +1145,12 @@ 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>"; }; - 96DD73780F9DA3100027FBCC /* VMTags.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMTags.h; sourceTree = "<group>"; }; 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDateMath.cpp; sourceTree = "<group>"; }; 9788FC231471AD0C0068CE2D /* JSDateMath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDateMath.h; sourceTree = "<group>"; }; - 97941A3F130299DB004A3447 /* OSRandomSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OSRandomSource.cpp; sourceTree = "<group>"; }; - 97941A40130299DB004A3447 /* OSRandomSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSRandomSource.h; sourceTree = "<group>"; }; - 97941A7C1302A098004A3447 /* CryptographicallyRandomNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CryptographicallyRandomNumber.cpp; sourceTree = "<group>"; }; - 97941A7D1302A098004A3447 /* CryptographicallyRandomNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptographicallyRandomNumber.h; sourceTree = "<group>"; }; 97F6903A1169DF7F00A6BB46 /* Terminator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Terminator.h; sourceTree = "<group>"; }; A1712B3A11C7B212007A5315 /* RegExpCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpCache.cpp; sourceTree = "<group>"; }; A1712B3E11C7B228007A5315 /* RegExpCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpCache.h; sourceTree = "<group>"; }; A1712B4011C7B235007A5315 /* RegExpKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpKey.h; sourceTree = "<group>"; }; - A1D764511354448B00C5C7C0 /* Alignment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Alignment.h; sourceTree = "<group>"; }; A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITOpcodes32_64.cpp; 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>"; }; @@ -1315,20 +1164,6 @@ A7386551118697B400540279 /* SpecializedThunkJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SpecializedThunkJIT.h; sourceTree = "<group>"; }; A7386552118697B400540279 /* ThunkGenerators.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThunkGenerators.cpp; sourceTree = "<group>"; }; A7386553118697B400540279 /* ThunkGenerators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThunkGenerators.h; sourceTree = "<group>"; }; - A73BE154148420520091204B /* ArrayBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBuffer.cpp; sourceTree = "<group>"; }; - A73BE155148420520091204B /* ArrayBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBuffer.h; sourceTree = "<group>"; }; - A73BE156148420520091204B /* ArrayBufferView.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferView.cpp; sourceTree = "<group>"; }; - A73BE157148420520091204B /* ArrayBufferView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferView.h; sourceTree = "<group>"; }; - A73BE159148420520091204B /* Float32Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Float32Array.h; sourceTree = "<group>"; }; - A73BE15B148420520091204B /* Float64Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Float64Array.h; sourceTree = "<group>"; }; - A73BE15D148420520091204B /* Int8Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Int8Array.h; sourceTree = "<group>"; }; - A73BE15F148420520091204B /* Int16Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Int16Array.h; sourceTree = "<group>"; }; - A73BE161148420520091204B /* Int32Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Int32Array.h; sourceTree = "<group>"; }; - A73BE163148420520091204B /* Uint8Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uint8Array.h; sourceTree = "<group>"; }; - A73BE165148420520091204B /* Uint16Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uint16Array.h; sourceTree = "<group>"; }; - A73BE167148420520091204B /* Uint32Array.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Uint32Array.h; sourceTree = "<group>"; }; - A73BE17D148420840091204B /* TypedArrayBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypedArrayBase.h; sourceTree = "<group>"; }; - A73BE17F148420A80091204B /* IntegralTypedArrayBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntegralTypedArrayBase.h; 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>"; }; @@ -1339,37 +1174,27 @@ A76C51741182748D00715B05 /* JSInterfaceJIT.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSInterfaceJIT.h; sourceTree = "<group>"; }; A76F54A213B28AAB00EF2BCE /* JITWriteBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITWriteBarrier.h; sourceTree = "<group>"; }; A781E358141970C700094D90 /* StorageBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StorageBarrier.h; 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>"; }; - A7A275F514837A8E001DBB39 /* ExportMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExportMacros.h; sourceTree = "<group>"; }; A7A7EE7411B98B8D0065A14F /* ASTBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ASTBuilder.h; sourceTree = "<group>"; }; A7A7EE7711B98B8D0065A14F /* SyntaxChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SyntaxChecker.h; sourceTree = "<group>"; }; A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExecutableAllocator.h; sourceTree = "<group>"; }; A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocator.cpp; sourceTree = "<group>"; }; A7B4ACAE1484C9CE00B38A36 /* JSExportMacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSExportMacros.h; sourceTree = "<group>"; }; - A7BC0C81140608B000B1BB71 /* CheckedArithmetic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheckedArithmetic.h; sourceTree = "<group>"; }; A7C1E8C8112E701C00A37F98 /* JITPropertyAccess32_64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JITPropertyAccess32_64.cpp; sourceTree = "<group>"; }; A7C225CC139981F100FF1662 /* KeywordLookupGenerator.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = KeywordLookupGenerator.py; sourceTree = "<group>"; }; A7C225CD1399849C00FF1662 /* KeywordLookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeywordLookup.h; sourceTree = "<group>"; }; - A7C40C07130B057D00D002A1 /* BlockStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlockStack.h; sourceTree = "<group>"; }; - A7C40C08130B057D00D002A1 /* SentinelLinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SentinelLinkedList.h; sourceTree = "<group>"; }; - A7C40C09130B057D00D002A1 /* SinglyLinkedList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SinglyLinkedList.h; sourceTree = "<group>"; }; - A7D649A91015224E009B2E1B /* PossiblyNull.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PossiblyNull.h; sourceTree = "<group>"; }; A7DCB77912E3D90500911940 /* WriteBarrier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrier.h; sourceTree = "<group>"; }; A7E2EA690FB460CF00601F06 /* LiteralParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralParser.h; sourceTree = "<group>"; }; A7E2EA6A0FB460CF00601F06 /* LiteralParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralParser.cpp; sourceTree = "<group>"; }; A7E42C180E3938830065A544 /* JSStaticScopeObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStaticScopeObject.h; sourceTree = "<group>"; }; A7E42C190E3938830065A544 /* JSStaticScopeObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStaticScopeObject.cpp; sourceTree = "<group>"; }; - A7F19ECD11DD490900931E70 /* FixedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FixedArray.h; sourceTree = "<group>"; }; A7F8690E0F9584A100558697 /* CachedCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedCall.h; sourceTree = "<group>"; }; A7F869EC0F95C2EC00558697 /* CallFrameClosure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallFrameClosure.h; sourceTree = "<group>"; }; A7F9935D0FD7325100A0B2D0 /* JSONObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONObject.h; sourceTree = "<group>"; }; A7F9935E0FD7325100A0B2D0 /* JSONObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSONObject.cpp; sourceTree = "<group>"; }; A7FB604B103F5EAB0017A286 /* PropertyDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PropertyDescriptor.h; sourceTree = "<group>"; }; A7FB60A3103F7DC20017A286 /* PropertyDescriptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PropertyDescriptor.cpp; sourceTree = "<group>"; }; + A8A4748D151A8306004123FF /* libWTF.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libWTF.a; sourceTree = BUILT_PRODUCTS_DIR; }; A8E894310CD0602400367179 /* JSCallbackObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSCallbackObjectFunctions.h; sourceTree = "<group>"; }; A8E894330CD0603F00367179 /* JSGlobalObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObject.h; sourceTree = "<group>"; }; BC021BF1136900C300FC5467 /* CompilerVersion.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = CompilerVersion.xcconfig; sourceTree = "<group>"; }; @@ -1425,10 +1250,6 @@ BC337BDE0E1AF0B80076918A /* GetterSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetterSetter.h; sourceTree = "<group>"; }; BC337BEA0E1B00CB0076918A /* Error.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Error.cpp; sourceTree = "<group>"; }; BC3C4C9F1458F5450025FB62 /* JSGlobalThis.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalThis.cpp; sourceTree = "<group>"; }; - BC5F7BBB11823B590052C02C /* Atomics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Atomics.h; sourceTree = "<group>"; }; - BC5F7BBC11823B590052C02C /* ThreadingPrimitives.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadingPrimitives.h; sourceTree = "<group>"; }; - BC5F7BBD11823B590052C02C /* ThreadSafeRefCounted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadSafeRefCounted.h; sourceTree = "<group>"; }; - BC66BAE213F4928F00C23FAE /* Compiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Compiler.h; sourceTree = "<group>"; }; BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassInfo.h; sourceTree = "<group>"; }; BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalObjectFunctions.cpp; sourceTree = "<group>"; }; BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObjectFunctions.h; sourceTree = "<group>"; }; @@ -1465,80 +1286,29 @@ BCDE3AB10E6C82CF001453A7 /* Structure.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Structure.h; sourceTree = "<group>"; }; BCF605110E203EF800B9A64D /* ArgList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArgList.cpp; sourceTree = "<group>"; }; BCF605120E203EF800B9A64D /* ArgList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArgList.h; sourceTree = "<group>"; }; - BCF6553B0A2048DE0038A194 /* MathExtras.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = MathExtras.h; sourceTree = "<group>"; }; - BCFBE695122560E800309E9D /* PassOwnArrayPtr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PassOwnArrayPtr.h; sourceTree = "<group>"; }; BCFD8C900EEB2EE700283848 /* JumpTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JumpTable.cpp; sourceTree = "<group>"; }; BCFD8C910EEB2EE700283848 /* JumpTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JumpTable.h; sourceTree = "<group>"; }; - C0A2723F0E509F1E00E96E15 /* NotFound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotFound.h; sourceTree = "<group>"; }; - C22C529013FAF6EF00B7DC0D /* bignum-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "bignum-dtoa.cc"; sourceTree = "<group>"; }; - C22C529113FAF6EF00B7DC0D /* bignum-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "bignum-dtoa.h"; sourceTree = "<group>"; }; - C22C529213FAF6EF00B7DC0D /* bignum.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bignum.cc; sourceTree = "<group>"; }; - C22C529313FAF6EF00B7DC0D /* bignum.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bignum.h; sourceTree = "<group>"; }; - C22C529413FAF6EF00B7DC0D /* cached-powers.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "cached-powers.cc"; sourceTree = "<group>"; }; - C22C529513FAF6EF00B7DC0D /* cached-powers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "cached-powers.h"; sourceTree = "<group>"; }; - C22C529613FAF6EF00B7DC0D /* COPYING */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = COPYING; sourceTree = "<group>"; }; - C22C529713FAF6EF00B7DC0D /* diy-fp.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "diy-fp.cc"; sourceTree = "<group>"; }; - C22C529813FAF6EF00B7DC0D /* diy-fp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "diy-fp.h"; sourceTree = "<group>"; }; - C22C529913FAF6EF00B7DC0D /* double-conversion.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "double-conversion.cc"; sourceTree = "<group>"; }; - C22C529A13FAF6EF00B7DC0D /* double-conversion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "double-conversion.h"; sourceTree = "<group>"; }; - C22C529B13FAF6EF00B7DC0D /* double.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = double.h; sourceTree = "<group>"; }; - C22C529C13FAF6EF00B7DC0D /* fast-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "fast-dtoa.cc"; sourceTree = "<group>"; }; - C22C529D13FAF6EF00B7DC0D /* fast-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "fast-dtoa.h"; sourceTree = "<group>"; }; - C22C529E13FAF6EF00B7DC0D /* fixed-dtoa.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = "fixed-dtoa.cc"; sourceTree = "<group>"; }; - C22C529F13FAF6EF00B7DC0D /* fixed-dtoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "fixed-dtoa.h"; sourceTree = "<group>"; }; - C22C52A013FAF6EF00B7DC0D /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; }; - C22C52A113FAF6EF00B7DC0D /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; }; - C22C52A213FAF6EF00B7DC0D /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = "<group>"; }; - C22C52A313FAF6EF00B7DC0D /* SConscript */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SConscript; sourceTree = "<group>"; }; - C22C52A413FAF6EF00B7DC0D /* SConstruct */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = SConstruct; sourceTree = "<group>"; }; - C22C52B913FAF6EF00B7DC0D /* strtod.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = strtod.cc; sourceTree = "<group>"; }; - C22C52BA13FAF6EF00B7DC0D /* strtod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = strtod.h; sourceTree = "<group>"; }; - C22C52BB13FAF6EF00B7DC0D /* utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = utils.h; sourceTree = "<group>"; }; C240305314B404C90079EB64 /* CopiedSpace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CopiedSpace.cpp; sourceTree = "<group>"; }; C2B916C114DA014E00CBAC86 /* MarkedAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MarkedAllocator.h; sourceTree = "<group>"; }; C2B916C414DA040C00CBAC86 /* MarkedAllocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MarkedAllocator.cpp; sourceTree = "<group>"; }; C2C8D02B14A3C6B200578E65 /* CopiedSpaceInlineMethods.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedSpaceInlineMethods.h; sourceTree = "<group>"; }; C2C8D02E14A3CEFC00578E65 /* CopiedBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedBlock.h; sourceTree = "<group>"; }; C2C8D02F14A3CEFC00578E65 /* HeapBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapBlock.h; sourceTree = "<group>"; }; - C2D9CA1214BCC04600304B46 /* CheckedBoolean.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CheckedBoolean.h; sourceTree = "<group>"; }; C2EAA3F8149A830800FCE112 /* CopiedSpace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedSpace.h; sourceTree = "<group>"; }; C2EAD2FB14F0249800A4B159 /* CopiedAllocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopiedAllocator.h; sourceTree = "<group>"; }; - C2EE599D13FC972A009CEAFE /* DecimalNumber.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DecimalNumber.cpp; sourceTree = "<group>"; }; - C2EE599E13FC972A009CEAFE /* DecimalNumber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DecimalNumber.h; sourceTree = "<group>"; }; D21202280AD4310C00ED79B6 /* DateConversion.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = DateConversion.cpp; sourceTree = "<group>"; }; D21202290AD4310C00ED79B6 /* DateConversion.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DateConversion.h; sourceTree = "<group>"; }; - D75AF59512F8CB9500FC0ADF /* DynamicAnnotations.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicAnnotations.cpp; sourceTree = "<group>"; }; - D75AF59612F8CB9500FC0ADF /* DynamicAnnotations.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicAnnotations.h; sourceTree = "<group>"; }; - DD377CBB12072C18006A2517 /* Bitmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Bitmap.h; sourceTree = "<group>"; }; DDF7ABD211F60ED200108E36 /* GCActivityCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCActivityCallback.h; sourceTree = "<group>"; }; DDF7ABD311F60ED200108E36 /* GCActivityCallbackCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCActivityCallbackCF.cpp; sourceTree = "<group>"; }; - E11D51750B2E798D0056C188 /* StringExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringExtras.h; sourceTree = "<group>"; }; E124A8F50E555775003091F1 /* OpaqueJSString.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueJSString.h; sourceTree = "<group>"; }; E124A8F60E555775003091F1 /* OpaqueJSString.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OpaqueJSString.cpp; sourceTree = "<group>"; }; E178633F0D9BEC0000D74E75 /* InitializeThreading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InitializeThreading.h; sourceTree = "<group>"; }; E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InitializeThreading.cpp; sourceTree = "<group>"; }; - E17FF770112131D200076A19 /* ValueCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueCheck.h; sourceTree = "<group>"; }; E18E3A560DF9278C00D90B34 /* JSGlobalData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalData.h; sourceTree = "<group>"; }; E18E3A570DF9278C00D90B34 /* JSGlobalData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSGlobalData.cpp; sourceTree = "<group>"; }; - E195678F09E7CF1200B89D13 /* UnicodeIcu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnicodeIcu.h; sourceTree = "<group>"; }; - E195679409E7CF1200B89D13 /* Unicode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Unicode.h; sourceTree = "<group>"; }; - E1A596370DE3E1C300C17E37 /* AVLTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AVLTree.h; sourceTree = "<group>"; }; - E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollatorICU.cpp; sourceTree = "<group>"; }; - E1A862AA0D7EBB7D001EC6AA /* Collator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Collator.h; sourceTree = "<group>"; }; - E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CollatorDefault.cpp; sourceTree = "<group>"; }; - E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThreadSpecific.h; sourceTree = "<group>"; }; - E1EE79220D6C95CD00FEA3BA /* Threading.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Threading.h; sourceTree = "<group>"; }; - E1EE79270D6C964500FEA3BA /* Locker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Locker.h; sourceTree = "<group>"; }; - E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ThreadingPthreads.cpp; sourceTree = "<group>"; }; - E1EE798B0D6CA53D00FEA3BA /* MessageQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MessageQueue.h; sourceTree = "<group>"; }; - E1EF79A80CE97BA60088D500 /* UTF8.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UTF8.cpp; sourceTree = "<group>"; }; - E1EF79A90CE97BA60088D500 /* UTF8.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UTF8.h; sourceTree = "<group>"; }; - E48E0F2C0F82151700A8CA37 /* FastAllocBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FastAllocBase.h; sourceTree = "<group>"; }; E49DC14912EF261A00184A1F /* SourceProviderCacheItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceProviderCacheItem.h; sourceTree = "<group>"; }; E49DC15112EF272200184A1F /* SourceProviderCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SourceProviderCache.h; sourceTree = "<group>"; }; E49DC15512EF277200184A1F /* SourceProviderCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SourceProviderCache.cpp; sourceTree = "<group>"; }; - E4D8CE9B12FC42E100BC9F5A /* BloomFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BloomFilter.h; sourceTree = "<group>"; }; - F3BD31D0126730180065467F /* TextPosition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextPosition.h; path = text/TextPosition.h; sourceTree = "<group>"; }; F5BB2BC5030F772101FCFE1D /* Completion.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = Completion.h; sourceTree = "<group>"; tabWidth = 8; }; F5C290E60284F98E018635CA /* JavaScriptCorePrefix.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = JavaScriptCorePrefix.h; sourceTree = "<group>"; tabWidth = 8; }; F68EBB8C0255D4C601FF60F7 /* config.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; tabWidth = 8; }; @@ -1572,10 +1342,6 @@ F692A8850255597D01FF60F7 /* UString.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = UString.cpp; sourceTree = "<group>"; tabWidth = 8; }; F692A8860255597D01FF60F7 /* UString.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = UString.h; sourceTree = "<group>"; tabWidth = 8; }; F692A8870255597D01FF60F7 /* JSValue.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSValue.cpp; sourceTree = "<group>"; tabWidth = 8; }; - F69E86C114C6E551002C2C62 /* NumberOfCores.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NumberOfCores.cpp; sourceTree = "<group>"; }; - F69E86C214C6E551002C2C62 /* NumberOfCores.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NumberOfCores.h; sourceTree = "<group>"; }; - FDA15C1612B03028003A583A /* Complex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Complex.h; sourceTree = "<group>"; }; - FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StdLibExtras.h; sourceTree = "<group>"; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -1621,6 +1387,7 @@ A731B25A130093880040A7FA /* Foundation.framework in Frameworks */, 932F5BD70822A1C700736975 /* libicucore.dylib in Frameworks */, 932F5BD60822A1C700736975 /* libobjc.dylib in Frameworks */, + A8A4748E151A8306004123FF /* libWTF.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1651,14 +1418,6 @@ tabWidth = 4; usesTabs = 0; }; - 06D358A00DAAD9C4003B174E /* mac */ = { - isa = PBXGroup; - children = ( - 06D358A10DAAD9C4003B174E /* MainThreadMac.mm */, - ); - path = mac; - sourceTree = "<group>"; - }; 0867D691FE84028FC02AAC07 /* JavaScriptCore */ = { isa = PBXGroup; children = ( @@ -1686,7 +1445,6 @@ 7EF6E0BB0EB7A1EC0079AFAF /* runtime */, 141211000A48772600480255 /* tests */, 8603CEF014C753EF00AE59E3 /* tools */, - 65162EF108E6A21C007556CD /* wtf */, 86EAC48C0F93E8B9008EC948 /* yarr */, 1C90513E0BA9E8830081E9D0 /* Configurations */, 650FDF8D09D0FCA700769E54 /* Derived Sources */, @@ -1700,6 +1458,7 @@ 0867D69AFE84028FC02AAC07 /* Frameworks */ = { isa = PBXGroup; children = ( + A8A4748D151A8306004123FF /* libWTF.a */, 6560A4CF04B3B3E7008AE952 /* CoreFoundation.framework */, 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */, 5D5D8AD00E0D0EBE00F9C692 /* libedit.dylib */, @@ -1768,15 +1527,12 @@ 1429D92C0ED22D7000B89619 /* jit */ = { isa = PBXGroup; children = ( - 0F0776BD14FF002800102332 /* JITCompilationEffort.h */, - 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */, - 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */, - 0F46807F14BA572700BFE272 /* JITExceptions.cpp */, - 0F46808014BA572700BFE272 /* JITExceptions.h */, 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */, A7B48DB60EE74CFC00DCBDB6 /* ExecutableAllocator.cpp */, A7B48DB50EE74CFC00DCBDB6 /* ExecutableAllocator.h */, 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */, + 0F4680D014BBC5F800BFE272 /* HostCallReturnValue.cpp */, + 0F4680D114BBC5F800BFE272 /* HostCallReturnValue.h */, 1429D92D0ED22D7000B89619 /* JIT.cpp */, 1429D92E0ED22D7000B89619 /* JIT.h */, 86A90ECF0EE7D51F00AB350D /* JITArithmetic.cpp */, @@ -1784,7 +1540,10 @@ 86CC85A20EE79B7400288682 /* JITCall.cpp */, 146FE51111A710430087AE66 /* JITCall32_64.cpp */, 86CCEFDD0F413F8900FD7F9E /* JITCode.h */, + 0F0776BD14FF002800102332 /* JITCompilationEffort.h */, 0F21C26614BE5F5E00ADC64B /* JITDriver.h */, + 0F46807F14BA572700BFE272 /* JITExceptions.cpp */, + 0F46808014BA572700BFE272 /* JITExceptions.h */, 86CC85A00EE79A4700288682 /* JITInlineMethods.h */, BCDD51E90FB8DF74004A8BDC /* JITOpcodes.cpp */, A71236E41195F33C00BD2174 /* JITOpcodes32_64.cpp */, @@ -1805,20 +1564,22 @@ 142E312A134FF0A600AFADB5 /* heap */ = { isa = PBXGroup; children = ( + 14816E19154CC56C00B8054C /* BlockAllocator.cpp */, + 14816E1A154CC56C00B8054C /* BlockAllocator.h */, + A7521E121429169A003C8D0C /* CardSet.h */, + 146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */, + 149DAAF212EB559D0083B12B /* ConservativeRoots.h */, C2EAD2FB14F0249800A4B159 /* CopiedAllocator.h */, C2C8D02E14A3CEFC00578E65 /* CopiedBlock.h */, C240305314B404C90079EB64 /* CopiedSpace.cpp */, C2EAA3F8149A830800FCE112 /* CopiedSpace.h */, C2C8D02B14A3C6B200578E65 /* CopiedSpaceInlineMethods.h */, - A7521E121429169A003C8D0C /* CardSet.h */, - 146B14DB12EB5B12001BEC1B /* ConservativeRoots.cpp */, - 149DAAF212EB559D0083B12B /* ConservativeRoots.h */, 0F2C556D14738F2E00121E4F /* DFGCodeBlocks.cpp */, 0F2C556E14738F2E00121E4F /* DFGCodeBlocks.h */, BCBE2CAD14E985AA000593AD /* GCAssertions.h */, 142E312B134FF0A600AFADB5 /* Handle.h */, - 142E312C134FF0A600AFADB5 /* HandleHeap.cpp */, - 142E312D134FF0A600AFADB5 /* HandleHeap.h */, + 142E312C134FF0A600AFADB5 /* HandleSet.cpp */, + 142E312D134FF0A600AFADB5 /* HandleSet.h */, 142E312E134FF0A600AFADB5 /* HandleStack.cpp */, 142E312F134FF0A600AFADB5 /* HandleStack.h */, 146FA5A81378F6B0003627A3 /* HandleTypes.h */, @@ -1849,7 +1610,15 @@ 0FC815121405118600CFA603 /* VTableSpectrum.cpp */, 0FC815141405118D00CFA603 /* VTableSpectrum.h */, 142E3133134FF0A600AFADB5 /* Weak.h */, + 14E84F9914EE1ACC00D6D5D4 /* WeakBlock.cpp */, + 14E84F9A14EE1ACC00D6D5D4 /* WeakBlock.h */, + 14F7256314EE265E00B1652B /* WeakHandleOwner.cpp */, + 14F7256414EE265E00B1652B /* WeakHandleOwner.h */, + 14E84F9D14EE1ACC00D6D5D4 /* WeakImpl.h */, 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */, + 14E84F9B14EE1ACC00D6D5D4 /* WeakSet.cpp */, + 14E84F9C14EE1ACC00D6D5D4 /* WeakSet.h */, + 14150132154BB13F005D8C98 /* WeakSetInlines.h */, 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */, 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */, ); @@ -1935,15 +1704,6 @@ path = debugger; sourceTree = "<group>"; }; - 1A082776142168D60090CCAC /* threads */ = { - isa = PBXGroup; - children = ( - 1A082777142168D70090CCAC /* BinarySemaphore.cpp */, - 1A082778142168D70090CCAC /* BinarySemaphore.h */, - ); - path = threads; - sourceTree = "<group>"; - }; 1C90513E0BA9E8830081E9D0 /* Configurations */ = { isa = PBXGroup; children = ( @@ -1961,43 +1721,6 @@ tabWidth = 4; usesTabs = 0; }; - 2684B2C214D4A9B20072C0B6 /* url */ = { - isa = PBXGroup; - children = ( - 2684B2C314D4A9B20072C0B6 /* api */, - 2684B2C714D4A9B20072C0B6 /* src */, - ); - path = url; - sourceTree = "<group>"; - }; - 2684B2C314D4A9B20072C0B6 /* api */ = { - isa = PBXGroup; - children = ( - 2684B2C414D4A9B20072C0B6 /* ParsedURL.cpp */, - 2684B2C514D4A9B20072C0B6 /* ParsedURL.h */, - 2684B2C614D4A9B20072C0B6 /* URLString.h */, - ); - path = api; - sourceTree = "<group>"; - }; - 2684B2C714D4A9B20072C0B6 /* src */ = { - isa = PBXGroup; - children = ( - 2684B2C814D4A9B20072C0B6 /* RawURLBuffer.h */, - 2684B2C914D4A9B20072C0B6 /* URLBuffer.h */, - 2684B2CA14D4A9B20072C0B6 /* URLCharacterTypes.cpp */, - 2684B2CB14D4A9B20072C0B6 /* URLCharacterTypes.h */, - 2684B2CC14D4A9B20072C0B6 /* URLComponent.h */, - 2684B2CD14D4A9B20072C0B6 /* URLEscape.cpp */, - 2684B2CE14D4A9B20072C0B6 /* URLEscape.h */, - 2684B2CF14D4A9B20072C0B6 /* URLParser.h */, - 2684B2D014D4A9B20072C0B6 /* URLQueryCanonicalizer.h */, - 2684B2D114D4A9B20072C0B6 /* URLSegments.cpp */, - 2684B2D214D4A9B20072C0B6 /* URLSegments.h */, - ); - path = src; - sourceTree = "<group>"; - }; 650FDF8D09D0FCA700769E54 /* Derived Sources */ = { isa = PBXGroup; children = ( @@ -2021,188 +1744,6 @@ tabWidth = 4; usesTabs = 0; }; - 65162EF108E6A21C007556CD /* wtf */ = { - isa = PBXGroup; - children = ( - C22C524813FAF6EF00B7DC0D /* dtoa */, - 06D358A00DAAD9C4003B174E /* mac */, - 8656573E115BE35200291F40 /* text */, - 1A082776142168D60090CCAC /* threads */, - E195678D09E7CF1200B89D13 /* unicode */, - 2684B2C214D4A9B20072C0B6 /* url */, - A1D764511354448B00C5C7C0 /* Alignment.h */, - 93AA4F770957251F0084B3A7 /* AlwaysInline.h */, - A73BE154148420520091204B /* ArrayBuffer.cpp */, - A73BE155148420520091204B /* ArrayBuffer.h */, - A73BE156148420520091204B /* ArrayBufferView.cpp */, - A73BE157148420520091204B /* ArrayBufferView.h */, - 938C4F690CA06BC700D9310A /* ASCIICType.h */, - 65E217B808E7EECC0023E5F6 /* Assertions.cpp */, - 65E217B708E7EECC0023E5F6 /* Assertions.h */, - BC5F7BBB11823B590052C02C /* Atomics.h */, - E1A596370DE3E1C300C17E37 /* AVLTree.h */, - DD377CBB12072C18006A2517 /* Bitmap.h */, - 0F16D724142C39A200CF784A /* BitVector.cpp */, - 0FD82F491428069200179C94 /* BitVector.h */, - A7C40C07130B057D00D002A1 /* BlockStack.h */, - E4D8CE9B12FC42E100BC9F5A /* BloomFilter.h */, - 0FD82E82141F3FC900179C94 /* BoundsCheckedPointer.h */, - 86676D4D11FED55D004B6863 /* BumpPointerAllocator.h */, - A7A1F7AA0F252B3C00E184E2 /* ByteArray.cpp */, - A7A1F7AB0F252B3C00E184E2 /* ByteArray.h */, - A7BC0C81140608B000B1BB71 /* CheckedArithmetic.h */, - C2D9CA1214BCC04600304B46 /* CheckedBoolean.h */, - 0FB5468E14FADA6F002C2989 /* RefCountedArray.h */, - BC66BAE213F4928F00C23FAE /* Compiler.h */, - FDA15C1612B03028003A583A /* Complex.h */, - 97941A7C1302A098004A3447 /* CryptographicallyRandomNumber.cpp */, - 97941A7D1302A098004A3447 /* CryptographicallyRandomNumber.h */, - 180B9AEF0F16C569009BDBC5 /* CurrentTime.cpp */, - 180B9AF00F16C569009BDBC5 /* CurrentTime.h */, - 0F9FC8CD14E612D500D52AE0 /* DataLog.cpp */, - 0F9FC8CE14E612D500D52AE0 /* DataLog.h */, - 41359CF40FDD89CB00206180 /* DateMath.cpp */, - 41359CF50FDD89CB00206180 /* DateMath.h */, - C2EE599D13FC972A009CEAFE /* DecimalNumber.cpp */, - C2EE599E13FC972A009CEAFE /* DecimalNumber.h */, - 5135FAD512D26856003C083B /* Decoder.h */, - 5186111D0CC824830081412B /* Deque.h */, - 938C4F6B0CA06BCE00D9310A /* DisallowCType.h */, - 14456A311314657800212CA3 /* DoublyLinkedList.h */, - 651F6412039D5B5F0078395C /* dtoa.cpp */, - 651F6413039D5B5F0078395C /* dtoa.h */, - D75AF59512F8CB9500FC0ADF /* DynamicAnnotations.cpp */, - D75AF59612F8CB9500FC0ADF /* DynamicAnnotations.h */, - 5135FAD612D26856003C083B /* Encoder.h */, - A7A275F514837A8E001DBB39 /* ExportMacros.h */, - E48E0F2C0F82151700A8CA37 /* FastAllocBase.h */, - 65E217B908E7EECC0023E5F6 /* FastMalloc.cpp */, - 65E217BA08E7EECC0023E5F6 /* FastMalloc.h */, - A7F19ECD11DD490900931E70 /* FixedArray.h */, - A73BE159148420520091204B /* Float32Array.h */, - A73BE15B148420520091204B /* Float64Array.h */, - 935AF46909E9D9DB00ACD1D8 /* Forward.h */, - 1AA9E5501498093500001A8A /* Functional.h */, - 93B6A0DE0AA64DA40076DE27 /* GetPtr.h */, - 657EEBBF094E445E008C9C7B /* HashCountedSet.h */, - 65DFC92A08EA173A00F7300B /* HashFunctions.h */, - 652246A40C8D7A0E007BDAF7 /* HashIterators.h */, - 65DFC92B08EA173A00F7300B /* HashMap.h */, - 65DFC92C08EA173A00F7300B /* HashSet.h */, - 65DFC92D08EA173A00F7300B /* HashTable.cpp */, - 65DFC92E08EA173A00F7300B /* HashTable.h */, - 65DFC92F08EA173A00F7300B /* HashTraits.h */, - 7186A6E813100B57004479E1 /* HexNumber.h */, - 8699AA60146A0E2B00E23A73 /* InlineASM.h */, - A73BE15F148420520091204B /* Int16Array.h */, - A73BE161148420520091204B /* Int32Array.h */, - A73BE15D148420520091204B /* Int8Array.h */, - A73BE17F148420A80091204B /* IntegralTypedArrayBase.h */, - 657EB7450B708F540063461B /* ListHashSet.h */, - 148A1626095D16BB00666D0D /* ListRefPtr.h */, - E1EE79270D6C964500FEA3BA /* Locker.h */, - 06D358A20DAAD9C4003B174E /* MainThread.cpp */, - 06D358A30DAAD9C4003B174E /* MainThread.h */, - 5DBD18AF0C5401A700C15EAE /* MallocZoneSupport.h */, - BCF6553B0A2048DE0038A194 /* MathExtras.h */, - 511FC4C7117EE23D00425272 /* MD5.cpp */, - 511FC4CA117EE2A800425272 /* MD5.h */, - E1EE798B0D6CA53D00FEA3BA /* MessageQueue.h */, - 0F963B2B13F853C70002D9B2 /* MetaAllocator.cpp */, - 0F963B2A13F853BD0002D9B2 /* MetaAllocator.h */, - 0F963B2E13FC66AE0002D9B2 /* MetaAllocatorHandle.h */, - 9303F5690991190000AD71B8 /* Noncopyable.h */, - 65E1A2F4122B880D00B26097 /* NonCopyingSort.h */, - C0A2723F0E509F1E00E96E15 /* NotFound.h */, - 93854A9912C93D3B00DAAF77 /* NullPtr.cpp */, - 933F5CDB126922690049191E /* NullPtr.h */, - F69E86C114C6E551002C2C62 /* NumberOfCores.cpp */, - F69E86C214C6E551002C2C62 /* NumberOfCores.h */, - 1400067612A6F7830064D123 /* OSAllocator.h */, - 1400069212A6F9E10064D123 /* OSAllocatorPosix.cpp */, - 97941A3F130299DB004A3447 /* OSRandomSource.cpp */, - 97941A40130299DB004A3447 /* OSRandomSource.h */, - 9303F5A409911A5800AD71B8 /* OwnArrayPtr.h */, - 9303F567099118FA00AD71B8 /* OwnPtr.h */, - 440B7AED0FAF7FCB0073323E /* OwnPtrCommon.h */, - 0F636D9F142D27D200B2E66A /* PackedIntVector.h */, - 8627E5EA11F1281900A313B5 /* PageAllocation.h */, - 14FFF98A12BFFF7500795BB8 /* PageAllocationAligned.cpp */, - 14FFF98B12BFFF7500795BB8 /* PageAllocationAligned.h */, - 14B3EF0412BC24DD00D29EFF /* PageBlock.cpp */, - 14B3EF0312BC24DD00D29EFF /* PageBlock.h */, - 8690231412092D5C00630AF9 /* PageReservation.h */, - 7934BB761361979300CB99A1 /* ParallelJobs.h */, - 7934BB771361979300CB99A1 /* ParallelJobsGeneric.cpp */, - 7934BB781361979300CB99A1 /* ParallelJobsGeneric.h */, - 7934BB791361979300CB99A1 /* ParallelJobsLibdispatch.h */, - 7934BB7A1361979300CB99A1 /* ParallelJobsOpenMP.h */, - BCFBE695122560E800309E9D /* PassOwnArrayPtr.h */, - 44DD48520FAEA85000D6B4EB /* PassOwnPtr.h */, - 6580F795094070560082C219 /* PassRefPtr.h */, - 651DCA02136A6FAB00F74194 /* PassTraits.h */, - 65D6D87E09B5A32E0002E4D7 /* Platform.h */, - A7D649A91015224E009B2E1B /* PossiblyNull.h */, - 088FA5B90EF76D4300578E6F /* RandomNumber.cpp */, - 088FA5BA0EF76D4300578E6F /* RandomNumber.h */, - 08E279E80EF83B10007DB523 /* RandomNumberSeed.h */, - 0F963B2613F753990002D9B2 /* RedBlackTree.h */, - 1419D32C0CEA7CDE00FF507A /* RefCounted.h */, - 905B02AD0E28640F006DF882 /* RefCountedLeakCounter.cpp */, - 90D3469B0E285280009492EE /* RefCountedLeakCounter.h */, - 65C647B3093EF8D60022C380 /* RefPtr.h */, - 148A1ECD0D10C23B0069A47C /* RefPtrHashMap.h */, - 51F648D60BB4E2CA0033D760 /* RetainPtr.h */, - 969A07290ED1CE6900F1F681 /* SegmentedVector.h */, - A7C40C08130B057D00D002A1 /* SentinelLinkedList.h */, - 76FB9F1012E851960051A2EB /* SHA1.cpp */, - 76FB9F0E12E851860051A2EB /* SHA1.h */, - 0F56A1D6150028B9002992B1 /* SimpleStats.h */, - A7C40C09130B057D00D002A1 /* SinglyLinkedList.h */, - 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */, - 0F2E5BF5146357D2003EB2EB /* Spectrum.h */, - 86D87DA512BC4B14008E73A1 /* StackBounds.cpp */, - 86D87DA612BC4B14008E73A1 /* StackBounds.h */, - 868BFA5F117D048200B908B1 /* StaticConstructors.h */, - FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */, - E11D51750B2E798D0056C188 /* StringExtras.h */, - 5D63E9AC10F2BD6E00FC8AE9 /* StringHasher.h */, - 5DA479650CFBCF56009328A0 /* TCPackedCache.h */, - 6541BD6E08E80A17002CBEE7 /* TCPageMap.h */, - 6541BD6F08E80A17002CBEE7 /* TCSpinLock.h */, - 6541BD7008E80A17002CBEE7 /* TCSystemAlloc.cpp */, - 6541BD7108E80A17002CBEE7 /* TCSystemAlloc.h */, - 0BCD83541485841200EA2003 /* TemporaryChange.h */, - 18BAB52710DADFCD000D945B /* ThreadIdentifierDataPthreads.cpp */, - 18BAB52810DADFCD000D945B /* ThreadIdentifierDataPthreads.h */, - 5D6A566A0F05995500266145 /* Threading.cpp */, - E1EE79220D6C95CD00FEA3BA /* Threading.h */, - BC5F7BBC11823B590052C02C /* ThreadingPrimitives.h */, - E1EE793C0D6C9B9200FEA3BA /* ThreadingPthreads.cpp */, - 0BAC949E1338728400CF135B /* ThreadRestrictionVerifier.h */, - BC5F7BBD11823B590052C02C /* ThreadSafeRefCounted.h */, - E1B7C8BD0DA3A3360074B0DC /* ThreadSpecific.h */, - A73BE17D148420840091204B /* TypedArrayBase.h */, - 0B330C260F38C62300692DE3 /* TypeTraits.cpp */, - 0B4D7E620F319AC800AD7E58 /* TypeTraits.h */, - A73BE165148420520091204B /* Uint16Array.h */, - A73BE167148420520091204B /* Uint32Array.h */, - A73BE163148420520091204B /* Uint8Array.h */, - 91A3905514C0F47200F67901 /* Uint8ClampedArray.h */, - 0FD52AAC1430359D0026DC9F /* UnionFind.h */, - 935AF46B09E9D9DB00ACD1D8 /* UnusedParam.h */, - E17FF770112131D200076A19 /* ValueCheck.h */, - 6592C316098B7DE10003D4F6 /* Vector.h */, - 6592C317098B7DE10003D4F6 /* VectorTraits.h */, - 96DD73780F9DA3100027FBCC /* VMTags.h */, - 86D08D5111793613006E5ED0 /* WTFThreadData.cpp */, - 86D08D5211793613006E5ED0 /* WTFThreadData.h */, - ); - path = wtf; - sourceTree = "<group>"; - tabWidth = 4; - usesTabs = 0; - }; 7E39D81D0EC38EFA003AF11A /* bytecompiler */ = { isa = PBXGroup; children = ( @@ -2317,8 +1858,6 @@ 938772E5038BFE19008635CE /* JSArray.h */, 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */, 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */, - A791EF270F11E07900AE1F68 /* JSByteArray.cpp */, - A791EF260F11E07900AE1F68 /* JSByteArray.h */, BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */, BC1167D80E19BCC9008066DD /* JSCell.h */, 9788FC221471AD0C0068CE2D /* JSDateMath.cpp */, @@ -2349,6 +1888,8 @@ BC02E9B60E1842FA000F9297 /* JSString.cpp */, F692A8620255597D01FF60F7 /* JSString.h */, 86E85538111B9968001AF51E /* JSStringBuilder.h */, + 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */, + 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */, 14ABB454099C2A0F00E2A24F /* JSType.h */, 6507D2970E871E4A00D7D896 /* JSTypeInfo.h */, F692A8870255597D01FF60F7 /* JSValue.cpp */, @@ -2362,6 +1903,7 @@ A7E2EA690FB460CF00601F06 /* LiteralParser.h */, F692A8680255597D01FF60F7 /* Lookup.cpp */, F692A8690255597D01FF60F7 /* Lookup.h */, + 8612E4CB1522918400C836BE /* MatchResult.h */, F692A86A0255597D01FF60F7 /* MathObject.cpp */, F692A86B0255597D01FF60F7 /* MathObject.h */, 90213E3B123A40C200D422F3 /* MemoryStatistics.cpp */, @@ -2398,9 +1940,12 @@ F692A87E0255597D01FF60F7 /* RegExp.h */, A1712B3A11C7B212007A5315 /* RegExpCache.cpp */, A1712B3E11C7B228007A5315 /* RegExpCache.h */, + 86F75EFB151C062F007C9BA3 /* RegExpCachedResult.cpp */, + 86F75EFC151C062F007C9BA3 /* RegExpCachedResult.h */, BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */, BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */, A1712B4011C7B235007A5315 /* RegExpKey.h */, + 86F75EFD151C062F007C9BA3 /* RegExpMatchesArray.cpp */, 93CEDDFB0EA91EE600258EBE /* RegExpMatchesArray.h */, F692A87B0255597D01FF60F7 /* RegExpObject.cpp */, F692A87C0255597D01FF60F7 /* RegExpObject.h */, @@ -2460,36 +2005,13 @@ path = tools; sourceTree = "<group>"; }; - 8656573E115BE35200291F40 /* text */ = { - isa = PBXGroup; - children = ( - 434A8E7014956A50009126F7 /* ASCIIFastPath.h */, - 868BFA00117CEFD100B908B1 /* AtomicString.cpp */, - 868BFA01117CEFD100B908B1 /* AtomicString.h */, - 86F38858121130CA007A7CE3 /* AtomicStringHash.h */, - 868BFA02117CEFD100B908B1 /* AtomicStringImpl.h */, - 86565740115BE3DA00291F40 /* CString.cpp */, - 86565741115BE3DA00291F40 /* CString.h */, - 86B99AE1117E578100DF5A90 /* StringBuffer.h */, - 86438FC31265503E00E0DFCA /* StringBuilder.cpp */, - 081469481264375E00DFF935 /* StringBuilder.h */, - 0896C29E1265AB0900B1CDD3 /* StringConcatenate.h */, - 868BFA05117CEFD100B908B1 /* StringHash.h */, - 868BFA06117CEFD100B908B1 /* StringImpl.cpp */, - 868BFA07117CEFD100B908B1 /* StringImpl.h */, - 718A8482134F3A1200B87529 /* StringOperators.h */, - 8626BECE11928E3900782FAB /* StringStatics.cpp */, - F3BD31D0126730180065467F /* TextPosition.h */, - 868BFA15117CF19900B908B1 /* WTFString.cpp */, - 868BFA16117CF19900B908B1 /* WTFString.h */, - ); - name = text; - sourceTree = "<group>"; - }; 86EAC48C0F93E8B9008EC948 /* yarr */ = { isa = PBXGroup; children = ( 451539B812DC994500EF7AC4 /* Yarr.h */, + 863C6D981521111200585E4E /* YarrCanonicalizeUCS2.cpp */, + 863C6D991521111200585E4E /* YarrCanonicalizeUCS2.h */, + 863C6D9A1521111200585E4E /* YarrCanonicalizeUCS2.js */, 86704B7D12DBA33700A9FE7B /* YarrInterpreter.cpp */, 86704B7E12DBA33700A9FE7B /* YarrInterpreter.h */, 86704B7F12DBA33700A9FE7B /* YarrJIT.cpp */, @@ -2506,9 +2028,7 @@ 86EC9DB31328DF44002B2AD7 /* dfg */ = { isa = PBXGroup; children = ( - 0F1D085F150C5A800074D109 /* DFGNode.cpp */, - 0FFFC94914EF909500C72532 /* DFGArithNodeFlagsInferencePhase.cpp */, - 0FFFC94A14EF909500C72532 /* DFGArithNodeFlagsInferencePhase.h */, + 0F1E3A431534CBAD000F9456 /* DFGArgumentPosition.h */, 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */, 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */, 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */, @@ -2528,19 +2048,25 @@ 0FC0977E1469EBC400CF2442 /* DFGCommon.h */, 0FC0979D146B271E00CF2442 /* DFGCorrectableJumpPoint.cpp */, 0FC0979A146A772000CF2442 /* DFGCorrectableJumpPoint.h */, + 0F1E3A441534CBAD000F9456 /* DFGDoubleFormatState.h */, 0FD3C82014115CF800FD81CB /* DFGDriver.cpp */, 0FD3C82214115D0E00FD81CB /* DFGDriver.h */, 86AE6C4B136A11E400963012 /* DFGFPRInfo.h */, + 0F2BDC12151C5D4A00CD8910 /* DFGFixupPhase.cpp */, + 0F2BDC13151C5D4A00CD8910 /* DFGFixupPhase.h */, 86EC9DB61328DF82002B2AD7 /* DFGGenerationInfo.h */, 86AE6C4C136A11E400963012 /* DFGGPRInfo.h */, 86EC9DB71328DF82002B2AD7 /* DFGGraph.cpp */, 86EC9DB81328DF82002B2AD7 /* DFGGraph.h */, + 0F2BDC1F151E803800CD8910 /* DFGInsertionSet.h */, 86EC9DBB1328DF82002B2AD7 /* DFGJITCompiler.cpp */, 86EC9DBC1328DF82002B2AD7 /* DFGJITCompiler.h */, 86ECA3E9132DEF1C002B2AD7 /* DFGNode.h */, - 0F66E16814DF3F1300B7B2E4 /* DFGNodeReferenceBlob.h */, - 0F66E16914DF3F1300B7B2E4 /* DFGNodeUse.h */, - 0F620171143FCD2F0068B77C /* DFGOperands.h */, + 0FA581B7150E952A00B9A2D9 /* DFGNodeFlags.cpp */, + 0FA581B8150E952A00B9A2D9 /* DFGNodeFlags.h */, + 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */, + 0FA581B9150E952A00B9A2D9 /* DFGNodeType.h */, + 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */, 86EC9DBF1328DF82002B2AD7 /* DFGOperations.cpp */, 86EC9DC01328DF82002B2AD7 /* DFGOperations.h */, 0FD82E52141DAEDE00179C94 /* DFGOSREntry.cpp */, @@ -2643,6 +2169,7 @@ 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */, 0F21C27E14BEAA8000ADC64B /* BytecodeConventions.h */, 0F0FC45814BD15F100B81154 /* LLIntCallLinkInfo.h */, + 0F2BDC2B151FDE8B00CD8910 /* Operands.h */, 0F9FC8BF14E1B5FB00D52AE0 /* PolymorphicPutByIdList.cpp */, 0F9FC8C014E1B5FB00D52AE0 /* PolymorphicPutByIdList.h */, 0F9FC8C114E1B5FB00D52AE0 /* PutKind.h */, @@ -2679,7 +2206,6 @@ 969A07950ED1D3AE00F1F681 /* Opcode.h */, 0FD82E84141F3FDA00179C94 /* PredictedType.cpp */, 0FD82E4F141DAEA100179C94 /* PredictedType.h */, - 0FD82E50141DAEA100179C94 /* PredictionTracker.h */, 1429D8830ED21C3D00B89619 /* SamplingTool.cpp */, 1429D8840ED21C3D00B89619 /* SamplingTool.h */, BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */, @@ -2691,60 +2217,6 @@ path = bytecode; sourceTree = "<group>"; }; - C22C524813FAF6EF00B7DC0D /* dtoa */ = { - isa = PBXGroup; - children = ( - C22C529613FAF6EF00B7DC0D /* COPYING */, - C22C52A013FAF6EF00B7DC0D /* LICENSE */, - C22C52A113FAF6EF00B7DC0D /* Makefile */, - C22C52A213FAF6EF00B7DC0D /* README */, - C22C52A313FAF6EF00B7DC0D /* SConscript */, - C22C52A413FAF6EF00B7DC0D /* SConstruct */, - C22C529013FAF6EF00B7DC0D /* bignum-dtoa.cc */, - C22C529113FAF6EF00B7DC0D /* bignum-dtoa.h */, - C22C529213FAF6EF00B7DC0D /* bignum.cc */, - C22C529313FAF6EF00B7DC0D /* bignum.h */, - C22C529413FAF6EF00B7DC0D /* cached-powers.cc */, - C22C529513FAF6EF00B7DC0D /* cached-powers.h */, - C22C529713FAF6EF00B7DC0D /* diy-fp.cc */, - C22C529813FAF6EF00B7DC0D /* diy-fp.h */, - C22C529913FAF6EF00B7DC0D /* double-conversion.cc */, - C22C529A13FAF6EF00B7DC0D /* double-conversion.h */, - C22C529B13FAF6EF00B7DC0D /* double.h */, - C22C529C13FAF6EF00B7DC0D /* fast-dtoa.cc */, - C22C529D13FAF6EF00B7DC0D /* fast-dtoa.h */, - C22C529E13FAF6EF00B7DC0D /* fixed-dtoa.cc */, - C22C529F13FAF6EF00B7DC0D /* fixed-dtoa.h */, - C22C52B913FAF6EF00B7DC0D /* strtod.cc */, - C22C52BA13FAF6EF00B7DC0D /* strtod.h */, - C22C52BB13FAF6EF00B7DC0D /* utils.h */, - ); - path = dtoa; - sourceTree = "<group>"; - }; - E195678D09E7CF1200B89D13 /* unicode */ = { - isa = PBXGroup; - children = ( - E195678E09E7CF1200B89D13 /* icu */, - 2CFC5B7A12F44714004914E2 /* CharacterNames.h */, - E1A862AA0D7EBB7D001EC6AA /* Collator.h */, - E1A862D50D7F2B5C001EC6AA /* CollatorDefault.cpp */, - E195679409E7CF1200B89D13 /* Unicode.h */, - E1EF79A80CE97BA60088D500 /* UTF8.cpp */, - E1EF79A90CE97BA60088D500 /* UTF8.h */, - ); - path = unicode; - sourceTree = "<group>"; - }; - E195678E09E7CF1200B89D13 /* icu */ = { - isa = PBXGroup; - children = ( - E1A862A80D7EBB76001EC6AA /* CollatorICU.cpp */, - E195678F09E7CF1200B89D13 /* UnicodeIcu.h */, - ); - path = icu; - sourceTree = "<group>"; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -2781,7 +2253,6 @@ A784A26111D16622005776AC /* ASTBuilder.h in Headers */, 147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */, 866739D213BFDE710023D87C /* BigInteger.h in Headers */, - 1A08277A142168D70090CCAC /* BinarySemaphore.h in Headers */, BC18C3EC0E16F5CD00B34460 /* BooleanObject.h in Headers */, C2C8D03014A3CEFC00578E65 /* CopiedBlock.h in Headers */, C2EAA3FA149A835E00FCE112 /* CopiedSpace.h in Headers */, @@ -2828,7 +2299,6 @@ 86EC9DC81328DF82002B2AD7 /* DFGGraph.h in Headers */, 86EC9DCC1328DF82002B2AD7 /* DFGJITCompiler.h in Headers */, 86ECA3EA132DEF1C002B2AD7 /* DFGNode.h in Headers */, - 0F620175143FCD370068B77C /* DFGOperands.h in Headers */, 86EC9DD01328DF82002B2AD7 /* DFGOperations.h in Headers */, 0FD82E57141DAF1000179C94 /* DFGOSREntry.h in Headers */, 0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */, @@ -2851,7 +2321,7 @@ BC18C4050E16F5CD00B34460 /* FunctionPrototype.h in Headers */, DDF7ABD411F60ED200108E36 /* GCActivityCallback.h in Headers */, 142E3134134FF0A600AFADB5 /* Handle.h in Headers */, - 142E3136134FF0A600AFADB5 /* HandleHeap.h in Headers */, + 142E3136134FF0A600AFADB5 /* HandleSet.h in Headers */, 142E3138134FF0A600AFADB5 /* HandleStack.h in Headers */, 1478297B1379E8A800A7C2A3 /* HandleTypes.h in Headers */, 14BA7A9813AADFF8005B7C2C /* Heap.h in Headers */, @@ -2878,7 +2348,6 @@ BC18C4180E16F5CD00B34460 /* JSBase.h in Headers */, 140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */, 86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */, - A791EF280F11E07900AE1F68 /* JSByteArray.h in Headers */, BC18C4190E16F5CD00B34460 /* JSCallbackConstructor.h in Headers */, BC18C41A0E16F5CD00B34460 /* JSCallbackFunction.h in Headers */, BC18C41B0E16F5CD00B34460 /* JSCallbackObject.h in Headers */, @@ -2905,6 +2374,7 @@ BC18C4260E16F5CD00B34460 /* JSRetainPtr.h in Headers */, BC18C4270E16F5CD00B34460 /* JSString.h in Headers */, 86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */, + 2600B5A7152BAAA70091EE5F /* JSStringJoiner.h in Headers */, BC18C4280E16F5CD00B34460 /* JSStringRef.h in Headers */, BC18C4290E16F5CD00B34460 /* JSStringRefCF.h in Headers */, BC18C42A0E16F5CD00B34460 /* JSType.h in Headers */, @@ -2965,7 +2435,6 @@ 93052C350FB792190048FDC3 /* ParserArena.h in Headers */, 65303D641447B9E100D3F904 /* ParserTokens.h in Headers */, 0FD82E54141DAEEE00179C94 /* PredictedType.h in Headers */, - 0FD82E55141DAEEE00179C94 /* PredictionTracker.h in Headers */, BC18C4500E16F5CD00B34460 /* Profile.h in Headers */, BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */, BC18C4520E16F5CD00B34460 /* Profiler.h in Headers */, @@ -3075,23 +2544,36 @@ 0F9332A414CA7DD90085F3C6 /* PutByIdStatus.h in Headers */, 0F9332A514CA7DDD0085F3C6 /* StructureSet.h in Headers */, 0F55F0F514D1063C00AC7649 /* AbstractPC.h in Headers */, - 0F66E16B14DF3F1600B7B2E4 /* DFGNodeReferenceBlob.h in Headers */, - 0F66E16C14DF3F1600B7B2E4 /* DFGNodeUse.h in Headers */, + 0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */, + 0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */, 0F9FC8C414E1B60000D52AE0 /* PolymorphicPutByIdList.h in Headers */, 0F9FC8C514E1B60400D52AE0 /* PutKind.h in Headers */, BCBE2CAE14E985AA000593AD /* GCAssertions.h in Headers */, - 0FFFC95614EF909C00C72532 /* DFGArithNodeFlagsInferencePhase.h in Headers */, 0FFFC95814EF90A200C72532 /* DFGCFAPhase.h in Headers */, 0FFFC95A14EF90A900C72532 /* DFGCSEPhase.h in Headers */, 0FFFC95C14EF90AF00C72532 /* DFGPhase.h in Headers */, 0FFFC95E14EF90B700C72532 /* DFGPredictionPropagationPhase.h in Headers */, 0FFFC96014EF90BD00C72532 /* DFGVirtualRegisterAllocationPhase.h in Headers */, 1497209114EB831500FEB1B7 /* PassWeak.h in Headers */, + 14E84F9F14EE1ACC00D6D5D4 /* WeakBlock.h in Headers */, + 14E84FA114EE1ACC00D6D5D4 /* WeakSet.h in Headers */, + 14E84FA214EE1ACC00D6D5D4 /* WeakImpl.h in Headers */, + 14F7256614EE265E00B1652B /* WeakHandleOwner.h in Headers */, 0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */, 0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */, 0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */, 0F56A1D315000F35002992B1 /* ExecutionCounter.h in Headers */, 0A4337BE1506219B00991C95 /* DFGRedundantPhiEliminationPhase.h in Headers */, + 0FA581BB150E953000B9A2D9 /* DFGNodeFlags.h in Headers */, + 0FA581BC150E953000B9A2D9 /* DFGNodeType.h in Headers */, + 0F2BDC16151C5D4F00CD8910 /* DFGFixupPhase.h in Headers */, + 0F2BDC21151E803B00CD8910 /* DFGInsertionSet.h in Headers */, + 0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */, + 8612E4CD152389EC00C836BE /* MatchResult.h in Headers */, + 0F1E3A461534CBAF000F9456 /* DFGArgumentPosition.h in Headers */, + 0F1E3A471534CBB9000F9456 /* DFGDoubleFormatState.h in Headers */, + 14150133154BB13F005D8C98 /* WeakSetInlines.h in Headers */, + 14816E1C154CC56C00B8054C /* BlockAllocator.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3174,7 +2656,6 @@ buildConfigurationList = 149C275D08902AFE008A9EFC /* Build configuration list for PBXNativeTarget "JavaScriptCore" */; buildPhases = ( 5D2F7CF90C6875BB00B5B72B /* Update Info.plist with version information */, - A8D7082715049EA2001063BC /* Copy WTF Headers */, 932F5B3F0822A1C700736975 /* Headers */, 932F5B910822A1C700736975 /* Sources */, 932F5BD20822A1C700736975 /* Frameworks */, @@ -3245,6 +2726,7 @@ 651122F714046A4C002B101D /* testRegExp */, 0F4680A914BA7FD900BFE272 /* LLInt Offsets */, 0FF922C314F46B130041A24E /* JSCLLIntOffsetsExtractor */, + 5D6B2A47152B9E17005231DE /* Test Tools */, ); }; /* End PBXProject section */ @@ -3353,11 +2835,11 @@ ); name = "Install Support Script"; outputPaths = ( - "$(DSTROOT)$(JAVASCRIPTCORE_FRAMEWORKS_DIR)/JavaScriptCore.framework/Resources/testapi.js", + "$(DSTROOT)$(INSTALL_PATH)/testapi.js", ); runOnlyForDeploymentPostprocessing = 1; shellPath = /bin/sh; - shellScript = "if [[ \"${SKIP_INSTALL}\" == \"NO\" ]]; then\n cp \"${SRCROOT}/API/tests/testapi.js\" \"${DSTROOT}${JAVASCRIPTCORE_FRAMEWORKS_DIR}/JavaScriptCore.framework/Resources\"\nfi\n"; + shellScript = "if [[ \"${SKIP_INSTALL}\" == \"NO\" ]]; then\n cp \"${SRCROOT}/API/tests/testapi.js\" \"${DSTROOT}${INSTALL_PATH}/testapi.js\"\nfi\n"; }; 65FB3F6509D11E9100F49DEB /* Generate Derived Sources */ = { isa = PBXShellScriptBuildPhase; @@ -3403,20 +2885,6 @@ shellPath = /bin/sh; shellScript = "if [ \"${TARGET_GCC_VERSION}\" = \"LLVM_COMPILER\" ]; then\n exit 0;\nfi\n\nif [ -f ../../Tools/Scripts/check-for-exit-time-destructors ]; then\n ../../Tools/Scripts/check-for-exit-time-destructors || exit $?\nfi"; }; - A8D7082715049EA2001063BC /* Copy WTF Headers */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Copy WTF Headers"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "# WTF_PRIVATE_HEADERS_PATH will be replaced by PRIVATE_HEADERS_FOLDER_PATH\n# in the equivalent build-phase when WTF is its own project.\nWTF_PRIVATE_HEADERS_PATH=\"/usr/local/include\"\n\nif [[ \"${DEPLOYMENT_LOCATION}\" == \"NO\" ]]; then\nPRIVATE_HEADERS_PATH=\"${TARGET_BUILD_DIR%%/}${WTF_PRIVATE_HEADERS_PATH}\"\nelse\nPRIVATE_HEADERS_PATH=\"${DSTROOT%%/}${WTF_PRIVATE_HEADERS_PATH}\"\nfi;\n\nmkdir -p \"${PRIVATE_HEADERS_PATH}\"\nrsync -av --prune-empty-dirs --exclude \".svn\" --exclude \"usr\" --exclude \"DerivedSources\" --include \"*/\" --include \"*.h\" --exclude \"*\" \"${SRCROOT}/wtf\" \"${PRIVATE_HEADERS_PATH}\"\n"; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -3464,44 +2932,27 @@ 147F39BE107EC37600427A48 /* Arguments.cpp in Sources */, 86D3B2C310156BDE002865E7 /* ARMAssembler.cpp in Sources */, A74DE1D0120B875600D40D5B /* ARMv7Assembler.cpp in Sources */, - A73BE168148420520091204B /* ArrayBuffer.cpp in Sources */, - A73BE16A148420520091204B /* ArrayBufferView.cpp in Sources */, 147F39BF107EC37600427A48 /* ArrayConstructor.cpp in Sources */, 147F39C0107EC37600427A48 /* ArrayPrototype.cpp in Sources */, - 65FDE49C0BDD1D4A00E80111 /* Assertions.cpp in Sources */, - 868BFA08117CEFD100B908B1 /* AtomicString.cpp in Sources */, - C22C52F113FAF6EF00B7DC0D /* bignum-dtoa.cc in Sources */, - C22C52F313FAF6EF00B7DC0D /* bignum.cc in Sources */, - 1A082779142168D70090CCAC /* BinarySemaphore.cpp in Sources */, - 0F16D726142C39C000CF784A /* BitVector.cpp in Sources */, 14280863107EC11A0013E7B2 /* BooleanConstructor.cpp in Sources */, 14280864107EC11A0013E7B2 /* BooleanObject.cpp in Sources */, 14280865107EC11A0013E7B2 /* BooleanPrototype.cpp in Sources */, C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */, - A7A1F7AC0F252B3C00E184E2 /* ByteArray.cpp in Sources */, 148F21AA107EC53A0042EC2C /* BytecodeGenerator.cpp in Sources */, - C22C52F513FAF6EF00B7DC0D /* cached-powers.cc in Sources */, 1428082D107EC0570013E7B2 /* CallData.cpp in Sources */, 1429D8DD0ED2205B00B89619 /* CallFrame.cpp in Sources */, 969A07960ED1D3AE00F1F681 /* CodeBlock.cpp in Sources */, - E1A862D60D7F2B5C001EC6AA /* CollatorDefault.cpp in Sources */, - E1A862A90D7EBB76001EC6AA /* CollatorICU.cpp in Sources */, 147F39C1107EC37600427A48 /* CommonIdentifiers.cpp in Sources */, 147F39C2107EC37600427A48 /* Completion.cpp in Sources */, 146B16D812EB5B59001BEC1B /* ConservativeRoots.cpp in Sources */, 1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */, - 97941A7E1302A098004A3447 /* CryptographicallyRandomNumber.cpp in Sources */, - 86565742115BE3DA00291F40 /* CString.cpp in Sources */, - 180B9BFE0F16E94D009BDBC5 /* CurrentTime.cpp in Sources */, 147F39C3107EC37600427A48 /* DateConstructor.cpp in Sources */, 147F39C4107EC37600427A48 /* DateConversion.cpp in Sources */, 147F39C5107EC37600427A48 /* DateInstance.cpp in Sources */, - 41359CF60FDD89CB00206180 /* DateMath.cpp in Sources */, 147F39C6107EC37600427A48 /* DatePrototype.cpp in Sources */, 14280823107EC02C0013E7B2 /* Debugger.cpp in Sources */, BC3135650F302FA3003DFD3A /* DebuggerActivation.cpp in Sources */, 149559EE0DDCDDF700648087 /* DebuggerCallFrame.cpp in Sources */, - C2EE59A113FC9768009CEAFE /* DecimalNumber.cpp in Sources */, 0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */, 0FC0976E1468AB5100CF2442 /* DFGAssemblyHelpers.cpp in Sources */, 86EC9DC41328DF82002B2AD7 /* DFGByteCodeParser.cpp in Sources */, @@ -3523,9 +2974,6 @@ 86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */, 86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */, 0FC097A1146B28CA00CF2442 /* DFGThunks.cpp in Sources */, - C22C52F713FAF6EF00B7DC0D /* diy-fp.cc in Sources */, - C22C52F913FAF6EF00B7DC0D /* double-conversion.cc in Sources */, - 14469DD7107EC79E00650446 /* dtoa.cpp in Sources */, 147F39C7107EC37600427A48 /* Error.cpp in Sources */, 147F39C8107EC37600427A48 /* ErrorConstructor.cpp in Sources */, 147F39C9107EC37600427A48 /* ErrorInstance.cpp in Sources */, @@ -3534,16 +2982,12 @@ 86CA032E1038E8440028A609 /* Executable.cpp in Sources */, A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */, 86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */, - C22C52FC13FAF6EF00B7DC0D /* fast-dtoa.cc in Sources */, - 14F8BA3E107EC886009892DC /* FastMalloc.cpp in Sources */, - C22C52FE13FAF6EF00B7DC0D /* fixed-dtoa.cc in Sources */, 147F39CB107EC37600427A48 /* FunctionConstructor.cpp in Sources */, 147F39CC107EC37600427A48 /* FunctionPrototype.cpp in Sources */, DDF7ABD511F60ED200108E36 /* GCActivityCallbackCF.cpp in Sources */, 14280855107EC0E70013E7B2 /* GetterSetter.cpp in Sources */, - 142E3135134FF0A600AFADB5 /* HandleHeap.cpp in Sources */, + 142E3135134FF0A600AFADB5 /* HandleSet.cpp in Sources */, 142E3137134FF0A600AFADB5 /* HandleStack.cpp in Sources */, - 65DFC93308EA173A00F7300B /* HashTable.cpp in Sources */, 14BA7A9713AADFF8005B7C2C /* Heap.cpp in Sources */, 147F39CE107EC37600427A48 /* Identifier.cpp in Sources */, E178636D0D9BEEC300D74E75 /* InitializeThreading.cpp in Sources */, @@ -3564,7 +3008,6 @@ 147F39D0107EC37600427A48 /* JSArray.cpp in Sources */, 1421359B0A677F4F00A8195E /* JSBase.cpp in Sources */, 86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */, - A791EF290F11E07900AE1F68 /* JSByteArray.cpp in Sources */, 1440F8AF0A508D200005F061 /* JSCallbackConstructor.cpp in Sources */, 1440F8920A508B100005F061 /* JSCallbackFunction.cpp in Sources */, 14ABDF600A437FEF00ECCA01 /* JSCallbackObject.cpp in Sources */, @@ -3586,6 +3029,7 @@ A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */, 140566D1107EC267005DBC8D /* JSStaticScopeObject.cpp in Sources */, 147F39D5107EC37600427A48 /* JSString.cpp in Sources */, + 2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */, 1482B74E0A43032800517CFC /* JSStringRef.cpp in Sources */, 146AAB380B66A94400E55F16 /* JSStringRefCF.cpp in Sources */, 147F39D6107EC37600427A48 /* JSValue.cpp in Sources */, @@ -3600,20 +3044,15 @@ 14B723B212D7DA46003BD5ED /* MachineStackMarker.cpp in Sources */, 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */, 86AE64A8135E5E1C00963012 /* MacroAssemblerSH4.cpp in Sources */, - 06D358B30DAADAA4003B174E /* MainThread.cpp in Sources */, - 06D358B40DAADAAA003B174E /* MainThreadMac.mm in Sources */, 142D6F0813539A2800B02E86 /* MarkedBlock.cpp in Sources */, 14D2F3DA139F4BE200491031 /* MarkedSpace.cpp in Sources */, 142D6F1113539A4100B02E86 /* MarkStack.cpp in Sources */, 14469DDF107EC7E700650446 /* MathObject.cpp in Sources */, - 511FC4C9117EE28700425272 /* MD5.cpp in Sources */, 90213E3D123A40C200D422F3 /* MemoryStatistics.cpp in Sources */, - 0F963B2C13F853EC0002D9B2 /* MetaAllocator.cpp in Sources */, 14469DE0107EC7E700650446 /* NativeErrorConstructor.cpp in Sources */, 14469DE1107EC7E700650446 /* NativeErrorPrototype.cpp in Sources */, 148F21B7107EC5470042EC2C /* Nodes.cpp in Sources */, 655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */, - 93854A9A12C93D3B00DAAF77 /* NullPtr.cpp in Sources */, 14469DE2107EC7E700650446 /* NumberConstructor.cpp in Sources */, 14469DE3107EC7E700650446 /* NumberObject.cpp in Sources */, 14469DE4107EC7E700650446 /* NumberPrototype.cpp in Sources */, @@ -3623,12 +3062,6 @@ 969A079A0ED1D3AE00F1F681 /* Opcode.cpp in Sources */, 14280850107EC0D70013E7B2 /* Operations.cpp in Sources */, 0FE228EE1436AB2C00196C48 /* Options.cpp in Sources */, - 1400069312A6F9E10064D123 /* OSAllocatorPosix.cpp in Sources */, - 97941A5713029AAB004A3447 /* OSRandomSource.cpp in Sources */, - 14FFF98C12BFFF7500795BB8 /* PageAllocationAligned.cpp in Sources */, - 14B3EF0612BC24DD00D29EFF /* PageBlock.cpp in Sources */, - 7934BB7C1361979400CB99A1 /* ParallelJobsGeneric.cpp in Sources */, - 2684B2D314D4A9B20072C0B6 /* ParsedURL.cpp in Sources */, 148F21BC107EC54D0042EC2C /* Parser.cpp in Sources */, 93052C340FB792190048FDC3 /* ParserArena.cpp in Sources */, 0FD82E86141F3FF100179C94 /* PredictedType.cpp in Sources */, @@ -3639,8 +3072,6 @@ A7FB60A4103F7DC20017A286 /* PropertyDescriptor.cpp in Sources */, 14469DE7107EC7E700650446 /* PropertyNameArray.cpp in Sources */, 14469DE8107EC7E700650446 /* PropertySlot.cpp in Sources */, - 088FA5BB0EF76D4300578E6F /* RandomNumber.cpp in Sources */, - 905B02AE0E28640F006DF882 /* RefCountedLeakCounter.cpp in Sources */, 14280841107EC0930013E7B2 /* RegExp.cpp in Sources */, A1712B3B11C7B212007A5315 /* RegExpCache.cpp in Sources */, 14280842107EC0930013E7B2 /* RegExpConstructor.cpp in Sources */, @@ -3650,39 +3081,21 @@ 0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */, 1429D8850ED21C3D00B89619 /* SamplingTool.cpp in Sources */, 14469DEA107EC7E700650446 /* ScopeChain.cpp in Sources */, - 76FB9F1112E851960051A2EB /* SHA1.cpp in Sources */, - 0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */, 9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */, E49DC16B12EF293E00184A1F /* SourceProviderCache.cpp in Sources */, - 86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */, A730B6131250068F009D25B1 /* StrictEvalActivation.cpp in Sources */, - 86438FC41265503E00E0DFCA /* StringBuilder.cpp in Sources */, 14469DEB107EC7E700650446 /* StringConstructor.cpp in Sources */, - 868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */, 14469DEC107EC7E700650446 /* StringObject.cpp in Sources */, 14469DED107EC7E700650446 /* StringPrototype.cpp in Sources */, 9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */, - 8626BECF11928E3900782FAB /* StringStatics.cpp in Sources */, - C22C531313FAF6EF00B7DC0D /* strtod.cc in Sources */, BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */, 7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */, BCCF0D0C0EF0B8A500413C8F /* StructureStubInfo.cpp in Sources */, - 14F8BA43107EC88C009892DC /* TCSystemAlloc.cpp in Sources */, - 18BAB55310DAE054000D945B /* ThreadIdentifierDataPthreads.cpp in Sources */, - 5D6A566B0F05995500266145 /* Threading.cpp in Sources */, - E1EE793D0D6C9B9200FEA3BA /* ThreadingPthreads.cpp in Sources */, A7386555118697B400540279 /* ThunkGenerators.cpp in Sources */, 14A42E3F0F4F60EE00599099 /* TimeoutChecker.cpp in Sources */, - 0B330C270F38C62300692DE3 /* TypeTraits.cpp in Sources */, - 2684B2D814D4A9B20072C0B6 /* URLCharacterTypes.cpp in Sources */, - 2684B2DB14D4A9B20072C0B6 /* URLEscape.cpp in Sources */, - 2684B2DF14D4A9B20072C0B6 /* URLSegments.cpp in Sources */, 14469DEE107EC7E700650446 /* UString.cpp in Sources */, - E1EF79AA0CE97BA60088D500 /* UTF8.cpp in Sources */, 0FC81516140511B500CFA603 /* VTableSpectrum.cpp in Sources */, 0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */, - 868BFA17117CF19900B908B1 /* WTFString.cpp in Sources */, - 86D08D5311793613006E5ED0 /* WTFThreadData.cpp in Sources */, 86704B8412DBA33700A9FE7B /* YarrInterpreter.cpp in Sources */, 86704B8612DBA33700A9FE7B /* YarrJIT.cpp in Sources */, 86704B8912DBA33700A9FE7B /* YarrPattern.cpp in Sources */, @@ -3697,7 +3110,6 @@ 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */, 0F0B83B014BCF71600885B4F /* CallLinkInfo.cpp in Sources */, 0F0B83B414BCF86000885B4F /* MethodCallLinkInfo.cpp in Sources */, - F69E86C314C6E551002C2C62 /* NumberOfCores.cpp in Sources */, 0F93329D14CA7DC30085F3C6 /* CallLinkStatus.cpp in Sources */, 0F93329F14CA7DCA0085F3C6 /* GetByIdStatus.cpp in Sources */, 0F9332A114CA7DD10085F3C6 /* MethodCallLinkStatus.cpp in Sources */, @@ -3706,9 +3118,10 @@ 86B5826714D2796C00A9C306 /* CodeProfile.cpp in Sources */, 86B5826914D2797000A9C306 /* CodeProfiling.cpp in Sources */, C2B916C514DA040C00CBAC86 /* MarkedAllocator.cpp in Sources */, - 0F9FC8D014E612D800D52AE0 /* DataLog.cpp in Sources */, 0F9FC8C314E1B5FE00D52AE0 /* PolymorphicPutByIdList.cpp in Sources */, - 0FFFC95514EF909A00C72532 /* DFGArithNodeFlagsInferencePhase.cpp in Sources */, + 14E84F9E14EE1ACC00D6D5D4 /* WeakBlock.cpp in Sources */, + 14E84FA014EE1ACC00D6D5D4 /* WeakSet.cpp in Sources */, + 14F7256514EE265E00B1652B /* WeakHandleOwner.cpp in Sources */, 0FFFC95714EF90A000C72532 /* DFGCFAPhase.cpp in Sources */, 0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */, 0FFFC95B14EF90AD00C72532 /* DFGPhase.cpp in Sources */, @@ -3718,7 +3131,12 @@ 0FB5467D14F5CFD6002C2989 /* MethodOfGettingAValueProfile.cpp in Sources */, 0F56A1D515001CF4002992B1 /* ExecutionCounter.cpp in Sources */, 0A4337BB1506218800991C95 /* DFGRedundantPhiEliminationPhase.cpp in Sources */, - 0F1D0861150C5A860074D109 /* DFGNode.cpp in Sources */, + 0FA581BA150E952C00B9A2D9 /* DFGNodeFlags.cpp in Sources */, + 0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */, + 8642C510151C06A90046D4EF /* RegExpCachedResult.cpp in Sources */, + 8642C512151C083D0046D4EF /* RegExpMatchesArray.cpp in Sources */, + 863C6D9C1521111A00585E4E /* YarrCanonicalizeUCS2.cpp in Sources */, + 14816E1B154CC56C00B8054C /* BlockAllocator.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3743,20 +3161,30 @@ target = 0FF922C314F46B130041A24E /* JSCLLIntOffsetsExtractor */; targetProxy = 0FF922D514F46B600041A24E /* PBXContainerItemProxy */; }; - 141214BF0A49190E00480255 /* PBXTargetDependency */ = { + 5D69E912152BE5470028D720 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 932F5BDA0822A1C700736975 /* jsc */; + targetProxy = 5D69E911152BE5470028D720 /* PBXContainerItemProxy */; + }; + 5D6B2A4F152B9E23005231DE /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 1412111F0A48793C00480255 /* minidom */; - targetProxy = 141214BE0A49190E00480255 /* PBXContainerItemProxy */; + targetProxy = 5D6B2A4E152B9E23005231DE /* PBXContainerItemProxy */; }; - 14BD59C70A3E8FA400BAF59C /* PBXTargetDependency */ = { + 5D6B2A51152B9E23005231DE /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 14BD59BE0A3E8F9000BAF59C /* testapi */; - targetProxy = 14BD59C60A3E8FA400BAF59C /* PBXContainerItemProxy */; + targetProxy = 5D6B2A50152B9E23005231DE /* PBXContainerItemProxy */; }; - 651123091404768B002B101D /* PBXTargetDependency */ = { + 5D6B2A55152B9E23005231DE /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 651122F714046A4C002B101D /* testRegExp */; - targetProxy = 651123081404768B002B101D /* PBXContainerItemProxy */; + targetProxy = 5D6B2A54152B9E23005231DE /* PBXContainerItemProxy */; + }; + 5D6B2A57152B9E2E005231DE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 5D6B2A47152B9E17005231DE /* Test Tools */; + targetProxy = 5D6B2A56152B9E2E005231DE /* PBXContainerItemProxy */; }; 65FB3F7E09D11EF300F49DEB /* PBXTargetDependency */ = { isa = PBXTargetDependency; @@ -3768,11 +3196,6 @@ target = 932F5B3E0822A1C700736975 /* JavaScriptCore */; targetProxy = 932F5BE60822A1C700736975 /* PBXContainerItemProxy */; }; - 932F5BE90822A1C700736975 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 932F5BDA0822A1C700736975 /* jsc */; - targetProxy = 932F5BE80822A1C700736975 /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ @@ -3834,25 +3257,22 @@ }; 1412113A0A48798400480255 /* Debug */ = { isa = XCBuildConfiguration; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { - PRODUCT_NAME = minidom; - SKIP_INSTALL = YES; }; name = Debug; }; 1412113B0A48798400480255 /* Release */ = { isa = XCBuildConfiguration; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { - PRODUCT_NAME = minidom; - SKIP_INSTALL = YES; }; name = Release; }; 1412113C0A48798400480255 /* Production */ = { isa = XCBuildConfiguration; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { - PRODUCT_NAME = minidom; - SKIP_INSTALL = YES; }; name = Production; }; @@ -3969,6 +3389,34 @@ }; name = Production; }; + 5D6B2A48152B9E17005231DE /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 5D6B2A49152B9E17005231DE /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 5D6B2A4A152B9E17005231DE /* Profiling */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profiling; + }; + 5D6B2A4B152B9E17005231DE /* Production */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Production; + }; 6511230114046A4C002B101D /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; @@ -4050,9 +3498,8 @@ }; A76148410E6402F700E357FA /* Profiling */ = { isa = XCBuildConfiguration; + baseConfigurationReference = BC021BF2136900C300FC5467 /* ToolExecutable.xcconfig */; buildSettings = { - PRODUCT_NAME = minidom; - SKIP_INSTALL = YES; }; name = Profiling; }; @@ -4161,6 +3608,17 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Production; }; + 5D6B2A4C152B9E17005231DE /* Build configuration list for PBXAggregateTarget "Test Tools" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5D6B2A48152B9E17005231DE /* Debug */, + 5D6B2A49152B9E17005231DE /* Release */, + 5D6B2A4A152B9E17005231DE /* Profiling */, + 5D6B2A4B152B9E17005231DE /* Production */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Production; + }; 6511230014046A4C002B101D /* Build configuration list for PBXNativeTarget "testRegExp" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Source/JavaScriptCore/KeywordLookupGenerator.py b/Source/JavaScriptCore/KeywordLookupGenerator.py index 29f50dfe0..748acf9dc 100644 --- a/Source/JavaScriptCore/KeywordLookupGenerator.py +++ b/Source/JavaScriptCore/KeywordLookupGenerator.py @@ -1,4 +1,5 @@ # Copyright (C) 2011 Apple Inc. All rights reserved. +# Copyright (C) 2012 Sony Network Entertainment. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions @@ -27,6 +28,15 @@ import operator keywordsText = open(sys.argv[1]).read() +# A second argument signifies that the output +# should be redirected to a file +redirect_to_file = len(sys.argv) > 2 + +# Change stdout to point to the file if requested +if redirect_to_file: + file_output = open(sys.argv[-1], "w") + sys.stdout = file_output + # Observed weights of the most common keywords, rounded to 2.s.d keyWordWeights = { "catch": 0.01, @@ -288,3 +298,8 @@ print(""" """) trie.printAsC() + +# Close the redirected file if requested +if (redirect_to_file): + file_output.close() + sys.stdout = sys.__stdout__ diff --git a/Source/JavaScriptCore/PlatformEfl.cmake b/Source/JavaScriptCore/PlatformEfl.cmake index f32a90bdd..448834cf7 100644 --- a/Source/JavaScriptCore/PlatformEfl.cmake +++ b/Source/JavaScriptCore/PlatformEfl.cmake @@ -7,6 +7,10 @@ LIST(APPEND JavaScriptCore_LIBRARIES ${ICU_I18N_LIBRARIES} ) +LIST(APPEND JavaScriptCore_INCLUDE_DIRECTORIES + ${ICU_INCLUDE_DIRS} +) + IF (ENABLE_GLIB_SUPPORT) LIST(APPEND JavaScriptCore_INCLUDE_DIRECTORIES ${JAVASCRIPTCORE_DIR}/wtf/gobject diff --git a/Source/JavaScriptCore/Target.pri b/Source/JavaScriptCore/Target.pri index 1480ae74b..017f3165a 100644 --- a/Source/JavaScriptCore/Target.pri +++ b/Source/JavaScriptCore/Target.pri @@ -71,8 +71,12 @@ SOURCES += \ heap/CopiedSpace.cpp \ heap/ConservativeRoots.cpp \ heap/DFGCodeBlocks.cpp \ - heap/HandleHeap.cpp \ + heap/WeakSet.cpp \ + heap/WeakHandleOwner.cpp \ + heap/WeakBlock.cpp \ + heap/HandleSet.cpp \ heap/HandleStack.cpp \ + heap/BlockAllocator.cpp \ heap/Heap.cpp \ heap/MachineStackMarker.cpp \ heap/MarkStack.cpp \ @@ -86,16 +90,16 @@ SOURCES += \ debugger/Debugger.cpp \ dfg/DFGAbstractState.cpp \ dfg/DFGAssemblyHelpers.cpp \ - dfg/DFGArithNodeFlagsInferencePhase.cpp \ dfg/DFGByteCodeParser.cpp \ dfg/DFGCapabilities.cpp \ dfg/DFGCFAPhase.cpp \ dfg/DFGCorrectableJumpPoint.cpp \ dfg/DFGCSEPhase.cpp \ dfg/DFGDriver.cpp \ + dfg/DFGFixupPhase.cpp \ dfg/DFGGraph.cpp \ dfg/DFGJITCompiler.cpp \ - dfg/DFGNode.cpp \ + dfg/DFGNodeFlags.cpp \ dfg/DFGOperations.cpp \ dfg/DFGOSREntry.cpp \ dfg/DFGOSRExit.cpp \ @@ -171,7 +175,6 @@ SOURCES += \ runtime/JSActivation.cpp \ runtime/JSAPIValueWrapper.cpp \ runtime/JSArray.cpp \ - runtime/JSByteArray.cpp \ runtime/JSCell.cpp \ runtime/JSDateMath.cpp \ runtime/JSFunction.cpp \ @@ -187,6 +190,7 @@ SOURCES += \ runtime/JSPropertyNameIterator.cpp \ runtime/JSStaticScopeObject.cpp \ runtime/JSString.cpp \ + runtime/JSStringJoiner.cpp \ runtime/JSValue.cpp \ runtime/JSVariableObject.cpp \ runtime/JSWrapperObject.cpp \ @@ -205,6 +209,8 @@ SOURCES += \ runtime/PropertyNameArray.cpp \ runtime/PropertySlot.cpp \ runtime/RegExpConstructor.cpp \ + runtime/RegExpCachedResult.cpp \ + runtime/RegExpMatchesArray.cpp \ runtime/RegExp.cpp \ runtime/RegExpObject.cpp \ runtime/RegExpPrototype.cpp \ diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h index 51788da08..5b523c277 100644 --- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h @@ -531,9 +531,11 @@ private: OP_STR_reg_T1 = 0x5000, OP_STRH_reg_T1 = 0x5200, OP_STRB_reg_T1 = 0x5400, + OP_LDRSB_reg_T1 = 0x5600, OP_LDR_reg_T1 = 0x5800, OP_LDRH_reg_T1 = 0x5A00, OP_LDRB_reg_T1 = 0x5C00, + OP_LDRSH_reg_T1 = 0x5E00, OP_STR_imm_T1 = 0x6000, OP_LDR_imm_T1 = 0x6800, OP_STRB_imm_T1 = 0x7000, @@ -570,7 +572,9 @@ private: OP_CMP_reg_T2 = 0xEBB0, OP_VMOV_CtoD = 0xEC00, OP_VMOV_DtoC = 0xEC10, + OP_FSTS = 0xED00, OP_VSTR = 0xED00, + OP_FLDS = 0xED10, OP_VLDR = 0xED10, OP_VMOV_CtoS = 0xEE00, OP_VMOV_StoC = 0xEE10, @@ -586,6 +590,8 @@ private: OP_VMRS = 0xEEB0, OP_VNEG_T2 = 0xEEB0, OP_VSQRT_T1 = 0xEEB0, + OP_VCVTSD_T1 = 0xEEB0, + OP_VCVTDS_T1 = 0xEEB0, OP_B_T3a = 0xF000, OP_B_T4a = 0xF000, OP_AND_imm_T1 = 0xF000, @@ -627,6 +633,8 @@ private: OP_LDRH_imm_T2 = 0xF8B0, OP_STR_imm_T3 = 0xF8C0, OP_LDR_imm_T3 = 0xF8D0, + OP_LDRSB_reg_T2 = 0xF910, + OP_LDRSH_reg_T2 = 0xF930, OP_LSL_reg_T2 = 0xFA00, OP_LSR_reg_T2 = 0xFA20, OP_ASR_reg_T2 = 0xFA40, @@ -638,10 +646,12 @@ private: typedef enum { OP_VADD_T2b = 0x0A00, OP_VDIVb = 0x0A00, + OP_FLDSb = 0x0A00, OP_VLDRb = 0x0A00, OP_VMOV_IMM_T2b = 0x0A00, OP_VMOV_T2b = 0x0A40, OP_VMUL_T2b = 0x0A00, + OP_FSTSb = 0x0A00, OP_VSTRb = 0x0A00, OP_VMOV_StoCb = 0x0A10, OP_VMOV_CtoSb = 0x0A10, @@ -654,6 +664,8 @@ private: OP_VNEG_T2b = 0x0A40, OP_VSUB_T2b = 0x0A40, OP_VSQRT_T1b = 0x0A40, + OP_VCVTSD_T1b = 0x0A40, + OP_VCVTDS_T1b = 0x0A40, OP_NOP_T2b = 0x8000, OP_B_T3b = 0x8000, OP_B_T4b = 0x9000, @@ -739,6 +751,7 @@ public: ASSERT(imm.isValid()); if (rn == ARMRegisters::sp) { + ASSERT(!(imm.getUInt16() & 3)); if (!(rd & 8) && imm.isUInt10()) { m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, static_cast<uint8_t>(imm.getUInt10() >> 2)); return; @@ -1157,6 +1170,30 @@ public: else m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm)); } + + void ldrsb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0) + { + ASSERT(rn != ARMRegisters::pc); + ASSERT(!BadReg(rm)); + ASSERT(shift <= 3); + + if (!shift && !((rt | rn | rm) & 8)) + m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSB_reg_T1, rm, rn, rt); + else + m_formatter.twoWordOp12Reg4FourFours(OP_LDRSB_reg_T2, rn, FourFours(rt, 0, shift, rm)); + } + + void ldrsh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0) + { + ASSERT(rn != ARMRegisters::pc); + ASSERT(!BadReg(rm)); + ASSERT(shift <= 3); + + if (!shift && !((rt | rn | rm) & 8)) + m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSH_reg_T1, rm, rn, rt); + else + m_formatter.twoWordOp12Reg4FourFours(OP_LDRSH_reg_T2, rn, FourFours(rt, 0, shift, rm)); + } void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount) { @@ -1511,6 +1548,7 @@ public: ASSERT(imm.isValid()); if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) { + ASSERT(!(imm.getUInt16() & 3)); m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2)); return; } else if (!((rd | rn) & 8)) { @@ -1572,6 +1610,7 @@ public: ASSERT(imm.isValid()); if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) { + ASSERT(!(imm.getUInt16() & 3)); m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2)); return; } else if (!((rd | rn) & 8)) { @@ -1689,6 +1728,11 @@ public: { m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm); } + + void flds(FPSingleRegisterID rd, RegisterID rn, int32_t imm) + { + m_formatter.vfpMemOp(OP_FLDS, OP_FLDSb, false, rn, rd, imm); + } void vmov(RegisterID rd, FPSingleRegisterID rn) { @@ -1737,6 +1781,11 @@ public: m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm); } + void fsts(FPSingleRegisterID rd, RegisterID rn, int32_t imm) + { + m_formatter.vfpMemOp(OP_FSTS, OP_FSTSb, false, rn, rd, imm); + } + void vsub(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) { m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm); @@ -1756,6 +1805,16 @@ public: { m_formatter.vfpOp(OP_VSQRT_T1, OP_VSQRT_T1b, true, VFPOperand(17), rd, rm); } + + void vcvtds(FPDoubleRegisterID rd, FPSingleRegisterID rm) + { + m_formatter.vfpOp(OP_VCVTDS_T1, OP_VCVTDS_T1b, false, VFPOperand(23), rd, rm); + } + + void vcvtsd(FPSingleRegisterID rd, FPDoubleRegisterID rm) + { + m_formatter.vfpOp(OP_VCVTSD_T1, OP_VCVTSD_T1b, true, VFPOperand(23), rd, rm); + } void nop() { @@ -1827,29 +1886,29 @@ public: if (jumpType == JumpCondition) { // 2-byte conditional T1 - const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT1))); + const uint16_t* jumpT1Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT1))); if (canBeJumpT1(jumpT1Location, to)) return LinkJumpT1; // 4-byte conditional T3 - const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT3))); + const uint16_t* jumpT3Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT3))); if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) { if (!mayTriggerErrata) return LinkJumpT3; } // 4-byte conditional T4 with IT const uint16_t* conditionalJumpT4Location = - reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkConditionalJumpT4))); + reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkConditionalJumpT4))); if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) { if (!mayTriggerErrata) return LinkConditionalJumpT4; } } else { // 2-byte unconditional T2 - const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT2))); + const uint16_t* jumpT2Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT2))); if (canBeJumpT2(jumpT2Location, to)) return LinkJumpT2; // 4-byte unconditional T4 - const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT4))); + const uint16_t* jumpT4Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT4))); if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) { if (!mayTriggerErrata) return LinkJumpT4; @@ -1888,25 +1947,25 @@ public: { switch (record.linkType()) { case LinkJumpT1: - linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to); + linkJumpT1(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkJumpT2: - linkJumpT2(reinterpret_cast<uint16_t*>(from), to); + linkJumpT2(reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkJumpT3: - linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to); + linkJumpT3(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkJumpT4: - linkJumpT4(reinterpret_cast<uint16_t*>(from), to); + linkJumpT4(reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkConditionalJumpT4: - linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to); + linkConditionalJumpT4(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkConditionalBX: - linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to); + linkConditionalBX(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkBX: - linkBX(reinterpret_cast<uint16_t*>(from), to); + linkBX(reinterpret_cast_ptr<uint16_t*>(from), to); break; default: ASSERT_NOT_REACHED(); diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h index ab343977e..4fb60dd2d 100644 --- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -26,6 +26,7 @@ #ifndef AbstractMacroAssembler_h #define AbstractMacroAssembler_h +#include "AssemblerBuffer.h" #include "CodeLocation.h" #include "MacroAssemblerCodeRef.h" #include <wtf/CryptographicallyRandomNumber.h> @@ -220,33 +221,17 @@ public: struct TrustedImm32 { explicit TrustedImm32(int32_t value) : m_value(value) -#if CPU(ARM) || CPU(MIPS) - , m_isPointer(false) -#endif { } #if !CPU(X86_64) explicit TrustedImm32(TrustedImmPtr ptr) : m_value(ptr.asIntptr()) -#if CPU(ARM) || CPU(MIPS) - , m_isPointer(true) -#endif { } #endif int32_t m_value; -#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 }; @@ -450,6 +435,12 @@ public: , m_condition(condition) { } +#elif CPU(SH4) + Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar) + : m_label(jmp) + , m_type(type) + { + } #else Jump(AssemblerLabel jmp) : m_label(jmp) @@ -461,6 +452,8 @@ public: { #if CPU(ARM_THUMB2) masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition); +#elif CPU(SH4) + masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type); #else masm->m_assembler.linkJump(m_label, masm->m_assembler.label()); #endif @@ -483,6 +476,24 @@ public: ARMv7Assembler::JumpType m_type; ARMv7Assembler::Condition m_condition; #endif +#if CPU(SH4) + SH4Assembler::JumpType m_type; +#endif + }; + + struct PatchableJump { + PatchableJump() + { + } + + explicit PatchableJump(Jump jump) + : m_jump(jump) + { + } + + operator Jump&() { return m_jump; } + + Jump m_jump; }; // JumpList: @@ -551,7 +562,7 @@ public: } template<typename T, typename U> - ptrdiff_t differenceBetween(T from, U to) + static ptrdiff_t differenceBetween(T from, U to) { return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label); } @@ -561,27 +572,15 @@ public: return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress()); } - void beginUninterruptedSequence() { m_inUninterruptedSequence = true; } - void endUninterruptedSequence() { m_inUninterruptedSequence = false; } - unsigned debugOffset() { return m_assembler.debugOffset(); } protected: AbstractMacroAssembler() - : m_inUninterruptedSequence(false) - , m_randomSource(cryptographicallyRandomNumber()) + : m_randomSource(cryptographicallyRandomNumber()) { } AssemblerType m_assembler; - - bool inUninterruptedSequence() - { - return m_inUninterruptedSequence; - } - - bool m_inUninterruptedSequence; - uint32_t random() { diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.h b/Source/JavaScriptCore/assembler/LinkBuffer.h index 6ec9a7eb9..5e91ef3ce 100644 --- a/Source/JavaScriptCore/assembler/LinkBuffer.h +++ b/Source/JavaScriptCore/assembler/LinkBuffer.h @@ -63,6 +63,7 @@ class LinkBuffer { typedef MacroAssemblerCodePtr CodePtr; typedef MacroAssembler::Label Label; typedef MacroAssembler::Jump Jump; + typedef MacroAssembler::PatchableJump PatchableJump; typedef MacroAssembler::JumpList JumpList; typedef MacroAssembler::Call Call; typedef MacroAssembler::DataLabelCompact DataLabelCompact; @@ -154,9 +155,9 @@ public: return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_label))); } - CodeLocationLabel locationOf(Jump jump) + CodeLocationLabel locationOf(PatchableJump jump) { - return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), applyOffset(jump.m_label))); + return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), applyOffset(jump.m_jump.m_label))); } CodeLocationLabel locationOf(Label label) @@ -260,9 +261,9 @@ private: // Copy the instructions from the last jump to the current one. size_t regionSize = jumpsToLink[i].from() - readPtr; - uint16_t* copySource = reinterpret_cast<uint16_t*>(inData + readPtr); - uint16_t* copyEnd = reinterpret_cast<uint16_t*>(inData + readPtr + regionSize); - uint16_t* copyDst = reinterpret_cast<uint16_t*>(outData + writePtr); + uint16_t* copySource = reinterpret_cast_ptr<uint16_t*>(inData + readPtr); + uint16_t* copyEnd = reinterpret_cast_ptr<uint16_t*>(inData + readPtr + regionSize); + uint16_t* copyDst = reinterpret_cast_ptr<uint16_t*>(outData + writePtr); ASSERT(!(regionSize % 2)); ASSERT(!(readPtr % 2)); ASSERT(!(writePtr % 2)); @@ -374,6 +375,23 @@ private: for (unsigned i = 0; i < tsize; i++) dataLog("\t.short\t0x%x\n", tcode[i]); +#elif CPU(ARM_TRADITIONAL) + // gcc -c jit.s + // objdump -D jit.o + static unsigned codeCount = 0; + unsigned int* tcode = static_cast<unsigned int*>(code); + size_t tsize = size / sizeof(unsigned int); + char nameBuf[128]; + snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++); + dataLog("\t.globl\t%s\n" + "\t.align 4\n" + "\t.code 32\n" + "\t.text\n" + "# %p\n" + "%s:\n", nameBuf, code, nameBuf); + + for (unsigned i = 0; i < tsize; i++) + dataLog("\t.long\t0x%x\n", tcode[i]); #endif } #endif diff --git a/Source/JavaScriptCore/assembler/MacroAssembler.h b/Source/JavaScriptCore/assembler/MacroAssembler.h index 4c54e29aa..516ffac16 100644 --- a/Source/JavaScriptCore/assembler/MacroAssembler.h +++ b/Source/JavaScriptCore/assembler/MacroAssembler.h @@ -229,6 +229,18 @@ public: branchTestPtr(cond, reg).linkTo(target, this); } +#if !CPU(ARM_THUMB2) + PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) + { + return PatchableJump(branchPtrWithPatch(cond, left, dataLabel, initialRightValue)); + } + + PatchableJump patchableJump() + { + return PatchableJump(jump()); + } +#endif + void jump(Label target) { jump().linkTo(target, this); @@ -529,7 +541,6 @@ public: bool shouldBlind(ImmPtr imm) { - ASSERT(!inUninterruptedSequence()); #if !defined(NDEBUG) UNUSED_PARAM(imm); // Debug always blind all constants, if only so we know @@ -636,7 +647,6 @@ public: #if ENABLE(JIT_CONSTANT_BLINDING) bool shouldBlind(Imm32 imm) { - ASSERT(!inUninterruptedSequence()); #if !defined(NDEBUG) UNUSED_PARAM(imm); // Debug always blind all constants, if only so we know @@ -699,8 +709,11 @@ public: BlindedImm32 additionBlindedConstant(Imm32 imm) { + // The addition immediate may be used as a pointer offset. Keep aligned based on "imm". + static uint32_t maskTable[4] = { 0xfffffffc, 0xffffffff, 0xfffffffe, 0xffffffff }; + uint32_t baseValue = imm.asTrustedImm32().m_value; - uint32_t key = keyForConstant(baseValue); + uint32_t key = keyForConstant(baseValue) & maskTable[baseValue & 3]; if (key > baseValue) key = key - baseValue; return BlindedImm32(baseValue - key, key); @@ -828,9 +841,17 @@ public: store32(blind.value1, dest); xor32(blind.value2, dest); #else - RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding(); - loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister); - store32(scratchRegister, dest); + if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) { + loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister); + store32(scratchRegister, dest); + } else { + // If we don't have a scratch register available for use, we'll just + // place a random number of nops. + uint32_t nopCount = random() & 3; + while (nopCount--) + nop(); + store32(imm.asTrustedImm32(), dest); + } #endif } else store32(imm.asTrustedImm32(), dest); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h index c0cd766cb..1775cb4cf 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -150,6 +150,11 @@ public: m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f)); } + void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + m_assembler.movs_r(dest, m_assembler.lsl(src, imm.m_value & 0x1f)); + } + void mul32(RegisterID src, RegisterID dest) { if (src == dest) { @@ -180,6 +185,11 @@ public: m_assembler.orrs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } + void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + m_assembler.orrs_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); + } + void or32(RegisterID op1, RegisterID op2, RegisterID dest) { m_assembler.orrs_r(dest, op1, op2); @@ -217,6 +227,11 @@ public: { m_assembler.movs_r(dest, m_assembler.lsr(dest, imm.m_value & 0x1f)); } + + void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + m_assembler.movs_r(dest, m_assembler.lsr(src, imm.m_value & 0x1f)); + } void sub32(RegisterID src, RegisterID dest) { @@ -259,6 +274,14 @@ public: m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } + void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (imm.m_value == -1) + m_assembler.mvns_r(dest, src); + else + m_assembler.eors_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); + } + void countLeadingZeros32(RegisterID src, RegisterID dest) { #if WTF_ARM_ARCH_AT_LEAST(5) @@ -353,10 +376,7 @@ public: void store32(TrustedImm32 imm, ImplicitAddress address) { - if (imm.m_isPointer) - m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value); - else - move(imm, ARMRegisters::S1); + move(imm, ARMRegisters::S1); store32(ARMRegisters::S1, address); } @@ -369,10 +389,7 @@ public: void store32(TrustedImm32 imm, void* address) { m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address)); - if (imm.m_isPointer) - m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value); - else - m_assembler.moveImm(imm.m_value, ARMRegisters::S1); + m_assembler.moveImm(imm.m_value, ARMRegisters::S1); m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0); } @@ -400,10 +417,7 @@ public: void move(TrustedImm32 imm, RegisterID dest) { - if (imm.m_isPointer) - m_assembler.ldr_un_imm(dest, imm.m_value); - else - m_assembler.moveImm(imm.m_value, dest); + m_assembler.moveImm(imm.m_value, dest); } void move(RegisterID src, RegisterID dest) @@ -456,16 +470,11 @@ public: Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right, int useConstantPool = 0) { - if (right.m_isPointer) { - m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value); - m_assembler.cmp_r(left, ARMRegisters::S0); - } else { - ARMWord tmp = (right.m_value == 0x80000000) ? ARMAssembler::INVALID_IMM : m_assembler.getOp2(-right.m_value); - if (tmp != ARMAssembler::INVALID_IMM) - m_assembler.cmn_r(left, tmp); - else - m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0)); - } + ARMWord tmp = (right.m_value == 0x80000000) ? ARMAssembler::INVALID_IMM : m_assembler.getOp2(-right.m_value); + if (tmp != ARMAssembler::INVALID_IMM) + m_assembler.cmn_r(left, tmp); + else + m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0)); return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool)); } @@ -627,6 +636,13 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } + Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + m_assembler.subs_r(dest, op1, op2); + return Jump(m_assembler.jmp(ARMCondition(cond))); + } + Jump branchNeg32(ResultCondition cond, RegisterID srcDest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -687,6 +703,12 @@ public: m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond)); } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + load8(left, ARMRegisters::S1); + compare32(cond, ARMRegisters::S1, right, dest); + } + void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest) { if (mask.m_value == -1) diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h index 43ea2ed5a..3b62cb5be 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -45,6 +45,11 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<ARMv7Assembler> { inline ARMRegisters::FPSingleRegisterID fpTempRegisterAsSingle() { return ARMRegisters::asSingle(fpTempRegister); } public: + MacroAssemblerARMv7() + : m_makeJumpPatchable(false) + { + } + typedef ARMv7Assembler::LinkRecord LinkRecord; typedef ARMv7Assembler::JumpType JumpType; typedef ARMv7Assembler::JumpLinkType JumpLinkType; @@ -499,9 +504,10 @@ private: } } - void load16Signed(ArmAddress, RegisterID) + void load16Signed(ArmAddress address, RegisterID dest) { - unreachableForPlatform(); + ASSERT(address.type == ArmAddress::HasIndex); + m_assembler.ldrsh(dest, address.base, address.u.index, address.u.scale); } void load8(ArmAddress address, RegisterID dest) @@ -518,9 +524,10 @@ private: } } - void load8Signed(ArmAddress, RegisterID) + void load8Signed(ArmAddress address, RegisterID dest) { - unreachableForPlatform(); + ASSERT(address.type == ArmAddress::HasIndex); + m_assembler.ldrsb(dest, address.base, address.u.index, address.u.scale); } protected: @@ -609,9 +616,9 @@ public: load8(setupArmAddress(address), dest); } - void load8Signed(BaseIndex, RegisterID) + void load8Signed(BaseIndex address, RegisterID dest) { - unreachableForPlatform(); + load8Signed(setupArmAddress(address), dest); } DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) @@ -649,9 +656,9 @@ public: m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale); } - void load16Signed(BaseIndex, RegisterID) + void load16Signed(BaseIndex address, RegisterID dest) { - unreachableForPlatform(); + load16Signed(setupArmAddress(address), dest); } void load16(ImplicitAddress address, RegisterID dest) @@ -722,7 +729,6 @@ public: } #if ENABLE(JIT_CONSTANT_BLINDING) - static RegisterID scratchRegisterForBlinding() { return dataTempRegister; } static bool shouldBlindForSpecificArch(uint32_t value) { ARMThumbImmediate immediate = ARMThumbImmediate::makeEncodedImm(value); @@ -764,18 +770,35 @@ public: m_assembler.vldr(dest, base, offset); } + void loadFloat(ImplicitAddress address, FPRegisterID dest) + { + RegisterID base = address.base; + int32_t offset = address.offset; + + // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2. + if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) { + add32(TrustedImm32(offset), base, addressTempRegister); + base = addressTempRegister; + offset = 0; + } + + m_assembler.flds(ARMRegisters::asSingle(dest), base, offset); + } + void loadDouble(BaseIndex address, FPRegisterID dest) { - UNUSED_PARAM(address); - UNUSED_PARAM(dest); - unreachableForPlatform(); + move(address.index, addressTempRegister); + lshift32(TrustedImm32(address.scale), addressTempRegister); + add32(address.base, addressTempRegister); + loadDouble(Address(addressTempRegister, address.offset), dest); } void loadFloat(BaseIndex address, FPRegisterID dest) { - UNUSED_PARAM(address); - UNUSED_PARAM(dest); - unreachableForPlatform(); + move(address.index, addressTempRegister); + lshift32(TrustedImm32(address.scale), addressTempRegister); + add32(address.base, addressTempRegister); + loadFloat(Address(addressTempRegister, address.offset), dest); } void moveDouble(FPRegisterID src, FPRegisterID dest) @@ -805,6 +828,21 @@ public: m_assembler.vstr(src, base, offset); } + void storeFloat(FPRegisterID src, ImplicitAddress address) + { + RegisterID base = address.base; + int32_t offset = address.offset; + + // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2. + if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) { + add32(TrustedImm32(offset), base, addressTempRegister); + base = addressTempRegister; + offset = 0; + } + + m_assembler.fsts(ARMRegisters::asSingle(src), base, offset); + } + void storeDouble(FPRegisterID src, const void* address) { move(TrustedImmPtr(address), addressTempRegister); @@ -814,7 +852,7 @@ public: void storeDouble(FPRegisterID src, BaseIndex address) { move(address.index, addressTempRegister); - mul32(TrustedImm32(1 << address.scale), addressTempRegister, addressTempRegister); + lshift32(TrustedImm32(address.scale), addressTempRegister); add32(address.base, addressTempRegister); storeDouble(src, Address(addressTempRegister, address.offset)); } @@ -822,11 +860,11 @@ public: void storeFloat(FPRegisterID src, BaseIndex address) { move(address.index, addressTempRegister); - mul32(TrustedImm32(1 << address.scale), addressTempRegister, addressTempRegister); + lshift32(TrustedImm32(address.scale), addressTempRegister); add32(address.base, addressTempRegister); - storeDouble(src, Address(addressTempRegister, address.offset)); + storeFloat(src, Address(addressTempRegister, address.offset)); } - + void addDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.vadd(dest, dest, src); @@ -908,7 +946,7 @@ public: void convertInt32ToDouble(RegisterID src, FPRegisterID dest) { - m_assembler.vmov(fpTempRegisterAsSingle(), src); + m_assembler.vmov(fpTempRegister, src, src); m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle()); } @@ -916,7 +954,7 @@ public: { // Fixme: load directly into the fpr! load32(address, dataTempRegister); - m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister); + m_assembler.vmov(fpTempRegister, dataTempRegister, dataTempRegister); m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle()); } @@ -924,22 +962,18 @@ public: { // Fixme: load directly into the fpr! load32(address.m_ptr, dataTempRegister); - m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister); + m_assembler.vmov(fpTempRegister, dataTempRegister, dataTempRegister); m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle()); } void convertFloatToDouble(FPRegisterID src, FPRegisterID dst) { - UNUSED_PARAM(src); - UNUSED_PARAM(dst); - unreachableForPlatform(); + m_assembler.vcvtds(dst, ARMRegisters::asSingle(src)); } void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst) { - UNUSED_PARAM(src); - UNUSED_PARAM(dst); - unreachableForPlatform(); + m_assembler.vcvtsd(ARMRegisters::asSingle(dst), src); } Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) @@ -995,8 +1029,17 @@ public: { m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src); m_assembler.vmov(dest, fpTempRegisterAsSingle()); + + Jump overflow = branch32(Equal, dest, TrustedImm32(0x7fffffff)); + Jump success = branch32(GreaterThanOrEqual, dest, TrustedImm32(0)); + overflow.link(this); - return branch32(branchType ? GreaterThanOrEqual : LessThan, dest, TrustedImm32(0)); + if (branchType == BranchIfTruncateSuccessful) + return success; + + Jump failure = jump(); + success.link(this); + return failure; } // Result is undefined if the value is outside of the integer range. @@ -1092,20 +1135,16 @@ public: { uint32_t value = imm.m_value; - if (imm.m_isPointer) - moveFixedWidthEncoding(imm, dest); - else { - ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(value); + ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(value); - if (armImm.isValid()) - m_assembler.mov(dest, armImm); - else if ((armImm = ARMThumbImmediate::makeEncodedImm(~value)).isValid()) - m_assembler.mvn(dest, armImm); - else { - m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(value)); - if (value & 0xffff0000) - m_assembler.movt(dest, ARMThumbImmediate::makeUInt16(value >> 16)); - } + if (armImm.isValid()) + m_assembler.mov(dest, armImm); + else if ((armImm = ARMThumbImmediate::makeEncodedImm(~value)).isValid()) + m_assembler.mvn(dest, armImm); + else { + m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(value)); + if (value & 0xffff0000) + m_assembler.movt(dest, ARMThumbImmediate::makeUInt16(value >> 16)); } } @@ -1527,6 +1566,12 @@ public: compare32(cond, dataTempRegister, right, dest); } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + load8(left, addressTempRegister); + compare32(cond, addressTempRegister, right, dest); + } + void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { compare32(left, right); @@ -1582,6 +1627,22 @@ public: return branch32(cond, addressTempRegister, dataTempRegister); } + PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) + { + m_makeJumpPatchable = true; + Jump result = branchPtrWithPatch(cond, left, dataLabel, initialRightValue); + m_makeJumpPatchable = false; + return PatchableJump(result); + } + + PatchableJump patchableJump() + { + m_makeJumpPatchable = true; + Jump result = jump(); + m_makeJumpPatchable = false; + return PatchableJump(result); + } + ALWAYS_INLINE DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) { DataLabelPtr label = moveWithPatch(initialValue, dataTempRegister); @@ -1616,18 +1677,17 @@ public: } protected: - ALWAYS_INLINE Jump jump() { moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); - return Jump(m_assembler.bx(dataTempRegister), inUninterruptedSequence() ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition); + return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition); } ALWAYS_INLINE Jump makeBranch(ARMv7Assembler::Condition cond) { m_assembler.it(cond, true, true); moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); - return Jump(m_assembler.bx(dataTempRegister), inUninterruptedSequence() ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond); + return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond); } ALWAYS_INLINE Jump makeBranch(RelationalCondition cond) { return makeBranch(armV7Condition(cond)); } ALWAYS_INLINE Jump makeBranch(ResultCondition cond) { return makeBranch(armV7Condition(cond)); } @@ -1724,6 +1784,7 @@ private: ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); } + bool m_makeJumpPatchable; }; } // namespace JSC diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h index 910bc5a47..f9c3457b5 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h @@ -116,7 +116,7 @@ public: void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 + if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) { /* addiu dest, src, imm @@ -148,8 +148,7 @@ public: sw dataTemp, offset(base) */ m_assembler.lw(dataTempRegister, address.base, address.offset); - if (!imm.m_isPointer - && imm.m_value >= -32768 && imm.m_value <= 32767 + if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); @@ -228,7 +227,7 @@ public: */ move(TrustedImmPtr(address.m_ptr), addrTempRegister); m_assembler.lw(dataTempRegister, addrTempRegister, 0); - if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767 + if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); else { @@ -245,9 +244,9 @@ public: void and32(TrustedImm32 imm, RegisterID dest) { - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + if (!imm.m_value && !m_fixedWidth) move(MIPSRegisters::zero, dest); - else if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535 + else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) m_assembler.andi(dest, dest, imm.m_value); else { @@ -277,9 +276,9 @@ public: void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + if (!imm.m_value && !m_fixedWidth) move(MIPSRegisters::zero, dest); - else if (!imm.m_isPointer && imm.m_value == 1 && !m_fixedWidth) + else if (imm.m_value == 1 && !m_fixedWidth) move(src, dest); else { /* @@ -308,10 +307,10 @@ public: void or32(TrustedImm32 imm, RegisterID dest) { - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + if (!imm.m_value && !m_fixedWidth) return; - if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535 + if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) { m_assembler.ori(dest, dest, imm.m_value); return; @@ -357,7 +356,7 @@ public: void sub32(TrustedImm32 imm, RegisterID dest) { - if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) { /* addiu dest, src, imm @@ -375,7 +374,7 @@ public: void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest) { - if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) { /* addiu dest, src, imm @@ -402,8 +401,7 @@ public: sw dataTemp, offset(base) */ m_assembler.lw(dataTempRegister, address.base, address.offset); - if (!imm.m_isPointer - && imm.m_value >= -32767 && imm.m_value <= 32768 + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); @@ -426,8 +424,7 @@ public: 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 + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); @@ -458,7 +455,7 @@ public: move(TrustedImmPtr(address.m_ptr), addrTempRegister); m_assembler.lw(dataTempRegister, addrTempRegister, 0); - if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768 + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) { m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); @@ -807,7 +804,7 @@ public: { if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { - if (!imm.m_isPointer && !imm.m_value) + if (!imm.m_value) m_assembler.sw(MIPSRegisters::zero, address.base, address.offset); else { @@ -822,7 +819,7 @@ public: */ m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + if (!imm.m_value && !m_fixedWidth) m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); else { @@ -850,7 +847,7 @@ public: li addrTemp, address sw src, 0(addrTemp) */ - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) { + if (!imm.m_value && !m_fixedWidth) { move(TrustedImmPtr(address), addrTempRegister); m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0); } else { @@ -928,9 +925,9 @@ public: void move(TrustedImm32 imm, RegisterID dest) { - if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) + if (!imm.m_value && !m_fixedWidth) move(MIPSRegisters::zero, dest); - else if (imm.m_isPointer || m_fixedWidth) { + else if (m_fixedWidth) { m_assembler.lui(dest, imm.m_value >> 16); m_assembler.ori(dest, dest, imm.m_value); } else @@ -994,6 +991,15 @@ public: return branch32(cond, dataTempRegister, immTempRegister); } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + // Make sure the immediate value is unsigned 8 bits. + ASSERT(!(right.m_value & 0xFFFFFF00)); + load8(left, dataTempRegister); + move(right, immTempRegister); + compare32(cond, dataTempRegister, immTempRegister, dest); + } + Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { ASSERT(!(right.m_value & 0xFFFFFF00)); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h index 2b5c0cc44..c132ad642 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h @@ -156,6 +156,17 @@ public: releaseScratch(scr); } + void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (src != dest) { + move(imm, dest); + and32(src, dest); + return; + } + + and32(imm, dest); + } + void lshift32(RegisterID shiftamount, RegisterID dest) { if (shiftamount == SH4Registers::r0) @@ -193,6 +204,14 @@ public: releaseScratch(scr); } + void lshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) + { + if (src != dest) + move(src, dest); + + lshift32(shiftamount, dest); + } + void mul32(RegisterID src, RegisterID dest) { m_assembler.imullRegReg(src, dest); @@ -239,6 +258,29 @@ public: } } + +void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (src != dest) { + move(imm, dest); + or32(src, dest); + return; + } + + or32(imm, dest); + } + + void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (src != dest) { + move(imm, dest); + xor32(src, dest); + return; + } + + xor32(imm, dest); + } + void rshift32(RegisterID shiftamount, RegisterID dest) { if (shiftamount == SH4Registers::r0) @@ -681,8 +723,7 @@ public: load8(scr, scr1); add32(TrustedImm32(1), scr); load8(scr, dest); - move(TrustedImm32(8), scr); - m_assembler.shllRegReg(dest, scr); + m_assembler.shllImm8r(8, dest); or32(scr1, dest); releaseScratch(scr); @@ -942,6 +983,12 @@ public: void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) { RegisterID scr = claimScratch(); + RegisterID scr1 = claimScratch(); + Jump m_jump; + JumpList end; + + if (dest != SH4Registers::r0) + move(SH4Registers::r0, scr1); move(address.index, scr); lshift32(TrustedImm32(address.scale), scr); @@ -950,13 +997,44 @@ public: if (address.offset) add32(TrustedImm32(address.offset), scr); - RegisterID scr1 = claimScratch(); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 68, sizeof(uint32_t)); + move(scr, SH4Registers::r0); + m_assembler.andlImm8r(0x3, SH4Registers::r0); + m_assembler.cmpEqImmR0(0x0, SH4Registers::r0); + m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear); + if (dest != SH4Registers::r0) + move(scr1, SH4Registers::r0); + + load32(scr, dest); + end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear)); + m_assembler.nop(); + m_jump.link(this); + m_assembler.andlImm8r(0x1, SH4Registers::r0); + m_assembler.cmpEqImmR0(0x0, SH4Registers::r0); + + if (dest != SH4Registers::r0) + move(scr1, SH4Registers::r0); + + m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear); load16(scr, scr1); add32(TrustedImm32(2), scr); load16(scr, dest); - move(TrustedImm32(16), scr); - m_assembler.shllRegReg(dest, scr); + m_assembler.shllImm8r(16, dest); or32(scr1, dest); + end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear)); + m_assembler.nop(); + m_jump.link(this); + load8(scr, scr1); + add32(TrustedImm32(1), scr); + load16(scr, dest); + m_assembler.shllImm8r(8, dest); + or32(dest, scr1); + add32(TrustedImm32(2), scr); + load8(scr, dest); + m_assembler.shllImm8r(8, dest); + m_assembler.shllImm8r(16, dest); + or32(scr1, dest); + end.link(this); releaseScratch(scr); releaseScratch(scr1); @@ -999,19 +1077,22 @@ public: if (cond == DoubleNotEqual) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 8); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 4); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(right, left); releaseScratch(scr); - return branchFalse(); + Jump m_jump = branchFalse(); + end.link(this); + return m_jump; } if (cond == DoubleGreaterThan) { @@ -1036,113 +1117,135 @@ public: if (cond == DoubleEqualOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(left, right); + Jump m_jump = Jump(m_assembler.je()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchTrue(); + return m_jump; } if (cond == DoubleGreaterThanOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(right, left); + Jump m_jump = Jump(m_assembler.je()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchTrue(); + return m_jump; } if (cond == DoubleGreaterThanOrEqualOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(left, right); + Jump m_jump = Jump(m_assembler.jne()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchFalse(); + return m_jump; } if (cond == DoubleLessThanOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(left, right); + Jump m_jump = Jump(m_assembler.je()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchTrue(); + return m_jump; } if (cond == DoubleLessThanOrEqualOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(right, left); + Jump m_jump = Jump(m_assembler.jne()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchFalse(); + return m_jump; } ASSERT(cond == DoubleNotEqualOrUnordered); RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(right, left); + Jump m_jump = Jump(m_assembler.jne()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchFalse(); + return m_jump; } Jump branchTrue() { m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); Jump m_jump = Jump(m_assembler.je()); - m_assembler.loadConstantUnReusable(0x0, scratchReg3); - m_assembler.nop(); - m_assembler.nop(); + m_assembler.extraInstrForBranch(scratchReg3); return m_jump; } @@ -1150,9 +1253,7 @@ public: { m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); Jump m_jump = Jump(m_assembler.jne()); - m_assembler.loadConstantUnReusable(0x0, scratchReg3); - m_assembler.nop(); - m_assembler.nop(); + m_assembler.extraInstrForBranch(scratchReg3); return m_jump; } @@ -1207,6 +1308,14 @@ public: return jmp; } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + RegisterID addressTempRegister = claimScratch(); + load8(left, addressTempRegister); + compare32(cond, addressTempRegister, right, dest); + releaseScratch(addressTempRegister); + } + Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) { m_assembler.ftrcdrmfpul(src); @@ -1677,6 +1786,13 @@ public: return branchSub32(cond, scratchReg3, dest); } + Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) + { + if (src1 != dest) + move(src1, dest); + return branchSub32(cond, src2, dest); + } + Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -1738,6 +1854,14 @@ public: releaseScratch(scr); } + void urshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) + { + if (src != dest) + move(src, dest); + + urshift32(shiftamount, dest); + } + Call call() { return Call(m_assembler.call(), Call::Linkable); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h index 8cb442cc5..e398dcdad 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -129,6 +129,11 @@ public: { m_assembler.addl_rm(src, dest.offset, dest.base); } + + void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + m_assembler.leal_mr(imm.m_value, src, dest); + } void and32(RegisterID src, RegisterID dest) { @@ -1348,6 +1353,12 @@ public: m_assembler.ret(); } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + m_assembler.cmpb_im(right.m_value, left.offset, left.base); + set32(x86Condition(cond), dest); + } + void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest) { m_assembler.cmpl_rr(right, left); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h index a2b4311e5..41479f996 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -402,7 +402,7 @@ public: m_assembler.testq_rr(reg, mask); return Jump(m_assembler.jCC(x86Condition(cond))); } - + Jump branchTestPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { // if we are only interested in the low seven bits, this can be tested with a testb @@ -415,6 +415,23 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } + void testPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest) + { + if (mask.m_value == -1) + m_assembler.testq_rr(reg, reg); + else if ((mask.m_value & ~0x7f) == 0) + m_assembler.testb_i8r(mask.m_value, reg); + else + m_assembler.testq_i32r(mask.m_value, reg); + set32(x86Condition(cond), dest); + } + + void testPtr(ResultCondition cond, RegisterID reg, RegisterID mask, RegisterID dest) + { + m_assembler.testq_rr(reg, mask); + set32(x86Condition(cond), dest); + } + Jump branchTestPtr(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) { loadPtr(address.m_ptr, scratchRegister); diff --git a/Source/JavaScriptCore/assembler/RepatchBuffer.h b/Source/JavaScriptCore/assembler/RepatchBuffer.h index e56185fdb..a87294b1b 100644 --- a/Source/JavaScriptCore/assembler/RepatchBuffer.h +++ b/Source/JavaScriptCore/assembler/RepatchBuffer.h @@ -26,7 +26,7 @@ #ifndef RepatchBuffer_h #define RepatchBuffer_h -#if ENABLE(ASSEMBLER) +#if ENABLE(JIT) #include "CodeBlock.h" #include <MacroAssembler.h> diff --git a/Source/JavaScriptCore/assembler/SH4Assembler.h b/Source/JavaScriptCore/assembler/SH4Assembler.h index 1cf96b735..11e954cad 100644 --- a/Source/JavaScriptCore/assembler/SH4Assembler.h +++ b/Source/JavaScriptCore/assembler/SH4Assembler.h @@ -326,6 +326,10 @@ public: padForAlign32 = 0x00090009, }; + enum JumpType { JumpFar, + JumpNear + }; + SH4Assembler() { m_claimscratchReg = 0x0; @@ -1188,6 +1192,13 @@ public: return label; } + void extraInstrForBranch(RegisterID dst) + { + loadConstantUnReusable(0x0, dst); + nop(); + nop(); + } + AssemblerLabel jmp(RegisterID dst) { jmpReg(dst); @@ -1215,6 +1226,13 @@ public: return label; } + AssemblerLabel bra() + { + AssemblerLabel label = m_buffer.label(); + branch(BRA_OPCODE, 0); + return label; + } + void ret() { m_buffer.ensureSpace(maxInstructionSize + 2); @@ -1424,7 +1442,7 @@ public: // Linking & patching - void linkJump(AssemblerLabel from, AssemblerLabel to) + void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type = JumpFar) { ASSERT(to.isSet()); ASSERT(from.isSet()); @@ -1433,6 +1451,14 @@ public: uint16_t instruction = *instructionPtr; int offsetBits; + if (type == JumpNear) { + ASSERT((instruction == BT_OPCODE) || (instruction == BF_OPCODE) || (instruction == BRA_OPCODE)); + int offset = (codeSize() - from.m_offset) - 4; + *instructionPtr++ = instruction | (offset >> 1); + printInstr(*instructionPtr, from.m_offset + 2); + return; + } + if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) { /* BT label => BF 2 nop LDR reg diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index 20972cc63..7b828acab 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -1248,17 +1248,6 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& dataLog("[%4d] throw_reference_error\t %s\n", location, constantName(exec, k0, getConstant(k0)).data()); break; } - case op_jsr: { - int retAddrDst = (++it)->u.operand; - int offset = (++it)->u.operand; - dataLog("[%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; - dataLog("[%4d] sret\t\t %s\n", location, registerName(exec, retAddrSrc).data()); - break; - } case op_debug: { int debugHookID = (++it)->u.operand; int firstLine = (++it)->u.operand; @@ -1443,6 +1432,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab) , m_symbolTable(symTab) , m_speculativeSuccessCounter(0) , m_speculativeFailCounter(0) + , m_forcedOSRExitCounter(0) , m_optimizationDelayCounter(0) , m_reoptimizationRetryCounter(0) #if ENABLE(JIT) @@ -1765,7 +1755,7 @@ void CodeBlock::finalizeUnconditionally() Interpreter* interpreter = m_globalData->interpreter; // interpreter->classicEnabled() returns true if the old C++ interpreter is enabled. If that's enabled // then we're not using LLInt. - if (!interpreter->classicEnabled()) { + if (!interpreter->classicEnabled() && !!numberOfInstructions()) { for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) { Instruction* curInstruction = &instructions()[m_propertyAccessInstructions[i]]; switch (interpreter->getOpcodeID(curInstruction[0].u.opcode)) { @@ -1936,7 +1926,7 @@ void CodeBlock::stronglyVisitStrongReferences(SlotVisitor& visitor) for (size_t i = 0; i < m_functionDecls.size(); ++i) visitor.append(&m_functionDecls[i]); #if ENABLE(CLASSIC_INTERPRETER) - if (m_globalData->interpreter->classicEnabled()) { + if (m_globalData->interpreter->classicEnabled() && !!numberOfInstructions()) { for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) visitStructures(visitor, &instructions()[m_propertyAccessInstructions[i]]); for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i) diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index 469028097..778376f94 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -56,7 +56,6 @@ #include "LazyOperandValueProfile.h" #include "LineInfo.h" #include "Nodes.h" -#include "PredictionTracker.h" #include "RegExpObject.h" #include "StructureStubInfo.h" #include "UString.h" @@ -1006,12 +1005,15 @@ namespace JSC { uint32_t speculativeSuccessCounter() const { return m_speculativeSuccessCounter; } uint32_t speculativeFailCounter() const { return m_speculativeFailCounter; } + uint32_t forcedOSRExitCounter() const { return m_forcedOSRExitCounter; } uint32_t* addressOfSpeculativeSuccessCounter() { return &m_speculativeSuccessCounter; } uint32_t* addressOfSpeculativeFailCounter() { return &m_speculativeFailCounter; } + uint32_t* addressOfForcedOSRExitCounter() { return &m_forcedOSRExitCounter; } static ptrdiff_t offsetOfSpeculativeSuccessCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeSuccessCounter); } static ptrdiff_t offsetOfSpeculativeFailCounter() { return OBJECT_OFFSETOF(CodeBlock, m_speculativeFailCounter); } + static ptrdiff_t offsetOfForcedOSRExitCounter() { return OBJECT_OFFSETOF(CodeBlock, m_forcedOSRExitCounter); } #if ENABLE(JIT) // The number of failures that triggers the use of the ratio. @@ -1020,12 +1022,20 @@ namespace JSC { bool shouldReoptimizeNow() { - return Options::desiredSpeculativeSuccessFailRatio * speculativeFailCounter() >= speculativeSuccessCounter() && speculativeFailCounter() >= largeFailCountThreshold(); + return (Options::desiredSpeculativeSuccessFailRatio * + speculativeFailCounter() >= speculativeSuccessCounter() + && speculativeFailCounter() >= largeFailCountThreshold()) + || forcedOSRExitCounter() >= + Options::forcedOSRExitCountForReoptimization; } bool shouldReoptimizeFromLoopNow() { - return Options::desiredSpeculativeSuccessFailRatio * speculativeFailCounter() >= speculativeSuccessCounter() && speculativeFailCounter() >= largeFailCountThresholdForLoop(); + return (Options::desiredSpeculativeSuccessFailRatio * + speculativeFailCounter() >= speculativeSuccessCounter() + && speculativeFailCounter() >= largeFailCountThresholdForLoop()) + || forcedOSRExitCounter() >= + Options::forcedOSRExitCountForReoptimization; } #endif @@ -1228,6 +1238,7 @@ namespace JSC { int32_t m_totalJITExecutions; uint32_t m_speculativeSuccessCounter; uint32_t m_speculativeFailCounter; + uint32_t m_forcedOSRExitCounter; uint16_t m_optimizationDelayCounter; uint16_t m_reoptimizationRetryCounter; @@ -1385,13 +1396,18 @@ namespace JSC { #endif }; + inline CodeBlock* baselineCodeBlockForInlineCallFrame(InlineCallFrame* inlineCallFrame) + { + ASSERT(inlineCallFrame); + ExecutableBase* executable = inlineCallFrame->executable.get(); + ASSERT(executable->structure()->classInfo() == &FunctionExecutable::s_info); + return static_cast<FunctionExecutable*>(executable)->baselineCodeBlockFor(inlineCallFrame->isCall ? CodeForCall : CodeForConstruct); + } + inline CodeBlock* baselineCodeBlockForOriginAndBaselineCodeBlock(const CodeOrigin& codeOrigin, CodeBlock* baselineCodeBlock) { - if (codeOrigin.inlineCallFrame) { - ExecutableBase* executable = codeOrigin.inlineCallFrame->executable.get(); - ASSERT(executable->structure()->classInfo() == &FunctionExecutable::s_info); - return static_cast<FunctionExecutable*>(executable)->baselineCodeBlockFor(codeOrigin.inlineCallFrame->isCall ? CodeForCall : CodeForConstruct); - } + if (codeOrigin.inlineCallFrame) + return baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame); return baselineCodeBlock; } diff --git a/Source/JavaScriptCore/bytecode/DFGExitProfile.h b/Source/JavaScriptCore/bytecode/DFGExitProfile.h index edabfabf9..31db084f5 100644 --- a/Source/JavaScriptCore/bytecode/DFGExitProfile.h +++ b/Source/JavaScriptCore/bytecode/DFGExitProfile.h @@ -38,6 +38,7 @@ enum ExitKind { BadCache, // We exited because an inline cache was wrong. Overflow, // We exited because of overflow. NegativeZero, // We exited because we encountered negative zero. + InadequateCoverage, // We exited because we ended up in code that didn't have profiling coverage. Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME. }; @@ -54,6 +55,8 @@ inline const char* exitKindToString(ExitKind kind) return "Overflow"; case NegativeZero: return "NegativeZero"; + case InadequateCoverage: + return "InadequateCoverage"; default: return "Unknown"; } diff --git a/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp index b3fd3ef26..ea335005e 100644 --- a/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp +++ b/Source/JavaScriptCore/bytecode/ExecutionCounter.cpp @@ -28,7 +28,6 @@ #include "CodeBlock.h" #include "ExecutableAllocator.h" -#include <wtf/DataLog.h> namespace JSC { diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h index 45598f899..a564de2da 100644 --- a/Source/JavaScriptCore/bytecode/Opcode.h +++ b/Source/JavaScriptCore/bytecode/Opcode.h @@ -189,9 +189,6 @@ namespace JSC { macro(op_throw, 2) \ macro(op_throw_reference_error, 2) \ \ - macro(op_jsr, 3) \ - macro(op_sret, 2) \ - \ macro(op_debug, 4) \ macro(op_profile_will_call, 2) \ macro(op_profile_did_call, 2) \ diff --git a/Source/JavaScriptCore/dfg/DFGOperands.h b/Source/JavaScriptCore/bytecode/Operands.h index 9ce43119c..a05159f81 100644 --- a/Source/JavaScriptCore/dfg/DFGOperands.h +++ b/Source/JavaScriptCore/bytecode/Operands.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 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,17 +23,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DFGOperands_h -#define DFGOperands_h - -#include <wtf/Platform.h> - -#if ENABLE(DFG_JIT) +#ifndef Operands_h +#define Operands_h #include "CallFrame.h" +#include "JSObject.h" +#include "ScopeChain.h" #include <wtf/Vector.h> -namespace JSC { namespace DFG { +namespace JSC { // argument 0 is 'this'. inline bool operandIsArgument(int operand) { return operand < 0; } @@ -157,9 +155,7 @@ void dumpOperands(Operands<T, Traits>& operands, FILE* out) } } -} } // namespace JSC::DFG - -#endif // ENABLE(DFG_JIT) +} // namespace JSC -#endif // DFGOperands_h +#endif // Operands_h diff --git a/Source/JavaScriptCore/bytecode/PredictedType.cpp b/Source/JavaScriptCore/bytecode/PredictedType.cpp index b04ff1f57..e8a71772b 100644 --- a/Source/JavaScriptCore/bytecode/PredictedType.cpp +++ b/Source/JavaScriptCore/bytecode/PredictedType.cpp @@ -30,7 +30,6 @@ #include "PredictedType.h" #include "JSArray.h" -#include "JSByteArray.h" #include "JSFunction.h" #include "ValueProfile.h" #include <wtf/BoundsCheckedPointer.h> @@ -68,11 +67,6 @@ const char* predictionToString(PredictedType value) else isTop = false; - if (value & PredictByteArray) - ptr.strcat("Bytearray"); - else - isTop = false; - if (value & PredictInt8Array) ptr.strcat("Int8array"); else @@ -166,6 +160,49 @@ const char* predictionToString(PredictedType value) return description; } +const char* predictionToAbbreviatedString(PredictedType prediction) +{ + if (isFinalObjectPrediction(prediction)) + return "<Final>"; + if (isArrayPrediction(prediction)) + return "<Array>"; + if (isStringPrediction(prediction)) + return "<String>"; + if (isFunctionPrediction(prediction)) + return "<Function>"; + if (isInt8ArrayPrediction(prediction)) + return "<Int8array>"; + if (isInt16ArrayPrediction(prediction)) + return "<Int16array>"; + if (isInt32ArrayPrediction(prediction)) + return "<Int32array>"; + if (isUint8ArrayPrediction(prediction)) + return "<Uint8array>"; + if (isUint16ArrayPrediction(prediction)) + return "<Uint16array>"; + if (isUint32ArrayPrediction(prediction)) + return "<Uint32array>"; + if (isFloat32ArrayPrediction(prediction)) + return "<Float32array>"; + if (isFloat64ArrayPrediction(prediction)) + return "<Float64array>"; + if (isObjectPrediction(prediction)) + return "<Object>"; + if (isCellPrediction(prediction)) + return "<Cell>"; + if (isInt32Prediction(prediction)) + return "<Int32>"; + if (isDoublePrediction(prediction)) + return "<Double>"; + if (isNumberPrediction(prediction)) + return "<Number>"; + if (isBooleanPrediction(prediction)) + return "<Boolean>"; + if (isOtherPrediction(prediction)) + return "<Other>"; + return ""; +} + PredictedType predictionFromClassInfo(const ClassInfo* classInfo) { if (classInfo == &JSFinalObject::s_info) @@ -180,8 +217,6 @@ PredictedType predictionFromClassInfo(const ClassInfo* classInfo) if (classInfo->isSubClassOf(&JSFunction::s_info)) return PredictFunction; - if (classInfo->isSubClassOf(&JSByteArray::s_info)) - return PredictByteArray; if (classInfo->typedArrayStorageType != TypedArrayNone) { switch (classInfo->typedArrayStorageType) { diff --git a/Source/JavaScriptCore/bytecode/PredictedType.h b/Source/JavaScriptCore/bytecode/PredictedType.h index 0b7916610..54b308124 100644 --- a/Source/JavaScriptCore/bytecode/PredictedType.h +++ b/Source/JavaScriptCore/bytecode/PredictedType.h @@ -39,7 +39,6 @@ typedef uint32_t PredictedType; static const PredictedType PredictNone = 0x00000000; // We don't know anything yet. static const PredictedType PredictFinalObject = 0x00000001; // It's definitely a JSFinalObject. static const PredictedType PredictArray = 0x00000002; // It's definitely a JSArray. -static const PredictedType PredictByteArray = 0x00000004; // It's definitely a JSByteArray or one of its subclasses. static const PredictedType PredictFunction = 0x00000008; // It's definitely a JSFunction or one of its subclasses. static const PredictedType PredictInt8Array = 0x00000010; // It's definitely an Int8Array or one of its subclasses. static const PredictedType PredictInt16Array = 0x00000020; // It's definitely an Int16Array or one of its subclasses. @@ -50,7 +49,7 @@ static const PredictedType PredictUint16Array = 0x00000200; // It's defini static const PredictedType PredictUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses. static const PredictedType PredictFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses. static const PredictedType PredictFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses. -static const PredictedType PredictObjectOther = 0x00002000; // It's definitely an object but not JSFinalObject, JSArray, JSByteArray, or JSFunction. +static const PredictedType PredictObjectOther = 0x00002000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction. static const PredictedType PredictObjectMask = 0x00003fff; // Bitmask used for testing for any kind of object prediction. static const PredictedType PredictString = 0x00004000; // It's definitely a JSString. static const PredictedType PredictCellOther = 0x00008000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString. @@ -65,7 +64,7 @@ static const PredictedType PredictOther = 0x08000000; // It's defini static const PredictedType PredictTop = 0x0fffffff; // It can be any of the above. static const PredictedType PredictEmpty = 0x10000000; // It's definitely an empty value marker. static const PredictedType PredictEmptyOrTop = 0x1fffffff; // It can be any of the above. -static const PredictedType FixedIndexedStorageMask = PredictByteArray | PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint8ClampedArray | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array; +static const PredictedType FixedIndexedStorageMask = PredictInt8Array | PredictInt16Array | PredictInt32Array | PredictUint8Array | PredictUint8ClampedArray | PredictUint16Array | PredictUint32Array | PredictFloat32Array | PredictFloat64Array; typedef bool (*PredictionChecker)(PredictedType); @@ -109,11 +108,6 @@ inline bool isFunctionPrediction(PredictedType value) return value == PredictFunction; } -inline bool isByteArrayPrediction(PredictedType value) -{ - return value == PredictByteArray; -} - inline bool isInt8ArrayPrediction(PredictedType value) { return value == PredictInt8Array; @@ -159,25 +153,35 @@ inline bool isFloat64ArrayPrediction(PredictedType value) return value == PredictFloat64Array; } -inline bool isActionableMutableArrayPrediction(PredictedType value) +inline bool isActionableIntMutableArrayPrediction(PredictedType value) { - return isArrayPrediction(value) - || isByteArrayPrediction(value) -#if CPU(X86) || CPU(X86_64) - || isInt8ArrayPrediction(value) + return isInt8ArrayPrediction(value) || isInt16ArrayPrediction(value) -#endif || isInt32ArrayPrediction(value) || isUint8ArrayPrediction(value) || isUint8ClampedArrayPrediction(value) || isUint16ArrayPrediction(value) - || isUint32ArrayPrediction(value) -#if CPU(X86) || CPU(X86_64) - || isFloat32ArrayPrediction(value) -#endif + || isUint32ArrayPrediction(value); +} + +inline bool isActionableFloatMutableArrayPrediction(PredictedType value) +{ + return isFloat32ArrayPrediction(value) || isFloat64ArrayPrediction(value); } +inline bool isActionableTypedMutableArrayPrediction(PredictedType value) +{ + return isActionableIntMutableArrayPrediction(value) + || isActionableFloatMutableArrayPrediction(value); +} + +inline bool isActionableMutableArrayPrediction(PredictedType value) +{ + return isArrayPrediction(value) + || isActionableTypedMutableArrayPrediction(value); +} + inline bool isActionableArrayPrediction(PredictedType value) { return isStringPrediction(value) @@ -225,6 +229,7 @@ inline bool isEmptyPrediction(PredictedType value) } const char* predictionToString(PredictedType value); +const char* predictionToAbbreviatedString(PredictedType value); // Merge two predictions. Note that currently this just does left | right. It may // seem tempting to do so directly, but you would be doing so at your own peril, diff --git a/Source/JavaScriptCore/bytecode/SamplingTool.h b/Source/JavaScriptCore/bytecode/SamplingTool.h index fcb1986fd..52a6e35ad 100644 --- a/Source/JavaScriptCore/bytecode/SamplingTool.h +++ b/Source/JavaScriptCore/bytecode/SamplingTool.h @@ -124,7 +124,7 @@ namespace JSC { static void sample(); - static void dump(); + JS_EXPORT_PRIVATE static void dump(); private: const char* m_name; diff --git a/Source/JavaScriptCore/bytecode/StructureSet.h b/Source/JavaScriptCore/bytecode/StructureSet.h index 344183b45..bfc30fc3c 100644 --- a/Source/JavaScriptCore/bytecode/StructureSet.h +++ b/Source/JavaScriptCore/bytecode/StructureSet.h @@ -27,13 +27,12 @@ #define StructureSet_h #include "PredictedType.h" +#include "Structure.h" #include <stdio.h> #include <wtf/Vector.h> namespace JSC { -class Structure; - namespace DFG { class StructureAbstractValue; } @@ -107,6 +106,15 @@ public: size_t size() const { return m_structures.size(); } + bool allAreUsingInlinePropertyStorage() const + { + for (size_t i = 0; i < m_structures.size(); ++i) { + if (!m_structures[i]->isUsingInlineStorage()) + return false; + } + return true; + } + Structure* at(size_t i) const { return m_structures.at(i); } Structure* operator[](size_t i) const { return at(i); } diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp index f2657b785..f66860a45 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp @@ -92,7 +92,7 @@ bool StructureStubInfo::visitWeakReferences() } case access_get_by_id_proto_list: { PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList; - if (!polymorphicStructures->visitWeak(u.getByIdSelfList.listSize)) + if (!polymorphicStructures->visitWeak(u.getByIdProtoList.listSize)) return false; break; } diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h index 8fad5c0cc..03c64bf39 100644 --- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h +++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h @@ -122,8 +122,8 @@ namespace JSC { { accessType = access_get_by_id_self_list; - u.getByIdProtoList.structureList = structureList; - u.getByIdProtoList.listSize = listSize; + u.getByIdSelfList.structureList = structureList; + u.getByIdSelfList.listSize = listSize; } void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize) @@ -163,8 +163,8 @@ namespace JSC { void reset() { - accessType = access_unset; deref(); + accessType = access_unset; stubRoutine = MacroAssemblerCodeRef(); } @@ -186,27 +186,60 @@ namespace JSC { int8_t accessType; int8_t seen; - + #if ENABLE(DFG_JIT) CodeOrigin codeOrigin; - int8_t registersFlushed; - int8_t baseGPR; +#endif // ENABLE(DFG_JIT) + + union { + struct { + int8_t registersFlushed; + int8_t baseGPR; #if USE(JSVALUE32_64) - int8_t valueTagGPR; + int8_t valueTagGPR; #endif - int8_t valueGPR; - int8_t scratchGPR; - int16_t deltaCallToDone; - int16_t deltaCallToStructCheck; - int16_t deltaCallToSlowCase; - int16_t deltaCheckImmToCall; + int8_t valueGPR; + int8_t scratchGPR; + int16_t deltaCallToDone; + int16_t deltaCallToStructCheck; + int16_t deltaCallToSlowCase; + int16_t deltaCheckImmToCall; #if USE(JSVALUE64) - int16_t deltaCallToLoadOrStore; + int16_t deltaCallToLoadOrStore; #else - int16_t deltaCallToTagLoadOrStore; - int16_t deltaCallToPayloadLoadOrStore; + int16_t deltaCallToTagLoadOrStore; + int16_t deltaCallToPayloadLoadOrStore; #endif -#endif // ENABLE(DFG_JIT) + } dfg; + struct { + union { + struct { + int16_t structureToCompare; + int16_t structureCheck; +#if USE(JSVALUE64) + int16_t displacementLabel; +#else + int16_t displacementLabel1; + int16_t displacementLabel2; +#endif + int16_t putResult; + int16_t coldPathBegin; + } get; + struct { + int16_t structureToCompare; +#if USE(JSVALUE64) + int16_t displacementLabel; +#else + int16_t displacementLabel1; + int16_t displacementLabel2; +#endif + } put; + } u; + int16_t methodCheckProtoObj; + int16_t methodCheckProtoStructureToCompare; + int16_t methodCheckPutFunction; + } baseline; + } patch; union { struct { diff --git a/Source/JavaScriptCore/bytecode/ValueRecovery.h b/Source/JavaScriptCore/bytecode/ValueRecovery.h index 4d2134e0a..007c6d3b7 100644 --- a/Source/JavaScriptCore/bytecode/ValueRecovery.h +++ b/Source/JavaScriptCore/bytecode/ValueRecovery.h @@ -192,6 +192,8 @@ public: ValueRecoveryTechnique technique() const { return m_technique; } + bool isConstant() const { return m_technique == Constant; } + bool isInRegisters() const { switch (m_technique) { @@ -208,6 +210,20 @@ public: } } + bool isAlreadyInRegisterFile() const + { + switch (technique()) { + case AlreadyInRegisterFile: + case AlreadyInRegisterFileAsUnboxedInt32: + case AlreadyInRegisterFileAsUnboxedCell: + case AlreadyInRegisterFileAsUnboxedBoolean: + case AlreadyInRegisterFileAsUnboxedDouble: + return true; + default: + return false; + } + } + MacroAssembler::RegisterID gpr() const { ASSERT(m_technique == InGPR || m_technique == UnboxedInt32InGPR || m_technique == UnboxedBooleanInGPR || m_technique == UInt32InGPR); diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp index 4a6f4653e..a520a4c78 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * Copyright (C) 2012 Igalia, S.L. * @@ -200,10 +200,10 @@ bool BytecodeGenerator::addVar(const Identifier& ident, bool isConstant, Registe { int index = m_calleeRegisters.size(); SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); - pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry); + SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry); - if (!result.second) { - r0 = ®isterFor(result.first->second.getIndex()); + if (!result.isNewEntry) { + r0 = ®isterFor(result.iterator->second.getIndex()); return false; } @@ -215,9 +215,9 @@ int BytecodeGenerator::addGlobalVar(const Identifier& ident, bool isConstant) { int index = symbolTable().size(); SymbolTableEntry newEntry(index, isConstant ? ReadOnly : 0); - pair<SymbolTable::iterator, bool> result = symbolTable().add(ident.impl(), newEntry); - if (!result.second) - index = result.first->second.getIndex(); + SymbolTable::AddResult result = symbolTable().add(ident.impl(), newEntry); + if (!result.isNewEntry) + index = result.iterator->second.getIndex(); return index; } @@ -968,24 +968,24 @@ PassRefPtr<Label> BytecodeGenerator::emitJumpIfNotFunctionApply(RegisterID* cond unsigned BytecodeGenerator::addConstant(const Identifier& ident) { StringImpl* rep = ident.impl(); - pair<IdentifierMap::iterator, bool> result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers()); - if (result.second) // new entry + IdentifierMap::AddResult result = m_identifierMap.add(rep, m_codeBlock->numberOfIdentifiers()); + if (result.isNewEntry) m_codeBlock->addIdentifier(Identifier(m_globalData, rep)); - return result.first->second; + return result.iterator->second; } RegisterID* BytecodeGenerator::addConstantValue(JSValue v) { int index = m_nextConstantOffset; - pair<JSValueMap::iterator, bool> result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset); - if (result.second) { + JSValueMap::AddResult result = m_jsValueMap.add(JSValue::encode(v), m_nextConstantOffset); + if (result.isNewEntry) { m_constantPoolRegisters.append(FirstConstantRegisterIndex + m_nextConstantOffset); ++m_nextConstantOffset; m_codeBlock->addConstant(JSValue(v)); } else - index = result.first->second; + index = result.iterator->second; return &m_constantPoolRegisters[index]; } @@ -1132,7 +1132,7 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number) // work correctly with NaN as a key. if (isnan(number) || number == HashTraits<double>::emptyValue() || HashTraits<double>::isDeletedValue(number)) return emitLoad(dst, jsNumber(number)); - JSValue& valueInMap = m_numberMap.add(number, JSValue()).first->second; + JSValue& valueInMap = m_numberMap.add(number, JSValue()).iterator->second; if (!valueInMap) valueInMap = jsNumber(number); return emitLoad(dst, valueInMap); @@ -1140,7 +1140,7 @@ RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, double number) RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, const Identifier& identifier) { - JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second; + JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).iterator->second; if (!stringInMap) stringInMap = jsOwnedString(globalData(), identifier.ustring()); return emitLoad(dst, JSValue(stringInMap)); @@ -1185,7 +1185,7 @@ ResolveResult BytecodeGenerator::resolve(const Identifier& property) flags |= ResolveResult::DynamicFlag; break; } - JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope); + JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope); SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl()); // Found the property @@ -1242,7 +1242,7 @@ ResolveResult BytecodeGenerator::resolveConstDecl(const Identifier& property) JSObject* currentScope = iter->get(); if (!currentScope->isVariableObject()) continue; - JSVariableObject* currentVariableObject = static_cast<JSVariableObject*>(currentScope); + JSVariableObject* currentVariableObject = jsCast<JSVariableObject*>(currentScope); SymbolTableEntry entry = currentVariableObject->symbolTable().get(property.impl()); if (entry.isNull()) continue; @@ -1648,7 +1648,7 @@ unsigned BytecodeGenerator::addConstantBuffer(unsigned length) JSString* BytecodeGenerator::addStringConstant(const Identifier& identifier) { - JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).first->second; + JSString*& stringInMap = m_stringMap.add(identifier.impl(), 0).iterator->second; if (!stringInMap) { stringInMap = jsString(globalData(), identifier.ustring()); addConstantValue(stringInMap); @@ -1718,10 +1718,10 @@ RegisterID* BytecodeGenerator::emitNewFunction(RegisterID* dst, FunctionBodyNode RegisterID* BytecodeGenerator::emitLazyNewFunction(RegisterID* dst, FunctionBodyNode* function) { - std::pair<FunctionOffsetMap::iterator, bool> ptr = m_functionOffsets.add(function, 0); - if (ptr.second) - ptr.first->second = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function)); - return emitNewFunctionInternal(dst, ptr.first->second, true); + FunctionOffsetMap::AddResult ptr = m_functionOffsets.add(function, 0); + if (ptr.isNewEntry) + ptr.iterator->second = m_codeBlock->addFunctionDecl(makeFunction(m_globalData, function)); + return emitNewFunctionInternal(dst, ptr.iterator->second, true); } RegisterID* BytecodeGenerator::emitNewFunctionInternal(RegisterID* dst, unsigned index, bool doNullCheck) @@ -2004,11 +2004,19 @@ void BytecodeGenerator::emitDebugHook(DebugHookID debugHookID, int firstLine, in instructions().append(lastLine); } -void BytecodeGenerator::pushFinallyContext(Label* target, RegisterID* retAddrDst) +void BytecodeGenerator::pushFinallyContext(StatementNode* finallyBlock) { ControlFlowContext scope; scope.isFinallyBlock = true; - FinallyContext context = { target, retAddrDst }; + FinallyContext context = { + finallyBlock, + m_scopeContextStack.size(), + m_switchContextStack.size(), + m_forInContextStack.size(), + m_labelScopes.size(), + m_finallyDepth, + m_dynamicScopeDepth + }; scope.finallyContext = context; m_scopeContextStack.append(scope); m_finallyDepth++; @@ -2134,9 +2142,63 @@ PassRefPtr<Label> BytecodeGenerator::emitComplexJumpScopes(Label* target, Contro instructions().append(nextInsn->bind(begin, instructions().size())); emitLabel(nextInsn.get()); } - + + Vector<ControlFlowContext> savedScopeContextStack; + Vector<SwitchInfo> savedSwitchContextStack; + Vector<ForInContext> savedForInContextStack; + SegmentedVector<LabelScope, 8> savedLabelScopes; while (topScope > bottomScope && topScope->isFinallyBlock) { - emitJumpSubroutine(topScope->finallyContext.retAddrDst, topScope->finallyContext.finallyAddr); + // Save the current state of the world while instating the state of the world + // for the finally block. + FinallyContext finallyContext = topScope->finallyContext; + bool flipScopes = finallyContext.scopeContextStackSize != m_scopeContextStack.size(); + bool flipSwitches = finallyContext.switchContextStackSize != m_switchContextStack.size(); + bool flipForIns = finallyContext.forInContextStackSize != m_forInContextStack.size(); + bool flipLabelScopes = finallyContext.labelScopesSize != m_labelScopes.size(); + int topScopeIndex = -1; + int bottomScopeIndex = -1; + if (flipScopes) { + topScopeIndex = topScope - m_scopeContextStack.begin(); + bottomScopeIndex = bottomScope - m_scopeContextStack.begin(); + savedScopeContextStack = m_scopeContextStack; + m_scopeContextStack.shrink(finallyContext.scopeContextStackSize); + } + if (flipSwitches) { + savedSwitchContextStack = m_switchContextStack; + m_switchContextStack.shrink(finallyContext.switchContextStackSize); + } + if (flipForIns) { + savedForInContextStack = m_forInContextStack; + m_forInContextStack.shrink(finallyContext.forInContextStackSize); + } + if (flipLabelScopes) { + savedLabelScopes = m_labelScopes; + while (m_labelScopes.size() > finallyContext.labelScopesSize) + m_labelScopes.removeLast(); + } + int savedFinallyDepth = m_finallyDepth; + m_finallyDepth = finallyContext.finallyDepth; + int savedDynamicScopeDepth = m_dynamicScopeDepth; + m_dynamicScopeDepth = finallyContext.dynamicScopeDepth; + + // Emit the finally block. + emitNode(finallyContext.finallyBlock); + + // Restore the state of the world. + if (flipScopes) { + m_scopeContextStack = savedScopeContextStack; + topScope = &m_scopeContextStack[topScopeIndex]; // assert it's within bounds + bottomScope = m_scopeContextStack.begin() + bottomScopeIndex; // don't assert, since it the index might be -1. + } + if (flipSwitches) + m_switchContextStack = savedSwitchContextStack; + if (flipForIns) + m_forInContextStack = savedForInContextStack; + if (flipLabelScopes) + m_labelScopes = savedLabelScopes; + m_finallyDepth = savedFinallyDepth; + m_dynamicScopeDepth = savedDynamicScopeDepth; + --topScope; } } @@ -2216,23 +2278,6 @@ void BytecodeGenerator::emitThrowReferenceError(const UString& message) instructions().append(addConstantValue(jsString(globalData(), message))->index()); } -PassRefPtr<Label> BytecodeGenerator::emitJumpSubroutine(RegisterID* retAddrDst, Label* finally) -{ - size_t begin = instructions().size(); - - emitOpcode(op_jsr); - instructions().append(retAddrDst->index()); - instructions().append(finally->bind(begin, instructions().size())); - emitLabel(newLabel().get()); // Record the fact that the next instruction is implicitly labeled, because op_sret will return to it. - return finally; -} - -void BytecodeGenerator::emitSubroutineReturn(RegisterID* retAddrSrc) -{ - emitOpcode(op_sret); - instructions().append(retAddrSrc->index()); -} - void BytecodeGenerator::emitPushNewScope(RegisterID* dst, const Identifier& property, RegisterID* value) { ControlFlowContext context; diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h index e7fe236e5..a71bbb785 100644 --- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h +++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> * Copyright (C) 2012 Igalia, S.L. * @@ -71,8 +71,13 @@ namespace JSC { }; struct FinallyContext { - Label* finallyAddr; - RegisterID* retAddrDst; + StatementNode* finallyBlock; + unsigned scopeContextStackSize; + unsigned switchContextStackSize; + unsigned forInContextStackSize; + unsigned labelScopesSize; + int finallyDepth; + int dynamicScopeDepth; }; struct ControlFlowContext { @@ -479,9 +484,6 @@ namespace JSC { PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target); PassRefPtr<Label> emitJumpScopes(Label* target, int targetScopeDepth); - PassRefPtr<Label> emitJumpSubroutine(RegisterID* retAddrDst, Label*); - void emitSubroutineReturn(RegisterID* retAddrSrc); - RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget); RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target); @@ -504,7 +506,7 @@ namespace JSC { int scopeDepth() { return m_dynamicScopeDepth + m_finallyDepth; } bool hasFinaliser() { return m_finallyDepth != 0; } - void pushFinallyContext(Label* target, RegisterID* returnAddrDst); + void pushFinallyContext(StatementNode* finallyBlock); void popFinallyContext(); void pushOptimisedForIn(RegisterID* expectedBase, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister) diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp index bb95cafb6..e23f1e4d6 100644 --- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp +++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) -* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. +* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * Copyright (C) 2007 Eric Seidel <eric@webkit.org> @@ -256,9 +256,9 @@ RegisterID* PropertyListNode::emitBytecode(BytecodeGenerator& generator, Registe continue; GetterSetterPair pair(node, static_cast<PropertyNode*>(0)); - std::pair<GetterSetterMap::iterator, bool> result = map.add(node->name().impl(), pair); - if (!result.second) - result.first->second.second = node; + GetterSetterMap::AddResult result = map.add(node->name().impl(), pair); + if (!result.isNewEntry) + result.iterator->second.second = node; } // Iterate over the remaining properties in the list. @@ -1727,7 +1727,7 @@ RegisterID* ReturnNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d RefPtr<RegisterID> returnRegister; if (generator.scopeDepth()) { RefPtr<Label> l0 = generator.newLabel(); - if (generator.hasFinaliser() && !r0->isTemporary()) { + if (generator.hasFinaliser()) { returnRegister = generator.emitMove(generator.newTemporary(), r0); r0 = returnRegister.get(); } @@ -1957,13 +1957,8 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) generator.emitDebugHook(WillExecuteStatement, firstLine(), lastLine()); RefPtr<Label> tryStartLabel = generator.newLabel(); - RefPtr<Label> finallyStart; - RefPtr<RegisterID> finallyReturnAddr; - if (m_finallyBlock) { - finallyStart = generator.newLabel(); - finallyReturnAddr = generator.newTemporary(); - generator.pushFinallyContext(finallyStart.get(), finallyReturnAddr.get()); - } + if (m_finallyBlock) + generator.pushFinallyContext(m_finallyBlock); generator.emitLabel(tryStartLabel.get()); generator.emitNode(dst, m_tryBlock); @@ -1985,27 +1980,18 @@ RegisterID* TryNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst) if (m_finallyBlock) { generator.popFinallyContext(); - // there may be important registers live at the time we jump - // to a finally block (such as for a return or throw) so we - // ref the highest register ever used as a conservative - // approach to not clobbering anything important - RefPtr<RegisterID> highestUsedRegister = generator.highestUsedRegister(); + RefPtr<Label> finallyEndLabel = generator.newLabel(); - // Normal path: invoke the finally block, then jump over it. - generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); + // Normal path: run the finally code, and jump to the end. + generator.emitNode(dst, m_finallyBlock); generator.emitJump(finallyEndLabel.get()); // Uncaught exception path: invoke the finally block, then re-throw the exception. RefPtr<Label> here = generator.emitLabel(generator.newLabel().get()); RefPtr<RegisterID> tempExceptionRegister = generator.emitCatch(generator.newTemporary(), tryStartLabel.get(), here.get()); - generator.emitJumpSubroutine(finallyReturnAddr.get(), finallyStart.get()); - generator.emitThrow(tempExceptionRegister.get()); - - // The finally block. - generator.emitLabel(finallyStart.get()); generator.emitNode(dst, m_finallyBlock); - generator.emitSubroutineReturn(finallyReturnAddr.get()); + generator.emitThrow(tempExceptionRegister.get()); generator.emitLabel(finallyEndLabel.get()); } diff --git a/Source/JavaScriptCore/config.h b/Source/JavaScriptCore/config.h index ba65476a5..1e49c96bf 100644 --- a/Source/JavaScriptCore/config.h +++ b/Source/JavaScriptCore/config.h @@ -61,17 +61,6 @@ #endif -#if OS(UNIX) || OS(WINDOWS) -#define WTF_USE_OS_RANDOMNESS 1 -#endif - -#if (OS(FREEBSD) || OS(OPENBSD)) && !defined(__GLIBC__) -#define HAVE_PTHREAD_NP_H 1 -#endif - -/* FIXME: if all platforms have these, do they really need #defines? */ -#define HAVE_STDINT_H 1 - #define WTF_CHANGES 1 #ifdef __cplusplus diff --git a/Source/JavaScriptCore/create_hash_table b/Source/JavaScriptCore/create_hash_table index ae49ce47a..cb2809d76 100755 --- a/Source/JavaScriptCore/create_hash_table +++ b/Source/JavaScriptCore/create_hash_table @@ -290,6 +290,10 @@ sub output() { $intrinsic = "ArrayPushIntrinsic" if ($key eq "push"); $intrinsic = "ArrayPopIntrinsic" if ($key eq "pop"); } + if ($name eq "regExpPrototypeTable") { + $intrinsic = "RegExpExecIntrinsic" if ($key eq "exec"); + $intrinsic = "RegExpTestIntrinsic" if ($key eq "test"); + } print " { \"$key\", $attrs[$i], (intptr_t)" . $castStr . "($firstValue), (intptr_t)$secondValue, $intrinsic },\n"; $i++; diff --git a/Source/JavaScriptCore/debugger/Debugger.cpp b/Source/JavaScriptCore/debugger/Debugger.cpp index 13d6ad8f3..ede8a9ba2 100644 --- a/Source/JavaScriptCore/debugger/Debugger.cpp +++ b/Source/JavaScriptCore/debugger/Debugger.cpp @@ -67,7 +67,7 @@ inline void Recompiler::operator()(JSCell* cell) if (!cell->inherits(&JSFunction::s_info)) return; - JSFunction* function = asFunction(cell); + JSFunction* function = jsCast<JSFunction*>(cell); if (function->executable()->isHostFunction()) return; @@ -75,7 +75,7 @@ inline void Recompiler::operator()(JSCell* cell) // Check if the function is already in the set - if so, // we've already retranslated it, nothing to do here. - if (!m_functionExecutables.add(executable).second) + if (!m_functionExecutables.add(executable).isNewEntry) return; ExecState* exec = function->scope()->globalObject->JSGlobalObject::globalExec(); diff --git a/Source/JavaScriptCore/debugger/DebuggerActivation.cpp b/Source/JavaScriptCore/debugger/DebuggerActivation.cpp index 529a02f16..2a83f5138 100644 --- a/Source/JavaScriptCore/debugger/DebuggerActivation.cpp +++ b/Source/JavaScriptCore/debugger/DebuggerActivation.cpp @@ -44,7 +44,7 @@ void DebuggerActivation::finishCreation(JSGlobalData& globalData, JSObject* acti Base::finishCreation(globalData); ASSERT(activation); ASSERT(activation->isActivationObject()); - m_activation.set(globalData, this, static_cast<JSActivation*>(activation)); + m_activation.set(globalData, this, jsCast<JSActivation*>(activation)); } void DebuggerActivation::visitChildren(JSCell* cell, SlotVisitor& visitor) diff --git a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp index 6a8cdb2dc..a48e7d156 100644 --- a/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp +++ b/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp @@ -47,7 +47,7 @@ const UString* DebuggerCallFrame::functionName() const JSObject* function = m_callFrame->callee(); if (!function || !function->inherits(&JSFunction::s_info)) return 0; - return &asFunction(function)->name(m_callFrame); + return &jsCast<JSFunction*>(function)->name(m_callFrame); } UString DebuggerCallFrame::calculatedFunctionName() const diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp index 7ab05f329..6df40ca6f 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.cpp @@ -100,7 +100,7 @@ void AbstractState::initialize(Graph& graph) root->cfaShouldRevisit = true; for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) { Node& node = graph[root->variablesAtHead.argument(i)]; - ASSERT(node.op == SetArgument); + ASSERT(node.op() == SetArgument); if (!node.shouldGenerate()) { // The argument is dead. We don't do any checks for such arguments, and so // for the purpose of the analysis, they contain no value. @@ -118,8 +118,6 @@ void AbstractState::initialize(Graph& graph) root->valuesAtHead.argument(i).set(PredictInt32); else if (isArrayPrediction(prediction)) root->valuesAtHead.argument(i).set(PredictArray); - else if (isByteArrayPrediction(prediction)) - root->valuesAtHead.argument(i).set(PredictByteArray); else if (isBooleanPrediction(prediction)) root->valuesAtHead.argument(i).set(PredictBoolean); else if (isInt8ArrayPrediction(prediction)) @@ -222,7 +220,7 @@ bool AbstractState::execute(unsigned indexInBlock) if (!node.shouldGenerate()) return true; - switch (node.op) { + switch (node.op()) { case JSConstant: case WeakJSConstant: { JSValue value = m_graph.valueOfJSConstant(nodeIndex); @@ -253,13 +251,11 @@ bool AbstractState::execute(unsigned indexInBlock) break; } - PredictedType predictedType = node.variableAccessData()->prediction(); + PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction(); if (isInt32Prediction(predictedType)) forNode(node.child1()).filter(PredictInt32); else if (isArrayPrediction(predictedType)) forNode(node.child1()).filter(PredictArray); - else if (isByteArrayPrediction(predictedType)) - forNode(node.child1()).filter(PredictByteArray); else if (isBooleanPrediction(predictedType)) forNode(node.child1()).filter(PredictBoolean); @@ -290,15 +286,30 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(nodeIndex).set(PredictInt32); break; + case DoubleAsInt32: + forNode(node.child1()).filter(PredictNumber); + forNode(nodeIndex).set(PredictInt32); + break; + case ValueToInt32: - if (m_graph[node.child1()].shouldNotSpeculateInteger()) { - if (m_graph[node.child1()].shouldSpeculateDouble()) - forNode(node.child1()).filter(PredictNumber); - } else + if (m_graph[node.child1()].shouldSpeculateInteger()) forNode(node.child1()).filter(PredictInt32); + else if (m_graph[node.child1()].shouldSpeculateNumber()) + forNode(node.child1()).filter(PredictNumber); + else if (m_graph[node.child1()].shouldSpeculateBoolean()) + forNode(node.child1()).filter(PredictBoolean); forNode(nodeIndex).set(PredictInt32); break; + + case Int32ToDouble: + forNode(node.child1()).filter(PredictNumber); + forNode(nodeIndex).set(PredictDouble); + break; + + case CheckNumber: + forNode(node.child1()).filter(PredictNumber); + break; case ValueAdd: case ArithAdd: { @@ -314,7 +325,7 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(nodeIndex).set(PredictDouble); break; } - if (node.op == ValueAdd) { + if (node.op() == ValueAdd) { clobberStructures(indexInBlock); forNode(nodeIndex).set(PredictString | PredictInt32 | PredictNumber); break; @@ -351,7 +362,8 @@ bool AbstractState::execute(unsigned indexInBlock) case ArithMul: case ArithDiv: case ArithMin: - case ArithMax: { + case ArithMax: + case ArithMod: { if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) && node.canSpeculateInteger()) { forNode(node.child1()).filter(PredictInt32); forNode(node.child2()).filter(PredictInt32); @@ -364,19 +376,6 @@ bool AbstractState::execute(unsigned indexInBlock) break; } - case ArithMod: { - if (m_graph[node.child1()].shouldNotSpeculateInteger() || m_graph[node.child2()].shouldNotSpeculateInteger() || !node.canSpeculateInteger()) { - forNode(node.child1()).filter(PredictNumber); - forNode(node.child2()).filter(PredictNumber); - forNode(nodeIndex).set(PredictDouble); - break; - } - forNode(node.child1()).filter(PredictInt32); - forNode(node.child2()).filter(PredictInt32); - forNode(nodeIndex).set(PredictInt32); - break; - } - case ArithAbs: if (m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger()) { forNode(node.child1()).filter(PredictInt32); @@ -394,7 +393,7 @@ bool AbstractState::execute(unsigned indexInBlock) case LogicalNot: { Node& child = m_graph[node.child1()]; - if (isBooleanPrediction(child.prediction()) || !child.prediction()) + if (isBooleanPrediction(child.prediction())) forNode(node.child1()).filter(PredictBoolean); else if (child.shouldSpeculateFinalObjectOrOther()) forNode(node.child1()).filter(PredictFinalObject | PredictOther); @@ -409,12 +408,24 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(nodeIndex).set(PredictBoolean); break; } + + case IsUndefined: + case IsBoolean: + case IsNumber: + case IsString: + case IsObject: + case IsFunction: { + forNode(nodeIndex).set(PredictBoolean); + break; + } case CompareLess: case CompareLessEq: case CompareGreater: case CompareGreaterEq: case CompareEq: { + forNode(nodeIndex).set(PredictBoolean); + Node& left = m_graph[node.child1()]; Node& right = m_graph[node.child2()]; PredictedType filter; @@ -422,17 +433,45 @@ bool AbstractState::execute(unsigned indexInBlock) filter = PredictInt32; else if (Node::shouldSpeculateNumber(left, right)) filter = PredictNumber; - else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(left, right)) - filter = PredictFinalObject; - else if (node.op == CompareEq && Node::shouldSpeculateArray(left, right)) - filter = PredictArray; - else { + else if (node.op() == CompareEq) { + if ((m_graph.isConstant(node.child1().index()) + && m_graph.valueOfJSConstant(node.child1().index()).isNull()) + || (m_graph.isConstant(node.child2().index()) + && m_graph.valueOfJSConstant(node.child2().index()).isNull())) { + // We know that this won't clobber the world. But that's all we know. + break; + } + + if (Node::shouldSpeculateFinalObject(left, right)) + filter = PredictFinalObject; + else if (Node::shouldSpeculateArray(left, right)) + filter = PredictArray; + else if (left.shouldSpeculateFinalObject() && right.shouldSpeculateFinalObjectOrOther()) { + forNode(node.child1()).filter(PredictFinalObject); + forNode(node.child2()).filter(PredictFinalObject | PredictOther); + break; + } else if (right.shouldSpeculateFinalObject() && left.shouldSpeculateFinalObjectOrOther()) { + forNode(node.child1()).filter(PredictFinalObject | PredictOther); + forNode(node.child2()).filter(PredictFinalObject); + break; + } else if (left.shouldSpeculateArray() && right.shouldSpeculateArrayOrOther()) { + forNode(node.child1()).filter(PredictFinalObject); + forNode(node.child2()).filter(PredictFinalObject | PredictOther); + break; + } else if (right.shouldSpeculateArray() && left.shouldSpeculateArrayOrOther()) { + forNode(node.child1()).filter(PredictFinalObject | PredictOther); + forNode(node.child2()).filter(PredictFinalObject); + break; + } else { + filter = PredictTop; + clobberStructures(indexInBlock); + } + } else { filter = PredictTop; clobberStructures(indexInBlock); } forNode(node.child1()).filter(filter); forNode(node.child2()).filter(filter); - forNode(nodeIndex).set(PredictBoolean); break; } @@ -468,12 +507,6 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(nodeIndex).set(PredictString); break; } - if (m_graph[node.child1()].shouldSpeculateByteArray()) { - forNode(node.child1()).filter(PredictByteArray); - forNode(node.child2()).filter(PredictInt32); - forNode(nodeIndex).set(PredictInt32); - break; - } if (m_graph[node.child1()].shouldSpeculateInt8Array()) { forNode(node.child1()).filter(PredictInt8Array); @@ -514,7 +547,10 @@ bool AbstractState::execute(unsigned indexInBlock) if (m_graph[node.child1()].shouldSpeculateUint32Array()) { forNode(node.child1()).filter(PredictUint32Array); forNode(node.child2()).filter(PredictInt32); - forNode(nodeIndex).set(PredictDouble); + if (node.shouldSpeculateInteger()) + forNode(nodeIndex).set(PredictInt32); + else + forNode(nodeIndex).set(PredictDouble); break; } if (m_graph[node.child1()].shouldSpeculateFloat32Array()) { @@ -543,58 +579,73 @@ bool AbstractState::execute(unsigned indexInBlock) break; } if (!m_graph[node.child2()].shouldSpeculateInteger() || !isActionableMutableArrayPrediction(m_graph[node.child1()].prediction())) { - ASSERT(node.op == PutByVal); + ASSERT(node.op() == PutByVal); clobberStructures(indexInBlock); forNode(nodeIndex).makeTop(); break; } - if (m_graph[node.child1()].shouldSpeculateByteArray()) { - forNode(node.child1()).filter(PredictByteArray); - forNode(node.child2()).filter(PredictInt32); - forNode(node.child3()).filter(PredictNumber); - break; - } if (m_graph[node.child1()].shouldSpeculateInt8Array()) { forNode(node.child1()).filter(PredictInt8Array); forNode(node.child2()).filter(PredictInt32); - forNode(node.child3()).filter(PredictNumber); + if (m_graph[node.child3()].shouldSpeculateInteger()) + forNode(node.child3()).filter(PredictInt32); + else + forNode(node.child3()).filter(PredictNumber); break; } if (m_graph[node.child1()].shouldSpeculateInt16Array()) { forNode(node.child1()).filter(PredictInt16Array); forNode(node.child2()).filter(PredictInt32); - forNode(node.child3()).filter(PredictNumber); + if (m_graph[node.child3()].shouldSpeculateInteger()) + forNode(node.child3()).filter(PredictInt32); + else + forNode(node.child3()).filter(PredictNumber); break; } if (m_graph[node.child1()].shouldSpeculateInt32Array()) { forNode(node.child1()).filter(PredictInt32Array); forNode(node.child2()).filter(PredictInt32); - forNode(node.child3()).filter(PredictNumber); + if (m_graph[node.child3()].shouldSpeculateInteger()) + forNode(node.child3()).filter(PredictInt32); + else + forNode(node.child3()).filter(PredictNumber); break; } if (m_graph[node.child1()].shouldSpeculateUint8Array()) { forNode(node.child1()).filter(PredictUint8Array); forNode(node.child2()).filter(PredictInt32); - forNode(node.child3()).filter(PredictNumber); + if (m_graph[node.child3()].shouldSpeculateInteger()) + forNode(node.child3()).filter(PredictInt32); + else + forNode(node.child3()).filter(PredictNumber); break; } if (m_graph[node.child1()].shouldSpeculateUint8ClampedArray()) { forNode(node.child1()).filter(PredictUint8ClampedArray); forNode(node.child2()).filter(PredictInt32); - forNode(node.child3()).filter(PredictNumber); + if (m_graph[node.child3()].shouldSpeculateInteger()) + forNode(node.child3()).filter(PredictInt32); + else + forNode(node.child3()).filter(PredictNumber); break; } if (m_graph[node.child1()].shouldSpeculateUint16Array()) { forNode(node.child1()).filter(PredictUint16Array); forNode(node.child2()).filter(PredictInt32); - forNode(node.child3()).filter(PredictNumber); + if (m_graph[node.child3()].shouldSpeculateInteger()) + forNode(node.child3()).filter(PredictInt32); + else + forNode(node.child3()).filter(PredictNumber); break; } if (m_graph[node.child1()].shouldSpeculateUint32Array()) { forNode(node.child1()).filter(PredictUint32Array); forNode(node.child2()).filter(PredictInt32); - forNode(node.child3()).filter(PredictNumber); + if (m_graph[node.child3()].shouldSpeculateInteger()) + forNode(node.child3()).filter(PredictInt32); + else + forNode(node.child3()).filter(PredictNumber); break; } if (m_graph[node.child1()].shouldSpeculateFloat32Array()) { @@ -625,6 +676,13 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(nodeIndex).makeTop(); break; + case RegExpExec: + case RegExpTest: + forNode(node.child1()).filter(PredictCell); + forNode(node.child2()).filter(PredictCell); + forNode(nodeIndex).makeTop(); + break; + case Jump: break; @@ -633,7 +691,7 @@ bool AbstractState::execute(unsigned indexInBlock) // propagation, and to take it one step further, where a variable's value // is specialized on each direction of a branch. For now, we don't do this. Node& child = m_graph[node.child1()]; - if (isBooleanPrediction(child.prediction()) || !child.prediction()) + if (child.shouldSpeculateBoolean()) forNode(node.child1()).filter(PredictBoolean); else if (child.shouldSpeculateFinalObjectOrOther()) forNode(node.child1()).filter(PredictFinalObject | PredictOther); @@ -787,10 +845,6 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(nodeIndex).set(PredictInt32); break; - case GetByteArrayLength: - forNode(node.child1()).filter(PredictByteArray); - forNode(nodeIndex).set(PredictInt32); - break; case GetInt8ArrayLength: forNode(node.child1()).filter(PredictInt8Array); forNode(nodeIndex).set(PredictInt32); @@ -854,11 +908,6 @@ bool AbstractState::execute(unsigned indexInBlock) forNode(nodeIndex).clear(); break; } - if (m_graph[node.child1()].shouldSpeculateByteArray()) { - forNode(node.child1()).filter(PredictByteArray); - forNode(nodeIndex).clear(); - break; - } if (m_graph[node.child1()].shouldSpeculateInt8Array()) { forNode(node.child1()).filter(PredictInt8Array); @@ -974,6 +1023,10 @@ bool AbstractState::execute(unsigned indexInBlock) case InlineStart: case Nop: break; + + case LastNodeType: + ASSERT_NOT_REACHED(); + break; } return m_isValid; @@ -1005,10 +1058,10 @@ inline bool AbstractState::mergeStateAtTail(AbstractValue& destination, Abstract return false; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" It's live, node @%u.\n", nodeIndex); + dataLog(" It's live, node @%u.\n", nodeIndex); #endif - - switch (node.op) { + + switch (node.op()) { case Phi: case SetArgument: case Flush: @@ -1110,7 +1163,7 @@ inline bool AbstractState::mergeToSuccessors(Graph& graph, BasicBlock* basicBloc ASSERT(terminal.isTerminal()); - switch (terminal.op) { + switch (terminal.op()) { case Jump: return merge(basicBlock, graph.m_blocks[terminal.takenBlockIndex()].get()); diff --git a/Source/JavaScriptCore/dfg/DFGAbstractState.h b/Source/JavaScriptCore/dfg/DFGAbstractState.h index d9d5cc0f8..3325e0703 100644 --- a/Source/JavaScriptCore/dfg/DFGAbstractState.h +++ b/Source/JavaScriptCore/dfg/DFGAbstractState.h @@ -101,7 +101,7 @@ public: return m_nodes[nodeIndex]; } - AbstractValue& forNode(NodeUse nodeUse) + AbstractValue& forNode(Edge nodeUse) { return forNode(nodeUse.index()); } diff --git a/Source/JavaScriptCore/dfg/DFGNodeReferenceBlob.h b/Source/JavaScriptCore/dfg/DFGAdjacencyList.h index df3ff5f5f..e2b096bf4 100644 --- a/Source/JavaScriptCore/dfg/DFGNodeReferenceBlob.h +++ b/Source/JavaScriptCore/dfg/DFGAdjacencyList.h @@ -23,26 +23,26 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DFGNodeReferenceBlob_h -#define DFGNodeReferenceBlob_h +#ifndef DFGAdjacencyList_h +#define DFGAdjacencyList_h #include <wtf/Platform.h> #if ENABLE(DFG_JIT) #include "DFGCommon.h" -#include "DFGNodeUse.h" +#include "DFGEdge.h" namespace JSC { namespace DFG { -class NodeReferenceBlob { +class AdjacencyList { public: enum Kind { Fixed, Variable }; - NodeReferenceBlob(Kind kind) + AdjacencyList(Kind kind) #if !ASSERT_DISABLED : m_kind(kind) #endif @@ -53,7 +53,7 @@ public: } } - NodeReferenceBlob(Kind kind, NodeIndex child1, NodeIndex child2, NodeIndex child3) + AdjacencyList(Kind kind, NodeIndex child1, NodeIndex child2, NodeIndex child3) #if !ASSERT_DISABLED : m_kind(Fixed) #endif @@ -62,7 +62,7 @@ public: initialize(child1, child2, child3); } - NodeReferenceBlob(Kind kind, unsigned firstChild, unsigned numChildren) + AdjacencyList(Kind kind, unsigned firstChild, unsigned numChildren) #if !ASSERT_DISABLED : m_kind(Variable) #endif @@ -72,42 +72,42 @@ public: setNumChildren(numChildren); } - const NodeUse& child(unsigned i) const + const Edge& child(unsigned i) const { ASSERT(i < 3); ASSERT(m_kind == Fixed); return m_words[i]; } - NodeUse& child(unsigned i) + Edge& child(unsigned i) { ASSERT(i < 3); ASSERT(m_kind == Fixed); return m_words[i]; } - void setChild(unsigned i, NodeUse nodeUse) + void setChild(unsigned i, Edge nodeUse) { ASSERT(i < 30); ASSERT(m_kind == Fixed); m_words[i] = nodeUse; } - NodeUse child1() const { return child(0); } - NodeUse child2() const { return child(1); } - NodeUse child3() const { return child(2); } + Edge child1() const { return child(0); } + Edge child2() const { return child(1); } + Edge child3() const { return child(2); } - NodeUse& child1() { return child(0); } - NodeUse& child2() { return child(1); } - NodeUse& child3() { return child(2); } + Edge& child1() { return child(0); } + Edge& child2() { return child(1); } + Edge& child3() { return child(2); } - void setChild1(NodeUse nodeUse) { setChild(0, nodeUse); } - void setChild2(NodeUse nodeUse) { setChild(1, nodeUse); } - void setChild3(NodeUse nodeUse) { setChild(2, nodeUse); } + void setChild1(Edge nodeUse) { setChild(0, nodeUse); } + void setChild2(Edge nodeUse) { setChild(1, nodeUse); } + void setChild3(Edge nodeUse) { setChild(2, nodeUse); } - NodeUse child1Unchecked() const { return m_words[0]; } + Edge child1Unchecked() const { return m_words[0]; } - void initialize(NodeUse child1, NodeUse child2, NodeUse child3) + void initialize(Edge child1, Edge child2, Edge child3) { child(0) = child1; child(1) = child2; @@ -116,7 +116,7 @@ public: void initialize(NodeIndex child1, NodeIndex child2, NodeIndex child3) { - initialize(NodeUse(child1), NodeUse(child2), NodeUse(child3)); + initialize(Edge(child1), Edge(child2), Edge(child3)); } unsigned firstChild() const @@ -142,7 +142,7 @@ public: } private: - NodeUse m_words[3]; + Edge m_words[3]; #if !ASSERT_DISABLED Kind m_kind; #endif @@ -152,4 +152,4 @@ private: #endif // ENABLE(DFG_JIT) -#endif // DFGNodeReferenceBlob_h +#endif // DFGAdjacencyList_h diff --git a/Source/JavaScriptCore/bytecode/PredictionTracker.h b/Source/JavaScriptCore/dfg/DFGArgumentPosition.h index 7551cd3f3..ed447ff91 100644 --- a/Source/JavaScriptCore/bytecode/PredictionTracker.h +++ b/Source/JavaScriptCore/dfg/DFGArgumentPosition.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2012 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,54 +23,53 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef PredictionTracker_h -#define PredictionTracker_h +#ifndef DFGArgumentPosition_h +#define DFGArgumentPosition_h +#include "DFGDoubleFormatState.h" +#include "DFGVariableAccessData.h" #include "PredictedType.h" -#include <wtf/HashMap.h> -namespace JSC { +namespace JSC { namespace DFG { -struct PredictionSlot { +class ArgumentPosition { public: - PredictionSlot() - : m_value(PredictNone) - { - } - PredictedType m_value; -}; - -class PredictionTracker { -public: - PredictionTracker() + ArgumentPosition() + : m_prediction(PredictNone) + , m_doubleFormatState(EmptyDoubleFormatState) { } - bool predictGlobalVar(unsigned varNumber, PredictedType prediction) + void addVariable(VariableAccessData* variable) { - HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVars.find(varNumber + 1); - if (iter == m_globalVars.end()) { - PredictionSlot predictionSlot; - bool result = mergePrediction(predictionSlot.m_value, prediction); - m_globalVars.add(varNumber + 1, predictionSlot); - return result; - } - return mergePrediction(iter->second.m_value, prediction); + m_variables.append(variable); } - PredictedType getGlobalVarPrediction(unsigned varNumber) + bool mergeArgumentAwareness() { - HashMap<unsigned, PredictionSlot>::iterator iter = m_globalVars.find(varNumber + 1); - if (iter == m_globalVars.end()) - return PredictNone; - return iter->second.m_value; + bool changed = false; + for (unsigned i = 0; i < m_variables.size(); ++i) { + changed |= mergePrediction(m_prediction, m_variables[i]->argumentAwarePrediction()); + changed |= mergeDoubleFormatState(m_doubleFormatState, m_variables[i]->doubleFormatState()); + } + if (!changed) + return false; + changed = false; + for (unsigned i = 0; i < m_variables.size(); ++i) { + changed |= m_variables[i]->mergeArgumentAwarePrediction(m_prediction); + changed |= m_variables[i]->mergeDoubleFormatState(m_doubleFormatState); + } + return changed; } private: - HashMap<unsigned, PredictionSlot> m_globalVars; + PredictedType m_prediction; + DoubleFormatState m_doubleFormatState; + + Vector<VariableAccessData*, 2> m_variables; }; -} // namespace JSC +} } // namespace JSC::DFG -#endif // PredictionTracker_h +#endif // DFGArgumentPosition_h diff --git a/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.cpp b/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.cpp deleted file mode 100644 index 9a49364dd..000000000 --- a/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (C) 2011 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 "DFGArithNodeFlagsInferencePhase.h" - -#if ENABLE(DFG_JIT) - -#include "DFGGraph.h" -#include "DFGPhase.h" - -namespace JSC { namespace DFG { - -class ArithNodeFlagsInferencePhase : public Phase { -public: - ArithNodeFlagsInferencePhase(Graph& graph) - : Phase(graph, "arithmetic node flags inference") - { - } - - void run() - { -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - m_count = 0; -#endif - do { - m_changed = false; - - // Up here we start with a backward pass because we suspect that to be - // more profitable. - propagateBackward(); - if (!m_changed) - break; - - m_changed = false; - propagateForward(); - } while (m_changed); - } - -private: - bool isNotNegZero(NodeIndex nodeIndex) - { - if (!m_graph.isNumberConstant(nodeIndex)) - return false; - double value = m_graph.valueOfNumberConstant(nodeIndex); - return !value && 1.0 / value < 0.0; - } - - bool isNotZero(NodeIndex nodeIndex) - { - if (!m_graph.isNumberConstant(nodeIndex)) - return false; - return !!m_graph.valueOfNumberConstant(nodeIndex); - } - - void propagate(Node& node) - { - if (!node.shouldGenerate()) - return; - - NodeType op = static_cast<NodeType>(node.op); - NodeFlags flags = node.flags; - -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" %s @%u: %s ", Graph::opName(op), m_compileIndex, arithNodeFlagsAsString(flags)); -#endif - - flags &= NodeUsedAsMask; - - bool changed = false; - - switch (op) { - case ValueToInt32: - case BitAnd: - case BitOr: - case BitXor: - case BitLShift: - case BitRShift: - case BitURShift: { - // These operations are perfectly happy with truncated integers, - // so we don't want to propagate anything. - break; - } - - case UInt32ToNumber: { - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); - break; - } - - case ArithAdd: - case ValueAdd: { - if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index())) - flags &= ~NodeNeedsNegZero; - - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); - changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); - break; - } - - case ArithSub: { - if (isNotZero(node.child1().index()) || isNotZero(node.child2().index())) - flags &= ~NodeNeedsNegZero; - - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); - changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); - break; - } - - case ArithNegate: { - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); - break; - } - - case ArithMul: - case ArithDiv: { - // As soon as a multiply happens, we can easily end up in the part - // of the double domain where the point at which you do truncation - // can change the outcome. So, ArithMul always checks for overflow - // no matter what, and always forces its inputs to check as well. - - flags |= NodeUsedAsNumber | NodeNeedsNegZero; - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); - changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); - break; - } - - case ArithMin: - case ArithMax: { - flags |= NodeUsedAsNumber; - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); - changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); - break; - } - - case ArithAbs: { - flags &= ~NodeNeedsNegZero; - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); - break; - } - - case PutByVal: { - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); - changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber); - changed |= m_graph[node.child3()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); - break; - } - - case GetByVal: { - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags | NodeUsedAsNumber | NodeNeedsNegZero); - changed |= m_graph[node.child2()].mergeArithNodeFlags(flags | NodeUsedAsNumber); - break; - } - - default: - flags |= NodeUsedAsNumber | NodeNeedsNegZero; - if (node.flags & NodeHasVarArgs) { - for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) - changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeArithNodeFlags(flags); - } else { - if (!node.child1()) - break; - changed |= m_graph[node.child1()].mergeArithNodeFlags(flags); - if (!node.child2()) - break; - changed |= m_graph[node.child2()].mergeArithNodeFlags(flags); - if (!node.child3()) - break; - changed |= m_graph[node.child3()].mergeArithNodeFlags(flags); - } - break; - } - -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog("%s\n", changed ? "CHANGED" : ""); -#endif - - m_changed |= changed; - } - - void propagateForward() - { -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog("Propagating arithmetic node flags forward [%u]\n", ++m_count); -#endif - for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) - propagate(m_graph[m_compileIndex]); - } - - void propagateBackward() - { -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog("Propagating arithmetic node flags backward [%u]\n", ++m_count); -#endif - for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;) - propagate(m_graph[m_compileIndex]); - } - - NodeIndex m_compileIndex; - bool m_changed; -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - unsigned m_count; -#endif -}; - -void performArithNodeFlagsInference(Graph& graph) -{ - runPhase<ArithNodeFlagsInferencePhase>(graph); -} - -} } // namespace JSC::DFG - -#endif // ENABLE(DFG_JIT) - diff --git a/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.h b/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.h deleted file mode 100644 index 64546e253..000000000 --- a/Source/JavaScriptCore/dfg/DFGArithNodeFlagsInferencePhase.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011 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 DFGArithNodeFlagsInferencePhase_h -#define DFGArithNodeFlagsInferencePhase_h - -#include <wtf/Platform.h> - -#if ENABLE(DFG_JIT) - -namespace JSC { namespace DFG { - -class Graph; - -// Determine which arithmetic nodes' results are only used in a context that -// truncates to integer anyway. This is great for optimizing away checks for -// overflow and negative zero. NB the way this phase integrates into the rest -// of the DFG makes it non-optional. Instead of proving that a node is only -// used in integer context, it actually does the opposite: finds nodes that -// are used in non-integer contexts. Hence failing to run this phase will make -// the compiler assume that all nodes are just used as integers! - -void performArithNodeFlagsInference(Graph&); - -} } // namespace JSC::DFG::Phase - -#endif // ENABLE(DFG_JIT) - -#endif // DFGArithNodeFlagsInferencePhase_h diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp index 969101e87..15f6d19a5 100644 --- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp +++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp @@ -38,12 +38,12 @@ Vector<BytecodeAndMachineOffset>& AssemblyHelpers::decodedCodeMapFor(CodeBlock* ASSERT(codeBlock->getJITType() == JITCode::BaselineJIT); ASSERT(codeBlock->jitCodeMap()); - std::pair<HashMap<CodeBlock*, Vector<BytecodeAndMachineOffset> >::iterator, bool> result = m_decodedCodeMaps.add(codeBlock, Vector<BytecodeAndMachineOffset>()); + HashMap<CodeBlock*, Vector<BytecodeAndMachineOffset> >::AddResult result = m_decodedCodeMaps.add(codeBlock, Vector<BytecodeAndMachineOffset>()); - if (result.second) - codeBlock->jitCodeMap()->decode(result.first->second); + if (result.isNewEntry) + codeBlock->jitCodeMap()->decode(result.iterator->second); - return result.first->second; + return result.iterator->second; } #if ENABLE(SAMPLING_FLAGS) @@ -140,6 +140,13 @@ void AssemblyHelpers::jitAssertIsCell(GPRReg gpr) checkCell.link(this); } #endif // USE(JSVALUE32_64) + +void AssemblyHelpers::jitAssertHasValidCallFrame() +{ + Jump checkCFR = branchTestPtr(Zero, GPRInfo::callFrameRegister, TrustedImm32(7)); + breakpoint(); + checkCFR.link(this); +} #endif // DFG_ENABLE(JIT_ASSERT) } } // namespace JSC::DFG diff --git a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h index 00a226d4c..e7a3132f3 100644 --- a/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h +++ b/Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h @@ -150,6 +150,23 @@ public: return branch8(Below, Address(structureReg, Structure::typeInfoTypeOffset()), TrustedImm32(ObjectType)); } + static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg) + { + if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0) + return GPRInfo::regT0; + + if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1) + return GPRInfo::regT1; + + if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2) + return GPRInfo::regT2; + + if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3) + return GPRInfo::regT3; + + return GPRInfo::regT4; + } + // Add a debug call. This call has no effect on JIT code execution state. void debugCall(V_DFGDebugOperation_EP function, void* argument) { @@ -164,14 +181,16 @@ public: #if CPU(X86_64) || CPU(ARM_THUMB2) move(TrustedImmPtr(argument), GPRInfo::argumentGPR1); move(GPRInfo::callFrameRegister, GPRInfo::argumentGPR0); + GPRReg scratch = selectScratchGPR(GPRInfo::argumentGPR0, GPRInfo::argumentGPR1); #elif CPU(X86) poke(GPRInfo::callFrameRegister, 0); poke(TrustedImmPtr(argument), 1); + GPRReg scratch = GPRInfo::regT0; #else #error "DFG JIT not supported on this platform." #endif - move(TrustedImmPtr(reinterpret_cast<void*>(function)), GPRInfo::regT0); - call(GPRInfo::regT0); + move(TrustedImmPtr(reinterpret_cast<void*>(function)), scratch); + call(scratch); for (unsigned i = 0; i < FPRInfo::numberOfRegisters; ++i) { move(TrustedImmPtr(buffer + GPRInfo::numberOfRegisters + i), GPRInfo::regT0); loadDouble(GPRInfo::regT0, FPRInfo::toRegister(i)); @@ -187,12 +206,14 @@ public: void jitAssertIsJSNumber(GPRReg); void jitAssertIsJSDouble(GPRReg); void jitAssertIsCell(GPRReg); + void jitAssertHasValidCallFrame(); #else void jitAssertIsInt32(GPRReg) { } void jitAssertIsJSInt32(GPRReg) { } void jitAssertIsJSNumber(GPRReg) { } void jitAssertIsJSDouble(GPRReg) { } void jitAssertIsCell(GPRReg) { } + void jitAssertHasValidCallFrame() { } #endif // These methods convert between doubles, and doubles boxed and JSValues. diff --git a/Source/JavaScriptCore/dfg/DFGBasicBlock.h b/Source/JavaScriptCore/dfg/DFGBasicBlock.h index 1c890b498..92df58d09 100644 --- a/Source/JavaScriptCore/dfg/DFGBasicBlock.h +++ b/Source/JavaScriptCore/dfg/DFGBasicBlock.h @@ -30,7 +30,7 @@ #include "DFGAbstractValue.h" #include "DFGNode.h" -#include "DFGOperands.h" +#include "Operands.h" #include <wtf/OwnPtr.h> #include <wtf/Vector.h> diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp index 3a3678d12..7a2d7bdee 100644 --- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp +++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp @@ -89,6 +89,8 @@ private: void emitFunctionCheck(JSFunction* expectedFunction, NodeIndex callTarget, int registerOffset, CodeSpecializationKind); // Handle inlining. Return true if it succeeded, false if we need to plant a call. bool handleInlining(bool usesResult, int callTarget, NodeIndex callTargetNodeIndex, int resultOperand, bool certainAboutExpectedFunction, JSFunction*, int registerOffset, int argumentCountIncludingThis, unsigned nextOffset, CodeSpecializationKind); + // Handle setting the result of an intrinsic. + void setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex); // Handle intrinsic functions. Return true if it succeeded, false if we need to plant a call. bool handleIntrinsic(bool usesResult, int resultOperand, Intrinsic, int registerOffset, int argumentCountIncludingThis, PredictedType prediction); // Prepare to parse a block. @@ -162,7 +164,7 @@ private: NodeIndex injectLazyOperandPrediction(NodeIndex nodeIndex) { Node& node = m_graph[nodeIndex]; - ASSERT(node.op == GetLocal); + ASSERT(node.op() == GetLocal); ASSERT(node.codeOrigin.bytecodeIndex == m_currentIndex); PredictedType prediction = m_inlineStackTop->m_lazyOperands.prediction( @@ -182,13 +184,13 @@ private: if (nodeIndex != NoNode) { Node* nodePtr = &m_graph[nodeIndex]; - if (nodePtr->op == Flush) { + if (nodePtr->op() == Flush) { // Two possibilities: either the block wants the local to be live // but has not loaded its value, or it has loaded its value, in // which case we're done. nodeIndex = nodePtr->child1().index(); Node& flushChild = m_graph[nodeIndex]; - if (flushChild.op == Phi) { + if (flushChild.op() == Phi) { VariableAccessData* variableAccessData = flushChild.variableAccessData(); nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex)); m_currentBlock->variablesAtTail.local(operand) = nodeIndex; @@ -198,7 +200,7 @@ private: } ASSERT(&m_graph[nodeIndex] == nodePtr); - ASSERT(nodePtr->op != Flush); + ASSERT(nodePtr->op() != Flush); if (m_graph.localIsCaptured(operand)) { // We wish to use the same variable access data as the previous access, @@ -206,15 +208,15 @@ private: // know, at this stage of compilation, the local has been clobbered. // Make sure we link to the Phi node, not to the GetLocal. - if (nodePtr->op == GetLocal) + if (nodePtr->op() == GetLocal) nodeIndex = nodePtr->child1().index(); return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex)); } - if (nodePtr->op == GetLocal) + if (nodePtr->op() == GetLocal) return nodeIndex; - ASSERT(nodePtr->op == SetLocal); + ASSERT(nodePtr->op() == SetLocal); return nodePtr->child1().index(); } @@ -238,7 +240,29 @@ private: VariableAccessData* variableAccessData = newVariableAccessData(operand); NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value); m_currentBlock->variablesAtTail.local(operand) = nodeIndex; - if (m_graph.localIsCaptured(operand)) + + bool shouldFlush = m_graph.localIsCaptured(operand); + + if (!shouldFlush) { + // If this is in argument position, then it should be flushed. + for (InlineStackEntry* stack = m_inlineStackTop; ; stack = stack->m_caller) { + InlineCallFrame* inlineCallFrame = stack->m_inlineCallFrame; + if (!inlineCallFrame) + break; + if (static_cast<int>(operand) >= inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize) + continue; + if (static_cast<int>(operand) == inlineCallFrame->stackOffset + CallFrame::thisArgumentOffset()) + continue; + if (operand < inlineCallFrame->stackOffset - RegisterFile::CallFrameHeaderSize - inlineCallFrame->arguments.size()) + continue; + int argument = operandToArgument(operand - inlineCallFrame->stackOffset); + stack->m_argumentPositions[argument]->addVariable(variableAccessData); + shouldFlush = true; + break; + } + } + + if (shouldFlush) addToGraph(Flush, OpInfo(variableAccessData), nodeIndex); } @@ -252,13 +276,13 @@ private: if (nodeIndex != NoNode) { Node* nodePtr = &m_graph[nodeIndex]; - if (nodePtr->op == Flush) { + if (nodePtr->op() == Flush) { // Two possibilities: either the block wants the local to be live // but has not loaded its value, or it has loaded its value, in // which case we're done. nodeIndex = nodePtr->child1().index(); Node& flushChild = m_graph[nodeIndex]; - if (flushChild.op == Phi) { + if (flushChild.op() == Phi) { VariableAccessData* variableAccessData = flushChild.variableAccessData(); nodeIndex = injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(variableAccessData), nodeIndex)); m_currentBlock->variablesAtTail.local(operand) = nodeIndex; @@ -268,9 +292,9 @@ private: } ASSERT(&m_graph[nodeIndex] == nodePtr); - ASSERT(nodePtr->op != Flush); + ASSERT(nodePtr->op() != Flush); - if (nodePtr->op == SetArgument) { + if (nodePtr->op() == SetArgument) { // We're getting an argument in the first basic block; link // the GetLocal to the SetArgument. ASSERT(nodePtr->local() == static_cast<VirtualRegister>(operand)); @@ -280,15 +304,15 @@ private: } if (m_graph.argumentIsCaptured(argument)) { - if (nodePtr->op == GetLocal) + if (nodePtr->op() == GetLocal) nodeIndex = nodePtr->child1().index(); return injectLazyOperandPrediction(addToGraph(GetLocal, OpInfo(nodePtr->variableAccessData()), nodeIndex)); } - if (nodePtr->op == GetLocal) + if (nodePtr->op() == GetLocal) return nodeIndex; - ASSERT(nodePtr->op == SetLocal); + ASSERT(nodePtr->op() == SetLocal); return nodePtr->child1().index(); } @@ -309,13 +333,17 @@ private: ASSERT(argument < m_numArguments); VariableAccessData* variableAccessData = newVariableAccessData(operand); + InlineStackEntry* stack = m_inlineStackTop; + while (stack->m_inlineCallFrame) // find the machine stack entry. + stack = stack->m_caller; + stack->m_argumentPositions[argument]->addVariable(variableAccessData); NodeIndex nodeIndex = addToGraph(SetLocal, OpInfo(variableAccessData), value); m_currentBlock->variablesAtTail.argument(argument) = nodeIndex; - if (m_graph.argumentIsCaptured(argument)) - addToGraph(Flush, OpInfo(variableAccessData), nodeIndex); + // Always flush arguments. + addToGraph(Flush, OpInfo(variableAccessData), nodeIndex); } - void flushArgument(int operand) + VariableAccessData* flushArgument(int operand) { // FIXME: This should check if the same operand had already been flushed to // some other local variable. @@ -337,16 +365,26 @@ private: if (nodeIndex != NoNode) { Node& node = m_graph[nodeIndex]; - if (node.op == Flush) + switch (node.op()) { + case Flush: nodeIndex = node.child1().index(); + break; + case GetLocal: + nodeIndex = node.child1().index(); + break; + default: + break; + } - ASSERT(m_graph[nodeIndex].op != Flush); + ASSERT(m_graph[nodeIndex].op() != Flush + && m_graph[nodeIndex].op() != GetLocal); // Emit a Flush regardless of whether we already flushed it. // This gives us guidance to see that the variable also needs to be flushed // for arguments, even if it already had to be flushed for other reasons. - addToGraph(Flush, OpInfo(node.variableAccessData()), nodeIndex); - return; + VariableAccessData* variableAccessData = node.variableAccessData(); + addToGraph(Flush, OpInfo(variableAccessData), nodeIndex); + return variableAccessData; } VariableAccessData* variableAccessData = newVariableAccessData(operand); @@ -361,6 +399,7 @@ private: m_currentBlock->variablesAtTail.local(index) = nodeIndex; m_currentBlock->variablesAtHead.setLocalFirstTime(index, nodeIndex); } + return variableAccessData; } // Get an operand, and perform a ToInt32/ToNumber conversion on it. @@ -377,11 +416,11 @@ private: if (node.hasInt32Result()) return index; - if (node.op == UInt32ToNumber) + if (node.op() == UInt32ToNumber) return node.child1().index(); // Check for numeric constants boxed as JSValues. - if (node.op == JSConstant) { + if (node.op() == JSConstant) { JSValue v = valueOfJSConstant(index); if (v.isInt32()) return getJSConstant(node.constantNumber()); @@ -427,7 +466,7 @@ private: // Convenience methods for checking nodes for constants. bool isJSConstant(NodeIndex index) { - return m_graph[index].op == JSConstant; + return m_graph[index].op() == JSConstant; } bool isInt32Constant(NodeIndex nodeIndex) { @@ -551,11 +590,11 @@ private: NodeIndex cellConstant(JSCell* cell) { - pair<HashMap<JSCell*, NodeIndex>::iterator, bool> iter = m_cellConstantNodes.add(cell, NoNode); - if (iter.second) - iter.first->second = addToGraph(WeakJSConstant, OpInfo(cell)); + HashMap<JSCell*, NodeIndex>::AddResult result = m_cellConstantNodes.add(cell, NoNode); + if (result.isNewEntry) + result.iterator->second = addToGraph(WeakJSConstant, OpInfo(cell)); - return iter.first->second; + return result.iterator->second; } CodeOrigin currentCodeOrigin() @@ -626,7 +665,7 @@ private: void addVarArgChild(NodeIndex child) { - m_graph.m_varArgChildren.append(NodeUse(child)); + m_graph.m_varArgChildren.append(Edge(child)); m_numPassedVarArgs++; } @@ -693,23 +732,27 @@ private: NodeIndex makeSafe(NodeIndex nodeIndex) { - if (!m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex) + Node& node = m_graph[nodeIndex]; + + bool likelyToTakeSlowCase; + if (!isX86() && node.op() == ArithMod) + likelyToTakeSlowCase = false; + else + likelyToTakeSlowCase = m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex); + + if (!likelyToTakeSlowCase && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow) && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)) return nodeIndex; -#if DFG_ENABLE(DEBUG_VERBOSE) - dataLog("Making %s @%u safe at bc#%u because slow-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(static_cast<NodeType>(m_graph[nodeIndex].op)), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)); -#endif - - switch (m_graph[nodeIndex].op) { + switch (m_graph[nodeIndex].op()) { case UInt32ToNumber: case ArithAdd: case ArithSub: case ArithNegate: case ValueAdd: - case ArithMod: // for ArithMode "MayOverflow" means we tried to divide by zero, or we saw double. - m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow); + case ArithMod: // for ArithMod "MayOverflow" means we tried to divide by zero, or we saw double. + m_graph[nodeIndex].mergeFlags(NodeMayOverflow); break; case ArithMul: @@ -718,13 +761,13 @@ private: #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("Making ArithMul @%u take deepest slow case.\n", nodeIndex); #endif - m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero); + m_graph[nodeIndex].mergeFlags(NodeMayOverflow | NodeMayNegZero); } else if (m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex) || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)) { #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("Making ArithMul @%u take faster slow case.\n", nodeIndex); #endif - m_graph[nodeIndex].mergeArithNodeFlags(NodeMayNegZero); + m_graph[nodeIndex].mergeFlags(NodeMayNegZero); } break; @@ -738,7 +781,7 @@ private: NodeIndex makeDivSafe(NodeIndex nodeIndex) { - ASSERT(m_graph[nodeIndex].op == ArithDiv); + ASSERT(m_graph[nodeIndex].op() == ArithDiv); // The main slow case counter for op_div in the old JIT counts only when // the operands are not numbers. We don't care about that since we already @@ -752,12 +795,12 @@ private: return nodeIndex; #if DFG_ENABLE(DEBUG_VERBOSE) - dataLog("Making %s @%u safe at bc#%u because special fast-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(static_cast<NodeType>(m_graph[nodeIndex].op)), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->specialFastCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)); + dataLog("Making %s @%u safe at bc#%u because special fast-case counter is at %u and exit profiles say %d, %d\n", Graph::opName(m_graph[nodeIndex].op()), nodeIndex, m_currentIndex, m_inlineStackTop->m_profiledBlock->specialFastCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, NegativeZero)); #endif // FIXME: It might be possible to make this more granular. The DFG certainly can // distinguish between negative zero and overflow in its exit profiles. - m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow | NodeMayNegZero); + m_graph[nodeIndex].mergeFlags(NodeMayOverflow | NodeMayNegZero); return nodeIndex; } @@ -936,6 +979,9 @@ private: // Did we have any early returns? bool m_didEarlyReturn; + // Pointers to the argument position trackers for this slice of code. + Vector<ArgumentPosition*> m_argumentPositions; + InlineStackEntry* m_caller; InlineStackEntry(ByteCodeParser*, CodeBlock*, CodeBlock* profiledBlock, BlockIndex callsiteBlockHead, VirtualRegister calleeVR, JSFunction* callee, VirtualRegister returnValueVR, VirtualRegister inlineCallFrameStart, CodeSpecializationKind); @@ -993,13 +1039,19 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn NodeIndex callTarget = get(currentInstruction[1].u.operand); enum { ConstantFunction, LinkedFunction, UnknownFunction } callType; -#if DFG_ENABLE(DEBUG_VERBOSE) - dataLog("Slow case count for call at @%zu bc#%u: %u/%u; exit profile: %d.\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_profiledBlock->executionEntryCount(), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); -#endif - CallLinkStatus callLinkStatus = CallLinkStatus::computeFor( m_inlineStackTop->m_profiledBlock, m_currentIndex); +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("For call at @%lu bc#%u: ", m_graph.size(), m_currentIndex); + if (callLinkStatus.isSet()) { + if (callLinkStatus.couldTakeSlowPath()) + dataLog("could take slow path, "); + dataLog("target = %p\n", callLinkStatus.callTarget()); + } else + dataLog("not set.\n"); +#endif + if (m_graph.isFunctionConstant(callTarget)) callType = ConstantFunction; else if (callLinkStatus.isSet() && !callLinkStatus.couldTakeSlowPath() @@ -1125,14 +1177,15 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c // FIXME: Don't flush constants! + Vector<VariableAccessData*, 8> arguments; for (int i = 1; i < argumentCountIncludingThis; ++i) - flushArgument(registerOffset + argumentToOperand(i)); + arguments.append(flushArgument(registerOffset + argumentToOperand(i))); int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - RegisterFile::CallFrameHeaderSize; // Make sure that the area used by the call frame is reserved. for (int arg = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart;) - m_preservedVars.set(m_inlineStackTop->remapOperand(arg)); + m_preservedVars.set(arg); // Make sure that we have enough locals. unsigned newNumLocals = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numCalleeRegisters; @@ -1144,6 +1197,10 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c InlineStackEntry inlineStackEntry(this, codeBlock, profiledBlock, m_graph.m_blocks.size() - 1, (VirtualRegister)m_inlineStackTop->remapOperand(callTarget), expectedFunction, (VirtualRegister)m_inlineStackTop->remapOperand(usesResult ? resultOperand : InvalidVirtualRegister), (VirtualRegister)inlineCallFrameStart, kind); + // Link up the argument variable access datas to their argument positions. + for (int i = 1; i < argumentCountIncludingThis; ++i) + inlineStackEntry.m_argumentPositions[i]->addVariable(arguments[i - 1]); + // This is where the actual inlining really happens. unsigned oldIndex = m_currentIndex; unsigned oldProfilingIndex = m_currentProfilingIndex; @@ -1222,7 +1279,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c BasicBlock* block = m_graph.m_blocks[inlineStackEntry.m_unlinkedBlocks[i].m_blockIndex].get(); ASSERT(!block->isLinked); Node& node = m_graph[block->last()]; - ASSERT(node.op == Jump); + ASSERT(node.op() == Jump); ASSERT(node.takenBlockIndex() == NoBlock); node.setTakenBlockIndex(m_graph.m_blocks.size()); inlineStackEntry.m_unlinkedBlocks[i].m_needsEarlyReturnLinking = false; @@ -1251,23 +1308,30 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c return true; } -bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis) +void ByteCodeParser::setIntrinsicResult(bool usesResult, int resultOperand, NodeIndex nodeIndex) { if (!usesResult) - return true; + return; + set(resultOperand, nodeIndex); +} +bool ByteCodeParser::handleMinMax(bool usesResult, int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis) +{ if (argumentCountIncludingThis == 1) { // Math.min() - set(resultOperand, constantNaN()); + setIntrinsicResult(usesResult, resultOperand, constantNaN()); return true; } if (argumentCountIncludingThis == 2) { // Math.min(x) - set(resultOperand, get(registerOffset + argumentToOperand(1))); + // FIXME: what we'd really like is a ValueToNumber, except we don't support that right now. Oh well. + NodeIndex result = get(registerOffset + argumentToOperand(1)); + addToGraph(CheckNumber, result); + setIntrinsicResult(usesResult, resultOperand, result); return true; } if (argumentCountIncludingThis == 3) { // Math.min(x, y) - set(resultOperand, addToGraph(op, get(registerOffset + argumentToOperand(1)), get(registerOffset + argumentToOperand(2)))); + setIntrinsicResult(usesResult, resultOperand, addToGraph(op, get(registerOffset + argumentToOperand(1)), get(registerOffset + argumentToOperand(2)))); return true; } @@ -1281,14 +1345,8 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins { switch (intrinsic) { case AbsIntrinsic: { - if (!usesResult) { - // There is no such thing as executing abs for effect, so this - // is dead code. - return true; - } - if (argumentCountIncludingThis == 1) { // Math.abs() - set(resultOperand, constantNaN()); + setIntrinsicResult(usesResult, resultOperand, constantNaN()); return true; } @@ -1297,8 +1355,8 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins NodeIndex nodeIndex = addToGraph(ArithAbs, get(registerOffset + argumentToOperand(1))); if (m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, Overflow)) - m_graph[nodeIndex].mergeArithNodeFlags(NodeMayOverflow); - set(resultOperand, nodeIndex); + m_graph[nodeIndex].mergeFlags(NodeMayOverflow); + setIntrinsicResult(usesResult, resultOperand, nodeIndex); return true; } @@ -1309,18 +1367,15 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins return handleMinMax(usesResult, resultOperand, ArithMax, registerOffset, argumentCountIncludingThis); case SqrtIntrinsic: { - if (!usesResult) - return true; - if (argumentCountIncludingThis == 1) { // Math.sqrt() - set(resultOperand, constantNaN()); + setIntrinsicResult(usesResult, resultOperand, constantNaN()); return true; } if (!MacroAssembler::supportsFloatingPointSqrt()) return false; - set(resultOperand, addToGraph(ArithSqrt, get(registerOffset + argumentToOperand(1)))); + setIntrinsicResult(usesResult, resultOperand, addToGraph(ArithSqrt, get(registerOffset + argumentToOperand(1)))); return true; } @@ -1379,6 +1434,28 @@ bool ByteCodeParser::handleIntrinsic(bool usesResult, int resultOperand, Intrins return true; } + case RegExpExecIntrinsic: { + if (argumentCountIncludingThis != 2) + return false; + + NodeIndex regExpExec = addToGraph(RegExpExec, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1))); + if (usesResult) + set(resultOperand, regExpExec); + + return true; + } + + case RegExpTestIntrinsic: { + if (argumentCountIncludingThis != 2) + return false; + + NodeIndex regExpExec = addToGraph(RegExpTest, OpInfo(0), OpInfo(prediction), get(registerOffset + argumentToOperand(0)), get(registerOffset + argumentToOperand(1))); + if (usesResult) + set(resultOperand, regExpExec); + + return true; + } + default: return false; } @@ -1449,7 +1526,7 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_convert_this: { NodeIndex op1 = getThis(); - if (m_graph[op1].op == ConvertThis) + if (m_graph[op1].op() == ConvertThis) setThis(op1); else setThis(addToGraph(ConvertThis, op1)); @@ -1678,6 +1755,42 @@ bool ByteCodeParser::parseBlock(unsigned limit) set(currentInstruction[1].u.operand, addToGraph(InstanceOf, value, baseValue, prototype)); NEXT_OPCODE(op_instanceof); } + + case op_is_undefined: { + NodeIndex value = get(currentInstruction[2].u.operand); + set(currentInstruction[1].u.operand, addToGraph(IsUndefined, value)); + NEXT_OPCODE(op_is_undefined); + } + + case op_is_boolean: { + NodeIndex value = get(currentInstruction[2].u.operand); + set(currentInstruction[1].u.operand, addToGraph(IsBoolean, value)); + NEXT_OPCODE(op_is_boolean); + } + + case op_is_number: { + NodeIndex value = get(currentInstruction[2].u.operand); + set(currentInstruction[1].u.operand, addToGraph(IsNumber, value)); + NEXT_OPCODE(op_is_number); + } + + case op_is_string: { + NodeIndex value = get(currentInstruction[2].u.operand); + set(currentInstruction[1].u.operand, addToGraph(IsString, value)); + NEXT_OPCODE(op_is_string); + } + + case op_is_object: { + NodeIndex value = get(currentInstruction[2].u.operand); + set(currentInstruction[1].u.operand, addToGraph(IsObject, value)); + NEXT_OPCODE(op_is_object); + } + + case op_is_function: { + NodeIndex value = get(currentInstruction[2].u.operand); + set(currentInstruction[1].u.operand, addToGraph(IsFunction, value)); + NEXT_OPCODE(op_is_function); + } case op_not: { NodeIndex value = get(currentInstruction[2].u.operand); @@ -1857,10 +1970,6 @@ bool ByteCodeParser::parseBlock(unsigned limit) GetByIdStatus getByIdStatus = GetByIdStatus::computeFor( m_inlineStackTop->m_profiledBlock, m_currentIndex, identifier); -#if DFG_ENABLE(DEBUG_VERBOSE) - dataLog("Slow case count for GetById @%zu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); -#endif - if (getByIdStatus.isSimpleDirect() && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) { ASSERT(getByIdStatus.structureSet().size()); @@ -1871,10 +1980,20 @@ bool ByteCodeParser::parseBlock(unsigned limit) addToGraph(ForceOSRExit); addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base); - set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base))); + NodeIndex propertyStorage; + size_t offsetOffset; + if (getByIdStatus.structureSet().allAreUsingInlinePropertyStorage()) { + propertyStorage = base; + ASSERT(!(sizeof(JSObject) % sizeof(EncodedJSValue))); + offsetOffset = sizeof(JSObject) / sizeof(EncodedJSValue); + } else { + propertyStorage = addToGraph(GetPropertyStorage, base); + offsetOffset = 0; + } + set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), propertyStorage)); StorageAccessData storageAccessData; - storageAccessData.offset = getByIdStatus.offset(); + storageAccessData.offset = getByIdStatus.offset() + offsetOffset; storageAccessData.identifierNumber = identifierNumber; m_graph.m_storageAccessData.append(storageAccessData); } else @@ -1899,10 +2018,6 @@ bool ByteCodeParser::parseBlock(unsigned limit) bool hasExitSite = m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache); -#if DFG_ENABLE(DEBUG_VERBOSE) - dataLog("Slow case count for PutById @%zu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)); -#endif - if (!hasExitSite && putByIdStatus.isSimpleReplace()) { addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base); addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value); @@ -1971,9 +2086,8 @@ bool ByteCodeParser::parseBlock(unsigned limit) case op_get_global_var: { PredictedType prediction = getPrediction(); - NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand)); + NodeIndex getGlobalVar = addToGraph(GetGlobalVar, OpInfo(currentInstruction[2].u.operand), OpInfo(prediction)); set(currentInstruction[1].u.operand, getGlobalVar); - m_graph.predictGlobalVar(currentInstruction[2].u.operand, prediction); NEXT_OPCODE(op_get_global_var); } @@ -2340,7 +2454,7 @@ void ByteCodeParser::processPhiStack() else predecessorBlock->variablesAtHead.setLocalFirstTime(varNo, valueInPredecessor); phiStack.append(PhiStackEntry(predecessorBlock, valueInPredecessor, varNo)); - } else if (m_graph[valueInPredecessor].op == GetLocal) { + } else if (m_graph[valueInPredecessor].op() == GetLocal) { #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Found GetLocal @%u.\n", valueInPredecessor); #endif @@ -2357,10 +2471,10 @@ void ByteCodeParser::processPhiStack() dataLog(" Found @%u.\n", valueInPredecessor); #endif } - ASSERT(m_graph[valueInPredecessor].op == SetLocal - || m_graph[valueInPredecessor].op == Phi - || m_graph[valueInPredecessor].op == Flush - || (m_graph[valueInPredecessor].op == SetArgument + ASSERT(m_graph[valueInPredecessor].op() == SetLocal + || m_graph[valueInPredecessor].op() == Phi + || m_graph[valueInPredecessor].op() == Flush + || (m_graph[valueInPredecessor].op() == SetArgument && stackType == ArgumentPhiStack)); VariableAccessData* dataForPredecessor = m_graph[valueInPredecessor].variableAccessData(); @@ -2382,7 +2496,7 @@ void ByteCodeParser::processPhiStack() #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Setting @%u->child1 = @%u.\n", entry.m_phi, valueInPredecessor); #endif - phiNode->children.setChild1(NodeUse(valueInPredecessor)); + phiNode->children.setChild1(Edge(valueInPredecessor)); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Children of @%u: ", entry.m_phi); phiNode->dumpChildren(WTF::dataFile()); @@ -2394,7 +2508,7 @@ void ByteCodeParser::processPhiStack() #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Setting @%u->child2 = @%u.\n", entry.m_phi, valueInPredecessor); #endif - phiNode->children.setChild2(NodeUse(valueInPredecessor)); + phiNode->children.setChild2(Edge(valueInPredecessor)); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Children of @%u: ", entry.m_phi); phiNode->dumpChildren(WTF::dataFile()); @@ -2406,7 +2520,7 @@ void ByteCodeParser::processPhiStack() #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Setting @%u->child3 = @%u.\n", entry.m_phi, valueInPredecessor); #endif - phiNode->children.setChild3(NodeUse(valueInPredecessor)); + phiNode->children.setChild3(Edge(valueInPredecessor)); #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog(" Children of @%u: ", entry.m_phi); phiNode->dumpChildren(WTF::dataFile()); @@ -2460,7 +2574,7 @@ void ByteCodeParser::linkBlock(BasicBlock* block, Vector<BlockIndex>& possibleTa Node& node = m_graph[block->last()]; ASSERT(node.isTerminal()); - switch (node.op) { + switch (node.op()) { case Jump: node.setTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(possibleTargets, node.takenBytecodeOffsetDuringParsing())); #if DFG_ENABLE(DEBUG_VERBOSE) @@ -2564,6 +2678,13 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(ByteCodeParser* byteCodeParse , m_didEarlyReturn(false) , m_caller(byteCodeParser->m_inlineStackTop) { + m_argumentPositions.resize(codeBlock->numParameters()); + for (unsigned i = codeBlock->numParameters(); i--;) { + byteCodeParser->m_graph.m_argumentPositions.append(ArgumentPosition()); + ArgumentPosition* argumentPosition = &byteCodeParser->m_graph.m_argumentPositions.last(); + m_argumentPositions[i] = argumentPosition; + } + if (m_caller) { // Inline case. ASSERT(codeBlock != byteCodeParser->m_codeBlock); @@ -2589,10 +2710,10 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(ByteCodeParser* byteCodeParse for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i) { StringImpl* rep = codeBlock->identifier(i).impl(); - pair<IdentifierMap::iterator, bool> result = byteCodeParser->m_identifierMap.add(rep, byteCodeParser->m_codeBlock->numberOfIdentifiers()); - if (result.second) + IdentifierMap::AddResult result = byteCodeParser->m_identifierMap.add(rep, byteCodeParser->m_codeBlock->numberOfIdentifiers()); + if (result.isNewEntry) byteCodeParser->m_codeBlock->addIdentifier(Identifier(byteCodeParser->m_globalData, rep)); - m_identifierRemap[i] = result.first->second; + m_identifierRemap[i] = result.iterator->second; } for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i) { JSValue value = codeBlock->getConstant(i + FirstConstantRegisterIndex); @@ -2605,12 +2726,12 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(ByteCodeParser* byteCodeParse m_constantRemap[i] = byteCodeParser->m_emptyJSValueIndex; continue; } - pair<JSValueMap::iterator, bool> result = byteCodeParser->m_jsValueMap.add(JSValue::encode(value), byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex); - if (result.second) { + JSValueMap::AddResult result = byteCodeParser->m_jsValueMap.add(JSValue::encode(value), byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex); + if (result.isNewEntry) { byteCodeParser->m_codeBlock->addConstant(value); byteCodeParser->m_constants.append(ConstantRecord()); } - m_constantRemap[i] = result.first->second; + m_constantRemap[i] = result.iterator->second; } m_callsiteBlockHeadNeedsLinking = true; diff --git a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h index 16793bb46..256608f0d 100644 --- a/Source/JavaScriptCore/dfg/DFGCCallHelpers.h +++ b/Source/JavaScriptCore/dfg/DFGCCallHelpers.h @@ -82,6 +82,12 @@ public: addCallArgument(arg2); } + ALWAYS_INLINE void setupArguments(GPRReg arg1) + { + resetCallArguments(); + addCallArgument(arg1); + } + ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2) { resetCallArguments(); @@ -386,6 +392,11 @@ public: } #endif + ALWAYS_INLINE void setupArguments(GPRReg arg1) + { + move(arg1, GPRInfo::argumentGPR0); + } + ALWAYS_INLINE void setupArguments(GPRReg arg1, GPRReg arg2) { setupTwoStubArgs<GPRInfo::argumentGPR0, GPRInfo::argumentGPR1>(arg1, arg2); diff --git a/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp index b4e75f808..6e69c1094 100644 --- a/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCFAPhase.cpp @@ -87,7 +87,7 @@ private: if (!m_graph[nodeIndex].shouldGenerate()) continue; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" %s @%u: ", Graph::opName(static_cast<NodeType>(m_graph[nodeIndex].op)), nodeIndex); + dataLog(" %s @%u: ", Graph::opName(m_graph[nodeIndex].op()), nodeIndex); m_state.dump(WTF::dataFile()); dataLog("\n"); #endif diff --git a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp index 82e1b4609..020b1cfd2 100644 --- a/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp @@ -58,19 +58,19 @@ private: if (nodeIndex == NoNode) return NoNode; - if (m_graph[nodeIndex].op == ValueToInt32) + if (m_graph[nodeIndex].op() == ValueToInt32) nodeIndex = m_graph[nodeIndex].child1().index(); return nodeIndex; } - NodeIndex canonicalize(NodeUse nodeUse) + NodeIndex canonicalize(Edge nodeUse) { return canonicalize(nodeUse.indexUnchecked()); } unsigned endIndexForPureCSE() { - unsigned result = m_lastSeen[m_graph[m_compileIndex].op]; + unsigned result = m_lastSeen[m_graph[m_compileIndex].op()]; if (result == UINT_MAX) result = 0; else @@ -94,7 +94,7 @@ private: break; Node& otherNode = m_graph[index]; - if (node.op != otherNode.op) + if (node.op() != otherNode.op()) continue; if (node.arithNodeFlags() != otherNode.arithNodeFlags()) @@ -139,7 +139,7 @@ private: bool byValIsPure(Node& node) { return m_graph[node.child2()].shouldSpeculateInteger() - && ((node.op == PutByVal || node.op == PutByValAlias) + && ((node.op() == PutByVal || node.op() == PutByValAlias) ? isActionableMutableArrayPrediction(m_graph[node.child1()].prediction()) : isActionableArrayPrediction(m_graph[node.child1()].prediction())); } @@ -147,11 +147,11 @@ private: bool clobbersWorld(NodeIndex nodeIndex) { Node& node = m_graph[nodeIndex]; - if (node.flags & NodeClobbersWorld) + if (node.flags() & NodeClobbersWorld) return true; - if (!(node.flags & NodeMightClobber)) + if (!(node.flags() & NodeMightClobber)) return false; - switch (node.op) { + switch (node.op()) { case ValueAdd: case CompareLess: case CompareLessEq: @@ -181,7 +181,7 @@ private: break; Node& otherNode = m_graph[index]; - if (node.op == otherNode.op + if (node.op() == otherNode.op() && node.arithNodeFlags() == otherNode.arithNodeFlags()) { NodeIndex otherChild = canonicalize(otherNode.child1()); if (otherChild == NoNode) @@ -210,7 +210,7 @@ private: for (unsigned i = m_indexInBlock; i--;) { NodeIndex index = m_currentBlock->at(i); Node& node = m_graph[index]; - switch (node.op) { + switch (node.op()) { case GetGlobalVar: if (node.varNumber() == varNumber && codeBlock()->globalObjectFor(node.codeOrigin) == globalObject) return index; @@ -236,7 +236,7 @@ private: break; Node& node = m_graph[index]; - switch (node.op) { + switch (node.op()) { case GetByVal: if (!byValIsPure(node)) return NoNode; @@ -280,7 +280,7 @@ private: break; Node& node = m_graph[index]; - if (node.op == CheckFunction && node.child1() == child1 && node.function() == function) + if (node.op() == CheckFunction && node.child1() == child1 && node.function() == function) return true; } return false; @@ -294,7 +294,7 @@ private: break; Node& node = m_graph[index]; - switch (node.op) { + switch (node.op()) { case CheckStructure: if (node.child1() == child1 && structureSet.isSupersetOf(node.structureSet())) @@ -340,7 +340,7 @@ private: break; Node& node = m_graph[index]; - switch (node.op) { + switch (node.op()) { case GetByOffset: if (node.child1() == child1 && m_graph.m_storageAccessData[node.storageAccessDataIndex()].identifierNumber == identifierNumber) @@ -386,7 +386,7 @@ private: break; Node& node = m_graph[index]; - switch (node.op) { + switch (node.op()) { case GetPropertyStorage: if (node.child1() == child1) return index; @@ -425,7 +425,7 @@ private: break; Node& node = m_graph[index]; - switch (node.op) { + switch (node.op()) { case GetIndexedPropertyStorage: { PredictedType basePrediction = m_graph[node.child2()].prediction(); bool nodeHasIntegerIndexPrediction = !(!(basePrediction & PredictInt32) && basePrediction); @@ -463,14 +463,14 @@ private: for (unsigned i = endIndexForPureCSE(); i--;) { NodeIndex index = m_currentBlock->at(i); Node& node = m_graph[index]; - if (node.op == GetScopeChain + if (node.op() == GetScopeChain && node.scopeChainDepth() == depth) return index; } return NoNode; } - void performSubstitution(NodeUse& child, bool addRef = true) + void performSubstitution(Edge& child, bool addRef = true) { // Check if this operand is actually unused. if (!child) @@ -529,7 +529,7 @@ private: { bool shouldGenerate = node.shouldGenerate(); - if (node.flags & NodeHasVarArgs) { + if (node.flags() & NodeHasVarArgs) { for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) performSubstitution(m_graph.m_varArgChildren[childIdx], shouldGenerate); } else { @@ -542,7 +542,7 @@ private: return; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" %s @%u: ", Graph::opName(static_cast<NodeType>(m_graph[m_compileIndex].op)), m_compileIndex); + dataLog(" %s @%u: ", Graph::opName(m_graph[m_compileIndex].op()), m_compileIndex); #endif // NOTE: there are some nodes that we deliberately don't CSE even though we @@ -554,7 +554,7 @@ private: // ToPrimitive, but we could change that with some speculations if we really // needed to. - switch (node.op) { + switch (node.op()) { // Handle the pure nodes. These nodes never have any side-effects. case BitAnd: @@ -573,7 +573,6 @@ private: case ArithMin: case ArithMax: case ArithSqrt: - case GetByteArrayLength: case GetInt8ArrayLength: case GetInt16ArrayLength: case GetInt32ArrayLength: @@ -587,6 +586,14 @@ private: case GetStringLength: case StringCharAt: case StringCharCodeAt: + case Int32ToDouble: + case IsUndefined: + case IsBoolean: + case IsNumber: + case IsString: + case IsObject: + case IsFunction: + case DoubleAsInt32: setReplacement(pureCSE(node)); break; @@ -636,7 +643,7 @@ private: case PutByVal: if (byValIsPure(node) && getByValLoadElimination(node.child1().index(), node.child2().index()) != NoNode) - node.op = PutByValAlias; + node.setOp(PutByValAlias); break; case CheckStructure: @@ -669,7 +676,7 @@ private: break; } - m_lastSeen[node.op] = m_indexInBlock; + m_lastSeen[node.op()] = m_indexInBlock; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) dataLog("\n"); #endif diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp index a8dec067f..450a5d83e 100644 --- a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp +++ b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp @@ -27,12 +27,23 @@ #include "DFGCapabilities.h" #include "CodeBlock.h" +#include "DFGCommon.h" #include "Interpreter.h" namespace JSC { namespace DFG { #if ENABLE(DFG_JIT) +static inline void debugFail(CodeBlock* codeBlock, OpcodeID opcodeID) +{ +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("Cannot handle code block %p because of opcode %s.\n", codeBlock, opcodeNames[opcodeID]); +#else + UNUSED_PARAM(codeBlock); + UNUSED_PARAM(opcodeID); +#endif +} + template<bool (*canHandleOpcode)(OpcodeID)> bool canHandleOpcodes(CodeBlock* codeBlock) { @@ -42,11 +53,13 @@ bool canHandleOpcodes(CodeBlock* codeBlock) for (unsigned bytecodeOffset = 0; bytecodeOffset < instructionCount; ) { switch (interpreter->getOpcodeID(instructionsBegin[bytecodeOffset].u.opcode)) { -#define DEFINE_OP(opcode, length) \ - case opcode: \ - if (!canHandleOpcode(opcode)) \ - return false; \ - bytecodeOffset += length; \ +#define DEFINE_OP(opcode, length) \ + case opcode: \ + if (!canHandleOpcode(opcode)) { \ + debugFail(codeBlock, opcode); \ + return false; \ + } \ + bytecodeOffset += length; \ break; FOR_EACH_OPCODE_ID(DEFINE_OP) #undef DEFINE_OP @@ -61,6 +74,8 @@ bool canHandleOpcodes(CodeBlock* codeBlock) bool canCompileOpcodes(CodeBlock* codeBlock) { + if (!MacroAssembler::supportsFloatingPoint()) + return false; return canHandleOpcodes<canCompileOpcode>(codeBlock); } diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.h b/Source/JavaScriptCore/dfg/DFGCapabilities.h index 6509dbc3d..b807979ba 100644 --- a/Source/JavaScriptCore/dfg/DFGCapabilities.h +++ b/Source/JavaScriptCore/dfg/DFGCapabilities.h @@ -96,6 +96,12 @@ inline bool canCompileOpcode(OpcodeID opcodeID) case op_mov: case op_check_has_instance: case op_instanceof: + case op_is_undefined: + case op_is_boolean: + case op_is_number: + case op_is_string: + case op_is_object: + case op_is_function: case op_not: case op_less: case op_lesseq: diff --git a/Source/JavaScriptCore/dfg/DFGCommon.h b/Source/JavaScriptCore/dfg/DFGCommon.h index 8ff1e5cdd..828bcb2a3 100644 --- a/Source/JavaScriptCore/dfg/DFGCommon.h +++ b/Source/JavaScriptCore/dfg/DFGCommon.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -97,9 +97,32 @@ struct NodeIndexTraits { enum UseKind { UntypedUse, + DoubleUse, LastUseKind // Must always be the last entry in the enum, as it is used to denote the number of enum elements. }; +inline const char* useKindToString(UseKind useKind) +{ + switch (useKind) { + case UntypedUse: + return ""; + case DoubleUse: + return "d"; + default: + ASSERT_NOT_REACHED(); + return 0; + } +} + +inline bool isX86() +{ +#if CPU(X86_64) || CPU(X86) + return true; +#else + return false; +#endif +} + } } // namespace JSC::DFG #endif // ENABLE(DFG_JIT) diff --git a/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h b/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h index 983f479c2..bfa149604 100644 --- a/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h +++ b/Source/JavaScriptCore/dfg/DFGCorrectableJumpPoint.h @@ -39,7 +39,7 @@ namespace JSC { namespace DFG { // Thus it goes through three states: // // 1) Label of unpatchable branch or jump (i.e. MacroAssembler::Jump). -// 2) Label of patchable jump (i.e. MacroAssembler::Jump). +// 2) Label of patchable jump (i.e. MacroAssembler::PatchableJump). // 3) Corrected post-linking label of patchable jump (i.e. CodeLocationJump). // // The setting of state (1) corresponds to planting the in-line unpatchable @@ -66,7 +66,7 @@ public: #endif } - void switchToLateJump(MacroAssembler::Jump check) + void switchToLateJump(MacroAssembler::PatchableJump check) { #ifndef NDEBUG ASSERT(m_mode == InitialJump); @@ -74,12 +74,12 @@ public: #endif // Late jumps should only ever be real jumps. #if CPU(ARM_THUMB2) - ASSERT(check.m_type == ARMv7Assembler::JumpNoConditionFixedSize); - ASSERT(check.m_condition == ARMv7Assembler::ConditionInvalid); + ASSERT(check.m_jump.m_type == ARMv7Assembler::JumpNoConditionFixedSize); + ASSERT(check.m_jump.m_condition == ARMv7Assembler::ConditionInvalid); m_type = ARMv7Assembler::JumpNoConditionFixedSize; m_condition = ARMv7Assembler::ConditionInvalid; #endif - m_codeOffset = check.m_label.m_offset; + m_codeOffset = check.m_jump.m_label.m_offset; } void correctInitialJump(LinkBuffer& linkBuffer) diff --git a/Source/JavaScriptCore/dfg/DFGDoubleFormatState.h b/Source/JavaScriptCore/dfg/DFGDoubleFormatState.h new file mode 100644 index 000000000..2aa0f3d4d --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGDoubleFormatState.h @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2012 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 DFGDoubleFormatState_h +#define DFGDoubleFormatState_h + +namespace JSC { namespace DFG { + +enum DoubleFormatState { + EmptyDoubleFormatState, // bottom + UsingDoubleFormat, + NotUsingDoubleFormat, + CantUseDoubleFormat // top +}; + +inline DoubleFormatState mergeDoubleFormatStates(DoubleFormatState a, DoubleFormatState b) +{ + switch (a) { + case EmptyDoubleFormatState: + return b; + case UsingDoubleFormat: + switch (b) { + case EmptyDoubleFormatState: + case UsingDoubleFormat: + return UsingDoubleFormat; + case NotUsingDoubleFormat: + case CantUseDoubleFormat: + return CantUseDoubleFormat; + } + case NotUsingDoubleFormat: + switch (b) { + case EmptyDoubleFormatState: + case NotUsingDoubleFormat: + return NotUsingDoubleFormat; + case UsingDoubleFormat: + case CantUseDoubleFormat: + return CantUseDoubleFormat; + } + case CantUseDoubleFormat: + return CantUseDoubleFormat; + } + ASSERT_NOT_REACHED(); + return CantUseDoubleFormat; +} + +inline bool mergeDoubleFormatState(DoubleFormatState& dest, DoubleFormatState src) +{ + DoubleFormatState newState = mergeDoubleFormatStates(dest, src); + if (newState == dest) + return false; + dest = newState; + return true; +} + +inline const char* doubleFormatStateToString(DoubleFormatState state) +{ + switch (state) { + case EmptyDoubleFormatState: + return "Empty"; + case UsingDoubleFormat: + return "DoubleFormat"; + case NotUsingDoubleFormat: + return "ValueFormat"; + case CantUseDoubleFormat: + return "ForceValue"; + } + ASSERT_NOT_REACHED(); + return 0; +} + +} } // namespace JSC::DFG + +#endif // DFGDoubleFormatState_h + diff --git a/Source/JavaScriptCore/dfg/DFGDriver.cpp b/Source/JavaScriptCore/dfg/DFGDriver.cpp index a0af3e6ad..205e94e6b 100644 --- a/Source/JavaScriptCore/dfg/DFGDriver.cpp +++ b/Source/JavaScriptCore/dfg/DFGDriver.cpp @@ -28,10 +28,10 @@ #if ENABLE(DFG_JIT) -#include "DFGArithNodeFlagsInferencePhase.h" #include "DFGByteCodeParser.h" #include "DFGCFAPhase.h" #include "DFGCSEPhase.h" +#include "DFGFixupPhase.h" #include "DFGJITCompiler.h" #include "DFGPredictionPropagationPhase.h" #include "DFGRedundantPhiEliminationPhase.h" @@ -60,8 +60,8 @@ inline bool compile(CompileMode compileMode, JSGlobalData& globalData, CodeBlock dfg.predictArgumentTypes(); performRedundantPhiElimination(dfg); - performArithNodeFlagsInference(dfg); performPredictionPropagation(dfg); + performFixup(dfg); performCSE(dfg); performVirtualRegisterAllocation(dfg); performCFA(dfg); diff --git a/Source/JavaScriptCore/dfg/DFGNodeUse.h b/Source/JavaScriptCore/dfg/DFGEdge.h index 71154997c..7b4b5b8bf 100644 --- a/Source/JavaScriptCore/dfg/DFGNodeUse.h +++ b/Source/JavaScriptCore/dfg/DFGEdge.h @@ -23,8 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DFGNodeUse_h -#define DFGNodeUse_h +#ifndef DFGEdge_h +#define DFGEdge_h #include <wtf/Platform.h> @@ -34,21 +34,21 @@ namespace JSC { namespace DFG { -class NodeReferenceBlob; +class AdjacencyList; -class NodeUse { +class Edge { public: - NodeUse() + Edge() : m_encodedWord(makeWord(NoNode, UntypedUse)) { } - explicit NodeUse(NodeIndex nodeIndex) + explicit Edge(NodeIndex nodeIndex) : m_encodedWord(makeWord(nodeIndex, UntypedUse)) { } - NodeUse(NodeIndex nodeIndex, UseKind useKind) + Edge(NodeIndex nodeIndex, UseKind useKind) : m_encodedWord(makeWord(nodeIndex, useKind)) { } @@ -80,17 +80,17 @@ public: bool isSet() const { return indexUnchecked() != NoNode; } bool operator!() const { return !isSet(); } - bool operator==(NodeUse other) const + bool operator==(Edge other) const { return m_encodedWord == other.m_encodedWord; } - bool operator!=(NodeUse other) const + bool operator!=(Edge other) const { return m_encodedWord != other.m_encodedWord; } private: - friend class NodeReferenceBlob; + friend class AdjacencyList; static uint32_t shift() { return 4; } @@ -105,19 +105,19 @@ private: int32_t m_encodedWord; }; -inline bool operator==(NodeUse nodeUse, NodeIndex nodeIndex) +inline bool operator==(Edge nodeUse, NodeIndex nodeIndex) { return nodeUse.indexUnchecked() == nodeIndex; } -inline bool operator==(NodeIndex nodeIndex, NodeUse nodeUse) +inline bool operator==(NodeIndex nodeIndex, Edge nodeUse) { return nodeUse.indexUnchecked() == nodeIndex; } -inline bool operator!=(NodeUse nodeUse, NodeIndex nodeIndex) +inline bool operator!=(Edge nodeUse, NodeIndex nodeIndex) { return nodeUse.indexUnchecked() != nodeIndex; } -inline bool operator!=(NodeIndex nodeIndex, NodeUse nodeUse) +inline bool operator!=(NodeIndex nodeIndex, Edge nodeUse) { return nodeUse.indexUnchecked() != nodeIndex; } @@ -126,5 +126,5 @@ inline bool operator!=(NodeIndex nodeIndex, NodeUse nodeUse) #endif // ENABLE(DFG_JIT) -#endif // DFGNodeUse_h +#endif // DFGEdge_h diff --git a/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp new file mode 100644 index 000000000..242fdf852 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2012 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 "DFGFixupPhase.h" + +#if ENABLE(DFG_JIT) + +#include "DFGGraph.h" +#include "DFGInsertionSet.h" +#include "DFGPhase.h" + +namespace JSC { namespace DFG { + +class FixupPhase : public Phase { +public: + FixupPhase(Graph& graph) + : Phase(graph, "fixup") + { + } + + void run() + { + for (BlockIndex blockIndex = 0; blockIndex < m_graph.m_blocks.size(); ++blockIndex) + fixupBlock(m_graph.m_blocks[blockIndex].get()); + } + +private: + void fixupBlock(BasicBlock* block) + { + for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) { + m_compileIndex = block->at(m_indexInBlock); + fixupNode(m_graph[m_compileIndex]); + } + m_insertionSet.execute(*block); + } + + void fixupNode(Node& node) + { + if (!node.shouldGenerate()) + return; + + NodeType op = node.op(); + +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + dataLog(" %s @%u: ", Graph::opName(op), m_compileIndex); +#endif + + switch (op) { + case GetById: { + if (!isInt32Prediction(m_graph[m_compileIndex].prediction())) + break; + if (codeBlock()->identifier(node.identifierNumber()) != globalData().propertyNames->length) + break; + bool isArray = isArrayPrediction(m_graph[node.child1()].prediction()); + bool isString = isStringPrediction(m_graph[node.child1()].prediction()); + bool isInt8Array = m_graph[node.child1()].shouldSpeculateInt8Array(); + bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array(); + bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array(); + bool isUint8Array = m_graph[node.child1()].shouldSpeculateUint8Array(); + bool isUint8ClampedArray = m_graph[node.child1()].shouldSpeculateUint8ClampedArray(); + bool isUint16Array = m_graph[node.child1()].shouldSpeculateUint16Array(); + bool isUint32Array = m_graph[node.child1()].shouldSpeculateUint32Array(); + bool isFloat32Array = m_graph[node.child1()].shouldSpeculateFloat32Array(); + bool isFloat64Array = m_graph[node.child1()].shouldSpeculateFloat64Array(); + if (!isArray && !isString && !isInt8Array && !isInt16Array && !isInt32Array && !isUint8Array && !isUint8ClampedArray && !isUint16Array && !isUint32Array && !isFloat32Array && !isFloat64Array) + break; + +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + dataLog(" @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength"); +#endif + if (isArray) + node.setOp(GetArrayLength); + else if (isString) + node.setOp(GetStringLength); + else if (isInt8Array) + node.setOp(GetInt8ArrayLength); + else if (isInt16Array) + node.setOp(GetInt16ArrayLength); + else if (isInt32Array) + node.setOp(GetInt32ArrayLength); + else if (isUint8Array) + node.setOp(GetUint8ArrayLength); + else if (isUint8ClampedArray) + node.setOp(GetUint8ClampedArrayLength); + else if (isUint16Array) + node.setOp(GetUint16ArrayLength); + else if (isUint32Array) + node.setOp(GetUint32ArrayLength); + else if (isFloat32Array) + node.setOp(GetFloat32ArrayLength); + else if (isFloat64Array) + node.setOp(GetFloat64ArrayLength); + else + ASSERT_NOT_REACHED(); + // No longer MustGenerate + ASSERT(node.flags() & NodeMustGenerate); + node.clearFlags(NodeMustGenerate); + m_graph.deref(m_compileIndex); + break; + } + case GetIndexedPropertyStorage: { + PredictedType basePrediction = m_graph[node.child2()].prediction(); + if (!(basePrediction & PredictInt32) && basePrediction) { + node.setOpAndDefaultFlags(Nop); + m_graph.clearAndDerefChild1(node); + m_graph.clearAndDerefChild2(node); + m_graph.clearAndDerefChild3(node); + node.setRefCount(0); + } + break; + } + case GetByVal: + case StringCharAt: + case StringCharCodeAt: { + if (!!node.child3() && m_graph[node.child3()].op() == Nop) + node.children.child3() = Edge(); + break; + } + + case ValueToInt32: { + if (m_graph[node.child1()].shouldSpeculateNumber()) { + node.clearFlags(NodeMustGenerate); + m_graph.deref(m_compileIndex); + } + break; + } + + case BitAnd: + case BitOr: + case BitXor: + case BitRShift: + case BitLShift: + case BitURShift: { + fixIntEdge(node.children.child1()); + fixIntEdge(node.children.child2()); + break; + } + + case CompareEq: + case CompareLess: + case CompareLessEq: + case CompareGreater: + case CompareGreaterEq: + case CompareStrictEq: { + if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()])) + break; + if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) + break; + fixDoubleEdge(0); + fixDoubleEdge(1); + break; + } + + case LogicalNot: { + if (m_graph[node.child1()].shouldSpeculateInteger()) + break; + if (!m_graph[node.child1()].shouldSpeculateNumber()) + break; + fixDoubleEdge(0); + break; + } + + case Branch: { + if (!m_graph[node.child1()].shouldSpeculateInteger() + && m_graph[node.child1()].shouldSpeculateNumber()) + fixDoubleEdge(0); + + Node& myNode = m_graph[m_compileIndex]; // reload because the graph may have changed + Edge logicalNotEdge = myNode.child1(); + Node& logicalNot = m_graph[logicalNotEdge]; + if (logicalNot.op() == LogicalNot + && logicalNot.adjustedRefCount() == 1) { + Edge newChildEdge = logicalNot.child1(); + if (m_graph[newChildEdge].hasBooleanResult()) { + m_graph.ref(newChildEdge); + m_graph.deref(logicalNotEdge); + myNode.children.setChild1(newChildEdge); + + BlockIndex toBeTaken = myNode.notTakenBlockIndex(); + BlockIndex toBeNotTaken = myNode.takenBlockIndex(); + myNode.setTakenBlockIndex(toBeTaken); + myNode.setNotTakenBlockIndex(toBeNotTaken); + } + } + break; + } + + case SetLocal: { + if (m_graph.isCaptured(node.local())) + break; + if (!node.variableAccessData()->shouldUseDoubleFormat()) + break; + fixDoubleEdge(0); + break; + } + + case ArithAdd: + case ValueAdd: { + if (m_graph.addShouldSpeculateInteger(node)) + break; + if (!Node::shouldSpeculateNumber(m_graph[node.child1()], m_graph[node.child2()])) + break; + fixDoubleEdge(0); + fixDoubleEdge(1); + break; + } + + case ArithSub: { + if (m_graph.addShouldSpeculateInteger(node) + && node.canSpeculateInteger()) + break; + fixDoubleEdge(0); + fixDoubleEdge(1); + break; + } + + case ArithNegate: { + if (m_graph.negateShouldSpeculateInteger(node)) + break; + fixDoubleEdge(0); + break; + } + + case ArithMin: + case ArithMax: + case ArithMul: + case ArithMod: { + if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) + && node.canSpeculateInteger()) + break; + fixDoubleEdge(0); + fixDoubleEdge(1); + break; + } + + case ArithDiv: { + if (Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child2()]) + && node.canSpeculateInteger()) { + if (isX86()) + break; + fixDoubleEdge(0); + fixDoubleEdge(1); + + Node& oldDivision = m_graph[m_compileIndex]; + + Node newDivision = oldDivision; + newDivision.setRefCount(2); + newDivision.predict(PredictDouble); + NodeIndex newDivisionIndex = m_graph.size(); + + oldDivision.setOp(DoubleAsInt32); + oldDivision.children.initialize(Edge(newDivisionIndex, DoubleUse), Edge(), Edge()); + + m_graph.append(newDivision); + m_insertionSet.append(m_indexInBlock, newDivisionIndex); + + break; + } + fixDoubleEdge(0); + fixDoubleEdge(1); + break; + } + + case ArithAbs: { + if (m_graph[node.child1()].shouldSpeculateInteger() + && node.canSpeculateInteger()) + break; + fixDoubleEdge(0); + break; + } + + case ArithSqrt: { + fixDoubleEdge(0); + break; + } + + case PutByVal: { + if (!m_graph[node.child1()].prediction() || !m_graph[node.child2()].prediction()) + break; + if (!m_graph[node.child2()].shouldSpeculateInteger()) + break; + if (isActionableIntMutableArrayPrediction(m_graph[node.child1()].prediction())) { + if (m_graph[node.child3()].isConstant()) + break; + if (m_graph[node.child3()].shouldSpeculateInteger()) + break; + fixDoubleEdge(2); + break; + } + if (isActionableFloatMutableArrayPrediction(m_graph[node.child1()].prediction())) { + fixDoubleEdge(2); + break; + } + break; + } + + default: + break; + } + +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + if (!(node.flags() & NodeHasVarArgs)) { + dataLog("new children: "); + node.dumpChildren(WTF::dataFile()); + } + dataLog("\n"); +#endif + } + + void fixIntEdge(Edge& edge) + { + Node& node = m_graph[edge]; + if (node.op() != ValueToInt32) + return; + + if (!m_graph[node.child1()].shouldSpeculateInteger()) + return; + + Edge oldEdge = edge; + Edge newEdge = node.child1(); + + m_graph.ref(newEdge); + m_graph.deref(oldEdge); + + edge = newEdge; + } + + void fixDoubleEdge(unsigned childIndex) + { + Node& source = m_graph[m_compileIndex]; + Edge& edge = source.children.child(childIndex); + + if (!m_graph[edge].shouldSpeculateInteger()) { + edge.setUseKind(DoubleUse); + return; + } + + NodeIndex resultIndex = (NodeIndex)m_graph.size(); + +#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) + dataLog("(replacing @%u->@%u with @%u->@%u) ", + m_compileIndex, edge.index(), m_compileIndex, resultIndex); +#endif + + // Fix the edge up here because it's a reference that will be clobbered by + // the append() below. + NodeIndex oldIndex = edge.index(); + edge = Edge(resultIndex, DoubleUse); + + m_graph.append(Node(Int32ToDouble, source.codeOrigin, oldIndex)); + m_insertionSet.append(m_indexInBlock, resultIndex); + + Node& int32ToDouble = m_graph[resultIndex]; + int32ToDouble.predict(PredictDouble); + int32ToDouble.ref(); + } + + unsigned m_indexInBlock; + NodeIndex m_compileIndex; + InsertionSet<NodeIndex> m_insertionSet; +}; + +void performFixup(Graph& graph) +{ + runPhase<FixupPhase>(graph); +} + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + diff --git a/Source/JavaScriptCore/wtf/DataLog.h b/Source/JavaScriptCore/dfg/DFGFixupPhase.h index bcbebb9e2..1ba85ebfe 100644 --- a/Source/JavaScriptCore/wtf/DataLog.h +++ b/Source/JavaScriptCore/dfg/DFGFixupPhase.h @@ -23,24 +23,24 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef DataLog_h -#define DataLog_h +#ifndef DFGFixupPhase_h +#define DFGFixupPhase_h -#include <stdarg.h> -#include <stdio.h> #include <wtf/Platform.h> -#include <wtf/StdLibExtras.h> -namespace WTF { +#if ENABLE(DFG_JIT) -FILE* dataFile(); +namespace JSC { namespace DFG { -void dataLogV(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(1, 0); -void dataLog(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2); +class Graph; -} // namespace WTF +// Fix portions of the graph that are inefficient given the predictions that +// we have. This should run after prediction propagation but before CSE. -using WTF::dataLog; +void performFixup(Graph&); -#endif // DataLog_h +} } // namespace JSC::DFG::Phase +#endif // ENABLE(DFG_JIT) + +#endif // DFGFixupPhase_h diff --git a/Source/JavaScriptCore/dfg/DFGGPRInfo.h b/Source/JavaScriptCore/dfg/DFGGPRInfo.h index f010d8c18..4a250328f 100644 --- a/Source/JavaScriptCore/dfg/DFGGPRInfo.h +++ b/Source/JavaScriptCore/dfg/DFGGPRInfo.h @@ -386,18 +386,17 @@ private: class GPRInfo { public: typedef GPRReg RegisterType; - static const unsigned numberOfRegisters = 9; + static const unsigned numberOfRegisters = 8; // Temporary registers. static const GPRReg regT0 = ARMRegisters::r0; static const GPRReg regT1 = ARMRegisters::r1; static const GPRReg regT2 = ARMRegisters::r2; static const GPRReg regT3 = ARMRegisters::r4; - static const GPRReg regT4 = ARMRegisters::r7; - static const GPRReg regT5 = ARMRegisters::r8; - static const GPRReg regT6 = ARMRegisters::r9; - static const GPRReg regT7 = ARMRegisters::r10; - static const GPRReg regT8 = ARMRegisters::r11; + static const GPRReg regT4 = ARMRegisters::r8; + static const GPRReg regT5 = ARMRegisters::r9; + static const GPRReg regT6 = ARMRegisters::r10; + static const GPRReg regT7 = ARMRegisters::r11; // These registers match the baseline JIT. static const GPRReg cachedResultRegister = regT0; static const GPRReg cachedResultRegister2 = regT1; @@ -418,7 +417,7 @@ public: static GPRReg toRegister(unsigned index) { ASSERT(index < numberOfRegisters); - static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 }; + static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7 }; return registerForIndex[index]; } @@ -426,7 +425,7 @@ public: { ASSERT(reg != InvalidGPRReg); ASSERT(reg < 16); - static const unsigned indexForRegister[16] = { 0, 1, 2, InvalidIndex, 3, InvalidIndex, InvalidIndex, 4, 5, 6, 7, 8, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex }; + static const unsigned indexForRegister[16] = { 0, 1, 2, InvalidIndex, 3, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex }; unsigned result = indexForRegister[reg]; ASSERT(result != InvalidIndex); return result; diff --git a/Source/JavaScriptCore/dfg/DFGGenerationInfo.h b/Source/JavaScriptCore/dfg/DFGGenerationInfo.h index 6f0fe3143..125a5a4f9 100644 --- a/Source/JavaScriptCore/dfg/DFGGenerationInfo.h +++ b/Source/JavaScriptCore/dfg/DFGGenerationInfo.h @@ -1,3 +1,4 @@ + /* * Copyright (C) 2011 Apple Inc. All rights reserved. * diff --git a/Source/JavaScriptCore/dfg/DFGGraph.cpp b/Source/JavaScriptCore/dfg/DFGGraph.cpp index 900251e10..3c99e5d4e 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.cpp +++ b/Source/JavaScriptCore/dfg/DFGGraph.cpp @@ -27,6 +27,7 @@ #include "DFGGraph.h" #include "CodeBlock.h" +#include <wtf/BoundsCheckedPointer.h> #if ENABLE(DFG_JIT) @@ -83,13 +84,13 @@ static void printWhiteSpace(unsigned amount) dataLog(" "); } -void Graph::dumpCodeOrigin(NodeIndex nodeIndex) +void Graph::dumpCodeOrigin(NodeIndex prevNodeIndex, NodeIndex nodeIndex) { - if (!nodeIndex) + if (prevNodeIndex == NoNode) return; Node& currentNode = at(nodeIndex); - Node& previousNode = at(nodeIndex - 1); + Node& previousNode = at(prevNodeIndex); if (previousNode.codeOrigin.inlineCallFrame == currentNode.codeOrigin.inlineCallFrame) return; @@ -120,7 +121,7 @@ void Graph::dumpCodeOrigin(NodeIndex nodeIndex) void Graph::dump(NodeIndex nodeIndex) { Node& node = at(nodeIndex); - NodeType op = static_cast<NodeType>(node.op); + NodeType op = node.op(); unsigned refCount = node.refCount(); bool skipped = !refCount; @@ -130,7 +131,6 @@ void Graph::dump(NodeIndex nodeIndex) --refCount; } - dumpCodeOrigin(nodeIndex); printWhiteSpace((node.codeOrigin.inlineDepth() - 1) * 2); // Example/explanation of dataflow dump output @@ -157,26 +157,41 @@ void Graph::dump(NodeIndex nodeIndex) dataLog("-"); dataLog(">\t%s(", opName(op)); bool hasPrinted = false; - if (node.flags & NodeHasVarArgs) { + if (node.flags() & NodeHasVarArgs) { for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) { if (hasPrinted) dataLog(", "); else hasPrinted = true; - dataLog("@%u", m_varArgChildren[childIdx].index()); + dataLog("%s@%u%s", + useKindToString(m_varArgChildren[childIdx].useKind()), + m_varArgChildren[childIdx].index(), + predictionToAbbreviatedString(at(childIdx).prediction())); } } else { - if (!!node.child1()) - dataLog("@%u", node.child1().index()); - if (!!node.child2()) - dataLog(", @%u", node.child2().index()); - if (!!node.child3()) - dataLog(", @%u", node.child3().index()); + if (!!node.child1()) { + dataLog("%s@%u%s", + useKindToString(node.child1().useKind()), + node.child1().index(), + predictionToAbbreviatedString(at(node.child1()).prediction())); + } + if (!!node.child2()) { + dataLog(", %s@%u%s", + useKindToString(node.child2().useKind()), + node.child2().index(), + predictionToAbbreviatedString(at(node.child2()).prediction())); + } + if (!!node.child3()) { + dataLog(", %s@%u%s", + useKindToString(node.child3().useKind()), + node.child3().index(), + predictionToAbbreviatedString(at(node.child3()).prediction())); + } hasPrinted = !!node.child1(); } - if (node.arithNodeFlags()) { - dataLog("%s%s", hasPrinted ? ", " : "", arithNodeFlagsAsString(node.arithNodeFlags())); + if (node.flags()) { + dataLog("%s%s", hasPrinted ? ", " : "", nodeFlagsAsString(node.flags())); hasPrinted = true; } if (node.hasVarNumber()) { @@ -253,8 +268,6 @@ void Graph::dump(NodeIndex nodeIndex) dataLog(" predicting %s, double ratio %lf%s", predictionToString(node.variableAccessData()->prediction()), node.variableAccessData()->doubleVoteRatio(), node.variableAccessData()->shouldUseDoubleFormat() ? ", forcing double" : ""); else if (node.hasHeapPrediction()) dataLog(" predicting %s", predictionToString(node.getHeapPrediction())); - else if (node.hasVarNumber()) - dataLog(" predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber()))); } dataLog("\n"); @@ -262,6 +275,7 @@ void Graph::dump(NodeIndex nodeIndex) void Graph::dump() { + NodeIndex lastNodeIndex = NoNode; for (size_t b = 0; b < m_blocks.size(); ++b) { BasicBlock* block = m_blocks[b].get(); dataLog("Block #%u (bc#%u): %s%s\n", (int)b, block->bytecodeBegin, block->isReachable ? "" : " (skipped)", block->isOSRTarget ? " (OSR target)" : ""); @@ -280,8 +294,11 @@ void Graph::dump() dataLog(" var links: "); dumpOperands(block->variablesAtHead, WTF::dataFile()); dataLog("\n"); - for (size_t i = 0; i < block->size(); ++i) + for (size_t i = 0; i < block->size(); ++i) { + dumpCodeOrigin(lastNodeIndex, block->at(i)); dump(block->at(i)); + lastNodeIndex = block->at(i); + } dataLog(" vars after: "); if (block->cfaHasVisited) dumpOperands(block->valuesAtTail, WTF::dataFile()); @@ -294,7 +311,7 @@ void Graph::dump() // FIXME: Convert this to be iterative, not recursive. #define DO_TO_CHILDREN(node, thingToDo) do { \ Node& _node = (node); \ - if (_node.flags & NodeHasVarArgs) { \ + if (_node.flags() & NodeHasVarArgs) { \ for (unsigned _childIdx = _node.firstChild(); \ _childIdx < _node.firstChild() + _node.numChildren(); \ _childIdx++) \ diff --git a/Source/JavaScriptCore/dfg/DFGGraph.h b/Source/JavaScriptCore/dfg/DFGGraph.h index bacbac827..0c8ac2dcf 100644 --- a/Source/JavaScriptCore/dfg/DFGGraph.h +++ b/Source/JavaScriptCore/dfg/DFGGraph.h @@ -29,11 +29,11 @@ #if ENABLE(DFG_JIT) #include "CodeBlock.h" +#include "DFGArgumentPosition.h" #include "DFGAssemblyHelpers.h" #include "DFGBasicBlock.h" #include "DFGNode.h" #include "MethodOfGettingAValueProfile.h" -#include "PredictionTracker.h" #include "RegisterFile.h" #include <wtf/BitVector.h> #include <wtf/HashMap.h> @@ -84,11 +84,11 @@ public: using Vector<Node, 64>::operator[]; using Vector<Node, 64>::at; - Node& operator[](NodeUse nodeUse) { return at(nodeUse.index()); } - const Node& operator[](NodeUse nodeUse) const { return at(nodeUse.index()); } + Node& operator[](Edge nodeUse) { return at(nodeUse.index()); } + const Node& operator[](Edge nodeUse) const { return at(nodeUse.index()); } - Node& at(NodeUse nodeUse) { return at(nodeUse.index()); } - const Node& at(NodeUse nodeUse) const { return at(nodeUse.index()); } + Node& at(Edge nodeUse) { return at(nodeUse.index()); } + const Node& at(Edge nodeUse) const { return at(nodeUse.index()); } // Mark a node as being referenced. void ref(NodeIndex nodeIndex) @@ -98,7 +98,7 @@ public: if (node.ref()) refChildren(nodeIndex); } - void ref(NodeUse nodeUse) + void ref(Edge nodeUse) { ref(nodeUse.index()); } @@ -108,7 +108,7 @@ public: if (at(nodeIndex).deref()) derefChildren(nodeIndex); } - void deref(NodeUse nodeUse) + void deref(Edge nodeUse) { deref(nodeUse.index()); } @@ -118,7 +118,7 @@ public: if (!node.child1()) return; deref(node.child1()); - node.children.child1() = NodeUse(); + node.children.child1() = Edge(); } void clearAndDerefChild2(Node& node) @@ -126,7 +126,7 @@ public: if (!node.child2()) return; deref(node.child2()); - node.children.child2() = NodeUse(); + node.children.child2() = Edge(); } void clearAndDerefChild3(Node& node) @@ -134,7 +134,7 @@ public: if (!node.child3()) return; deref(node.child3()); - node.children.child3() = NodeUse(); + node.children.child3() = Edge(); } // CodeBlock is optional, but may allow additional information to be dumped (e.g. Identifier names). @@ -143,20 +143,10 @@ public: // Dump the code origin of the given node as a diff from the code origin of the // preceding node. - void dumpCodeOrigin(NodeIndex); + void dumpCodeOrigin(NodeIndex, NodeIndex); BlockIndex blockIndexForBytecodeOffset(Vector<BlockIndex>& blocks, unsigned bytecodeBegin); - bool predictGlobalVar(unsigned varNumber, PredictedType prediction) - { - return m_predictions.predictGlobalVar(varNumber, prediction); - } - - PredictedType getGlobalVarPrediction(unsigned varNumber) - { - return m_predictions.getGlobalVarPrediction(varNumber); - } - PredictedType getJSConstantPrediction(Node& node) { return predictionFromValue(node.valueOfJSConstant(m_codeBlock)); @@ -164,7 +154,7 @@ public: bool addShouldSpeculateInteger(Node& add) { - ASSERT(add.op == ValueAdd || add.op == ArithAdd || add.op == ArithSub); + ASSERT(add.op() == ValueAdd || add.op() == ArithAdd || add.op() == ArithSub); Node& left = at(add.child1()); Node& right = at(add.child2()); @@ -179,7 +169,7 @@ public: bool negateShouldSpeculateInteger(Node& negate) { - ASSERT(negate.op == ArithNegate); + ASSERT(negate.op() == ArithNegate); return at(negate.child1()).shouldSpeculateInteger() && negate.canSpeculateInteger(); } @@ -242,7 +232,7 @@ public: { JSCell* function = getJSFunction(valueOfJSConstant(nodeIndex)); ASSERT(function); - return asFunction(function); + return jsCast<JSFunction*>(function); } static const char *opName(NodeType); @@ -301,7 +291,7 @@ public: Node& node = at(nodeIndex); CodeBlock* profiledBlock = baselineCodeBlockFor(node.codeOrigin); - if (node.op == GetLocal) { + if (node.op() == GetLocal) { return MethodOfGettingAValueProfile::fromLazyOperand( profiledBlock, LazyOperandValueProfileKey( @@ -351,11 +341,12 @@ public: CodeBlock* m_profiledBlock; Vector< OwnPtr<BasicBlock> , 8> m_blocks; - Vector<NodeUse, 16> m_varArgChildren; + Vector<Edge, 16> m_varArgChildren; Vector<StorageAccessData> m_storageAccessData; Vector<ResolveGlobalData> m_resolveGlobalData; Vector<NodeIndex, 8> m_arguments; SegmentedVector<VariableAccessData, 16> m_variableAccessData; + SegmentedVector<ArgumentPosition, 8> m_argumentPositions; SegmentedVector<StructureSet, 16> m_structureSet; SegmentedVector<StructureTransitionData, 8> m_structureTransitionData; BitVector m_preservedVars; @@ -388,8 +379,6 @@ private: // When a node's refCount goes from 0 to 1, it must (logically) recursively ref all of its children, and vice versa. void refChildren(NodeIndex); void derefChildren(NodeIndex); - - PredictionTracker m_predictions; }; class GetBytecodeBeginForBlock { diff --git a/Source/JavaScriptCore/dfg/DFGInsertionSet.h b/Source/JavaScriptCore/dfg/DFGInsertionSet.h new file mode 100644 index 000000000..82a6a6fa4 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGInsertionSet.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2012 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 DFGInsertionSet_h +#define DFGInsectionSet_h + +#include <wtf/Platform.h> + +#if ENABLE(DFG_JIT) + +#include <wtf/Vector.h> + +namespace JSC { namespace DFG { + +template<typename ElementType> +class Insertion { +public: + Insertion() { } + + Insertion(size_t index, const ElementType& element) + : m_index(index) + , m_element(element) + { + } + + size_t index() const { return m_index; } + const ElementType& element() const { return m_element; } +private: + size_t m_index; + ElementType m_element; +}; + +template<typename ElementType> +class InsertionSet { +public: + InsertionSet() { } + + void append(const Insertion<ElementType>& insertion) + { + ASSERT(!m_insertions.size() || m_insertions.last().index() <= insertion.index()); + m_insertions.append(insertion); + } + + void append(size_t index, const ElementType& element) + { + append(Insertion<ElementType>(index, element)); + } + + template<typename CollectionType> + void execute(CollectionType& collection) + { + if (!m_insertions.size()) + return; + collection.grow(collection.size() + m_insertions.size()); + size_t lastIndex = collection.size(); + for (size_t indexInInsertions = m_insertions.size(); indexInInsertions--;) { + Insertion<ElementType>& insertion = m_insertions[indexInInsertions]; + size_t firstIndex = insertion.index() + indexInInsertions; + size_t indexOffset = indexInInsertions + 1; + for (size_t i = lastIndex; i-- > firstIndex;) + collection[i] = collection[i - indexOffset]; + collection[firstIndex] = insertion.element(); + lastIndex = firstIndex; + } + m_insertions.resize(0); + } +private: + Vector<Insertion<ElementType>, 8> m_insertions; +}; + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGInsertionSet_h + diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp index af98f8d7a..56e0d4e18 100644 --- a/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp @@ -44,10 +44,9 @@ void JITCompiler::linkOSRExits() for (unsigned i = 0; i < codeBlock()->numberOfOSRExits(); ++i) { OSRExit& exit = codeBlock()->osrExit(i); exit.m_check.initialJump().link(this); + jitAssertHasValidCallFrame(); store32(TrustedImm32(i), &globalData()->osrExitIndex); - beginUninterruptedSequence(); - exit.m_check.switchToLateJump(jump()); - endUninterruptedSequence(); + exit.m_check.switchToLateJump(patchableJump()); } } @@ -152,25 +151,25 @@ void JITCompiler::link(LinkBuffer& linkBuffer) CodeLocationCall callReturnLocation = linkBuffer.locationOf(m_propertyAccesses[i].m_functionCall); info.codeOrigin = m_propertyAccesses[i].m_codeOrigin; info.callReturnLocation = callReturnLocation; - info.deltaCheckImmToCall = differenceBetweenCodePtr(linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCheckImmToCall), callReturnLocation); - info.deltaCallToStructCheck = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToStructCheck)); + info.patch.dfg.deltaCheckImmToCall = differenceBetweenCodePtr(linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCheckImmToCall), callReturnLocation); + info.patch.dfg.deltaCallToStructCheck = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToStructCheck)); #if USE(JSVALUE64) - info.deltaCallToLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToLoadOrStore)); + info.patch.dfg.deltaCallToLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToLoadOrStore)); #else - info.deltaCallToTagLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToTagLoadOrStore)); - info.deltaCallToPayloadLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToPayloadLoadOrStore)); + info.patch.dfg.deltaCallToTagLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToTagLoadOrStore)); + info.patch.dfg.deltaCallToPayloadLoadOrStore = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToPayloadLoadOrStore)); #endif - info.deltaCallToSlowCase = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToSlowCase)); - info.deltaCallToDone = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToDone)); - info.baseGPR = m_propertyAccesses[i].m_baseGPR; + info.patch.dfg.deltaCallToSlowCase = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToSlowCase)); + info.patch.dfg.deltaCallToDone = differenceBetweenCodePtr(callReturnLocation, linkBuffer.locationOf(m_propertyAccesses[i].m_deltaCallToDone)); + info.patch.dfg.baseGPR = m_propertyAccesses[i].m_baseGPR; #if USE(JSVALUE64) - info.valueGPR = m_propertyAccesses[i].m_valueGPR; + info.patch.dfg.valueGPR = m_propertyAccesses[i].m_valueGPR; #else - info.valueTagGPR = m_propertyAccesses[i].m_valueTagGPR; - info.valueGPR = m_propertyAccesses[i].m_valueGPR; + info.patch.dfg.valueTagGPR = m_propertyAccesses[i].m_valueTagGPR; + info.patch.dfg.valueGPR = m_propertyAccesses[i].m_valueGPR; #endif - info.scratchGPR = m_propertyAccesses[i].m_scratchGPR; - info.registersFlushed = m_propertyAccesses[i].m_registerMode == PropertyAccessRecord::RegistersFlushed; + info.patch.dfg.scratchGPR = m_propertyAccesses[i].m_scratchGPR; + info.patch.dfg.registersFlushed = m_propertyAccesses[i].m_registerMode == PropertyAccessRecord::RegistersFlushed; } m_codeBlock->setNumberOfCallLinkInfos(m_jsCalls.size()); diff --git a/Source/JavaScriptCore/dfg/DFGJITCompiler.h b/Source/JavaScriptCore/dfg/DFGJITCompiler.h index 2df2703b0..01a1e7246 100644 --- a/Source/JavaScriptCore/dfg/DFGJITCompiler.h +++ b/Source/JavaScriptCore/dfg/DFGJITCompiler.h @@ -130,9 +130,9 @@ struct PropertyAccessRecord { enum RegisterMode { RegistersFlushed, RegistersInUse }; #if USE(JSVALUE64) - PropertyAccessRecord(CodeOrigin codeOrigin, MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::Jump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueGPR, int8_t scratchGPR, RegisterMode registerMode = RegistersInUse) + PropertyAccessRecord(CodeOrigin codeOrigin, MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::PatchableJump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueGPR, int8_t scratchGPR, RegisterMode registerMode = RegistersInUse) #elif USE(JSVALUE32_64) - PropertyAccessRecord(CodeOrigin codeOrigin, MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::Jump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToTagLoadOrStore, MacroAssembler::DataLabelCompact deltaCallToPayloadLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueTagGPR, int8_t valueGPR, int8_t scratchGPR, RegisterMode registerMode = RegistersInUse) + PropertyAccessRecord(CodeOrigin codeOrigin, MacroAssembler::DataLabelPtr deltaCheckImmToCall, MacroAssembler::Call functionCall, MacroAssembler::PatchableJump deltaCallToStructCheck, MacroAssembler::DataLabelCompact deltaCallToTagLoadOrStore, MacroAssembler::DataLabelCompact deltaCallToPayloadLoadOrStore, MacroAssembler::Label deltaCallToSlowCase, MacroAssembler::Label deltaCallToDone, int8_t baseGPR, int8_t valueTagGPR, int8_t valueGPR, int8_t scratchGPR, RegisterMode registerMode = RegistersInUse) #endif : m_codeOrigin(codeOrigin) , m_deltaCheckImmToCall(deltaCheckImmToCall) @@ -159,7 +159,7 @@ struct PropertyAccessRecord { CodeOrigin m_codeOrigin; MacroAssembler::DataLabelPtr m_deltaCheckImmToCall; MacroAssembler::Call m_functionCall; - MacroAssembler::Jump m_deltaCallToStructCheck; + MacroAssembler::PatchableJump m_deltaCallToStructCheck; #if USE(JSVALUE64) MacroAssembler::DataLabelCompact m_deltaCallToLoadOrStore; #elif USE(JSVALUE32_64) @@ -200,12 +200,6 @@ public: // Accessors for properties. Graph& graph() { return m_graph; } - // Just get a token for beginning a call. - CallBeginToken beginJSCall() - { - return CallBeginToken(m_currentCodeOriginIndex++); - } - // Get a token for beginning a call, and set the current code origin index in // the call frame. CallBeginToken beginCall() @@ -247,7 +241,7 @@ public: // Helper methods to get predictions PredictedType getPrediction(Node& node) { return node.prediction(); } PredictedType getPrediction(NodeIndex nodeIndex) { return getPrediction(graph()[nodeIndex]); } - PredictedType getPrediction(NodeUse nodeUse) { return getPrediction(nodeUse.index()); } + PredictedType getPrediction(Edge nodeUse) { return getPrediction(nodeUse.index()); } #if USE(JSVALUE32_64) void* addressOfDoubleConstant(NodeIndex nodeIndex) diff --git a/Source/JavaScriptCore/dfg/DFGNode.h b/Source/JavaScriptCore/dfg/DFGNode.h index b672b67c5..f79a93a69 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.h +++ b/Source/JavaScriptCore/dfg/DFGNode.h @@ -32,15 +32,15 @@ #include "CodeBlock.h" #include "CodeOrigin.h" +#include "DFGAdjacencyList.h" #include "DFGCommon.h" -#include "DFGNodeReferenceBlob.h" -#include "DFGOperands.h" +#include "DFGNodeFlags.h" +#include "DFGNodeType.h" #include "DFGVariableAccessData.h" #include "JSValue.h" +#include "Operands.h" #include "PredictedType.h" #include "ValueProfile.h" -#include <wtf/BoundsCheckedPointer.h> -#include <wtf/Vector.h> namespace JSC { namespace DFG { @@ -57,240 +57,6 @@ struct StructureTransitionData { } }; -// Entries in the NodeType enum (below) are composed of an id, a result type (possibly none) -// and some additional informative flags (must generate, is constant, etc). -#define NodeResultMask 0xF -#define NodeResultJS 0x1 -#define NodeResultNumber 0x2 -#define NodeResultInt32 0x3 -#define NodeResultBoolean 0x4 -#define NodeResultStorage 0x5 -#define NodeMustGenerate 0x10 // set on nodes that have side effects, and may not trivially be removed by DCE. -#define NodeHasVarArgs 0x20 -#define NodeClobbersWorld 0x40 -#define NodeMightClobber 0x80 -#define NodeArithMask 0xF00 -#define NodeUseBottom 0x000 -#define NodeUsedAsNumber 0x100 -#define NodeNeedsNegZero 0x200 -#define NodeUsedAsMask 0x300 -#define NodeMayOverflow 0x400 -#define NodeMayNegZero 0x800 -#define NodeBehaviorMask 0xc00 - -typedef uint16_t NodeFlags; - -static inline bool nodeUsedAsNumber(NodeFlags flags) -{ - return !!(flags & NodeUsedAsNumber); -} - -static inline bool nodeCanTruncateInteger(NodeFlags flags) -{ - return !nodeUsedAsNumber(flags); -} - -static inline bool nodeCanIgnoreNegativeZero(NodeFlags flags) -{ - return !(flags & NodeNeedsNegZero); -} - -static inline bool nodeMayOverflow(NodeFlags flags) -{ - return !!(flags & NodeMayOverflow); -} - -static inline bool nodeCanSpeculateInteger(NodeFlags flags) -{ - if (flags & NodeMayOverflow) - return !nodeUsedAsNumber(flags); - - if (flags & NodeMayNegZero) - return nodeCanIgnoreNegativeZero(flags); - - return true; -} - -const char* arithNodeFlagsAsString(NodeFlags); - -// This macro defines a set of information about all known node types, used to populate NodeId, NodeType below. -#define FOR_EACH_DFG_OP(macro) \ - /* A constant in the CodeBlock's constant pool. */\ - macro(JSConstant, NodeResultJS) \ - \ - /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\ - /* code block. */\ - macro(WeakJSConstant, NodeResultJS) \ - \ - /* Nodes for handling functions (both as call and as construct). */\ - macro(ConvertThis, NodeResultJS) \ - macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \ - macro(GetCallee, NodeResultJS) \ - \ - /* Nodes for local variable access. */\ - macro(GetLocal, NodeResultJS) \ - macro(SetLocal, 0) \ - macro(Phantom, NodeMustGenerate) \ - macro(Nop, 0) \ - macro(Phi, 0) \ - macro(Flush, NodeMustGenerate) \ - \ - /* Marker for arguments being set. */\ - macro(SetArgument, 0) \ - \ - /* Hint that inlining begins here. No code is generated for this node. It's only */\ - /* used for copying OSR data into inline frame data, to support reification of */\ - /* call frames of inlined functions. */\ - macro(InlineStart, 0) \ - \ - /* Nodes for bitwise operations. */\ - macro(BitAnd, NodeResultInt32) \ - macro(BitOr, NodeResultInt32) \ - macro(BitXor, NodeResultInt32) \ - macro(BitLShift, NodeResultInt32) \ - macro(BitRShift, NodeResultInt32) \ - macro(BitURShift, NodeResultInt32) \ - /* Bitwise operators call ToInt32 on their operands. */\ - macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \ - /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\ - macro(UInt32ToNumber, NodeResultNumber) \ - \ - /* Nodes for arithmetic operations. */\ - macro(ArithAdd, NodeResultNumber) \ - macro(ArithSub, NodeResultNumber) \ - macro(ArithNegate, NodeResultNumber) \ - macro(ArithMul, NodeResultNumber) \ - macro(ArithDiv, NodeResultNumber) \ - macro(ArithMod, NodeResultNumber) \ - macro(ArithAbs, NodeResultNumber) \ - macro(ArithMin, NodeResultNumber) \ - macro(ArithMax, NodeResultNumber) \ - macro(ArithSqrt, NodeResultNumber) \ - \ - /* Add of values may either be arithmetic, or result in string concatenation. */\ - macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \ - \ - /* Property access. */\ - /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\ - /* Since a put to 'length' may invalidate optimizations here, */\ - /* this must be the directly subsequent property put. */\ - macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \ - macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \ - macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \ - macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ - macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ - macro(PutById, NodeMustGenerate | NodeClobbersWorld) \ - macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \ - macro(CheckStructure, NodeMustGenerate) \ - macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \ - macro(GetPropertyStorage, NodeResultStorage) \ - macro(GetIndexedPropertyStorage, NodeMustGenerate | NodeResultStorage) \ - macro(GetByOffset, NodeResultJS) \ - macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \ - macro(GetArrayLength, NodeResultInt32) \ - macro(GetStringLength, NodeResultInt32) \ - macro(GetByteArrayLength, NodeResultInt32) \ - macro(GetInt8ArrayLength, NodeResultInt32) \ - macro(GetInt16ArrayLength, NodeResultInt32) \ - macro(GetInt32ArrayLength, NodeResultInt32) \ - macro(GetUint8ArrayLength, NodeResultInt32) \ - macro(GetUint8ClampedArrayLength, NodeResultInt32) \ - macro(GetUint16ArrayLength, NodeResultInt32) \ - macro(GetUint32ArrayLength, NodeResultInt32) \ - macro(GetFloat32ArrayLength, NodeResultInt32) \ - macro(GetFloat64ArrayLength, NodeResultInt32) \ - macro(GetScopeChain, NodeResultJS) \ - macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \ - macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \ - macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \ - macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \ - macro(CheckFunction, NodeMustGenerate) \ - \ - /* Optimizations for array mutation. */\ - macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ - macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ - \ - /* Optimizations for string access */ \ - macro(StringCharCodeAt, NodeResultInt32) \ - macro(StringCharAt, NodeResultJS) \ - \ - /* Nodes for comparison operations. */\ - macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ - macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ - macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ - macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ - macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ - macro(CompareStrictEq, NodeResultBoolean) \ - \ - /* Calls. */\ - macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \ - macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \ - \ - /* Allocations. */\ - macro(NewObject, NodeResultJS) \ - macro(NewArray, NodeResultJS | NodeHasVarArgs) \ - macro(NewArrayBuffer, NodeResultJS) \ - macro(NewRegexp, NodeResultJS) \ - \ - /* Resolve nodes. */\ - macro(Resolve, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ - macro(ResolveBase, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ - macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ - macro(ResolveGlobal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ - \ - /* Nodes for misc operations. */\ - macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \ - macro(CheckHasInstance, NodeMustGenerate) \ - macro(InstanceOf, NodeResultBoolean) \ - macro(LogicalNot, NodeResultBoolean | NodeMightClobber) \ - macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ - macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \ - \ - /* Nodes used for activations. Activation support works by having it anchored at */\ - /* epilgoues via TearOffActivation, and all CreateActivation nodes kept alive by */\ - /* being threaded with each other. */\ - macro(CreateActivation, NodeResultJS) \ - macro(TearOffActivation, NodeMustGenerate) \ - \ - /* Nodes for creating functions. */\ - macro(NewFunctionNoCheck, NodeResultJS) \ - macro(NewFunction, NodeResultJS) \ - macro(NewFunctionExpression, NodeResultJS) \ - \ - /* Block terminals. */\ - macro(Jump, NodeMustGenerate) \ - macro(Branch, NodeMustGenerate) \ - macro(Return, NodeMustGenerate) \ - macro(Throw, NodeMustGenerate) \ - macro(ThrowReferenceError, NodeMustGenerate) \ - \ - /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\ - /* this point, but execution does continue in the basic block - just in a */\ - /* different compiler. */\ - macro(ForceOSRExit, NodeMustGenerate) - -// This enum generates a monotonically increasing id for all Node types, -// and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask). -enum NodeType { -#define DFG_OP_ENUM(opcode, flags) opcode, - FOR_EACH_DFG_OP(DFG_OP_ENUM) -#undef DFG_OP_ENUM - LastNodeType -}; - -// Specifies the default flags for each node. -inline NodeFlags defaultFlags(NodeType op) -{ - switch (op) { -#define DFG_OP_ENUM(opcode, flags) case opcode: return flags; - FOR_EACH_DFG_OP(DFG_OP_ENUM) -#undef DFG_OP_ENUM - default: - ASSERT_NOT_REACHED(); - return 0; - } -} - // This type used in passing an immediate argument to Node constructor; // distinguishes an immediate value (typically an index into a CodeBlock data structure - // a constant index, argument, or identifier) from a NodeIndex. @@ -313,32 +79,32 @@ struct Node { // Construct a node with up to 3 children, no immediate value. Node(NodeType op, CodeOrigin codeOrigin, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) : codeOrigin(codeOrigin) - , children(NodeReferenceBlob::Fixed, child1, child2, child3) + , children(AdjacencyList::Fixed, child1, child2, child3) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_prediction(PredictNone) { setOpAndDefaultFlags(op); - ASSERT(!(flags & NodeHasVarArgs)); + ASSERT(!(m_flags & NodeHasVarArgs)); } // Construct a node with up to 3 children and an immediate value. Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) : codeOrigin(codeOrigin) - , children(NodeReferenceBlob::Fixed, child1, child2, child3) + , children(AdjacencyList::Fixed, child1, child2, child3) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_opInfo(imm.m_value) , m_prediction(PredictNone) { setOpAndDefaultFlags(op); - ASSERT(!(flags & NodeHasVarArgs)); + ASSERT(!(m_flags & NodeHasVarArgs)); } // Construct a node with up to 3 children and two immediate values. Node(NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, NodeIndex child1 = NoNode, NodeIndex child2 = NoNode, NodeIndex child3 = NoNode) : codeOrigin(codeOrigin) - , children(NodeReferenceBlob::Fixed, child1, child2, child3) + , children(AdjacencyList::Fixed, child1, child2, child3) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_opInfo(imm1.m_value) @@ -346,13 +112,13 @@ struct Node { , m_prediction(PredictNone) { setOpAndDefaultFlags(op); - ASSERT(!(flags & NodeHasVarArgs)); + ASSERT(!(m_flags & NodeHasVarArgs)); } // Construct a node with a variable number of children and two immediate values. Node(VarArgTag, NodeType op, CodeOrigin codeOrigin, OpInfo imm1, OpInfo imm2, unsigned firstChild, unsigned numChildren) : codeOrigin(codeOrigin) - , children(NodeReferenceBlob::Variable, firstChild, numChildren) + , children(AdjacencyList::Variable, firstChild, numChildren) , m_virtualRegister(InvalidVirtualRegister) , m_refCount(0) , m_opInfo(imm1.m_value) @@ -360,28 +126,64 @@ struct Node { , m_prediction(PredictNone) { setOpAndDefaultFlags(op); - ASSERT(flags & NodeHasVarArgs); + ASSERT(m_flags & NodeHasVarArgs); + } + + NodeType op() const { return static_cast<NodeType>(m_op); } + NodeFlags flags() const { return m_flags; } + + void setOp(NodeType op) + { + m_op = op; + } + + void setFlags(NodeFlags flags) + { + m_flags = flags; + } + + bool mergeFlags(NodeFlags flags) + { + NodeFlags newFlags = m_flags | flags; + if (newFlags == m_flags) + return false; + m_flags = newFlags; + return true; + } + + bool filterFlags(NodeFlags flags) + { + NodeFlags newFlags = m_flags & flags; + if (newFlags == m_flags) + return false; + m_flags = newFlags; + return true; + } + + bool clearFlags(NodeFlags flags) + { + return filterFlags(~flags); } void setOpAndDefaultFlags(NodeType op) { - this->op = op; - flags = defaultFlags(op); + m_op = op; + m_flags = defaultFlags(op); } bool mustGenerate() { - return flags & NodeMustGenerate; + return m_flags & NodeMustGenerate; } bool isConstant() { - return op == JSConstant; + return op() == JSConstant; } bool isWeakConstant() { - return op == WeakJSConstant; + return op() == WeakJSConstant; } bool hasConstant() @@ -402,7 +204,7 @@ struct Node { JSValue valueOfJSConstant(CodeBlock* codeBlock) { - if (op == WeakJSConstant) + if (op() == WeakJSConstant) return JSValue(weakConstant()); return codeBlock->constantRegister(FirstConstantRegisterIndex + constantNumber()).get(); } @@ -434,7 +236,7 @@ struct Node { bool hasVariableAccessData() { - switch (op) { + switch (op()) { case GetLocal: case SetLocal: case Phi: @@ -464,7 +266,7 @@ struct Node { bool hasIdentifier() { - switch (op) { + switch (op()) { case GetById: case GetByIdFlush: case PutById: @@ -486,13 +288,13 @@ struct Node { unsigned resolveGlobalDataIndex() { - ASSERT(op == ResolveGlobal); + ASSERT(op() == ResolveGlobal); return m_opInfo; } bool hasArithNodeFlags() { - switch (op) { + switch (op()) { case UInt32ToNumber: case ArithAdd: case ArithSub: @@ -515,33 +317,15 @@ struct Node { // to know if it can speculate on negative zero. NodeFlags arithNodeFlags() { - NodeFlags result = flags & NodeArithMask; - if (op == ArithMul) + NodeFlags result = m_flags; + if (op() == ArithMul || op() == ArithDiv || op() == ArithMod) return result; return result & ~NodeNeedsNegZero; } - void setArithNodeFlag(NodeFlags newFlags) - { - ASSERT(!(newFlags & ~NodeArithMask)); - - flags &= ~NodeArithMask; - flags |= newFlags; - } - - bool mergeArithNodeFlags(NodeFlags newFlags) - { - ASSERT(!(newFlags & ~NodeArithMask)); - newFlags = flags | newFlags; - if (newFlags == flags) - return false; - flags = newFlags; - return true; - } - bool hasConstantBuffer() { - return op == NewArrayBuffer; + return op() == NewArrayBuffer; } unsigned startConstant() @@ -558,7 +342,7 @@ struct Node { bool hasRegexpIndex() { - return op == NewRegexp; + return op() == NewRegexp; } unsigned regexpIndex() @@ -569,7 +353,7 @@ struct Node { bool hasVarNumber() { - return op == GetGlobalVar || op == PutGlobalVar || op == GetScopedVar || op == PutScopedVar; + return op() == GetGlobalVar || op() == PutGlobalVar || op() == GetScopedVar || op() == PutScopedVar; } unsigned varNumber() @@ -580,7 +364,7 @@ struct Node { bool hasScopeChainDepth() { - return op == GetScopeChain; + return op() == GetScopeChain; } unsigned scopeChainDepth() @@ -591,42 +375,42 @@ struct Node { bool hasResult() { - return flags & NodeResultMask; + return m_flags & NodeResultMask; } bool hasInt32Result() { - return (flags & NodeResultMask) == NodeResultInt32; + return (m_flags & NodeResultMask) == NodeResultInt32; } bool hasNumberResult() { - return (flags & NodeResultMask) == NodeResultNumber; + return (m_flags & NodeResultMask) == NodeResultNumber; } bool hasJSResult() { - return (flags & NodeResultMask) == NodeResultJS; + return (m_flags & NodeResultMask) == NodeResultJS; } bool hasBooleanResult() { - return (flags & NodeResultMask) == NodeResultBoolean; + return (m_flags & NodeResultMask) == NodeResultBoolean; } bool isJump() { - return op == Jump; + return op() == Jump; } bool isBranch() { - return op == Branch; + return op() == Branch; } bool isTerminal() { - switch (op) { + switch (op()) { case Jump: case Branch: case Return: @@ -676,7 +460,7 @@ struct Node { bool hasHeapPrediction() { - switch (op) { + switch (op()) { case GetById: case GetByIdFlush: case GetByVal: @@ -690,6 +474,9 @@ struct Node { case ResolveGlobal: case ArrayPop: case ArrayPush: + case RegExpExec: + case RegExpTest: + case GetGlobalVar: return true; default: return false; @@ -711,7 +498,7 @@ struct Node { bool hasFunctionCheckData() { - return op == CheckFunction; + return op() == CheckFunction; } JSFunction* function() @@ -722,7 +509,7 @@ struct Node { bool hasStructureTransitionData() { - return op == PutStructure; + return op() == PutStructure; } StructureTransitionData& structureTransitionData() @@ -733,7 +520,7 @@ struct Node { bool hasStructureSet() { - return op == CheckStructure; + return op() == CheckStructure; } StructureSet& structureSet() @@ -744,7 +531,7 @@ struct Node { bool hasStorageAccessData() { - return op == GetByOffset || op == PutByOffset; + return op() == GetByOffset || op() == PutByOffset; } unsigned storageAccessDataIndex() @@ -755,8 +542,8 @@ struct Node { bool hasFunctionDeclIndex() { - return op == NewFunction - || op == NewFunctionNoCheck; + return op() == NewFunction + || op() == NewFunctionNoCheck; } unsigned functionDeclIndex() @@ -767,7 +554,7 @@ struct Node { bool hasFunctionExprIndex() { - return op == NewFunctionExpression; + return op() == NewFunctionExpression; } unsigned functionExprIndex() @@ -830,41 +617,41 @@ struct Node { return !--m_refCount; } - NodeUse child1() + Edge child1() { - ASSERT(!(flags & NodeHasVarArgs)); + ASSERT(!(m_flags & NodeHasVarArgs)); return children.child1(); } // This is useful if you want to do a fast check on the first child // before also doing a check on the opcode. Use this with care and // avoid it if possible. - NodeUse child1Unchecked() + Edge child1Unchecked() { return children.child1Unchecked(); } - NodeUse child2() + Edge child2() { - ASSERT(!(flags & NodeHasVarArgs)); + ASSERT(!(m_flags & NodeHasVarArgs)); return children.child2(); } - NodeUse child3() + Edge child3() { - ASSERT(!(flags & NodeHasVarArgs)); + ASSERT(!(m_flags & NodeHasVarArgs)); return children.child3(); } unsigned firstChild() { - ASSERT(flags & NodeHasVarArgs); + ASSERT(m_flags & NodeHasVarArgs); return children.firstChild(); } unsigned numChildren() { - ASSERT(flags & NodeHasVarArgs); + ASSERT(m_flags & NodeHasVarArgs); return children.numChildren(); } @@ -890,12 +677,12 @@ struct Node { bool shouldSpeculateNumber() { - return isNumberPrediction(prediction()) || prediction() == PredictNone; + return isNumberPrediction(prediction()); } - bool shouldNotSpeculateInteger() + bool shouldSpeculateBoolean() { - return !!(prediction() & PredictDouble); + return isBooleanPrediction(prediction()); } bool shouldSpeculateFinalObject() @@ -913,27 +700,14 @@ struct Node { return isArrayPrediction(prediction()); } - bool shouldSpeculateByteArray() - { - return !!(prediction() & PredictByteArray); - } - bool shouldSpeculateInt8Array() { -#if CPU(X86) || CPU(X86_64) return isInt8ArrayPrediction(prediction()); -#else - return false; -#endif } bool shouldSpeculateInt16Array() { -#if CPU(X86) || CPU(X86_64) return isInt16ArrayPrediction(prediction()); -#else - return false; -#endif } bool shouldSpeculateInt32Array() @@ -963,11 +737,7 @@ struct Node { bool shouldSpeculateFloat32Array() { -#if CPU(X86) || CPU(X86_64) return isFloat32ArrayPrediction(prediction()); -#else - return false; -#endif } bool shouldSpeculateFloat64Array() @@ -1002,14 +772,12 @@ struct Node { static bool shouldSpeculateFinalObject(Node& op1, Node& op2) { - return (op1.shouldSpeculateFinalObject() && op2.shouldSpeculateObject()) - || (op1.shouldSpeculateObject() && op2.shouldSpeculateFinalObject()); + return op1.shouldSpeculateFinalObject() && op2.shouldSpeculateFinalObject(); } static bool shouldSpeculateArray(Node& op1, Node& op2) { - return (op1.shouldSpeculateArray() && op2.shouldSpeculateObject()) - || (op1.shouldSpeculateObject() && op2.shouldSpeculateArray()); + return op1.shouldSpeculateArray() && op2.shouldSpeculateArray(); } bool canSpeculateInteger() @@ -1030,14 +798,14 @@ struct Node { fprintf(out, ", @%u", child3().index()); } - uint16_t op; // real type is NodeType - NodeFlags flags; // Used to look up exception handling information (currently implemented as a bytecode index). CodeOrigin codeOrigin; // References to up to 3 children, or links to a variable length set of children. - NodeReferenceBlob children; + AdjacencyList children; private: + uint16_t m_op; // real type is NodeType + NodeFlags m_flags; // The virtual register number (spill location) associated with this . VirtualRegister m_virtualRegister; // The number of uses of the result of this operation (+1 for 'must generate' nodes, which have side-effects). diff --git a/Source/JavaScriptCore/dfg/DFGNode.cpp b/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp index c53817ba9..54e6b69b7 100644 --- a/Source/JavaScriptCore/dfg/DFGNode.cpp +++ b/Source/JavaScriptCore/dfg/DFGNodeFlags.cpp @@ -24,26 +24,80 @@ */ #include "config.h" -#include "DFGNode.h" +#include "DFGNodeFlags.h" #if ENABLE(DFG_JIT) +#include <wtf/BoundsCheckedPointer.h> + namespace JSC { namespace DFG { -const char* arithNodeFlagsAsString(NodeFlags flags) +const char* nodeFlagsAsString(NodeFlags flags) { - flags &= NodeArithMask; - if (!flags) return "<empty>"; - static const int size = 64; + static const int size = 128; static char description[size]; BoundsCheckedPointer<char> ptr(description, size); bool hasPrinted = false; + if (flags & NodeResultMask) { + switch (flags & NodeResultMask) { + case NodeResultJS: + ptr.strcat("ResultJS"); + break; + case NodeResultNumber: + ptr.strcat("ResultNumber"); + break; + case NodeResultInt32: + ptr.strcat("ResultInt32"); + break; + case NodeResultBoolean: + ptr.strcat("ResultBoolean"); + break; + case NodeResultStorage: + ptr.strcat("ResultStorage"); + break; + default: + ASSERT_NOT_REACHED(); + break; + } + hasPrinted = true; + } + + if (flags & NodeMustGenerate) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("MustGenerate"); + hasPrinted = true; + } + + if (flags & NodeHasVarArgs) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("HasVarArgs"); + hasPrinted = true; + } + + if (flags & NodeClobbersWorld) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("ClobbersWorld"); + hasPrinted = true; + } + + if (flags & NodeMightClobber) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("MightClobber"); + hasPrinted = true; + } + if (flags & NodeUsedAsNumber) { + if (hasPrinted) + ptr.strcat("|"); ptr.strcat("UsedAsNum"); hasPrinted = true; } @@ -69,6 +123,13 @@ const char* arithNodeFlagsAsString(NodeFlags flags) hasPrinted = true; } + if (flags & NodeUsedAsInt) { + if (hasPrinted) + ptr.strcat("|"); + ptr.strcat("UsedAsInt"); + hasPrinted = true; + } + *ptr++ = 0; return description; diff --git a/Source/JavaScriptCore/dfg/DFGNodeFlags.h b/Source/JavaScriptCore/dfg/DFGNodeFlags.h new file mode 100644 index 000000000..16d76655e --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGNodeFlags.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2012 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 DFGNodeFlags_h +#define DFGNodeFlags_h + +#include <wtf/Platform.h> + +#if ENABLE(DFG_JIT) + +#include <wtf/StdLibExtras.h> + +namespace JSC { namespace DFG { + +// Entries in the NodeType enum (below) are composed of an id, a result type (possibly none) +// and some additional informative flags (must generate, is constant, etc). +#define NodeResultMask 0xF +#define NodeResultJS 0x1 +#define NodeResultNumber 0x2 +#define NodeResultInt32 0x3 +#define NodeResultBoolean 0x4 +#define NodeResultStorage 0x5 + +#define NodeMustGenerate 0x10 // set on nodes that have side effects, and may not trivially be removed by DCE. +#define NodeHasVarArgs 0x20 +#define NodeClobbersWorld 0x40 +#define NodeMightClobber 0x80 + +#define NodeBehaviorMask 0x300 +#define NodeMayOverflow 0x100 +#define NodeMayNegZero 0x200 + +#define NodeBackPropMask 0x1C00 +#define NodeUseBottom 0x000 +#define NodeUsedAsNumber 0x400 // The result of this computation may be used in a context that observes fractional results. +#define NodeNeedsNegZero 0x800 // The result of this computation may be used in a context that observes -0. +#define NodeUsedAsValue (NodeUsedAsNumber | NodeNeedsNegZero) +#define NodeUsedAsInt 0x1000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values. + +typedef uint16_t NodeFlags; + +static inline bool nodeUsedAsNumber(NodeFlags flags) +{ + return !!(flags & NodeUsedAsNumber); +} + +static inline bool nodeCanTruncateInteger(NodeFlags flags) +{ + return !nodeUsedAsNumber(flags); +} + +static inline bool nodeCanIgnoreNegativeZero(NodeFlags flags) +{ + return !(flags & NodeNeedsNegZero); +} + +static inline bool nodeMayOverflow(NodeFlags flags) +{ + return !!(flags & NodeMayOverflow); +} + +static inline bool nodeCanSpeculateInteger(NodeFlags flags) +{ + if (flags & NodeMayOverflow) + return !nodeUsedAsNumber(flags); + + if (flags & NodeMayNegZero) + return nodeCanIgnoreNegativeZero(flags); + + return true; +} + +const char* nodeFlagsAsString(NodeFlags); + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGNodeFlags_h + diff --git a/Source/JavaScriptCore/dfg/DFGNodeType.h b/Source/JavaScriptCore/dfg/DFGNodeType.h new file mode 100644 index 000000000..8a3828c31 --- /dev/null +++ b/Source/JavaScriptCore/dfg/DFGNodeType.h @@ -0,0 +1,237 @@ +/* + * Copyright (C) 2012 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 DFGNodeType_h +#define DFGNodeType_h + +#include <wtf/Platform.h> + +#if ENABLE(DFG_JIT) + +#include "DFGNodeFlags.h" + +namespace JSC { namespace DFG { + +// This macro defines a set of information about all known node types, used to populate NodeId, NodeType below. +#define FOR_EACH_DFG_OP(macro) \ + /* A constant in the CodeBlock's constant pool. */\ + macro(JSConstant, NodeResultJS) \ + \ + /* A constant not in the CodeBlock's constant pool. Uses get patched to jumps that exit the */\ + /* code block. */\ + macro(WeakJSConstant, NodeResultJS) \ + \ + /* Nodes for handling functions (both as call and as construct). */\ + macro(ConvertThis, NodeResultJS) \ + macro(CreateThis, NodeResultJS) /* Note this is not MustGenerate since we're returning it anyway. */ \ + macro(GetCallee, NodeResultJS) \ + \ + /* Nodes for local variable access. */\ + macro(GetLocal, NodeResultJS) \ + macro(SetLocal, 0) \ + macro(Phantom, NodeMustGenerate) \ + macro(Nop, 0) \ + macro(Phi, 0) \ + macro(Flush, NodeMustGenerate) \ + \ + /* Marker for arguments being set. */\ + macro(SetArgument, 0) \ + \ + /* Hint that inlining begins here. No code is generated for this node. It's only */\ + /* used for copying OSR data into inline frame data, to support reification of */\ + /* call frames of inlined functions. */\ + macro(InlineStart, 0) \ + \ + /* Nodes for bitwise operations. */\ + macro(BitAnd, NodeResultInt32) \ + macro(BitOr, NodeResultInt32) \ + macro(BitXor, NodeResultInt32) \ + macro(BitLShift, NodeResultInt32) \ + macro(BitRShift, NodeResultInt32) \ + macro(BitURShift, NodeResultInt32) \ + /* Bitwise operators call ToInt32 on their operands. */\ + macro(ValueToInt32, NodeResultInt32 | NodeMustGenerate) \ + /* Used to box the result of URShift nodes (result has range 0..2^32-1). */\ + macro(UInt32ToNumber, NodeResultNumber) \ + \ + /* Used to cast known integers to doubles, so as to separate the double form */\ + /* of the value from the integer form. */\ + macro(Int32ToDouble, NodeResultNumber) \ + /* Used to speculate that a double value is actually an integer. */\ + macro(DoubleAsInt32, NodeResultInt32) \ + /* Used to record places where we must check if a value is a number. */\ + macro(CheckNumber, NodeMustGenerate) \ + \ + /* Nodes for arithmetic operations. */\ + macro(ArithAdd, NodeResultNumber | NodeMustGenerate) \ + macro(ArithSub, NodeResultNumber | NodeMustGenerate) \ + macro(ArithNegate, NodeResultNumber | NodeMustGenerate) \ + macro(ArithMul, NodeResultNumber | NodeMustGenerate) \ + macro(ArithDiv, NodeResultNumber | NodeMustGenerate) \ + macro(ArithMod, NodeResultNumber | NodeMustGenerate) \ + macro(ArithAbs, NodeResultNumber | NodeMustGenerate) \ + macro(ArithMin, NodeResultNumber | NodeMustGenerate) \ + macro(ArithMax, NodeResultNumber | NodeMustGenerate) \ + macro(ArithSqrt, NodeResultNumber | NodeMustGenerate) \ + \ + /* Add of values may either be arithmetic, or result in string concatenation. */\ + macro(ValueAdd, NodeResultJS | NodeMustGenerate | NodeMightClobber) \ + \ + /* Property access. */\ + /* PutByValAlias indicates a 'put' aliases a prior write to the same property. */\ + /* Since a put to 'length' may invalidate optimizations here, */\ + /* this must be the directly subsequent property put. */\ + macro(GetByVal, NodeResultJS | NodeMustGenerate | NodeMightClobber) \ + macro(PutByVal, NodeMustGenerate | NodeClobbersWorld) \ + macro(PutByValAlias, NodeMustGenerate | NodeClobbersWorld) \ + macro(GetById, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ + macro(GetByIdFlush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ + macro(PutById, NodeMustGenerate | NodeClobbersWorld) \ + macro(PutByIdDirect, NodeMustGenerate | NodeClobbersWorld) \ + macro(CheckStructure, NodeMustGenerate) \ + macro(PutStructure, NodeMustGenerate | NodeClobbersWorld) \ + macro(GetPropertyStorage, NodeResultStorage) \ + macro(GetIndexedPropertyStorage, NodeMustGenerate | NodeResultStorage) \ + macro(GetByOffset, NodeResultJS) \ + macro(PutByOffset, NodeMustGenerate | NodeClobbersWorld) \ + macro(GetArrayLength, NodeResultInt32) \ + macro(GetStringLength, NodeResultInt32) \ + macro(GetInt8ArrayLength, NodeResultInt32) \ + macro(GetInt16ArrayLength, NodeResultInt32) \ + macro(GetInt32ArrayLength, NodeResultInt32) \ + macro(GetUint8ArrayLength, NodeResultInt32) \ + macro(GetUint8ClampedArrayLength, NodeResultInt32) \ + macro(GetUint16ArrayLength, NodeResultInt32) \ + macro(GetUint32ArrayLength, NodeResultInt32) \ + macro(GetFloat32ArrayLength, NodeResultInt32) \ + macro(GetFloat64ArrayLength, NodeResultInt32) \ + macro(GetScopeChain, NodeResultJS) \ + macro(GetScopedVar, NodeResultJS | NodeMustGenerate) \ + macro(PutScopedVar, NodeMustGenerate | NodeClobbersWorld) \ + macro(GetGlobalVar, NodeResultJS | NodeMustGenerate) \ + macro(PutGlobalVar, NodeMustGenerate | NodeClobbersWorld) \ + macro(CheckFunction, NodeMustGenerate) \ + \ + /* Optimizations for array mutation. */\ + macro(ArrayPush, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ + macro(ArrayPop, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ + \ + /* Optimizations for regular expression matching. */\ + macro(RegExpExec, NodeResultJS | NodeMustGenerate) \ + macro(RegExpTest, NodeResultJS | NodeMustGenerate) \ + \ + /* Optimizations for string access */ \ + macro(StringCharCodeAt, NodeResultInt32) \ + macro(StringCharAt, NodeResultJS) \ + \ + /* Nodes for comparison operations. */\ + macro(CompareLess, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ + macro(CompareLessEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ + macro(CompareGreater, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ + macro(CompareGreaterEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ + macro(CompareEq, NodeResultBoolean | NodeMustGenerate | NodeMightClobber) \ + macro(CompareStrictEq, NodeResultBoolean) \ + \ + /* Calls. */\ + macro(Call, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \ + macro(Construct, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \ + \ + /* Allocations. */\ + macro(NewObject, NodeResultJS) \ + macro(NewArray, NodeResultJS | NodeHasVarArgs) \ + macro(NewArrayBuffer, NodeResultJS) \ + macro(NewRegexp, NodeResultJS) \ + \ + /* Resolve nodes. */\ + macro(Resolve, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ + macro(ResolveBase, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ + macro(ResolveBaseStrictPut, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ + macro(ResolveGlobal, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ + \ + /* Nodes for misc operations. */\ + macro(Breakpoint, NodeMustGenerate | NodeClobbersWorld) \ + macro(CheckHasInstance, NodeMustGenerate) \ + macro(InstanceOf, NodeResultBoolean) \ + macro(IsUndefined, NodeResultBoolean) \ + macro(IsBoolean, NodeResultBoolean) \ + macro(IsNumber, NodeResultBoolean) \ + macro(IsString, NodeResultBoolean) \ + macro(IsObject, NodeResultBoolean) \ + macro(IsFunction, NodeResultBoolean) \ + macro(LogicalNot, NodeResultBoolean | NodeMightClobber) \ + macro(ToPrimitive, NodeResultJS | NodeMustGenerate | NodeClobbersWorld) \ + macro(StrCat, NodeResultJS | NodeMustGenerate | NodeHasVarArgs | NodeClobbersWorld) \ + \ + /* Nodes used for activations. Activation support works by having it anchored at */\ + /* epilgoues via TearOffActivation, and all CreateActivation nodes kept alive by */\ + /* being threaded with each other. */\ + macro(CreateActivation, NodeResultJS) \ + macro(TearOffActivation, NodeMustGenerate) \ + \ + /* Nodes for creating functions. */\ + macro(NewFunctionNoCheck, NodeResultJS) \ + macro(NewFunction, NodeResultJS) \ + macro(NewFunctionExpression, NodeResultJS) \ + \ + /* Block terminals. */\ + macro(Jump, NodeMustGenerate) \ + macro(Branch, NodeMustGenerate) \ + macro(Return, NodeMustGenerate) \ + macro(Throw, NodeMustGenerate) \ + macro(ThrowReferenceError, NodeMustGenerate) \ + \ + /* This is a pseudo-terminal. It means that execution should fall out of DFG at */\ + /* this point, but execution does continue in the basic block - just in a */\ + /* different compiler. */\ + macro(ForceOSRExit, NodeMustGenerate) + +// This enum generates a monotonically increasing id for all Node types, +// and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask). +enum NodeType { +#define DFG_OP_ENUM(opcode, flags) opcode, + FOR_EACH_DFG_OP(DFG_OP_ENUM) +#undef DFG_OP_ENUM + LastNodeType +}; + +// Specifies the default flags for each node. +inline NodeFlags defaultFlags(NodeType op) +{ + switch (op) { +#define DFG_OP_ENUM(opcode, flags) case opcode: return flags; + FOR_EACH_DFG_OP(DFG_OP_ENUM) +#undef DFG_OP_ENUM + default: + ASSERT_NOT_REACHED(); + return 0; + } +} + +} } // namespace JSC::DFG + +#endif // ENABLE(DFG_JIT) + +#endif // DFGNodeType_h + diff --git a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp index 65f4cfcdd..21c76c6fe 100644 --- a/Source/JavaScriptCore/dfg/DFGOSREntry.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSREntry.cpp @@ -141,13 +141,11 @@ void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIn dataLog(" OSR should succeed.\n"); #endif -#if USE(JSVALUE64) // 3) Perform data format conversions. for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) { if (entry->m_localsForcedDouble.get(local)) *bitwise_cast<double*>(exec->registers() + local) = exec->registers()[local].jsValue().asNumber(); } -#endif // 4) Fix the call frame. diff --git a/Source/JavaScriptCore/dfg/DFGOSREntry.h b/Source/JavaScriptCore/dfg/DFGOSREntry.h index e38a6ceb9..a5c264cd6 100644 --- a/Source/JavaScriptCore/dfg/DFGOSREntry.h +++ b/Source/JavaScriptCore/dfg/DFGOSREntry.h @@ -27,7 +27,7 @@ #define DFGOSREntry_h #include "DFGAbstractValue.h" -#include "DFGOperands.h" +#include "Operands.h" #include <wtf/BitVector.h> namespace JSC { diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp index 95e4d8bf2..844be2a7c 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExit.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExit.cpp @@ -33,17 +33,28 @@ namespace JSC { namespace DFG { +static unsigned computeNumVariablesForCodeOrigin( + CodeBlock* codeBlock, const CodeOrigin& codeOrigin) +{ + if (!codeOrigin.inlineCallFrame) + return codeBlock->m_numCalleeRegisters; + return + codeOrigin.inlineCallFrame->stackOffset + + baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame)->m_numCalleeRegisters; +} + OSRExit::OSRExit(ExitKind kind, JSValueSource jsValueSource, MethodOfGettingAValueProfile valueProfile, MacroAssembler::Jump check, SpeculativeJIT* jit, unsigned recoveryIndex) : m_jsValueSource(jsValueSource) , m_valueProfile(valueProfile) , m_check(check) , m_nodeIndex(jit->m_compileIndex) , m_codeOrigin(jit->m_codeOriginForOSR) + , m_codeOriginForExitProfile(m_codeOrigin) , m_recoveryIndex(recoveryIndex) , m_kind(kind) , m_count(0) , m_arguments(jit->m_arguments.size()) - , m_variables(jit->m_variables.size()) + , m_variables(computeNumVariablesForCodeOrigin(jit->m_jit.graph().m_profiledBlock, jit->m_codeOriginForOSR)) , m_lastSetOperand(jit->m_lastSetOperand) { ASSERT(m_codeOrigin.isSet()); @@ -67,7 +78,7 @@ bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* dfgCodeBlock, Code if (static_cast<double>(m_count) / dfgCodeBlock->speculativeFailCounter() <= Options::osrExitProminenceForFrequentExitSite) return false; - return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOrigin, profiledCodeBlock)->addFrequentExitSite(FrequentExitSite(m_codeOrigin.bytecodeIndex, m_kind)); + return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOriginForExitProfile, profiledCodeBlock)->addFrequentExitSite(FrequentExitSite(m_codeOriginForExitProfile.bytecodeIndex, m_kind)); } } } // namespace JSC::DFG diff --git a/Source/JavaScriptCore/dfg/DFGOSRExit.h b/Source/JavaScriptCore/dfg/DFGOSRExit.h index c28f7cbef..841fdddb3 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExit.h +++ b/Source/JavaScriptCore/dfg/DFGOSRExit.h @@ -35,9 +35,9 @@ #include "DFGCorrectableJumpPoint.h" #include "DFGExitProfile.h" #include "DFGGPRInfo.h" -#include "DFGOperands.h" #include "MacroAssembler.h" #include "MethodOfGettingAValueProfile.h" +#include "Operands.h" #include "ValueProfile.h" #include "ValueRecovery.h" #include <wtf/Vector.h> @@ -93,6 +93,7 @@ struct OSRExit { CorrectableJumpPoint m_check; NodeIndex m_nodeIndex; CodeOrigin m_codeOrigin; + CodeOrigin m_codeOriginForExitProfile; unsigned m_recoveryIndex; diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp index a195ee3ba..a63f671bc 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp @@ -74,7 +74,8 @@ void compileOSRExit(ExecState* exec) { AssemblyHelpers jit(globalData, codeBlock); OSRExitCompiler exitCompiler(jit); - + + jit.jitAssertHasValidCallFrame(); exitCompiler.compileExit(exit, recovery); LinkBuffer patchBuffer(*globalData, &jit, codeBlock); @@ -95,6 +96,64 @@ void compileOSRExit(ExecState* exec) } // extern "C" +void OSRExitCompiler::handleExitCounts(const OSRExit& exit) +{ + m_jit.add32(AssemblyHelpers::TrustedImm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count)); + + m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.codeBlock()), GPRInfo::regT0); + + AssemblyHelpers::JumpList tooFewFails; + + if (exit.m_kind == InadequateCoverage) { + // Proceed based on the assumption that we can profitably optimize this code once + // it has executed enough times. + + m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfForcedOSRExitCounter()), GPRInfo::regT2); + m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1); + m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2); + m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1); + m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfForcedOSRExitCounter())); + m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter())); + + tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(Options::forcedOSRExitCountForReoptimization))); + } else { + // Proceed based on the assumption that we can handle these exits so long as they + // don't get too frequent. + + m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()), GPRInfo::regT2); + m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1); + m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2); + m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1); + m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter())); + m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter())); + + m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0); + + tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(m_jit.codeBlock()->largeFailCountThreshold()))); + m_jit.mul32(AssemblyHelpers::TrustedImm32(Options::desiredSpeculativeSuccessFailRatio), GPRInfo::regT2, GPRInfo::regT2); + + tooFewFails.append(m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1)); + } + + // Reoptimize as soon as possible. + m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); + AssemblyHelpers::Jump doneAdjusting = m_jit.jump(); + + tooFewFails.link(&m_jit); + + // Adjust the execution counter such that the target is to only optimize after a while. + int32_t targetValue = + ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt( + m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp(), + m_jit.baselineCodeBlock()); + m_jit.store32(AssemblyHelpers::TrustedImm32(-targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); + m_jit.store32(AssemblyHelpers::TrustedImm32(targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); + m_jit.store32(AssemblyHelpers::TrustedImm32(ExecutionCounter::formattedTotalCount(targetValue)), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionTotalCount())); + + doneAdjusting.link(&m_jit); +} + } } // namespace JSC::DFG #endif // ENABLE(DFG_JIT) diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h index e08362f22..523644982 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h +++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler.h @@ -70,6 +70,8 @@ private: return result; } + void handleExitCounts(const OSRExit&); + AssemblyHelpers& m_jit; Vector<unsigned> m_poisonScratchIndices; }; diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp index bd45020d1..3c7f27579 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler32_64.cpp @@ -562,42 +562,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco // counter to 0; otherwise we set the counter to // counterValueForOptimizeAfterWarmUp(). - m_jit.add32(AssemblyHelpers::TrustedImm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count)); - - m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.codeBlock()), GPRInfo::regT0); - - m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()), GPRInfo::regT2); - m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1); - m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2); - m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1); - m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter())); - m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter())); - - m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0); - - AssemblyHelpers::Jump fewFails = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(m_jit.codeBlock()->largeFailCountThreshold())); - m_jit.mul32(AssemblyHelpers::TrustedImm32(Options::desiredSpeculativeSuccessFailRatio), GPRInfo::regT2, GPRInfo::regT2); - - AssemblyHelpers::Jump lowFailRate = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1); - - // Reoptimize as soon as possible. - m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); - m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); - AssemblyHelpers::Jump doneAdjusting = m_jit.jump(); - - fewFails.link(&m_jit); - lowFailRate.link(&m_jit); - - // Adjust the execution counter such that the target is to only optimize after a while. - int32_t targetValue = - ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt( - m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp(), - m_jit.baselineCodeBlock()); - m_jit.store32(AssemblyHelpers::TrustedImm32(-targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); - m_jit.store32(AssemblyHelpers::TrustedImm32(targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); - m_jit.store32(AssemblyHelpers::TrustedImm32(ExecutionCounter::formattedTotalCount(targetValue)), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionTotalCount())); - - doneAdjusting.link(&m_jit); + handleExitCounts(exit); // 12) Load the result of the last bytecode operation into regT0. diff --git a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp index 91a515c48..86d47b90e 100644 --- a/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp +++ b/Source/JavaScriptCore/dfg/DFGOSRExitCompiler64.cpp @@ -541,42 +541,7 @@ void OSRExitCompiler::compileExit(const OSRExit& exit, SpeculationRecovery* reco // counter to 0; otherwise we set the counter to // counterValueForOptimizeAfterWarmUp(). - m_jit.add32(AssemblyHelpers::TrustedImm32(1), AssemblyHelpers::AbsoluteAddress(&exit.m_count)); - - m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.codeBlock()), GPRInfo::regT0); - - m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter()), GPRInfo::regT2); - m_jit.load32(AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter()), GPRInfo::regT1); - m_jit.add32(AssemblyHelpers::TrustedImm32(1), GPRInfo::regT2); - m_jit.add32(AssemblyHelpers::TrustedImm32(-1), GPRInfo::regT1); - m_jit.store32(GPRInfo::regT2, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeFailCounter())); - m_jit.store32(GPRInfo::regT1, AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfSpeculativeSuccessCounter())); - - m_jit.move(AssemblyHelpers::TrustedImmPtr(m_jit.baselineCodeBlock()), GPRInfo::regT0); - - AssemblyHelpers::Jump fewFails = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(m_jit.codeBlock()->largeFailCountThreshold())); - m_jit.mul32(AssemblyHelpers::TrustedImm32(Options::desiredSpeculativeSuccessFailRatio), GPRInfo::regT2, GPRInfo::regT2); - - AssemblyHelpers::Jump lowFailRate = m_jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1); - - // Reoptimize as soon as possible. - m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); - m_jit.store32(AssemblyHelpers::TrustedImm32(0), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); - AssemblyHelpers::Jump doneAdjusting = m_jit.jump(); - - fewFails.link(&m_jit); - lowFailRate.link(&m_jit); - - // Adjust the execution counter such that the target is to only optimize after a while. - int32_t targetValue = - ExecutionCounter::applyMemoryUsageHeuristicsAndConvertToInt( - m_jit.baselineCodeBlock()->counterValueForOptimizeAfterLongWarmUp(), - m_jit.baselineCodeBlock()); - m_jit.store32(AssemblyHelpers::TrustedImm32(-targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter())); - m_jit.store32(AssemblyHelpers::TrustedImm32(targetValue), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionActiveThreshold())); - m_jit.store32(AssemblyHelpers::TrustedImm32(ExecutionCounter::formattedTotalCount(targetValue)), AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecutionTotalCount())); - - doneAdjusting.link(&m_jit); + handleExitCounts(exit); // 14) Load the result of the last bytecode operation into regT0. diff --git a/Source/JavaScriptCore/dfg/DFGOperations.cpp b/Source/JavaScriptCore/dfg/DFGOperations.cpp index 304c54d95..0e6e2f972 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.cpp +++ b/Source/JavaScriptCore/dfg/DFGOperations.cpp @@ -34,7 +34,6 @@ #include <wtf/InlineASM.h> #include "Interpreter.h" #include "JSActivation.h" -#include "JSByteArray.h" #include "JSGlobalData.h" #include "JSStaticScopeObject.h" #include "Operations.h" @@ -60,6 +59,7 @@ #define FUNCTION_WRAPPER_WITH_RETURN_ADDRESS(function, offset) \ asm( \ + ".text" "\n" \ ".globl " SYMBOL_STRING(function) "\n" \ HIDE_SYMBOL(function) "\n" \ SYMBOL_STRING(function) ":" "\n" \ @@ -83,7 +83,7 @@ ".thumb" "\n" \ ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \ SYMBOL_STRING(function) ":" "\n" \ - "cpy a2, lr" "\n" \ + "mov a2, lr" "\n" \ "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \ ); @@ -96,7 +96,7 @@ ".thumb" "\n" \ ".thumb_func " THUMB_FUNC_PARAM(function) "\n" \ SYMBOL_STRING(function) ":" "\n" \ - "cpy a4, lr" "\n" \ + "mov a4, lr" "\n" \ "b " SYMBOL_STRING_RELOCATION(function) "WithReturnAddress" "\n" \ ); @@ -149,12 +149,13 @@ namespace JSC { namespace DFG { template<bool strict> static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, JSValue value) { - JSGlobalData* globalData = &exec->globalData(); - + JSGlobalData& globalData = exec->globalData(); + NativeCallFrameTracer tracer(&globalData, exec); + if (isJSArray(baseValue)) { JSArray* array = asArray(baseValue); if (array->canSetIndex(index)) { - array->setIndex(*globalData, index, value); + array->setIndex(globalData, index, value); return; } @@ -162,20 +163,6 @@ static inline void putByVal(ExecState* exec, JSValue baseValue, uint32_t index, return; } - if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(index)) { - JSByteArray* byteArray = asByteArray(baseValue); - // FIXME: the JITstub used to relink this to an optimized form! - if (value.isInt32()) { - byteArray->setIndex(index, value.asInt32()); - return; - } - - if (value.isNumber()) { - byteArray->setIndex(index, value.asNumber()); - return; - } - } - baseValue.putByIndex(exec, index, value, strict); } @@ -230,7 +217,8 @@ inline JSCell* createThis(ExecState* exec, JSCell* prototype, JSFunction* constr #endif JSGlobalData& globalData = exec->globalData(); - + NativeCallFrameTracer tracer(&globalData, exec); + Structure* structure; if (prototype->isObject()) structure = asObject(prototype)->inheritorID(globalData); @@ -245,7 +233,7 @@ JSCell* DFG_OPERATION operationCreateThis(ExecState* exec, JSCell* prototype) JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); - return createThis(exec, prototype, asFunction(exec->callee())); + return createThis(exec, prototype, jsCast<JSFunction*>(exec->callee())); } JSCell* DFG_OPERATION operationCreateThisInlined(ExecState* exec, JSCell* prototype, JSCell* constructor) @@ -253,7 +241,7 @@ JSCell* DFG_OPERATION operationCreateThisInlined(ExecState* exec, JSCell* protot JSGlobalData* globalData = &exec->globalData(); NativeCallFrameTracer tracer(globalData, exec); - return createThis(exec, prototype, static_cast<JSFunction*>(constructor)); + return createThis(exec, prototype, jsCast<JSFunction*>(constructor)); } JSCell* DFG_OPERATION operationNewObject(ExecState* exec) @@ -293,6 +281,9 @@ EncodedJSValue DFG_OPERATION operationValueAddNotNumber(ExecState* exec, Encoded static inline EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t index) { + JSGlobalData& globalData = exec->globalData(); + NativeCallFrameTracer tracer(&globalData, exec); + // FIXME: the JIT used to handle these in compiled code! if (isJSArray(base) && asArray(base)->canGetIndex(index)) return JSValue::encode(asArray(base)->getIndex(index)); @@ -301,10 +292,6 @@ static inline EncodedJSValue getByVal(ExecState* exec, JSCell* base, uint32_t in if (isJSString(base) && asString(base)->canGetIndex(index)) return JSValue::encode(asString(base)->getIndex(exec, index)); - // FIXME: the JITstub used to relink this to an optimized form! - if (isJSByteArray(base) && asByteArray(base)->canAccessIndex(index)) - return JSValue::encode(asByteArray(base)->getIndex(exec, index)); - return JSValue::encode(JSValue(base).get(exec, index)); } @@ -502,6 +489,34 @@ EncodedJSValue DFG_OPERATION operationArrayPush(ExecState* exec, EncodedJSValue array->push(exec, JSValue::decode(encodedValue)); return JSValue::encode(jsNumber(array->length())); } + +EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState* exec, JSCell* base, JSCell* argument) +{ + JSGlobalData& globalData = exec->globalData(); + NativeCallFrameTracer tracer(&globalData, exec); + + if (!base->inherits(&RegExpObject::s_info)) + return throwVMTypeError(exec); + + ASSERT(argument->isString() || argument->isObject()); + JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec); + return JSValue::encode(asRegExpObject(base)->exec(exec, input)); +} + +size_t DFG_OPERATION operationRegExpTest(ExecState* exec, JSCell* base, JSCell* argument) +{ + JSGlobalData& globalData = exec->globalData(); + NativeCallFrameTracer tracer(&globalData, exec); + + if (!base->inherits(&RegExpObject::s_info)) { + throwTypeError(exec); + return false; + } + + ASSERT(argument->isString() || argument->isObject()); + JSString* input = argument->isString() ? asString(argument) : asObject(argument)->toString(exec); + return asRegExpObject(base)->test(exec, input); +} EncodedJSValue DFG_OPERATION operationArrayPop(ExecState* exec, JSArray* array) { @@ -770,6 +785,8 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ ASSERT(callType != CallTypeJS); if (callType == CallTypeHost) { + NativeCallFrameTracer tracer(globalData, execCallee); + execCallee->setCallee(asObject(callee)); globalData->hostCallReturnValue = JSValue::decode(callData.native.function(execCallee)); if (globalData->exception) return 0; @@ -790,6 +807,8 @@ static void* handleHostCall(ExecState* execCallee, JSValue callee, CodeSpecializ ASSERT(constructType != ConstructTypeJS); if (constructType == ConstructTypeHost) { + NativeCallFrameTracer tracer(globalData, execCallee); + execCallee->setCallee(asObject(callee)); globalData->hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee)); if (globalData->exception) return 0; @@ -813,7 +832,7 @@ inline void* linkFor(ExecState* execCallee, ReturnAddressPtr returnAddress, Code if (!calleeAsFunctionCell) return handleHostCall(execCallee, calleeAsValue, kind); - JSFunction* callee = asFunction(calleeAsFunctionCell); + JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell); execCallee->setScopeChain(callee->scopeUnchecked()); ExecutableBase* executable = callee->executable(); @@ -865,7 +884,7 @@ inline void* virtualFor(ExecState* execCallee, CodeSpecializationKind kind) if (UNLIKELY(!calleeAsFunctionCell)) return handleHostCall(execCallee, calleeAsValue, kind); - JSFunction* function = asFunction(calleeAsFunctionCell); + JSFunction* function = jsCast<JSFunction*>(calleeAsFunctionCell); execCallee->setScopeChain(function->scopeUnchecked()); ExecutableBase* executable = function->executable(); if (UNLIKELY(!executable->hasJITCodeFor(kind))) { @@ -976,11 +995,15 @@ EncodedJSValue DFG_OPERATION operationNewArray(ExecState* exec, void* start, siz EncodedJSValue DFG_OPERATION operationNewArrayBuffer(ExecState* exec, size_t start, size_t size) { + JSGlobalData& globalData = exec->globalData(); + NativeCallFrameTracer tracer(&globalData, exec); return JSValue::encode(constructArray(exec, exec->codeBlock()->constantBuffer(start), size)); } EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr) { + JSGlobalData& globalData = exec->globalData(); + NativeCallFrameTracer tracer(&globalData, exec); RegExp* regexp = static_cast<RegExp*>(regexpPtr); if (!regexp->isValid()) { throwError(exec, createSyntaxError(exec, "Invalid flags supplied to RegExp constructor.")); @@ -993,6 +1016,7 @@ EncodedJSValue DFG_OPERATION operationNewRegexp(ExecState* exec, void* regexpPtr JSCell* DFG_OPERATION operationCreateActivation(ExecState* exec) { JSGlobalData& globalData = exec->globalData(); + NativeCallFrameTracer tracer(&globalData, exec); JSActivation* activation = JSActivation::create( globalData, exec, static_cast<FunctionExecutable*>(exec->codeBlock()->ownerExecutable())); exec->setScopeChain(exec->scopeChain()->push(activation)); @@ -1003,12 +1027,16 @@ void DFG_OPERATION operationTearOffActivation(ExecState* exec, JSCell* activatio { ASSERT(activation); ASSERT(activation->inherits(&JSActivation::s_info)); - static_cast<JSActivation*>(activation)->tearOff(exec->globalData()); + JSGlobalData& globalData = exec->globalData(); + NativeCallFrameTracer tracer(&globalData, exec); + jsCast<JSActivation*>(activation)->tearOff(exec->globalData()); } JSCell* DFG_OPERATION operationNewFunction(ExecState* exec, JSCell* functionExecutable) { ASSERT(functionExecutable->inherits(&FunctionExecutable::s_info)); + JSGlobalData& globalData = exec->globalData(); + NativeCallFrameTracer tracer(&globalData, exec); return static_cast<FunctionExecutable*>(functionExecutable)->make(exec, exec->scopeChain()); } @@ -1027,6 +1055,21 @@ JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState* exec, JSCell* fu return function; } +size_t DFG_OPERATION operationIsObject(EncodedJSValue value) +{ + return jsIsObjectType(JSValue::decode(value)); +} + +size_t DFG_OPERATION operationIsFunction(EncodedJSValue value) +{ + return jsIsFunctionType(JSValue::decode(value)); +} + +double DFG_OPERATION operationFModOnInts(int32_t a, int32_t b) +{ + return fmod(a, b); +} + DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState* exec, uint32_t callIndex) { JSGlobalData* globalData = &exec->globalData(); @@ -1096,7 +1139,17 @@ void DFG_OPERATION debugOperationPrintSpeculationFailure(ExecState* exec, void* SpeculationFailureDebugInfo* debugInfo = static_cast<SpeculationFailureDebugInfo*>(debugInfoRaw); CodeBlock* codeBlock = debugInfo->codeBlock; CodeBlock* alternative = codeBlock->alternative(); - dataLog("Speculation failure in %p at @%u with executeCounter = %d, reoptimizationRetryCounter = %u, optimizationDelayCounter = %u, success/fail %u/%u\n", codeBlock, debugInfo->nodeIndex, alternative ? alternative->jitExecuteCounter() : 0, alternative ? alternative->reoptimizationRetryCounter() : 0, alternative ? alternative->optimizationDelayCounter() : 0, codeBlock->speculativeSuccessCounter(), codeBlock->speculativeFailCounter()); + dataLog("Speculation failure in %p at @%u with executeCounter = %d, " + "reoptimizationRetryCounter = %u, optimizationDelayCounter = %u, " + "success/fail %u/(%u+%u)\n", + codeBlock, + debugInfo->nodeIndex, + alternative ? alternative->jitExecuteCounter() : 0, + alternative ? alternative->reoptimizationRetryCounter() : 0, + alternative ? alternative->optimizationDelayCounter() : 0, + codeBlock->speculativeSuccessCounter(), + codeBlock->speculativeFailCounter(), + codeBlock->forcedOSRExitCounter()); } #endif @@ -1120,6 +1173,7 @@ SYMBOL_STRING(getHostCallReturnValue) ":" "\n" ); #elif CPU(X86) asm ( +".text" "\n" \ ".globl " SYMBOL_STRING(getHostCallReturnValue) "\n" HIDE_SYMBOL(getHostCallReturnValue) "\n" SYMBOL_STRING(getHostCallReturnValue) ":" "\n" @@ -1137,7 +1191,7 @@ HIDE_SYMBOL(getHostCallReturnValue) "\n" ".thumb_func " THUMB_FUNC_PARAM(getHostCallReturnValue) "\n" SYMBOL_STRING(getHostCallReturnValue) ":" "\n" "ldr r5, [r5, #-40]" "\n" - "cpy r0, r5" "\n" + "mov r0, r5" "\n" "b " SYMBOL_STRING_RELOCATION(getHostCallReturnValueWithExecState) "\n" ); #endif diff --git a/Source/JavaScriptCore/dfg/DFGOperations.h b/Source/JavaScriptCore/dfg/DFGOperations.h index 4ca58d621..52e99cb95 100644 --- a/Source/JavaScriptCore/dfg/DFGOperations.h +++ b/Source/JavaScriptCore/dfg/DFGOperations.h @@ -60,36 +60,40 @@ extern "C" { I: Identifier* G: GlobalResolveInfo* */ -typedef int32_t DFG_OPERATION (*Z_DFGOperation_D)(double); -typedef JSCell* DFG_OPERATION (*C_DFGOperation_E)(ExecState*); -typedef JSCell* DFG_OPERATION (*C_DFGOperation_EC)(ExecState*, JSCell*); -typedef JSCell* DFG_OPERATION (*C_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EA)(ExecState*, JSArray*); -typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJA)(ExecState*, EncodedJSValue, JSArray*); +typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*); +typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECI)(ExecState*, JSCell*, Identifier*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue); -typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue); +typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EGI)(ExecState*, GlobalResolveInfo*, Identifier*); +typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EI)(ExecState*, Identifier*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJ)(ExecState*, EncodedJSValue); -typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJP)(ExecState*, EncodedJSValue, void*); -typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ECI)(ExecState*, JSCell*, Identifier*); +typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJA)(ExecState*, EncodedJSValue, JSArray*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJI)(ExecState*, EncodedJSValue, Identifier*); +typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue); +typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EJP)(ExecState*, EncodedJSValue, void*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EP)(ExecState*, void*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPP)(ExecState*, void*, void*); -typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EGI)(ExecState*, GlobalResolveInfo*, Identifier*); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EPS)(ExecState*, void*, size_t); typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_ESS)(ExecState*, size_t, size_t); -typedef EncodedJSValue DFG_OPERATION (*J_DFGOperation_EI)(ExecState*, Identifier*); +typedef JSCell* DFG_OPERATION (*C_DFGOperation_E)(ExecState*); +typedef JSCell* DFG_OPERATION (*C_DFGOperation_EC)(ExecState*, JSCell*); +typedef JSCell* DFG_OPERATION (*C_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*); +typedef double DFG_OPERATION (*D_DFGOperation_DD)(double, double); +typedef double DFG_OPERATION (*D_DFGOperation_ZZ)(int32_t, int32_t); +typedef double DFG_OPERATION (*D_DFGOperation_EJ)(ExecState*, EncodedJSValue); +typedef int32_t DFG_OPERATION (*Z_DFGOperation_D)(double); +typedef size_t DFG_OPERATION (*S_DFGOperation_ECC)(ExecState*, JSCell*, JSCell*); typedef size_t DFG_OPERATION (*S_DFGOperation_EJ)(ExecState*, EncodedJSValue); typedef size_t DFG_OPERATION (*S_DFGOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue); -typedef void DFG_OPERATION (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue); +typedef size_t DFG_OPERATION (*S_DFGOperation_J)(EncodedJSValue); +typedef void DFG_OPERATION (*V_DFGOperation_EAZJ)(ExecState*, JSArray*, int32_t, EncodedJSValue); typedef void DFG_OPERATION (*V_DFGOperation_ECJJ)(ExecState*, JSCell*, EncodedJSValue, EncodedJSValue); -typedef void DFG_OPERATION (*V_DFGOperation_EJPP)(ExecState*, EncodedJSValue, EncodedJSValue, void*); typedef void DFG_OPERATION (*V_DFGOperation_EJCI)(ExecState*, EncodedJSValue, JSCell*, Identifier*); +typedef void DFG_OPERATION (*V_DFGOperation_EJJJ)(ExecState*, EncodedJSValue, EncodedJSValue, EncodedJSValue); +typedef void DFG_OPERATION (*V_DFGOperation_EJPP)(ExecState*, EncodedJSValue, EncodedJSValue, void*); typedef void DFG_OPERATION (*V_DFGOperation_EPZJ)(ExecState*, void*, int32_t, EncodedJSValue); -typedef void DFG_OPERATION (*V_DFGOperation_EAZJ)(ExecState*, JSArray*, int32_t, EncodedJSValue); -typedef double DFG_OPERATION (*D_DFGOperation_DD)(double, double); -typedef double DFG_OPERATION (*D_DFGOperation_EJ)(ExecState*, EncodedJSValue); -typedef void* DFG_OPERATION (*P_DFGOperation_E)(ExecState*); typedef void DFG_OPERATION (V_DFGOperation_EC)(ExecState*, JSCell*); +typedef void* DFG_OPERATION (*P_DFGOperation_E)(ExecState*); // These routines are provide callbacks out to C++ implementations of operations too complex to JIT. JSCell* DFG_OPERATION operationNewObject(ExecState*); @@ -123,6 +127,7 @@ void DFG_OPERATION operationPutByValBeyondArrayBoundsStrict(ExecState*, JSArray* void DFG_OPERATION operationPutByValBeyondArrayBoundsNonStrict(ExecState*, JSArray*, int32_t index, EncodedJSValue encodedValue); EncodedJSValue DFG_OPERATION operationArrayPush(ExecState*, EncodedJSValue encodedValue, JSArray*); EncodedJSValue DFG_OPERATION operationArrayPop(ExecState*, JSArray*); +EncodedJSValue DFG_OPERATION operationRegExpExec(ExecState*, JSCell*, JSCell*); void DFG_OPERATION operationPutByIdStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*); void DFG_OPERATION operationPutByIdNonStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*); void DFG_OPERATION operationPutByIdDirectStrict(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*); @@ -136,6 +141,7 @@ void DFG_OPERATION operationPutByIdNonStrictBuildList(ExecState*, EncodedJSValue void DFG_OPERATION operationPutByIdDirectStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*); void DFG_OPERATION operationPutByIdDirectNonStrictBuildList(ExecState*, EncodedJSValue encodedValue, JSCell* base, Identifier*); // These comparisons return a boolean within a size_t such that the value is zero extended to fill the register. +size_t DFG_OPERATION operationRegExpTest(ExecState*, JSCell*, JSCell*); size_t DFG_OPERATION operationCompareLess(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2); size_t DFG_OPERATION operationCompareLessEq(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2); size_t DFG_OPERATION operationCompareGreater(ExecState*, EncodedJSValue encodedOp1, EncodedJSValue encodedOp2); @@ -151,24 +157,17 @@ JSCell* DFG_OPERATION operationCreateActivation(ExecState*); void DFG_OPERATION operationTearOffActivation(ExecState*, JSCell*); JSCell* DFG_OPERATION operationNewFunction(ExecState*, JSCell*); JSCell* DFG_OPERATION operationNewFunctionExpression(ExecState*, JSCell*); +double DFG_OPERATION operationFModOnInts(int32_t, int32_t); +size_t DFG_OPERATION operationIsObject(EncodedJSValue); +size_t DFG_OPERATION operationIsFunction(EncodedJSValue); // This method is used to lookup an exception hander, keyed by faultLocation, which is // the return location from one of the calls out to one of the helper operations above. -struct DFGHandler { - DFGHandler(ExecState* exec, void* handler) - { - u.s.exec = exec; - u.s.handler = handler; - } - -#if !CPU(X86_64) - uint64_t encoded() - { - COMPILE_ASSERT(sizeof(Union) == sizeof(uint64_t), DFGHandler_Union_is_64bit); - return u.encoded; - } -#endif +// According to C++ rules, a type used for the return signature of function with C linkage (i.e. +// 'extern "C"') needs to be POD; hence putting any constructors into it could cause either compiler +// warnings, or worse, a change in the ABI used to return these types. +struct DFGHandler { union Union { struct Struct { ExecState* exec; @@ -177,17 +176,27 @@ struct DFGHandler { uint64_t encoded; } u; }; + +inline DFGHandler createDFGHandler(ExecState* exec, void* handler) +{ + DFGHandler result; + result.u.s.exec = exec; + result.u.s.handler = handler; + return result; +} + #if CPU(X86_64) typedef DFGHandler DFGHandlerEncoded; inline DFGHandlerEncoded dfgHandlerEncoded(ExecState* exec, void* handler) { - return DFGHandler(exec, handler); + return createDFGHandler(exec, handler); } #else typedef uint64_t DFGHandlerEncoded; inline DFGHandlerEncoded dfgHandlerEncoded(ExecState* exec, void* handler) { - return DFGHandler(exec, handler).encoded(); + COMPILE_ASSERT(sizeof(DFGHandler::Union) == sizeof(uint64_t), DFGHandler_Union_is_64bit); + return createDFGHandler(exec, handler).u.encoded; } #endif DFGHandlerEncoded DFG_OPERATION lookupExceptionHandler(ExecState*, uint32_t); diff --git a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp index 98bdaac06..53174604a 100644 --- a/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -45,8 +45,8 @@ public: #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) m_count = 0; #endif - // Two stage process: first propagate predictions, then propagate while doing double voting. - + // 1) propagate predictions + do { m_changed = false; @@ -64,6 +64,8 @@ public: propagateBackward(); } while (m_changed); + // 2) repropagate predictions while doing double voting. + do { m_changed = false; doRoundOfDoubleVoting(); @@ -75,8 +77,6 @@ public: doRoundOfDoubleVoting(); propagateBackward(); } while (m_changed); - - fixup(); } private: @@ -100,15 +100,31 @@ private: return m_graph[m_compileIndex].predict(prediction); } + bool isNotNegZero(NodeIndex nodeIndex) + { + if (!m_graph.isNumberConstant(nodeIndex)) + return false; + double value = m_graph.valueOfNumberConstant(nodeIndex); + return !value && 1.0 / value < 0.0; + } + + bool isNotZero(NodeIndex nodeIndex) + { + if (!m_graph.isNumberConstant(nodeIndex)) + return false; + return !!m_graph.valueOfNumberConstant(nodeIndex); + } + void propagate(Node& node) { if (!node.shouldGenerate()) return; - NodeType op = static_cast<NodeType>(node.op); + NodeType op = node.op(); + NodeFlags flags = node.flags() & NodeBackPropMask; #if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" %s @%u: ", Graph::opName(op), m_compileIndex); + dataLog(" %s @%u: %s ", Graph::opName(op), m_compileIndex, nodeFlagsAsString(flags)); #endif bool changed = false; @@ -121,14 +137,26 @@ private: } case GetLocal: { - PredictedType prediction = node.variableAccessData()->prediction(); + VariableAccessData* variableAccessData = node.variableAccessData(); + PredictedType prediction = variableAccessData->prediction(); if (prediction) changed |= mergePrediction(prediction); + + changed |= variableAccessData->mergeFlags(flags); break; } case SetLocal: { - changed |= node.variableAccessData()->predict(m_graph[node.child1()].prediction()); + VariableAccessData* variableAccessData = node.variableAccessData(); + changed |= variableAccessData->predict(m_graph[node.child1()].prediction()); + changed |= m_graph[node.child1()].mergeFlags(variableAccessData->flags()); + break; + } + + case Flush: { + // Make sure that the analysis knows that flushed locals escape. + VariableAccessData* variableAccessData = node.variableAccessData(); + changed |= variableAccessData->mergeFlags(NodeUsedAsValue); break; } @@ -137,21 +165,47 @@ private: case BitXor: case BitRShift: case BitLShift: - case BitURShift: + case BitURShift: { + changed |= setPrediction(PredictInt32); + flags |= NodeUsedAsInt; + flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero); + changed |= m_graph[node.child1()].mergeFlags(flags); + changed |= m_graph[node.child2()].mergeFlags(flags); + break; + } + case ValueToInt32: { changed |= setPrediction(PredictInt32); + flags |= NodeUsedAsInt; + flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero); + changed |= m_graph[node.child1()].mergeFlags(flags); break; } - case ArrayPop: + case ArrayPop: { + changed |= mergePrediction(node.getHeapPrediction()); + changed |= mergeDefaultFlags(node); + break; + } + case ArrayPush: { - if (node.getHeapPrediction()) - changed |= mergePrediction(node.getHeapPrediction()); + changed |= mergePrediction(node.getHeapPrediction()); + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); + changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsValue); + break; + } + + case RegExpExec: + case RegExpTest: { + changed |= mergePrediction(node.getHeapPrediction()); + changed |= mergeDefaultFlags(node); break; } case StringCharCodeAt: { changed |= mergePrediction(PredictInt32); + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); + changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt); break; } @@ -160,19 +214,26 @@ private: PredictedType right = m_graph[node.child2()].prediction(); if (left && right) { - if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags())) + if (isInt32Prediction(mergePredictions(left, right)) + && nodeCanSpeculateInteger(node.arithNodeFlags())) changed |= mergePrediction(PredictInt32); else changed |= mergePrediction(PredictDouble); } + + flags |= NodeUsedAsValue; + changed |= m_graph[node.child1()].mergeFlags(flags); + changed |= m_graph[node.child2()].mergeFlags(flags); break; } case UInt32ToNumber: { if (nodeCanSpeculateInteger(node.arithNodeFlags())) - changed |= setPrediction(PredictInt32); + changed |= mergePrediction(PredictInt32); else - changed |= setPrediction(PredictNumber); + changed |= mergePrediction(PredictNumber); + + changed |= m_graph[node.child1()].mergeFlags(flags); break; } @@ -192,10 +253,34 @@ private: } else changed |= mergePrediction(PredictString | PredictInt32 | PredictDouble); } + + if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index())) + flags &= ~NodeNeedsNegZero; + + changed |= m_graph[node.child1()].mergeFlags(flags); + changed |= m_graph[node.child2()].mergeFlags(flags); + break; + } + + case ArithAdd: { + PredictedType left = m_graph[node.child1()].prediction(); + PredictedType right = m_graph[node.child2()].prediction(); + + if (left && right) { + if (m_graph.addShouldSpeculateInteger(node)) + changed |= mergePrediction(PredictInt32); + else + changed |= mergePrediction(PredictDouble); + } + + if (isNotNegZero(node.child1().index()) || isNotNegZero(node.child2().index())) + flags &= ~NodeNeedsNegZero; + + changed |= m_graph[node.child1()].mergeFlags(flags); + changed |= m_graph[node.child2()].mergeFlags(flags); break; } - case ArithAdd: case ArithSub: { PredictedType left = m_graph[node.child1()].prediction(); PredictedType right = m_graph[node.child2()].prediction(); @@ -206,6 +291,12 @@ private: else changed |= mergePrediction(PredictDouble); } + + if (isNotZero(node.child1().index()) || isNotZero(node.child2().index())) + flags &= ~NodeNeedsNegZero; + + changed |= m_graph[node.child1()].mergeFlags(flags); + changed |= m_graph[node.child2()].mergeFlags(flags); break; } @@ -216,37 +307,68 @@ private: else changed |= mergePrediction(PredictDouble); } + + changed |= m_graph[node.child1()].mergeFlags(flags); break; - case ArithMul: case ArithMin: - case ArithMax: + case ArithMax: { + PredictedType left = m_graph[node.child1()].prediction(); + PredictedType right = m_graph[node.child2()].prediction(); + + if (left && right) { + if (isInt32Prediction(mergePredictions(left, right)) + && nodeCanSpeculateInteger(node.arithNodeFlags())) + changed |= mergePrediction(PredictInt32); + else + changed |= mergePrediction(PredictDouble); + } + + flags |= NodeUsedAsNumber; + changed |= m_graph[node.child1()].mergeFlags(flags); + changed |= m_graph[node.child2()].mergeFlags(flags); + break; + } + + case ArithMul: case ArithDiv: { PredictedType left = m_graph[node.child1()].prediction(); PredictedType right = m_graph[node.child2()].prediction(); if (left && right) { - if (isInt32Prediction(mergePredictions(left, right)) && nodeCanSpeculateInteger(node.arithNodeFlags())) + if (isInt32Prediction(mergePredictions(left, right)) + && nodeCanSpeculateInteger(node.arithNodeFlags())) changed |= mergePrediction(PredictInt32); else changed |= mergePrediction(PredictDouble); } + + // As soon as a multiply happens, we can easily end up in the part + // of the double domain where the point at which you do truncation + // can change the outcome. So, ArithMul always checks for overflow + // no matter what, and always forces its inputs to check as well. + + flags |= NodeUsedAsNumber | NodeNeedsNegZero; + changed |= m_graph[node.child1()].mergeFlags(flags); + changed |= m_graph[node.child2()].mergeFlags(flags); break; } case ArithSqrt: { changed |= setPrediction(PredictDouble); + changed |= m_graph[node.child1()].mergeFlags(flags | NodeUsedAsValue); break; } case ArithAbs: { PredictedType child = m_graph[node.child1()].prediction(); - if (child) { - if (nodeCanSpeculateInteger(node.arithNodeFlags())) - changed |= mergePrediction(child); - else - changed |= setPrediction(PredictDouble); - } + if (nodeCanSpeculateInteger(node.arithNodeFlags())) + changed |= mergePrediction(child); + else + changed |= setPrediction(PredictDouble); + + flags &= ~NodeNeedsNegZero; + changed |= m_graph[node.child1()].mergeFlags(flags); break; } @@ -257,64 +379,63 @@ private: case CompareGreaterEq: case CompareEq: case CompareStrictEq: - case InstanceOf: { + case InstanceOf: + case IsUndefined: + case IsBoolean: + case IsNumber: + case IsString: + case IsObject: + case IsFunction: { changed |= setPrediction(PredictBoolean); + changed |= mergeDefaultFlags(node); break; } case GetById: { - if (node.getHeapPrediction()) - changed |= mergePrediction(node.getHeapPrediction()); - else if (codeBlock()->identifier(node.identifierNumber()) == globalData().propertyNames->length) { - // If there is no prediction from value profiles, check if we might be - // able to infer the type ourselves. - bool isArray = isArrayPrediction(m_graph[node.child1()].prediction()); - bool isString = isStringPrediction(m_graph[node.child1()].prediction()); - bool isByteArray = m_graph[node.child1()].shouldSpeculateByteArray(); - bool isInt8Array = m_graph[node.child1()].shouldSpeculateInt8Array(); - bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array(); - bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array(); - bool isUint8Array = m_graph[node.child1()].shouldSpeculateUint8Array(); - bool isUint8ClampedArray = m_graph[node.child1()].shouldSpeculateUint8ClampedArray(); - bool isUint16Array = m_graph[node.child1()].shouldSpeculateUint16Array(); - bool isUint32Array = m_graph[node.child1()].shouldSpeculateUint32Array(); - bool isFloat32Array = m_graph[node.child1()].shouldSpeculateFloat32Array(); - bool isFloat64Array = m_graph[node.child1()].shouldSpeculateFloat64Array(); - if (isArray || isString || isByteArray || isInt8Array || isInt16Array || isInt32Array || isUint8Array || isUint8ClampedArray || isUint16Array || isUint32Array || isFloat32Array || isFloat64Array) - changed |= mergePrediction(PredictInt32); - } + changed |= mergePrediction(node.getHeapPrediction()); + changed |= mergeDefaultFlags(node); break; } case GetByIdFlush: - if (node.getHeapPrediction()) - changed |= mergePrediction(node.getHeapPrediction()); + changed |= mergePrediction(node.getHeapPrediction()); + changed |= mergeDefaultFlags(node); break; case GetByVal: { - if (m_graph[node.child1()].shouldSpeculateUint32Array() || m_graph[node.child1()].shouldSpeculateFloat32Array() || m_graph[node.child1()].shouldSpeculateFloat64Array()) + if (m_graph[node.child1()].shouldSpeculateFloat32Array() + || m_graph[node.child1()].shouldSpeculateFloat64Array()) changed |= mergePrediction(PredictDouble); - else if (node.getHeapPrediction()) + else changed |= mergePrediction(node.getHeapPrediction()); + + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); + changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt); break; } case GetPropertyStorage: case GetIndexedPropertyStorage: { changed |= setPrediction(PredictOther); + changed |= mergeDefaultFlags(node); break; } case GetByOffset: { - if (node.getHeapPrediction()) - changed |= mergePrediction(node.getHeapPrediction()); + changed |= mergePrediction(node.getHeapPrediction()); + changed |= mergeDefaultFlags(node); break; } case Call: case Construct: { - if (node.getHeapPrediction()) - changed |= mergePrediction(node.getHeapPrediction()); + changed |= mergePrediction(node.getHeapPrediction()); + for (unsigned childIdx = node.firstChild(); + childIdx < node.firstChild() + node.numChildren(); + ++childIdx) { + Edge edge = m_graph.m_varArgChildren[childIdx]; + changed |= m_graph[edge].mergeFlags(NodeUsedAsValue); + } break; } @@ -327,18 +448,17 @@ private: } changed |= mergePrediction(prediction); } + changed |= mergeDefaultFlags(node); break; } case GetGlobalVar: { - PredictedType prediction = m_graph.getGlobalVarPrediction(node.varNumber()); - if (prediction) - changed |= mergePrediction(prediction); + changed |= mergePrediction(node.getHeapPrediction()); break; } case PutGlobalVar: { - changed |= m_graph.predictGlobalVar(node.varNumber(), m_graph[node.child1()].prediction()); + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); break; } @@ -348,8 +468,7 @@ private: case ResolveBaseStrictPut: case ResolveGlobal: { PredictedType prediction = node.getHeapPrediction(); - if (prediction) - changed |= mergePrediction(prediction); + changed |= mergePrediction(prediction); break; } @@ -366,10 +485,21 @@ private: case CreateThis: case NewObject: { changed |= setPrediction(PredictFinalObject); + changed |= mergeDefaultFlags(node); + break; + } + + case NewArray: { + changed |= setPrediction(PredictArray); + for (unsigned childIdx = node.firstChild(); + childIdx < node.firstChild() + node.numChildren(); + ++childIdx) { + Edge edge = m_graph.m_varArgChildren[childIdx]; + changed |= m_graph[edge].mergeFlags(NodeUsedAsValue); + } break; } - case NewArray: case NewArrayBuffer: { changed |= setPrediction(PredictArray); break; @@ -380,9 +510,19 @@ private: break; } - case StringCharAt: + case StringCharAt: { + changed |= setPrediction(PredictString); + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); + changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt); + break; + } + case StrCat: { changed |= setPrediction(PredictString); + for (unsigned childIdx = node.firstChild(); + childIdx < node.firstChild() + node.numChildren(); + ++childIdx) + changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsNumber); break; } @@ -399,10 +539,12 @@ private: } else if (child & PredictObjectMask) { // Objects get turned into strings. So if the input has hints of objectness, // the output will have hinsts of stringiness. - changed |= mergePrediction(mergePredictions(child & ~PredictObjectMask, PredictString)); + changed |= mergePrediction( + mergePredictions(child & ~PredictObjectMask, PredictString)); } else changed |= mergePrediction(child); } + changed |= m_graph[node.child1()].mergeFlags(flags); break; } @@ -418,8 +560,8 @@ private: break; } + case PutByValAlias: case GetArrayLength: - case GetByteArrayLength: case GetInt8ArrayLength: case GetInt16ArrayLength: case GetInt32ArrayLength: @@ -429,38 +571,56 @@ private: case GetUint32ArrayLength: case GetFloat32ArrayLength: case GetFloat64ArrayLength: - case GetStringLength: { + case GetStringLength: + case Int32ToDouble: + case DoubleAsInt32: { // This node should never be visible at this stage of compilation. It is // inserted by fixup(), which follows this phase. ASSERT_NOT_REACHED(); break; } - case Flush: + case PutByVal: + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); + changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsNumber | NodeUsedAsInt); + changed |= m_graph[node.child3()].mergeFlags(NodeUsedAsValue); + break; + + case PutScopedVar: + case Return: + case Throw: + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); + break; + + case PutById: + case PutByIdDirect: + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); + changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsValue); + break; + + case PutByOffset: + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); + changed |= m_graph[node.child3()].mergeFlags(NodeUsedAsValue); + break; + + case Phi: break; #ifndef NDEBUG // These get ignored because they don't return anything. - case PutScopedVar: case DFG::Jump: case Branch: case Breakpoint: - case Return: case CheckHasInstance: - case Phi: - case Throw: case ThrowReferenceError: case ForceOSRExit: case SetArgument: - case PutByVal: - case PutByValAlias: - case PutById: - case PutByIdDirect: case CheckStructure: case CheckFunction: case PutStructure: - case PutByOffset: case TearOffActivation: + case CheckNumber: + changed |= mergeDefaultFlags(node); break; // These gets ignored because it doesn't do anything. @@ -474,6 +634,7 @@ private: break; #else default: + changed |= mergeDefaultFlags(node); break; #endif } @@ -484,6 +645,28 @@ private: m_changed |= changed; } + + bool mergeDefaultFlags(Node& node) + { + bool changed = false; + if (node.flags() & NodeHasVarArgs) { + for (unsigned childIdx = node.firstChild(); + childIdx < node.firstChild() + node.numChildren(); + childIdx++) + changed |= m_graph[m_graph.m_varArgChildren[childIdx]].mergeFlags(NodeUsedAsValue); + } else { + if (!node.child1()) + return changed; + changed |= m_graph[node.child1()].mergeFlags(NodeUsedAsValue); + if (!node.child2()) + return changed; + changed |= m_graph[node.child2()].mergeFlags(NodeUsedAsValue); + if (!node.child3()) + return changed; + changed |= m_graph[node.child3()].mergeFlags(NodeUsedAsValue); + } + return changed; + } void propagateForward() { @@ -502,10 +685,10 @@ private: for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;) propagate(m_graph[m_compileIndex]); } - - void vote(NodeUse nodeUse, VariableAccessData::Ballot ballot) + + void vote(Edge nodeUse, VariableAccessData::Ballot ballot) { - switch (m_graph[nodeUse].op) { + switch (m_graph[nodeUse].op()) { case ValueToInt32: case UInt32ToNumber: nodeUse = m_graph[nodeUse].child1(); @@ -514,14 +697,16 @@ private: break; } - if (m_graph[nodeUse].op == GetLocal) + if (m_graph[nodeUse].op() == GetLocal) m_graph[nodeUse].variableAccessData()->vote(ballot); } void vote(Node& node, VariableAccessData::Ballot ballot) { - if (node.flags & NodeHasVarArgs) { - for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) + if (node.flags() & NodeHasVarArgs) { + for (unsigned childIdx = node.firstChild(); + childIdx < node.firstChild() + node.numChildren(); + childIdx++) vote(m_graph.m_varArgChildren[childIdx], ballot); return; } @@ -546,7 +731,7 @@ private: m_graph.m_variableAccessData[i].find()->clearVotes(); for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) { Node& node = m_graph[m_compileIndex]; - switch (node.op) { + switch (node.op()) { case ValueAdd: case ArithAdd: case ArithSub: { @@ -576,7 +761,9 @@ private: VariableAccessData::Ballot ballot; - if (isNumberPrediction(left) && isNumberPrediction(right) && !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()]) && node.canSpeculateInteger())) + if (isNumberPrediction(left) && isNumberPrediction(right) + && !(Node::shouldSpeculateInteger(m_graph[node.child1()], m_graph[node.child1()]) + && node.canSpeculateInteger())) ballot = VariableAccessData::VoteDouble; else ballot = VariableAccessData::VoteValue; @@ -588,7 +775,8 @@ private: case ArithAbs: VariableAccessData::Ballot ballot; - if (!(m_graph[node.child1()].shouldSpeculateInteger() && node.canSpeculateInteger())) + if (!(m_graph[node.child1()].shouldSpeculateInteger() + && node.canSpeculateInteger())) ballot = VariableAccessData::VoteDouble; else ballot = VariableAccessData::VoteValue; @@ -615,115 +803,25 @@ private: } } for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) { - VariableAccessData* variableAccessData = m_graph.m_variableAccessData[i].find(); + VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i]; + if (!variableAccessData->isRoot()) + continue; if (operandIsArgument(variableAccessData->local()) || m_graph.isCaptured(variableAccessData->local())) continue; m_changed |= variableAccessData->tallyVotesForShouldUseDoubleFormat(); } - } - - void fixupNode(Node& node) - { - if (!node.shouldGenerate()) - return; - - NodeType op = static_cast<NodeType>(node.op); - -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" %s @%u: ", Graph::opName(op), m_compileIndex); -#endif - - switch (op) { - case GetById: { - if (!isInt32Prediction(m_graph[m_compileIndex].prediction())) - break; - if (codeBlock()->identifier(node.identifierNumber()) != globalData().propertyNames->length) - break; - bool isArray = isArrayPrediction(m_graph[node.child1()].prediction()); - bool isString = isStringPrediction(m_graph[node.child1()].prediction()); - bool isByteArray = m_graph[node.child1()].shouldSpeculateByteArray(); - bool isInt8Array = m_graph[node.child1()].shouldSpeculateInt8Array(); - bool isInt16Array = m_graph[node.child1()].shouldSpeculateInt16Array(); - bool isInt32Array = m_graph[node.child1()].shouldSpeculateInt32Array(); - bool isUint8Array = m_graph[node.child1()].shouldSpeculateUint8Array(); - bool isUint8ClampedArray = m_graph[node.child1()].shouldSpeculateUint8ClampedArray(); - bool isUint16Array = m_graph[node.child1()].shouldSpeculateUint16Array(); - bool isUint32Array = m_graph[node.child1()].shouldSpeculateUint32Array(); - bool isFloat32Array = m_graph[node.child1()].shouldSpeculateFloat32Array(); - bool isFloat64Array = m_graph[node.child1()].shouldSpeculateFloat64Array(); - if (!isArray && !isString && !isByteArray && !isInt8Array && !isInt16Array && !isInt32Array && !isUint8Array && !isUint8ClampedArray && !isUint16Array && !isUint32Array && !isFloat32Array && !isFloat64Array) - break; - -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog(" @%u -> %s", m_compileIndex, isArray ? "GetArrayLength" : "GetStringLength"); -#endif - if (isArray) - node.op = GetArrayLength; - else if (isString) - node.op = GetStringLength; - else if (isByteArray) - node.op = GetByteArrayLength; - else if (isInt8Array) - node.op = GetInt8ArrayLength; - else if (isInt16Array) - node.op = GetInt16ArrayLength; - else if (isInt32Array) - node.op = GetInt32ArrayLength; - else if (isUint8Array) - node.op = GetUint8ArrayLength; - else if (isUint8ClampedArray) - node.op = GetUint8ClampedArrayLength; - else if (isUint16Array) - node.op = GetUint16ArrayLength; - else if (isUint32Array) - node.op = GetUint32ArrayLength; - else if (isFloat32Array) - node.op = GetFloat32ArrayLength; - else if (isFloat64Array) - node.op = GetFloat64ArrayLength; - else - ASSERT_NOT_REACHED(); - // No longer MustGenerate - ASSERT(node.flags & NodeMustGenerate); - node.flags &= ~NodeMustGenerate; - m_graph.deref(m_compileIndex); - break; - } - case GetIndexedPropertyStorage: { - PredictedType basePrediction = m_graph[node.child2()].prediction(); - if (!(basePrediction & PredictInt32) && basePrediction) { - node.setOpAndDefaultFlags(Nop); - m_graph.clearAndDerefChild1(node); - m_graph.clearAndDerefChild2(node); - m_graph.clearAndDerefChild3(node); - node.setRefCount(0); - } - break; - } - case GetByVal: - case StringCharAt: - case StringCharCodeAt: { - if (!!node.child3() && m_graph[node.child3()].op == Nop) - node.children.child3() = NodeUse(); - break; - } - default: - break; + for (unsigned i = 0; i < m_graph.m_argumentPositions.size(); ++i) + m_changed |= m_graph.m_argumentPositions[i].mergeArgumentAwareness(); + for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i) { + VariableAccessData* variableAccessData = &m_graph.m_variableAccessData[i]; + if (!variableAccessData->isRoot()) + continue; + if (operandIsArgument(variableAccessData->local()) + || m_graph.isCaptured(variableAccessData->local())) + continue; + m_changed |= variableAccessData->makePredictionForDoubleFormat(); } - -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog("\n"); -#endif - } - - void fixup() - { -#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE) - dataLog("Performing Fixup\n"); -#endif - for (m_compileIndex = 0; m_compileIndex < m_graph.size(); ++m_compileIndex) - fixupNode(m_graph[m_compileIndex]); } NodeIndex m_compileIndex; diff --git a/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.cpp b/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.cpp index fb30de742..b16a72a7e 100644 --- a/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGRedundantPhiEliminationPhase.cpp @@ -55,7 +55,7 @@ public: if (!node.shouldGenerate()) continue; - switch (node.op) { + switch (node.op()) { case GetLocal: replacePhiChild(node, 0); break; @@ -95,7 +95,7 @@ private: bool replaced = false; NodeIndex child = node.children.child(childIndex).indexUnchecked(); - if (child != NoNode && m_graph[child].op == Phi) { + if (child != NoNode && m_graph[child].op() == Phi) { NodeIndex childReplacement = getRedundantReplacement(child); if (childReplacement != NoNode) { node.children.child(childIndex).setIndex(childReplacement); @@ -138,7 +138,7 @@ private: for (size_t arg = 0; arg < basicBlock->variablesAtHead.numberOfArguments(); ++arg) { NodeIndex nodeIndex = basicBlock->variablesAtHead.argument(arg); - if (nodeIndex != NoNode && m_graph[nodeIndex].op == Phi && !m_graph[nodeIndex].refCount()) { + if (nodeIndex != NoNode && m_graph[nodeIndex].op() == Phi && !m_graph[nodeIndex].refCount()) { NodeIndex replacement = getRedundantReplacement(nodeIndex); if (replacement != NoNode) { // This argument must be unused in this block. @@ -151,7 +151,7 @@ private: for (size_t local = 0; local < basicBlock->variablesAtHead.numberOfLocals(); ++local) { NodeIndex nodeIndex = basicBlock->variablesAtHead.local(local); - if (nodeIndex != NoNode && m_graph[nodeIndex].op == Phi && !m_graph[nodeIndex].refCount()) { + if (nodeIndex != NoNode && m_graph[nodeIndex].op() == Phi && !m_graph[nodeIndex].refCount()) { NodeIndex replacement = getRedundantReplacement(nodeIndex); if (replacement != NoNode) { // This local variable must be unused in this block. diff --git a/Source/JavaScriptCore/dfg/DFGRepatch.cpp b/Source/JavaScriptCore/dfg/DFGRepatch.cpp index edf3c9505..794538184 100644 --- a/Source/JavaScriptCore/dfg/DFGRepatch.cpp +++ b/Source/JavaScriptCore/dfg/DFGRepatch.cpp @@ -51,19 +51,19 @@ static void dfgRepatchByIdSelfAccess(CodeBlock* codeBlock, StructureStubInfo& st repatchBuffer.relink(stubInfo.callReturnLocation, slowPathFunction); // Patch the structure check & the offset of the load. - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(intptr_t)stubInfo.deltaCheckImmToCall), structure); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(intptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), structure); #if USE(JSVALUE64) if (compact) - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.deltaCallToLoadOrStore), sizeof(JSValue) * offset); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), sizeof(JSValue) * offset); else - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.deltaCallToLoadOrStore), sizeof(JSValue) * offset); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), sizeof(JSValue) * offset); #elif USE(JSVALUE32_64) if (compact) { - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.deltaCallToTagLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.deltaCallToPayloadLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToTagLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToPayloadLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); } else { - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.deltaCallToTagLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.deltaCallToPayloadLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToTagLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToPayloadLoadOrStore), sizeof(JSValue) * offset + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)); } #endif } @@ -102,7 +102,7 @@ static void linkRestoreScratch(LinkBuffer& patchBuffer, bool needToRestoreScratc static void linkRestoreScratch(LinkBuffer& patchBuffer, bool needToRestoreScratch, StructureStubInfo& stubInfo, MacroAssembler::Jump success, MacroAssembler::Jump fail, MacroAssembler::JumpList failureCases) { - linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone), stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase)); + linkRestoreScratch(patchBuffer, needToRestoreScratch, success, fail, failureCases, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)); } static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stubInfo, StructureChain* chain, size_t count, size_t offset, Structure* structure, CodeLocationLabel successLabel, CodeLocationLabel slowCaseLabel, MacroAssemblerCodeRef& stubRoutine) @@ -111,12 +111,12 @@ static void generateProtoChainAccessStub(ExecState* exec, StructureStubInfo& stu MacroAssembler stubJit; - GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR); + GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR); #if USE(JSVALUE32_64) - GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.valueTagGPR); + GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR); #endif - GPRReg resultGPR = static_cast<GPRReg>(stubInfo.valueGPR); - GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.scratchGPR); + GPRReg resultGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR); + GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR); bool needToRestoreScratch = false; if (scratchGPR == InvalidGPRReg) { @@ -167,12 +167,12 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier JSGlobalData* globalData = &exec->globalData(); if (isJSArray(baseValue) && propertyName == exec->propertyNames().length) { - GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR); + GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR); #if USE(JSVALUE32_64) - GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.valueTagGPR); + GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR); #endif - GPRReg resultGPR = static_cast<GPRReg>(stubInfo.valueGPR); - GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.scratchGPR); + GPRReg resultGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR); + GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR); bool needToRestoreScratch = false; MacroAssembler stubJit; @@ -209,7 +209,7 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier stubInfo.stubRoutine = patchBuffer.finalizeCode(); RepatchBuffer repatchBuffer(codeBlock); - repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code())); + repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code())); repatchBuffer.relink(stubInfo.callReturnLocation, operationGetById); return true; @@ -255,10 +255,10 @@ static bool tryCacheGetByID(ExecState* exec, JSValue baseValue, const Identifier ASSERT(slot.slotBase().isObject()); - generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone), stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase), stubInfo.stubRoutine); + generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase), stubInfo.stubRoutine); RepatchBuffer repatchBuffer(codeBlock); - repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code())); + repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code())); repatchBuffer.relink(stubInfo.callReturnLocation, operationGetByIdProtoBuildList); stubInfo.initGetByIdChain(*globalData, codeBlock->ownerExecutable(), structure, prototypeChain); @@ -280,7 +280,7 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi || slot.slotBase() != baseValue) return false; - if (!stubInfo.registersFlushed) { + if (!stubInfo.patch.dfg.registersFlushed) { // We cannot do as much inline caching if the registers were not flushed prior to this GetById. In particular, // non-Value cached properties require planting calls, which requires registers to have been flushed. Thus, // if registers were not flushed, don't do non-Value caching. @@ -305,7 +305,7 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi listIndex = 0; } else if (stubInfo.accessType == access_get_by_id_self) { ASSERT(!stubInfo.stubRoutine); - polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), MacroAssemblerCodeRef::createSelfManagedCodeRef(stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase)), stubInfo.u.getByIdSelf.baseObjectStructure.get(), true); + polymorphicStructureList = new PolymorphicAccessStructureList(*globalData, codeBlock->ownerExecutable(), MacroAssemblerCodeRef::createSelfManagedCodeRef(stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)), stubInfo.u.getByIdSelf.baseObjectStructure.get(), true); stubInfo.initGetByIdSelfList(polymorphicStructureList, 1); listIndex = 1; } else { @@ -316,12 +316,12 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi if (listIndex < POLYMORPHIC_LIST_CACHE_SIZE) { stubInfo.u.getByIdSelfList.listSize++; - GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR); + GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR); #if USE(JSVALUE32_64) - GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.valueTagGPR); + GPRReg resultTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR); #endif - GPRReg resultGPR = static_cast<GPRReg>(stubInfo.valueGPR); - GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.scratchGPR); + GPRReg resultGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR); + GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR); CCallHelpers stubJit(globalData, codeBlock); @@ -395,11 +395,11 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi if (listIndex) lastProtoBegin = CodeLocationLabel(polymorphicStructureList->list[listIndex - 1].stubRoutine.code()); else - lastProtoBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase); + lastProtoBegin = stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase); ASSERT(!!lastProtoBegin); patchBuffer.link(wrongStruct, lastProtoBegin); - patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone)); + patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone)); if (!isDirect) { patchBuffer.link(operationCall, operationFunction); patchBuffer.link(handlerCall, lookupExceptionHandlerInStub); @@ -409,7 +409,7 @@ static bool tryBuildGetByIDList(ExecState* exec, JSValue baseValue, const Identi polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, isDirect); - CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck); + CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck); RepatchBuffer repatchBuffer(codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code())); @@ -471,11 +471,11 @@ static bool tryBuildGetByIDProtoList(ExecState* exec, JSValue baseValue, const I MacroAssemblerCodeRef stubRoutine; - generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone), lastProtoBegin, stubRoutine); + generateProtoChainAccessStub(exec, stubInfo, prototypeChain, count, offset, structure, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone), lastProtoBegin, stubRoutine); polymorphicStructureList->list[listIndex].set(*globalData, codeBlock->ownerExecutable(), stubRoutine, structure, true); - CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck); + CodeLocationJump jumpLocation = stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck); RepatchBuffer repatchBuffer(codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code())); @@ -540,12 +540,12 @@ static void emitPutReplaceStub( MacroAssemblerCodeRef& stubRoutine) { JSGlobalData* globalData = &exec->globalData(); - GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR); + GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR); #if USE(JSVALUE32_64) - GPRReg valueTagGPR = static_cast<GPRReg>(stubInfo.valueTagGPR); + GPRReg valueTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR); #endif - GPRReg valueGPR = static_cast<GPRReg>(stubInfo.valueGPR); - GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.scratchGPR); + GPRReg valueGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR); + GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR); bool needToRestoreScratch = false; #if ENABLE(GGC) || ENABLE(WRITE_BARRIER_PROFILING) GPRReg scratchGPR2; @@ -608,7 +608,7 @@ static void emitPutReplaceStub( } LinkBuffer patchBuffer(*globalData, &stubJit, exec->codeBlock()); - patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone)); + patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone)); patchBuffer.link(failure, failureLabel); stubRoutine = patchBuffer.finalizeCode(); @@ -629,12 +629,12 @@ static void emitPutTransitionStub( { JSGlobalData* globalData = &exec->globalData(); - GPRReg baseGPR = static_cast<GPRReg>(stubInfo.baseGPR); + GPRReg baseGPR = static_cast<GPRReg>(stubInfo.patch.dfg.baseGPR); #if USE(JSVALUE32_64) - GPRReg valueTagGPR = static_cast<GPRReg>(stubInfo.valueTagGPR); + GPRReg valueTagGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueTagGPR); #endif - GPRReg valueGPR = static_cast<GPRReg>(stubInfo.valueGPR); - GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.scratchGPR); + GPRReg valueGPR = static_cast<GPRReg>(stubInfo.patch.dfg.valueGPR); + GPRReg scratchGPR = static_cast<GPRReg>(stubInfo.patch.dfg.scratchGPR); bool needToRestoreScratch = false; ASSERT(scratchGPR != baseGPR); @@ -699,7 +699,7 @@ static void emitPutTransitionStub( success = stubJit.jump(); LinkBuffer patchBuffer(*globalData, &stubJit, exec->codeBlock()); - patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToDone)); + patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToDone)); if (needToRestoreScratch) patchBuffer.link(failure, failureLabel); else @@ -741,11 +741,11 @@ static bool tryCachePutByID(ExecState* exec, JSValue baseValue, const Identifier emitPutTransitionStub( exec, baseValue, ident, slot, stubInfo, putKind, structure, oldStructure, prototypeChain, - stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase), + stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase), stubInfo.stubRoutine); RepatchBuffer repatchBuffer(codeBlock); - repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code())); + repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubInfo.stubRoutine.code())); repatchBuffer.relink(stubInfo.callReturnLocation, appropriateListBuildingPutByIdFunction(slot, putKind)); stubInfo.initPutByIdTransition(*globalData, codeBlock->ownerExecutable(), oldStructure, structure, prototypeChain, putKind == Direct); @@ -804,7 +804,7 @@ static bool tryBuildPutByIdList(ExecState* exec, JSValue baseValue, const Identi // We're now committed to creating the stub. Mogrify the meta-data accordingly. list = PolymorphicPutByIdList::from( putKind, stubInfo, - stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase)); + stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)); emitPutTransitionStub( exec, baseValue, propertyName, slot, stubInfo, putKind, @@ -821,7 +821,7 @@ static bool tryBuildPutByIdList(ExecState* exec, JSValue baseValue, const Identi // We're now committed to creating the stub. Mogrify the meta-data accordingly. list = PolymorphicPutByIdList::from( putKind, stubInfo, - stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase)); + stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)); emitPutReplaceStub( exec, baseValue, propertyName, slot, stubInfo, putKind, @@ -834,7 +834,7 @@ static bool tryBuildPutByIdList(ExecState* exec, JSValue baseValue, const Identi } RepatchBuffer repatchBuffer(codeBlock); - repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck), CodeLocationLabel(stubRoutine.code())); + repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), CodeLocationLabel(stubRoutine.code())); if (list->isFull()) repatchBuffer.relink(stubInfo.callReturnLocation, appropriateGenericPutByIdFunction(slot, putKind)); @@ -877,14 +877,14 @@ void dfgLinkFor(ExecState* exec, CallLinkInfo& callLinkInfo, CodeBlock* calleeCo void dfgResetGetByID(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo) { repatchBuffer.relink(stubInfo.callReturnLocation, operationGetByIdOptimize); - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(uintptr_t)stubInfo.deltaCheckImmToCall), reinterpret_cast<void*>(-1)); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(uintptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), reinterpret_cast<void*>(-1)); #if USE(JSVALUE64) - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.deltaCallToLoadOrStore), 0); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), 0); #else - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.deltaCallToTagLoadOrStore), 0); - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.deltaCallToPayloadLoadOrStore), 0); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToTagLoadOrStore), 0); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelCompactAtOffset(stubInfo.patch.dfg.deltaCallToPayloadLoadOrStore), 0); #endif - repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck), stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase)); + repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)); } void dfgResetPutByID(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo) @@ -902,14 +902,14 @@ void dfgResetPutByID(RepatchBuffer& repatchBuffer, StructureStubInfo& stubInfo) optimizedFunction = operationPutByIdDirectNonStrictOptimize; } repatchBuffer.relink(stubInfo.callReturnLocation, optimizedFunction); - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(uintptr_t)stubInfo.deltaCheckImmToCall), reinterpret_cast<void*>(-1)); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabelPtrAtOffset(-(uintptr_t)stubInfo.patch.dfg.deltaCheckImmToCall), reinterpret_cast<void*>(-1)); #if USE(JSVALUE64) - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.deltaCallToLoadOrStore), 0); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToLoadOrStore), 0); #else - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.deltaCallToTagLoadOrStore), 0); - repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.deltaCallToPayloadLoadOrStore), 0); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToTagLoadOrStore), 0); + repatchBuffer.repatch(stubInfo.callReturnLocation.dataLabel32AtOffset(stubInfo.patch.dfg.deltaCallToPayloadLoadOrStore), 0); #endif - repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.deltaCallToStructCheck), stubInfo.callReturnLocation.labelAtOffset(stubInfo.deltaCallToSlowCase)); + repatchBuffer.relink(stubInfo.callReturnLocation.jumpAtOffset(stubInfo.patch.dfg.deltaCallToStructCheck), stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.dfg.deltaCallToSlowCase)); } } } // namespace JSC::DFG diff --git a/Source/JavaScriptCore/dfg/DFGScoreBoard.h b/Source/JavaScriptCore/dfg/DFGScoreBoard.h index 140de185b..578f2b147 100644 --- a/Source/JavaScriptCore/dfg/DFGScoreBoard.h +++ b/Source/JavaScriptCore/dfg/DFGScoreBoard.h @@ -122,7 +122,7 @@ public: m_free.append(index); } } - void use(NodeUse child) + void use(Edge child) { use(child.indexUnchecked()); } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index 7bcb44576..18db85c22 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -28,7 +28,6 @@ #if ENABLE(DFG_JIT) -#include "JSByteArray.h" #include "LinkBuffer.h" namespace JSC { namespace DFG { @@ -60,12 +59,16 @@ GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex) switch (info.registerFormat()) { case DataFormatNone: { - GPRReg gpr = allocate(); - ASSERT(info.spillFormat() == DataFormatStorage); - m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); - m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); - info.fillStorage(gpr); - return gpr; + if (info.spillFormat() == DataFormatStorage) { + GPRReg gpr = allocate(); + m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled); + m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), gpr); + info.fillStorage(gpr); + return gpr; + } + + // Must be a cell; fill it as a cell and then return the pointer. + return fillSpeculateCell(nodeIndex); } case DataFormatStorage: { @@ -75,33 +78,31 @@ GPRReg SpeculativeJIT::fillStorage(NodeIndex nodeIndex) } default: - ASSERT_NOT_REACHED(); + return fillSpeculateCell(nodeIndex); } - - return InvalidGPRReg; } void SpeculativeJIT::useChildren(Node& node) { - if (node.flags & NodeHasVarArgs) { + if (node.flags() & NodeHasVarArgs) { for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) use(m_jit.graph().m_varArgChildren[childIdx]); } else { - NodeUse child1 = node.child1(); + Edge child1 = node.child1(); if (!child1) { ASSERT(!node.child2() && !node.child3()); return; } use(child1); - NodeUse child2 = node.child2(); + Edge child2 = node.child2(); if (!child2) { ASSERT(!node.child3()); return; } use(child2); - NodeUse child3 = node.child3(); + Edge child3 = node.child3(); if (!child3) return; use(child3); @@ -184,31 +185,6 @@ bool SpeculativeJIT::isKnownNotNumber(NodeIndex nodeIndex) || (node.hasConstant() && !isNumberConstant(nodeIndex)); } -bool SpeculativeJIT::isKnownBoolean(NodeIndex nodeIndex) -{ - Node& node = m_jit.graph()[nodeIndex]; - if (node.hasBooleanResult()) - return true; - - if (isBooleanConstant(nodeIndex)) - return true; - - VirtualRegister virtualRegister = node.virtualRegister(); - GenerationInfo& info = m_generationInfo[virtualRegister]; - - return info.isJSBoolean(); -} - -bool SpeculativeJIT::isKnownNotBoolean(NodeIndex nodeIndex) -{ - Node& node = m_jit.graph()[nodeIndex]; - VirtualRegister virtualRegister = node.virtualRegister(); - GenerationInfo& info = m_generationInfo[virtualRegister]; - if (node.hasConstant() && !valueOfJSConstant(nodeIndex).isBoolean()) - return true; - return !(info.isJSBoolean() || info.isUnknownJS()); -} - void SpeculativeJIT::writeBarrier(MacroAssembler& jit, GPRReg owner, GPRReg scratch1, GPRReg scratch2, WriteBarrierUseKind useKind) { UNUSED_PARAM(jit); @@ -249,7 +225,7 @@ void SpeculativeJIT::markCellCard(MacroAssembler& jit, GPRReg owner, GPRReg scra #endif } -void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2) +void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch1, GPRReg scratch2) { UNUSED_PARAM(ownerGPR); UNUSED_PARAM(valueGPR); @@ -325,7 +301,7 @@ void SpeculativeJIT::writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUs #endif } -void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind useKind, GPRReg scratch) +void SpeculativeJIT::writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind useKind, GPRReg scratch) { UNUSED_PARAM(owner); UNUSED_PARAM(valueGPR); @@ -774,6 +750,9 @@ void ValueSource::dump(FILE* out) const case SourceNotSet: fprintf(out, "NotSet"); break; + case SourceIsDead: + fprintf(out, "IsDead"); + break; case ValueInRegisterFile: fprintf(out, "InRegFile"); break; @@ -882,25 +861,52 @@ bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::Relationa // so can be no intervening nodes to also reference the compare. ASSERT(node.adjustedRefCount() == 1); - if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) { + if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) compilePeepHoleIntegerBranch(node, branchNodeIndex, condition); - use(node.child1()); - use(node.child2()); - } else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) { + else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) compilePeepHoleDoubleBranch(node, branchNodeIndex, doubleCondition); - use(node.child1()); - use(node.child2()); - } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) { - compilePeepHoleObjectEquality(node, branchNodeIndex, &JSFinalObject::s_info, isFinalObjectPrediction); - use(node.child1()); - use(node.child2()); - } else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) { - compilePeepHoleObjectEquality(node, branchNodeIndex, &JSArray::s_info, isArrayPrediction); - use(node.child1()); - use(node.child2()); - } else + else if (node.op() == CompareEq) { + if (Node::shouldSpeculateFinalObject( + at(node.child1()), at(node.child2()))) { + compilePeepHoleObjectEquality( + node, branchNodeIndex, &JSFinalObject::s_info, + isFinalObjectPrediction); + } else if (Node::shouldSpeculateArray( + at(node.child1()), at(node.child2()))) { + compilePeepHoleObjectEquality( + node, branchNodeIndex, &JSArray::s_info, + isArrayPrediction); + } else if (at(node.child1()).shouldSpeculateFinalObject() + && at(node.child2()).shouldSpeculateFinalObjectOrOther()) { + compilePeepHoleObjectToObjectOrOtherEquality( + node.child1(), node.child2(), branchNodeIndex, + &JSFinalObject::s_info, isFinalObjectPrediction); + } else if (at(node.child1()).shouldSpeculateFinalObjectOrOther() + && at(node.child2()).shouldSpeculateFinalObject()) { + compilePeepHoleObjectToObjectOrOtherEquality( + node.child2(), node.child1(), branchNodeIndex, + &JSFinalObject::s_info, isFinalObjectPrediction); + } else if (at(node.child1()).shouldSpeculateArray() + && at(node.child2()).shouldSpeculateArrayOrOther()) { + compilePeepHoleObjectToObjectOrOtherEquality( + node.child1(), node.child2(), branchNodeIndex, + &JSArray::s_info, isArrayPrediction); + } else if (at(node.child1()).shouldSpeculateArrayOrOther() + && at(node.child2()).shouldSpeculateArray()) { + compilePeepHoleObjectToObjectOrOtherEquality( + node.child2(), node.child1(), branchNodeIndex, + &JSArray::s_info, isArrayPrediction); + } else { + nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation); + return true; + } + } else { nonSpeculativePeepholeBranch(node, branchNodeIndex, condition, operation); + return true; + } + use(node.child1()); + use(node.child2()); m_indexInBlock = branchIndexInBlock; m_compileIndex = branchNodeIndex; return true; @@ -910,7 +916,7 @@ bool SpeculativeJIT::compilePeepHoleBranch(Node& node, MacroAssembler::Relationa void SpeculativeJIT::compileMovHint(Node& node) { - ASSERT(node.op == SetLocal); + ASSERT(node.op() == SetLocal); setNodeIndexForOperand(node.child1().index(), node.local()); m_lastSetOperand = node.local(); @@ -927,6 +933,8 @@ void SpeculativeJIT::compile(BasicBlock& block) #if DFG_ENABLE(JIT_BREAK_ON_EVERY_BLOCK) m_jit.breakpoint(); #endif + + m_jit.jitAssertHasValidCallFrame(); ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments()); for (size_t i = 0; i < m_arguments.size(); ++i) { @@ -943,7 +951,9 @@ void SpeculativeJIT::compile(BasicBlock& block) ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals()); for (size_t i = 0; i < m_variables.size(); ++i) { NodeIndex nodeIndex = block.variablesAtHead.local(i); - if (nodeIndex == NoNode || m_jit.graph().localIsCaptured(i)) + if ((nodeIndex == NoNode || !at(nodeIndex).refCount()) && !m_jit.graph().localIsCaptured(i)) + m_variables[i] = ValueSource(SourceIsDead); + else if (m_jit.graph().localIsCaptured(i)) m_variables[i] = ValueSource(ValueInRegisterFile); else if (at(nodeIndex).variableAccessData()->shouldUseDoubleFormat()) m_variables[i] = ValueSource(DoubleInRegisterFile); @@ -969,7 +979,7 @@ void SpeculativeJIT::compile(BasicBlock& block) #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("SpeculativeJIT skipping Node @%d (bc#%u) at JIT offset 0x%x ", (int)m_compileIndex, node.codeOrigin.bytecodeIndex, m_jit.debugOffset()); #endif - switch (node.op) { + switch (node.op()) { case SetLocal: compileMovHint(node); break; @@ -979,10 +989,16 @@ void SpeculativeJIT::compile(BasicBlock& block) int argumentCountIncludingThis = inlineCallFrame->arguments.size(); for (int i = 0; i < argumentCountIncludingThis; ++i) { ValueRecovery recovery = computeValueRecoveryFor(m_variables[inlineCallFrame->stackOffset + CallFrame::argumentOffsetIncludingThis(i)]); - // The recovery cannot point to registers, since the call frame reification isn't - // as smart as OSR, so it can't handle that. The exception is the this argument, - // which we don't really need to be able to recover. - ASSERT(!i || !recovery.isInRegisters()); + // The recovery should refer either to something that has already been + // stored into the register file at the right place, or to a constant, + // since the Arguments code isn't smart enough to handle anything else. + // The exception is the this argument, which we don't really need to be + // able to recover. +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("\nRecovery for argument %d: ", i); + recovery.dump(WTF::dataFile()); +#endif + ASSERT(!i || (recovery.isAlreadyInRegisterFile() || recovery.isConstant())); inlineCallFrame->arguments[i] = recovery; } break; @@ -1076,7 +1092,7 @@ void SpeculativeJIT::checkArgumentTypes() for (int i = 0; i < m_jit.codeBlock()->numParameters(); ++i) { NodeIndex nodeIndex = m_jit.graph().m_arguments[i]; Node& node = at(nodeIndex); - ASSERT(node.op == SetArgument); + ASSERT(node.op() == SetArgument); if (!node.shouldGenerate()) { // The argument is dead. We don't do any checks for such arguments. continue; @@ -1096,11 +1112,6 @@ void SpeculativeJIT::checkArgumentTypes() m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr()); speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister)); speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); - } else if (isByteArrayPrediction(predictedType)) { - GPRTemporary temp(this); - m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr()); - speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchTestPtr(MacroAssembler::NonZero, temp.gpr(), GPRInfo::tagMaskRegister)); - speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); } else if (isBooleanPrediction(predictedType)) { GPRTemporary temp(this); m_jit.loadPtr(JITCompiler::addressFor(virtualRegister), temp.gpr()); @@ -1161,12 +1172,6 @@ void SpeculativeJIT::checkArgumentTypes() speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag))); m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr()); speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSArray::s_info))); - } else if (isByteArrayPrediction(predictedType)) { - GPRTemporary temp(this); - m_jit.load32(JITCompiler::tagFor(virtualRegister), temp.gpr()); - speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, temp.gpr(), TrustedImm32(JSValue::CellTag))); - m_jit.load32(JITCompiler::payloadFor(virtualRegister), temp.gpr()); - speculationCheck(BadType, valueSource, nodeIndex, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(temp.gpr(), JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); } else if (isBooleanPrediction(predictedType)) speculationCheck(BadType, valueSource, nodeIndex, m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::BooleanTag))); else if (isInt8ArrayPrediction(predictedType)) { @@ -1278,6 +1283,9 @@ void SpeculativeJIT::linkOSREntries(LinkBuffer& linkBuffer) ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource) { switch (valueSource.kind()) { + case SourceIsDead: + return ValueRecovery::constant(jsUndefined()); + case ValueInRegisterFile: return ValueRecovery::alreadyInRegisterFile(); @@ -1309,6 +1317,10 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo // Try to see if there is an alternate node that would contain the value we want. // There are four possibilities: // + // Int32ToDouble: We can use this in place of the original node, but + // we'd rather not; so we use it only if it is the only remaining + // live version. + // // ValueToInt32: If the only remaining live version of the value is // ValueToInt32, then we can use it. // @@ -1319,10 +1331,13 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo // The reverse of the above: This node could be a UInt32ToNumber, but its // alternative is still alive. This means that the only remaining uses of // the number would be fine with a UInt32 intermediate. + // + // DoubleAsInt32: Same as UInt32ToNumber. + // bool found = false; - if (nodePtr->op == UInt32ToNumber) { + if (nodePtr->op() == UInt32ToNumber || nodePtr->op() == DoubleAsInt32) { NodeIndex nodeIndex = nodePtr->child1().index(); nodePtr = &at(nodeIndex); infoPtr = &m_generationInfo[nodePtr->virtualRegister()]; @@ -1331,8 +1346,10 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo } if (!found) { + NodeIndex int32ToDoubleIndex = NoNode; NodeIndex valueToInt32Index = NoNode; NodeIndex uint32ToNumberIndex = NoNode; + NodeIndex doubleAsInt32Index = NoNode; for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) { GenerationInfo& info = m_generationInfo[virtualRegister]; @@ -1343,20 +1360,29 @@ ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSo Node& node = at(info.nodeIndex()); if (node.child1Unchecked() != valueSource.nodeIndex()) continue; - switch (node.op) { + switch (node.op()) { + case Int32ToDouble: + int32ToDoubleIndex = info.nodeIndex(); + break; case ValueToInt32: valueToInt32Index = info.nodeIndex(); break; case UInt32ToNumber: uint32ToNumberIndex = info.nodeIndex(); break; + case DoubleAsInt32: + doubleAsInt32Index = info.nodeIndex(); default: break; } } NodeIndex nodeIndexToUse; - if (valueToInt32Index != NoNode) + if (doubleAsInt32Index != NoNode) + nodeIndexToUse = doubleAsInt32Index; + else if (int32ToDoubleIndex != NoNode) + nodeIndexToUse = int32ToDoubleIndex; + else if (valueToInt32Index != NoNode) nodeIndexToUse = valueToInt32Index; else if (uint32ToNumberIndex != NoNode) nodeIndexToUse = uint32ToNumberIndex; @@ -1488,33 +1514,179 @@ void SpeculativeJIT::compileGetByValOnString(Node& node) cellResult(scratchReg, m_compileIndex); } +GeneratedOperandType SpeculativeJIT::checkGeneratedTypeForToInt32(NodeIndex nodeIndex) +{ +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("checkGeneratedTypeForToInt32@%d ", nodeIndex); +#endif + Node& node = at(nodeIndex); + VirtualRegister virtualRegister = node.virtualRegister(); + GenerationInfo& info = m_generationInfo[virtualRegister]; + + if (info.registerFormat() == DataFormatNone) { + if (node.hasConstant()) { + if (isInt32Constant(nodeIndex)) + return GeneratedOperandInteger; + + if (isNumberConstant(nodeIndex)) + return GeneratedOperandDouble; + + terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + return GeneratedOperandTypeUnknown; + } + + if (info.spillFormat() == DataFormatDouble) + return GeneratedOperandDouble; + } + + switch (info.registerFormat()) { + case DataFormatBoolean: // This type never occurs. + case DataFormatStorage: + ASSERT_NOT_REACHED(); + + case DataFormatCell: + terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + return GeneratedOperandTypeUnknown; + + case DataFormatNone: + case DataFormatJSCell: + case DataFormatJS: + case DataFormatJSBoolean: + return GeneratedOperandJSValue; + + case DataFormatJSInteger: + case DataFormatInteger: + return GeneratedOperandInteger; + + case DataFormatJSDouble: + case DataFormatDouble: + return GeneratedOperandDouble; + } + + ASSERT_NOT_REACHED(); + return GeneratedOperandTypeUnknown; +} + void SpeculativeJIT::compileValueToInt32(Node& node) { - if (at(node.child1()).shouldNotSpeculateInteger()) { - if (at(node.child1()).shouldSpeculateDouble()) { - SpeculateDoubleOperand op1(this, node.child1()); + if (at(node.child1()).shouldSpeculateInteger()) { + SpeculateIntegerOperand op1(this, node.child1()); + GPRTemporary result(this, op1); + m_jit.move(op1.gpr(), result.gpr()); + integerResult(result.gpr(), m_compileIndex, op1.format()); + return; + } + + if (at(node.child1()).shouldSpeculateNumber()) { + switch (checkGeneratedTypeForToInt32(node.child1().index())) { + case GeneratedOperandInteger: { + SpeculateIntegerOperand op1(this, node.child1()); + GPRTemporary result(this, op1); + m_jit.move(op1.gpr(), result.gpr()); + integerResult(result.gpr(), m_compileIndex, op1.format()); + return; + } + case GeneratedOperandDouble: { GPRTemporary result(this); + DoubleOperand op1(this, node.child1()); FPRReg fpr = op1.fpr(); GPRReg gpr = result.gpr(); JITCompiler::Jump truncatedToInteger = m_jit.branchTruncateDoubleToInt32(fpr, gpr, JITCompiler::BranchIfTruncateSuccessful); - + silentSpillAllRegisters(gpr); callOperation(toInt32, gpr, fpr); silentFillAllRegisters(gpr); - + truncatedToInteger.link(&m_jit); integerResult(gpr, m_compileIndex); return; } - // Do it the safe way. - nonSpeculativeValueToInt32(node); + case GeneratedOperandJSValue: { + GPRTemporary result(this); +#if USE(JSVALUE64) + JSValueOperand op1(this, node.child1()); + + GPRReg gpr = op1.gpr(); + GPRReg resultGpr = result.gpr(); + FPRTemporary tempFpr(this); + FPRReg fpr = tempFpr.fpr(); + + JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, gpr, GPRInfo::tagTypeNumberRegister); + + speculationCheck(BadType, JSValueRegs(gpr), node.child1().index(), m_jit.branchTestPtr(MacroAssembler::Zero, gpr, GPRInfo::tagTypeNumberRegister)); + + // First, if we get here we have a double encoded as a JSValue + m_jit.move(gpr, resultGpr); + unboxDouble(resultGpr, fpr); + + silentSpillAllRegisters(resultGpr); + callOperation(toInt32, resultGpr, fpr); + silentFillAllRegisters(resultGpr); + + JITCompiler::Jump converted = m_jit.jump(); + + isInteger.link(&m_jit); + m_jit.zeroExtend32ToPtr(gpr, resultGpr); + + converted.link(&m_jit); +#else + Node& childNode = at(node.child1().index()); + VirtualRegister virtualRegister = childNode.virtualRegister(); + GenerationInfo& info = m_generationInfo[virtualRegister]; + + JSValueOperand op1(this, node.child1()); + + GPRReg payloadGPR = op1.payloadGPR(); + GPRReg resultGpr = result.gpr(); + + if (info.registerFormat() == DataFormatJSInteger) + m_jit.move(payloadGPR, resultGpr); + else { + GPRReg tagGPR = op1.tagGPR(); + FPRTemporary tempFpr(this); + FPRReg fpr = tempFpr.fpr(); + FPRTemporary scratch(this); + + JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, tagGPR, TrustedImm32(JSValue::Int32Tag)); + + speculationCheck(BadType, JSValueRegs(tagGPR, payloadGPR), node.child1().index(), m_jit.branch32(MacroAssembler::AboveOrEqual, tagGPR, TrustedImm32(JSValue::LowestTag))); + + unboxDouble(tagGPR, payloadGPR, fpr, scratch.fpr()); + + silentSpillAllRegisters(resultGpr); + callOperation(toInt32, resultGpr, fpr); + silentFillAllRegisters(resultGpr); + + JITCompiler::Jump converted = m_jit.jump(); + + isInteger.link(&m_jit); + m_jit.move(payloadGPR, resultGpr); + + converted.link(&m_jit); + } +#endif + integerResult(resultGpr, m_compileIndex); + return; + } + case GeneratedOperandTypeUnknown: + ASSERT_NOT_REACHED(); + break; + } + } + + if (at(node.child1()).shouldSpeculateBoolean()) { + SpeculateBooleanOperand op1(this, node.child1()); + GPRTemporary result(this, op1); + + m_jit.and32(JITCompiler::TrustedImm32(1), op1.gpr()); + + integerResult(op1.gpr(), m_compileIndex); return; } - SpeculateIntegerOperand op1(this, node.child1()); - GPRTemporary result(this, op1); - m_jit.move(op1.gpr(), result.gpr()); - integerResult(result.gpr(), m_compileIndex, op1.format()); + // Do it the safe way. + nonSpeculativeValueToInt32(node); + return; } void SpeculativeJIT::compileUInt32ToNumber(Node& node) @@ -1547,26 +1719,105 @@ void SpeculativeJIT::compileUInt32ToNumber(Node& node) // instruction that follows us, rather than the one we're executing right now. We have // to do this because by this point, the original values necessary to compile whatever // operation the UInt32ToNumber originated from might be dead. - speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0))); - - // Verify that we can do roll forward. - ASSERT(at(m_compileIndex + 1).op == SetLocal); - ASSERT(at(m_compileIndex + 1).codeOrigin == node.codeOrigin); - ASSERT(at(m_compileIndex + 2).codeOrigin != node.codeOrigin); - - // Now do the magic. - OSRExit& exit = m_jit.codeBlock()->lastOSRExit(); - Node& setLocal = at(m_compileIndex + 1); - exit.m_codeOrigin = at(m_compileIndex + 2).codeOrigin; - exit.m_lastSetOperand = setLocal.local(); - - // Create the value recovery, and stuff it into the right place. - exit.valueRecoveryForOperand(setLocal.local()) = ValueRecovery::uint32InGPR(op1.gpr()); + forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op1.gpr(), TrustedImm32(0)), ValueRecovery::uint32InGPR(op1.gpr())); m_jit.move(op1.gpr(), result.gpr()); integerResult(result.gpr(), m_compileIndex, op1.format()); } +void SpeculativeJIT::compileDoubleAsInt32(Node& node) +{ + SpeculateDoubleOperand op1(this, node.child1()); + FPRTemporary scratch(this); + GPRTemporary result(this); + + FPRReg valueFPR = op1.fpr(); + FPRReg scratchFPR = scratch.fpr(); + GPRReg resultGPR = result.gpr(); + + JITCompiler::JumpList failureCases; + m_jit.branchConvertDoubleToInt32(valueFPR, resultGPR, failureCases, scratchFPR); + forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, failureCases, ValueRecovery::inFPR(valueFPR)); + + integerResult(resultGPR, m_compileIndex); +} + +void SpeculativeJIT::compileInt32ToDouble(Node& node) +{ +#if USE(JSVALUE64) + // On JSVALUE64 we have a way of loading double constants in a more direct manner + // than a int->double conversion. On 32_64, unfortunately, we currently don't have + // any such mechanism - though we could have it, if we just provisioned some memory + // in CodeBlock for the double form of integer constants. + if (at(node.child1()).hasConstant()) { + ASSERT(isInt32Constant(node.child1().index())); + FPRTemporary result(this); + GPRTemporary temp(this); + m_jit.move(MacroAssembler::ImmPtr(reinterpret_cast<void*>(reinterpretDoubleToIntptr(valueOfNumberConstant(node.child1().index())))), temp.gpr()); + m_jit.movePtrToDouble(temp.gpr(), result.fpr()); + doubleResult(result.fpr(), m_compileIndex); + return; + } +#endif + + if (isInt32Prediction(m_state.forNode(node.child1()).m_type)) { + SpeculateIntegerOperand op1(this, node.child1()); + FPRTemporary result(this); + m_jit.convertInt32ToDouble(op1.gpr(), result.fpr()); + doubleResult(result.fpr(), m_compileIndex); + return; + } + + JSValueOperand op1(this, node.child1()); + FPRTemporary result(this); + +#if USE(JSVALUE64) + GPRTemporary temp(this); + + GPRReg op1GPR = op1.gpr(); + GPRReg tempGPR = temp.gpr(); + FPRReg resultFPR = result.fpr(); + + JITCompiler::Jump isInteger = m_jit.branchPtr( + MacroAssembler::AboveOrEqual, op1GPR, GPRInfo::tagTypeNumberRegister); + + speculationCheck( + BadType, JSValueRegs(op1GPR), node.child1(), + m_jit.branchTestPtr(MacroAssembler::Zero, op1GPR, GPRInfo::tagTypeNumberRegister)); + + m_jit.move(op1GPR, tempGPR); + unboxDouble(tempGPR, resultFPR); + JITCompiler::Jump done = m_jit.jump(); + + isInteger.link(&m_jit); + m_jit.convertInt32ToDouble(op1GPR, resultFPR); + done.link(&m_jit); +#else + FPRTemporary temp(this); + + GPRReg op1TagGPR = op1.tagGPR(); + GPRReg op1PayloadGPR = op1.payloadGPR(); + FPRReg tempFPR = temp.fpr(); + FPRReg resultFPR = result.fpr(); + + JITCompiler::Jump isInteger = m_jit.branch32( + MacroAssembler::Equal, op1TagGPR, TrustedImm32(JSValue::Int32Tag)); + + speculationCheck( + BadType, JSValueRegs(op1TagGPR, op1PayloadGPR), node.child1(), + m_jit.branch32(MacroAssembler::AboveOrEqual, op1TagGPR, TrustedImm32(JSValue::LowestTag))); + + unboxDouble(op1TagGPR, op1PayloadGPR, resultFPR, tempFPR); + JITCompiler::Jump done = m_jit.jump(); + + isInteger.link(&m_jit); + m_jit.convertInt32ToDouble(op1PayloadGPR, resultFPR); + done.link(&m_jit); +#endif + + doubleResult(resultFPR, m_compileIndex); +} + static double clampDoubleToByte(double d) { d += 0.5; @@ -1619,85 +1870,6 @@ static void compileClampDoubleToByte(JITCompiler& jit, GPRReg result, FPRReg sou } -void SpeculativeJIT::compilePutByValForByteArray(GPRReg base, GPRReg property, Node& node) -{ - NodeUse baseUse = node.child1(); - NodeUse valueUse = node.child3(); - - if (!isByteArrayPrediction(m_state.forNode(baseUse).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse.index(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); - GPRTemporary value; - GPRReg valueGPR; - - if (at(valueUse).isConstant()) { - JSValue jsValue = valueOfJSConstant(valueUse.index()); - if (!jsValue.isNumber()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); - noResult(m_compileIndex); - return; - } - int clampedValue = clampDoubleToByte(jsValue.asNumber()); - GPRTemporary scratch(this); - GPRReg scratchReg = scratch.gpr(); - m_jit.move(Imm32(clampedValue), scratchReg); - value.adopt(scratch); - valueGPR = scratchReg; - } else if (!at(valueUse).shouldNotSpeculateInteger()) { - SpeculateIntegerOperand valueOp(this, valueUse); - GPRTemporary scratch(this); - GPRReg scratchReg = scratch.gpr(); - m_jit.move(valueOp.gpr(), scratchReg); - compileClampIntegerToByte(m_jit, scratchReg); - value.adopt(scratch); - valueGPR = scratchReg; - } else { - SpeculateDoubleOperand valueOp(this, valueUse); - GPRTemporary result(this); - FPRTemporary floatScratch(this); - FPRReg fpr = valueOp.fpr(); - GPRReg gpr = result.gpr(); - compileClampDoubleToByte(m_jit, gpr, fpr, floatScratch.fpr()); - value.adopt(result); - valueGPR = gpr; - } - ASSERT_UNUSED(valueGPR, valueGPR != property); - ASSERT(valueGPR != base); - GPRTemporary storage(this); - GPRReg storageReg = storage.gpr(); - ASSERT(valueGPR != storageReg); - m_jit.loadPtr(MacroAssembler::Address(base, JSByteArray::offsetOfStorage()), storageReg); - MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, property, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize())); - m_jit.store8(value.gpr(), MacroAssembler::BaseIndex(storageReg, property, MacroAssembler::TimesOne, ByteArray::offsetOfData())); - outOfBounds.link(&m_jit); - noResult(m_compileIndex); -} - -void SpeculativeJIT::compileGetByValOnByteArray(Node& node) -{ - SpeculateCellOperand base(this, node.child1()); - SpeculateStrictInt32Operand property(this, node.child2()); - - GPRReg baseReg = base.gpr(); - GPRReg propertyReg = property.gpr(); - - if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); - noResult(m_compileIndex); - return; - } - - // Load the character into scratchReg - GPRTemporary storage(this); - GPRReg storageReg = storage.gpr(); - m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg); - - // unsigned comparison so we can filter out negative indices and indices that are too large - speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(storageReg, ByteArray::offsetOfSize()))); - - m_jit.load8(MacroAssembler::BaseIndex(storageReg, propertyReg, MacroAssembler::TimesOne, ByteArray::offsetOfData()), storageReg); - integerResult(storageReg, m_compileIndex); -} - void SpeculativeJIT::compileGetTypedArrayLength(const TypedArrayDescriptor& descriptor, Node& node, bool needsSpeculationCheck) { SpeculateCellOperand base(this, node.child1()); @@ -1758,22 +1930,30 @@ void SpeculativeJIT::compileGetByValOnIntTypedArray(const TypedArrayDescriptor& ASSERT_NOT_REACHED(); } outOfBounds.link(&m_jit); - if (elementSize < 4 || signedness == SignedTypedArray) + if (elementSize < 4 || signedness == SignedTypedArray) { integerResult(resultReg, m_compileIndex); - else { - FPRTemporary fresult(this); - m_jit.convertInt32ToDouble(resultReg, fresult.fpr()); - JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0)); - m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr()); - positive.link(&m_jit); - doubleResult(fresult.fpr(), m_compileIndex); + return; } + + ASSERT(elementSize == 4 && signedness == UnsignedTypedArray); + if (node.shouldSpeculateInteger()) { + forwardSpeculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, resultReg, TrustedImm32(0)), ValueRecovery::uint32InGPR(resultReg)); + integerResult(resultReg, m_compileIndex); + return; + } + + FPRTemporary fresult(this); + m_jit.convertInt32ToDouble(resultReg, fresult.fpr()); + JITCompiler::Jump positive = m_jit.branch32(MacroAssembler::GreaterThanOrEqual, resultReg, TrustedImm32(0)); + m_jit.addDouble(JITCompiler::AbsoluteAddress(&AssemblyHelpers::twoToThe32), fresult.fpr()); + positive.link(&m_jit); + doubleResult(fresult.fpr(), m_compileIndex); } void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements, TypedArraySignedness signedness, TypedArrayRounding rounding) { - NodeUse baseUse = node.child1(); - NodeUse valueUse = node.child3(); + Edge baseUse = node.child1(); + Edge valueUse = node.child3(); if (speculationRequirements != NoTypedArrayTypeSpecCheck) speculationCheck(BadType, JSValueSource::unboxedCell(base), baseUse, m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(base, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(descriptor.m_classInfo))); @@ -1797,7 +1977,7 @@ void SpeculativeJIT::compilePutByValForIntTypedArray(const TypedArrayDescriptor& m_jit.move(Imm32(static_cast<int>(d)), scratchReg); value.adopt(scratch); valueGPR = scratchReg; - } else if (!at(valueUse).shouldNotSpeculateInteger()) { + } else if (at(valueUse).shouldSpeculateInteger()) { SpeculateIntegerOperand valueOp(this, valueUse); GPRTemporary scratch(this); GPRReg scratchReg = scratch.gpr(); @@ -1918,8 +2098,8 @@ void SpeculativeJIT::compileGetByValOnFloatTypedArray(const TypedArrayDescriptor void SpeculativeJIT::compilePutByValForFloatTypedArray(const TypedArrayDescriptor& descriptor, GPRReg base, GPRReg property, Node& node, size_t elementSize, TypedArraySpeculationRequirements speculationRequirements) { - NodeUse baseUse = node.child1(); - NodeUse valueUse = node.child3(); + Edge baseUse = node.child1(); + Edge valueUse = node.child3(); SpeculateDoubleOperand valueOp(this, valueUse); @@ -1999,8 +2179,12 @@ void SpeculativeJIT::compileInstanceOfForObject(Node&, GPRReg valueReg, GPRReg p void SpeculativeJIT::compileInstanceOf(Node& node) { - if (!!(at(node.child1()).prediction() & ~PredictCell) && !!(m_state.forNode(node.child1()).m_type & ~PredictCell)) { + if ((!!(at(node.child1()).prediction() & ~PredictCell) + && !!(m_state.forNode(node.child1()).m_type & ~PredictCell)) + || at(node.child1()).adjustedRefCount() == 1) { // It might not be a cell. Speculate less aggressively. + // Or: it might only be used once (i.e. by us), so we get zero benefit + // from speculating any more aggressively than we absolutely need to. JSValueOperand value(this, node.child1()); SpeculateCellOperand prototype(this, node.child3()); @@ -2055,172 +2239,139 @@ void SpeculativeJIT::compileInstanceOf(Node& node) #endif } -static bool isPowerOfTwo(int32_t num) -{ - return num && !(num & (num - 1)); -} - void SpeculativeJIT::compileSoftModulo(Node& node) { - bool shouldGeneratePowerOfTwoCheck = true; - // In the fast path, the dividend value could be the final result // (in case of |dividend| < |divisor|), so we speculate it as strict int32. SpeculateStrictInt32Operand op1(this, node.child1()); - GPRReg op1Gpr = op1.gpr(); - +#if CPU(X86) || CPU(X86_64) if (isInt32Constant(node.child2().index())) { int32_t divisor = valueOfInt32Constant(node.child2().index()); - if (divisor < 0) - divisor = -divisor; - - if (isPowerOfTwo(divisor)) { - GPRTemporary result(this); - GPRReg resultGPR = result.gpr(); - m_jit.move(op1Gpr, resultGPR); - JITCompiler::Jump positiveDividend = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1Gpr, TrustedImm32(0)); - m_jit.neg32(resultGPR); - m_jit.and32(TrustedImm32(divisor - 1), resultGPR); - m_jit.neg32(resultGPR); - JITCompiler::Jump done = m_jit.jump(); - - positiveDividend.link(&m_jit); - m_jit.and32(TrustedImm32(divisor - 1), resultGPR); - - done.link(&m_jit); - integerResult(resultGPR, m_compileIndex); - return; - } -#if CPU(X86) || CPU(X86_64) if (divisor) { + GPRReg op1Gpr = op1.gpr(); + GPRTemporary eax(this, X86Registers::eax); GPRTemporary edx(this, X86Registers::edx); GPRTemporary scratch(this); GPRReg scratchGPR = scratch.gpr(); + GPRReg op1SaveGPR; + if (op1Gpr == X86Registers::eax || op1Gpr == X86Registers::edx) { + op1SaveGPR = allocate(); + ASSERT(op1Gpr != op1SaveGPR); + m_jit.move(op1Gpr, op1SaveGPR); + } else + op1SaveGPR = op1Gpr; + ASSERT(op1SaveGPR != X86Registers::eax); + ASSERT(op1SaveGPR != X86Registers::edx); + m_jit.move(op1Gpr, eax.gpr()); m_jit.move(TrustedImm32(divisor), scratchGPR); + if (divisor == -1) + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, eax.gpr(), TrustedImm32(-2147483647-1))); m_jit.assembler().cdq(); m_jit.assembler().idivl_r(scratchGPR); + // Check that we're not about to create negative zero. + // FIXME: if the node use doesn't care about neg zero, we can do this more easily. + JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0)); + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr())); + numeratorPositive.link(&m_jit); + + if (op1SaveGPR != op1Gpr) + unlock(op1SaveGPR); + integerResult(edx.gpr(), m_compileIndex); return; } -#endif - // Fallback to non-constant case but avoid unnecessary checks. - shouldGeneratePowerOfTwoCheck = false; } +#endif SpeculateIntegerOperand op2(this, node.child2()); - GPRReg op2Gpr = op2.gpr(); - - speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2Gpr)); - #if CPU(X86) || CPU(X86_64) GPRTemporary eax(this, X86Registers::eax); GPRTemporary edx(this, X86Registers::edx); - GPRReg temp2 = InvalidGPRReg; - if (op2Gpr == X86Registers::eax || op2Gpr == X86Registers::edx) { - temp2 = allocate(); - m_jit.move(op2Gpr, temp2); - op2Gpr = temp2; - } - GPRReg resultGPR = edx.gpr(); - GPRReg scratchGPR = eax.gpr(); -#else - GPRTemporary result(this); - GPRTemporary scratch(this); - GPRTemporary scratch3(this); - GPRReg scratchGPR3 = scratch3.gpr(); - GPRReg resultGPR = result.gpr(); - GPRReg scratchGPR = scratch.gpr(); -#endif - - GPRTemporary scratch2(this); - GPRReg scratchGPR2 = scratch2.gpr(); - JITCompiler::JumpList exitBranch; - - // resultGPR is to hold the ABS value of the dividend before final result is produced - m_jit.move(op1Gpr, resultGPR); - // scratchGPR2 is to hold the ABS value of the divisor - m_jit.move(op2Gpr, scratchGPR2); - - // Check for negative result remainder - // According to ECMA-262, the sign of the result equals the sign of the dividend - JITCompiler::Jump positiveDividend = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1Gpr, TrustedImm32(0)); - m_jit.neg32(resultGPR); - m_jit.move(TrustedImm32(1), scratchGPR); - JITCompiler::Jump saveCondition = m_jit.jump(); - - positiveDividend.link(&m_jit); - m_jit.move(TrustedImm32(0), scratchGPR); - - // Save the condition for negative remainder - saveCondition.link(&m_jit); - m_jit.push(scratchGPR); - - JITCompiler::Jump positiveDivisor = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op2Gpr, TrustedImm32(0)); - m_jit.neg32(scratchGPR2); - - positiveDivisor.link(&m_jit); - exitBranch.append(m_jit.branch32(JITCompiler::LessThan, resultGPR, scratchGPR2)); - - // Power of two fast case - if (shouldGeneratePowerOfTwoCheck) { - m_jit.move(scratchGPR2, scratchGPR); - m_jit.sub32(TrustedImm32(1), scratchGPR); - JITCompiler::Jump notPowerOfTwo = m_jit.branchTest32(JITCompiler::NonZero, scratchGPR, scratchGPR2); - m_jit.and32(scratchGPR, resultGPR); - exitBranch.append(m_jit.jump()); - - notPowerOfTwo.link(&m_jit); + GPRReg op1GPR = op1.gpr(); + GPRReg op2GPR = op2.gpr(); + + GPRReg op2TempGPR; + GPRReg temp; + GPRReg op1SaveGPR; + + if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) { + op2TempGPR = allocate(); + temp = op2TempGPR; + } else { + op2TempGPR = InvalidGPRReg; + if (op1GPR == X86Registers::eax) + temp = X86Registers::edx; + else + temp = X86Registers::eax; } - -#if CPU(X86) || CPU(X86_64) - m_jit.move(resultGPR, eax.gpr()); - m_jit.assembler().cdq(); - m_jit.assembler().idivl_r(scratchGPR2); -#elif CPU(ARM_THUMB2) - m_jit.countLeadingZeros32(scratchGPR2, scratchGPR); - m_jit.countLeadingZeros32(resultGPR, scratchGPR3); - m_jit.sub32(scratchGPR3, scratchGPR); - - JITCompiler::Jump useFullTable = m_jit.branch32(JITCompiler::Equal, scratchGPR, TrustedImm32(31)); - - m_jit.neg32(scratchGPR); - m_jit.add32(TrustedImm32(31), scratchGPR); - - int elementSizeByShift = -1; - elementSizeByShift = 3; - m_jit.relativeTableJump(scratchGPR, elementSizeByShift); - - useFullTable.link(&m_jit); - // Modulo table - for (int i = 31; i > 0; --i) { - ShiftTypeAndAmount shift(SRType_LSL, i); - m_jit.assembler().sub_S(scratchGPR, resultGPR, scratchGPR2, shift); - m_jit.assembler().it(ARMv7Assembler::ConditionCS); - m_jit.assembler().mov(resultGPR, scratchGPR); + + if (op1GPR == X86Registers::eax || op1GPR == X86Registers::edx) { + op1SaveGPR = allocate(); + ASSERT(op1GPR != op1SaveGPR); + m_jit.move(op1GPR, op1SaveGPR); + } else + op1SaveGPR = op1GPR; + + ASSERT(temp != op1GPR); + ASSERT(temp != op2GPR); + ASSERT(op1SaveGPR != X86Registers::eax); + ASSERT(op1SaveGPR != X86Registers::edx); + + m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp); + + JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1)); + + JITCompiler::Jump done; + // FIXME: if the node is not used as number then we can do this more easily. + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR)); + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1))); + + safeDenominator.link(&m_jit); + + if (op2TempGPR != InvalidGPRReg) { + m_jit.move(op2GPR, op2TempGPR); + op2GPR = op2TempGPR; } + + m_jit.move(op1GPR, eax.gpr()); + m_jit.assembler().cdq(); + m_jit.assembler().idivl_r(op2GPR); + + if (op2TempGPR != InvalidGPRReg) + unlock(op2TempGPR); - JITCompiler::Jump lower = m_jit.branch32(JITCompiler::Below, resultGPR, scratchGPR2); - m_jit.sub32(scratchGPR2, resultGPR); - lower.link(&m_jit); + // Check that we're not about to create negative zero. + // FIXME: if the node use doesn't care about neg zero, we can do this more easily. + JITCompiler::Jump numeratorPositive = m_jit.branch32(JITCompiler::GreaterThanOrEqual, op1SaveGPR, TrustedImm32(0)); + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, edx.gpr())); + numeratorPositive.link(&m_jit); + + if (op1SaveGPR != op1GPR) + unlock(op1SaveGPR); + + integerResult(edx.gpr(), m_compileIndex); +#else // CPU(X86) || CPU(X86_64) --> so not X86 + // Do this the *safest* way possible: call out to a C function that will do the modulo, + // and then attempt to convert back. + GPRReg op1GPR = op1.gpr(); + GPRReg op2GPR = op2.gpr(); + + FPRResult result(this); + + flushRegisters(); + callOperation(operationFModOnInts, result.fpr(), op1GPR, op2GPR); + + FPRTemporary scratch(this); + GPRTemporary intResult(this); + JITCompiler::JumpList failureCases; + m_jit.branchConvertDoubleToInt32(result.fpr(), intResult.gpr(), failureCases, scratch.fpr()); + speculationCheck(Overflow, JSValueRegs(), NoNode, failureCases); + + integerResult(intResult.gpr(), m_compileIndex); #endif // CPU(X86) || CPU(X86_64) - - exitBranch.link(&m_jit); - - // Check for negative remainder - m_jit.pop(scratchGPR); - JITCompiler::Jump positiveResult = m_jit.branch32(JITCompiler::Equal, scratchGPR, TrustedImm32(0)); - m_jit.neg32(resultGPR); - positiveResult.link(&m_jit); - - integerResult(resultGPR, m_compileIndex); - -#if CPU(X86) || CPU(X86_64) - if (temp2 != InvalidGPRReg) - unlock(temp2); -#endif } void SpeculativeJIT::compileAdd(Node& node) @@ -2299,7 +2450,7 @@ void SpeculativeJIT::compileAdd(Node& node) return; } - if (node.op == ValueAdd) { + if (node.op() == ValueAdd) { compileValueAdd(node); return; } @@ -2444,9 +2595,85 @@ void SpeculativeJIT::compileArithMul(Node& node) doubleResult(result.fpr(), m_compileIndex); } +#if CPU(X86) || CPU(X86_64) +void SpeculativeJIT::compileIntegerArithDivForX86(Node& node) +{ + SpeculateIntegerOperand op1(this, node.child1()); + SpeculateIntegerOperand op2(this, node.child2()); + GPRTemporary eax(this, X86Registers::eax); + GPRTemporary edx(this, X86Registers::edx); + GPRReg op1GPR = op1.gpr(); + GPRReg op2GPR = op2.gpr(); + + GPRReg op2TempGPR; + GPRReg temp; + if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) { + op2TempGPR = allocate(); + temp = op2TempGPR; + } else { + op2TempGPR = InvalidGPRReg; + if (op1GPR == X86Registers::eax) + temp = X86Registers::edx; + else + temp = X86Registers::eax; + } + + ASSERT(temp != op1GPR); + ASSERT(temp != op2GPR); + + m_jit.add32(JITCompiler::TrustedImm32(1), op2GPR, temp); + + JITCompiler::Jump safeDenominator = m_jit.branch32(JITCompiler::Above, temp, JITCompiler::TrustedImm32(1)); + + JITCompiler::Jump done; + if (nodeUsedAsNumber(node.arithNodeFlags())) { + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR)); + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1))); + } else { + JITCompiler::Jump zero = m_jit.branchTest32(JITCompiler::Zero, op2GPR); + JITCompiler::Jump notNeg2ToThe31 = m_jit.branch32(JITCompiler::Equal, op1GPR, TrustedImm32(-2147483647-1)); + zero.link(&m_jit); + m_jit.move(TrustedImm32(0), eax.gpr()); + done = m_jit.jump(); + notNeg2ToThe31.link(&m_jit); + } + + safeDenominator.link(&m_jit); + + // If the user cares about negative zero, then speculate that we're not about + // to produce negative zero. + if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) { + MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR); + speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0))); + numeratorNonZero.link(&m_jit); + } + + if (op2TempGPR != InvalidGPRReg) { + m_jit.move(op2GPR, op2TempGPR); + op2GPR = op2TempGPR; + } + + m_jit.move(op1GPR, eax.gpr()); + m_jit.assembler().cdq(); + m_jit.assembler().idivl_r(op2GPR); + + if (op2TempGPR != InvalidGPRReg) + unlock(op2TempGPR); + + // Check that there was no remainder. If there had been, then we'd be obligated to + // produce a double result instead. + if (nodeUsedAsNumber(node.arithNodeFlags())) + speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr())); + else + done.link(&m_jit); + + integerResult(eax.gpr(), m_compileIndex); +} +#endif // CPU(X86) || CPU(X86_64) + void SpeculativeJIT::compileArithMod(Node& node) { - if (!at(node.child1()).shouldNotSpeculateInteger() && !at(node.child2()).shouldNotSpeculateInteger() + if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) { compileSoftModulo(node); return; @@ -2473,21 +2700,65 @@ bool SpeculativeJIT::compare(Node& node, MacroAssembler::RelationalCondition con if (compilePeepHoleBranch(node, condition, doubleCondition, operation)) return true; - if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) + if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2()))) { compileIntegerCompare(node, condition); - else if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) + return false; + } + + if (Node::shouldSpeculateNumber(at(node.child1()), at(node.child2()))) { compileDoubleCompare(node, doubleCondition); - else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) - compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction); - else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) - compileObjectEquality(node, &JSArray::s_info, isArrayPrediction); - else - nonSpeculativeNonPeepholeCompare(node, condition, operation); + return false; + } + if (node.op() == CompareEq) { + if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) { + compileObjectEquality(node, &JSFinalObject::s_info, isFinalObjectPrediction); + return false; + } + + if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) { + compileObjectEquality(node, &JSArray::s_info, isArrayPrediction); + return false; + } + + if (at(node.child1()).shouldSpeculateFinalObject() + && at(node.child2()).shouldSpeculateFinalObjectOrOther()) { + compileObjectToObjectOrOtherEquality( + node.child1(), node.child2(), &JSFinalObject::s_info, + isFinalObjectPrediction); + return false; + } + + if (at(node.child1()).shouldSpeculateFinalObjectOrOther() + && at(node.child2()).shouldSpeculateFinalObject()) { + compileObjectToObjectOrOtherEquality( + node.child2(), node.child1(), &JSFinalObject::s_info, + isFinalObjectPrediction); + return false; + } + + if (at(node.child1()).shouldSpeculateArray() + && at(node.child2()).shouldSpeculateArrayOrOther()) { + compileObjectToObjectOrOtherEquality( + node.child1(), node.child2(), &JSArray::s_info, + isArrayPrediction); + return false; + } + + if (at(node.child1()).shouldSpeculateArrayOrOther() + && at(node.child2()).shouldSpeculateArray()) { + compileObjectToObjectOrOtherEquality( + node.child2(), node.child1(), &JSArray::s_info, + isArrayPrediction); + return false; + } + } + + nonSpeculativeNonPeepholeCompare(node, condition, operation); return false; } -bool SpeculativeJIT::compileStrictEqForConstant(Node& node, NodeUse value, JSValue constant) +bool SpeculativeJIT::compileStrictEqForConstant(Node& node, Edge value, JSValue constant) { JSValueOperand op1(this, value); @@ -2652,7 +2923,7 @@ bool SpeculativeJIT::compileStrictEq(Node& node) void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node) { if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); return; } @@ -2679,10 +2950,6 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node) speculationCheck(Uncountable, JSValueRegs(), NoNode, m_jit.branchTest32(MacroAssembler::Zero, storageReg)); m_jit.loadPtr(MacroAssembler::Address(storageReg, StringImpl::dataOffset()), storageReg); - } else if (at(node.child1()).shouldSpeculateByteArray()) { - if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); - m_jit.loadPtr(MacroAssembler::Address(baseReg, JSByteArray::offsetOfStorage()), storageReg); } else if (at(node.child1()).shouldSpeculateInt8Array()) { const TypedArrayDescriptor& descriptor = m_jit.globalData()->int8ArrayDescriptor(); if (!isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type)) @@ -2758,6 +3025,46 @@ void SpeculativeJIT::compileNewFunctionExpression(Node& node) cellResult(resultGPR, m_compileIndex); } +bool SpeculativeJIT::compileRegExpExec(Node& node) +{ + unsigned branchIndexInBlock = detectPeepHoleBranch(); + if (branchIndexInBlock == UINT_MAX) + return false; + NodeIndex branchNodeIndex = m_jit.graph().m_blocks[m_block]->at(branchIndexInBlock); + ASSERT(node.adjustedRefCount() == 1); + + Node& branchNode = at(branchNodeIndex); + BlockIndex taken = branchNode.takenBlockIndex(); + BlockIndex notTaken = branchNode.notTakenBlockIndex(); + + bool invert = false; + if (taken == (m_block + 1)) { + invert = true; + BlockIndex tmp = taken; + taken = notTaken; + notTaken = tmp; + } + + SpeculateCellOperand base(this, node.child1()); + SpeculateCellOperand argument(this, node.child2()); + GPRReg baseGPR = base.gpr(); + GPRReg argumentGPR = argument.gpr(); + + flushRegisters(); + GPRResult result(this); + callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR); + + branchTest32(invert ? JITCompiler::Zero : JITCompiler::NonZero, result.gpr(), taken); + jump(notTaken); + + use(node.child1()); + use(node.child2()); + m_indexInBlock = branchIndexInBlock; + m_compileIndex = branchNodeIndex; + + return true; +} + } } // namespace JSC::DFG #endif diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h index 1744a03f3..dbfaec4f8 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h @@ -54,6 +54,7 @@ enum ValueSourceKind { CellInRegisterFile, BooleanInRegisterFile, DoubleInRegisterFile, + SourceIsDead, HaveNode }; @@ -81,7 +82,7 @@ public: { if (isInt32Prediction(prediction)) return ValueSource(Int32InRegisterFile); - if (isArrayPrediction(prediction) || isByteArrayPrediction(prediction)) + if (isArrayPrediction(prediction)) return ValueSource(CellInRegisterFile); if (isBooleanPrediction(prediction)) return ValueSource(BooleanInRegisterFile); @@ -123,7 +124,10 @@ private: NodeIndex m_nodeIndex; }; - + + +enum GeneratedOperandType { GeneratedOperandTypeUnknown, GeneratedOperandInteger, GeneratedOperandDouble, GeneratedOperandJSValue}; + // === SpeculativeJIT === // // The SpeculativeJIT is used to generate a fast, but potentially @@ -181,7 +185,7 @@ public: { return m_jit.graph()[nodeIndex]; } - Node& at(NodeUse nodeUse) + Node& at(Edge nodeUse) { return at(nodeUse.index()); } @@ -221,7 +225,7 @@ public: GenerationInfo& info = m_generationInfo[virtualRegister]; return info.canReuse(); } - bool canReuse(NodeUse nodeUse) + bool canReuse(Edge nodeUse) { return canReuse(nodeUse.index()); } @@ -325,7 +329,7 @@ public: m_gprs.release(info.gpr()); #endif } - void use(NodeUse nodeUse) + void use(Edge nodeUse) { use(nodeUse.index()); } @@ -333,25 +337,13 @@ public: static void markCellCard(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2); static void writeBarrier(MacroAssembler&, GPRReg ownerGPR, GPRReg scratchGPR1, GPRReg scratchGPR2, WriteBarrierUseKind); - void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg); + void writeBarrier(GPRReg ownerGPR, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg); void writeBarrier(GPRReg ownerGPR, JSCell* value, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg, GPRReg scratchGPR2 = InvalidGPRReg); - void writeBarrier(JSCell* owner, GPRReg valueGPR, NodeUse valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg); + void writeBarrier(JSCell* owner, GPRReg valueGPR, Edge valueUse, WriteBarrierUseKind, GPRReg scratchGPR1 = InvalidGPRReg); static GPRReg selectScratchGPR(GPRReg preserve1 = InvalidGPRReg, GPRReg preserve2 = InvalidGPRReg, GPRReg preserve3 = InvalidGPRReg, GPRReg preserve4 = InvalidGPRReg) { - if (preserve1 != GPRInfo::regT0 && preserve2 != GPRInfo::regT0 && preserve3 != GPRInfo::regT0 && preserve4 != GPRInfo::regT0) - return GPRInfo::regT0; - - if (preserve1 != GPRInfo::regT1 && preserve2 != GPRInfo::regT1 && preserve3 != GPRInfo::regT1 && preserve4 != GPRInfo::regT1) - return GPRInfo::regT1; - - if (preserve1 != GPRInfo::regT2 && preserve2 != GPRInfo::regT2 && preserve3 != GPRInfo::regT2 && preserve4 != GPRInfo::regT2) - return GPRInfo::regT2; - - if (preserve1 != GPRInfo::regT3 && preserve2 != GPRInfo::regT3 && preserve3 != GPRInfo::regT3 && preserve4 != GPRInfo::regT3) - return GPRInfo::regT3; - - return GPRInfo::regT4; + return AssemblyHelpers::selectScratchGPR(preserve1, preserve2, preserve3, preserve4); } // Called by the speculative operand types, below, to fill operand to @@ -361,6 +353,7 @@ public: FPRReg fillSpeculateDouble(NodeIndex); GPRReg fillSpeculateCell(NodeIndex); GPRReg fillSpeculateBoolean(NodeIndex); + GeneratedOperandType checkGeneratedTypeForToInt32(NodeIndex); private: void compile(Node&); @@ -730,9 +723,6 @@ private: bool isKnownNotInteger(NodeIndex); bool isKnownNotNumber(NodeIndex); - bool isKnownBoolean(NodeIndex); - bool isKnownNotBoolean(NodeIndex); - bool isKnownNotCell(NodeIndex); // Checks/accessors for constant values. @@ -890,7 +880,7 @@ private: // Check if the lastNode is a branch on this node. Node& lastNode = at(block->last()); - return lastNode.op == Branch && lastNode.child1().index() == m_compileIndex ? block->size() - 1 : UINT_MAX; + return lastNode.op() == Branch && lastNode.child1().index() == m_compileIndex ? block->size() - 1 : UINT_MAX; } void nonSpeculativeValueToNumber(Node&); @@ -900,15 +890,15 @@ private: enum SpillRegistersMode { NeedToSpill, DontSpill }; #if USE(JSVALUE64) JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill); - void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, NodeUse valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); + void cachedPutById(CodeOrigin, GPRReg base, GPRReg value, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); #elif USE(JSVALUE32_64) JITCompiler::Call cachedGetById(CodeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget = JITCompiler::Jump(), SpillRegistersMode = NeedToSpill); - void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeUse valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); + void cachedPutById(CodeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind, JITCompiler::Jump slowPathTarget = JITCompiler::Jump()); #endif - void nonSpeculativeNonPeepholeCompareNull(NodeUse operand, bool invert = false); - void nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex branchNodeIndex, bool invert = false); - bool nonSpeculativeCompareNull(Node&, NodeUse operand, bool invert = false); + void nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert = false); + void nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex branchNodeIndex, bool invert = false); + bool nonSpeculativeCompareNull(Node&, Edge operand, bool invert = false); void nonSpeculativePeepholeBranch(Node&, NodeIndex branchNodeIndex, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction); void nonSpeculativeNonPeepholeCompare(Node&, MacroAssembler::RelationalCondition, S_DFGOperation_EJJ helperFunction); @@ -1174,6 +1164,11 @@ private: m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell)); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(S_DFGOperation_J operation, GPRReg result, GPRReg arg1) + { + m_jit.setupArguments(arg1); + return appendCallSetResult(operation, result); + } JITCompiler::Call callOperation(S_DFGOperation_EJ operation, GPRReg result, GPRReg arg1) { m_jit.setupArgumentsWithExecState(arg1); @@ -1184,6 +1179,11 @@ private: m_jit.setupArgumentsWithExecState(arg1, arg2); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(S_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2) + { + m_jit.setupArgumentsWithExecState(arg1, arg2); + return appendCallWithExceptionCheckSetResult(operation, result); + } JITCompiler::Call callOperation(J_DFGOperation_EPP operation, GPRReg result, GPRReg arg1, GPRReg arg2) { m_jit.setupArgumentsWithExecState(arg1, arg2); @@ -1199,6 +1199,11 @@ private: m_jit.setupArgumentsWithExecState(MacroAssembler::TrustedImmPtr(static_cast<const void*>(JSValue::encode(jsNumber(imm.m_value)))), arg2); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(J_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2) + { + m_jit.setupArgumentsWithExecState(arg1, arg2); + return appendCallWithExceptionCheckSetResult(operation, result); + } JITCompiler::Call callOperation(J_DFGOperation_ECJ operation, GPRReg result, GPRReg arg1, GPRReg arg2) { m_jit.setupArgumentsWithExecState(arg1, arg2); @@ -1244,6 +1249,11 @@ private: m_jit.setupArgumentsWithExecState(arg1); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(D_DFGOperation_ZZ operation, FPRReg result, GPRReg arg1, GPRReg arg2) + { + m_jit.setupArguments(arg1, arg2); + return appendCallSetResult(operation, result); + } JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2) { m_jit.setupArguments(arg1, arg2); @@ -1252,6 +1262,7 @@ private: #else JITCompiler::Call callOperation(Z_DFGOperation_D operation, GPRReg result, FPRReg arg1) { + prepareForExternalCall(); m_jit.setupArguments(arg1); JITCompiler::Call call = m_jit.appendCall(operation); m_jit.zeroExtend32ToPtr(GPRInfo::returnValueGPR, result); @@ -1352,11 +1363,21 @@ private: m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell)); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(S_DFGOperation_J operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload) + { + m_jit.setupArguments(arg1Payload, arg1Tag); + return appendCallSetResult(operation, result); + } JITCompiler::Call callOperation(S_DFGOperation_EJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload) { m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag); return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(S_DFGOperation_ECC operation, GPRReg result, GPRReg arg1, GPRReg arg2) + { + m_jit.setupArgumentsWithExecState(arg1, arg2); + return appendCallWithExceptionCheckSetResult(operation, result); + } JITCompiler::Call callOperation(S_DFGOperation_EJJ operation, GPRReg result, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2Tag, GPRReg arg2Payload) { m_jit.setupArgumentsWithExecState(arg1Payload, arg1Tag, arg2Payload, arg2Tag); @@ -1382,6 +1403,11 @@ private: m_jit.setupArgumentsWithExecState(arg1, arg2Payload, arg2Tag); return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); } + JITCompiler::Call callOperation(J_DFGOperation_ECC operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2) + { + m_jit.setupArgumentsWithExecState(arg1, arg2); + return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag); + } JITCompiler::Call callOperation(V_DFGOperation_EC operation, GPRReg arg1) { m_jit.setupArgumentsWithExecState(arg1); @@ -1419,16 +1445,32 @@ private: return appendCallWithExceptionCheckSetResult(operation, result); } + JITCompiler::Call callOperation(D_DFGOperation_ZZ operation, FPRReg result, GPRReg arg1, GPRReg arg2) + { + m_jit.setupArguments(arg1, arg2); + return appendCallSetResult(operation, result); + } JITCompiler::Call callOperation(D_DFGOperation_DD operation, FPRReg result, FPRReg arg1, FPRReg arg2) { m_jit.setupArguments(arg1, arg2); return appendCallSetResult(operation, result); } #endif + +#ifndef NDEBUG + void prepareForExternalCall() + { + for (unsigned i = 0; i < sizeof(void*) / 4; i++) + m_jit.store32(TrustedImm32(0xbadbeef), reinterpret_cast<char*>(&m_jit.globalData()->topCallFrame) + i * 4); + } +#else + void prepareForExternalCall() { } +#endif // These methods add call instructions, with optional exception checks & setting results. JITCompiler::Call appendCallWithExceptionCheck(const FunctionPtr& function) { + prepareForExternalCall(); CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin; CallBeginToken token = m_jit.beginCall(); JITCompiler::Call call = m_jit.appendCall(function); @@ -1441,6 +1483,13 @@ private: m_jit.move(GPRInfo::returnValueGPR, result); return call; } + JITCompiler::Call appendCallSetResult(const FunctionPtr& function, GPRReg result) + { + prepareForExternalCall(); + JITCompiler::Call call = m_jit.appendCall(function); + m_jit.move(GPRInfo::returnValueGPR, result); + return call; + } JITCompiler::Call appendCallWithExceptionCheckSetResult(const FunctionPtr& function, GPRReg result1, GPRReg result2) { JITCompiler::Call call = appendCallWithExceptionCheck(function); @@ -1693,17 +1742,21 @@ private: void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition); void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition); void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker); + void compilePeepHoleObjectToObjectOrOtherEquality( + Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, const ClassInfo*, PredictionChecker); void compileObjectEquality(Node&, const ClassInfo*, PredictionChecker); + void compileObjectToObjectOrOtherEquality( + Edge leftChild, Edge rightChild, const ClassInfo*, PredictionChecker); void compileValueAdd(Node&); - void compileObjectOrOtherLogicalNot(NodeUse value, const ClassInfo*, bool needSpeculationCheck); + void compileObjectOrOtherLogicalNot(Edge value, const ClassInfo*, bool needSpeculationCheck); void compileLogicalNot(Node&); - void emitObjectOrOtherBranch(NodeUse value, BlockIndex taken, BlockIndex notTaken, const ClassInfo*, bool needSpeculationCheck); + void emitObjectOrOtherBranch(Edge value, BlockIndex taken, BlockIndex notTaken, const ClassInfo*, bool needSpeculationCheck); void emitBranch(Node&); void compileIntegerCompare(Node&, MacroAssembler::RelationalCondition); void compileDoubleCompare(Node&, MacroAssembler::DoubleCondition); - bool compileStrictEqForConstant(Node&, NodeUse value, JSValue constant); + bool compileStrictEqForConstant(Node&, Edge value, JSValue constant); bool compileStrictEq(Node&); @@ -1711,12 +1764,15 @@ private: void compileGetByValOnString(Node&); void compileValueToInt32(Node&); void compileUInt32ToNumber(Node&); - void compileGetByValOnByteArray(Node&); - void compilePutByValForByteArray(GPRReg base, GPRReg property, Node&); + void compileDoubleAsInt32(Node&); + void compileInt32ToDouble(Node&); void compileAdd(Node&); void compileArithSub(Node&); void compileArithNegate(Node&); void compileArithMul(Node&); +#if CPU(X86) || CPU(X86_64) + void compileIntegerArithDivForX86(Node&); +#endif void compileArithMod(Node&); void compileSoftModulo(Node&); void compileGetTypedArrayLength(const TypedArrayDescriptor&, Node&, bool needsSpeculationCheck); @@ -1738,8 +1794,9 @@ private: void compilePutByValForIntTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements, TypedArraySignedness, TypedArrayRounding = TruncateRounding); void compileGetByValOnFloatTypedArray(const TypedArrayDescriptor&, Node&, size_t elementSize, TypedArraySpeculationRequirements); void compilePutByValForFloatTypedArray(const TypedArrayDescriptor&, GPRReg base, GPRReg property, Node&, size_t elementSize, TypedArraySpeculationRequirements); - void compileNewFunctionNoCheck(Node& node); - void compileNewFunctionExpression(Node& node); + void compileNewFunctionNoCheck(Node&); + void compileNewFunctionExpression(Node&); + bool compileRegExpExec(Node&); template <typename ClassType, bool destructor, typename StructureType> void emitAllocateBasicJSObject(StructureType structure, GPRReg resultGPR, GPRReg scratchGPR, MacroAssembler::JumpList& slowPath) @@ -1750,7 +1807,7 @@ private: else allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType)); - m_jit.loadPtr(&allocator->m_firstFreeCell, resultGPR); + m_jit.loadPtr(&allocator->m_freeList.head, resultGPR); slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR)); // The object is half-allocated: we have what we know is a fresh object, but @@ -1762,7 +1819,7 @@ private: // Now that we have scratchGPR back, remove the object from the free list m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR); - m_jit.storePtr(scratchGPR, &allocator->m_firstFreeCell); + m_jit.storePtr(scratchGPR, &allocator->m_freeList.head); // Initialize the object's classInfo pointer m_jit.storePtr(MacroAssembler::TrustedImmPtr(&ClassType::s_info), MacroAssembler::Address(resultGPR, JSCell::classInfoOffset())); @@ -1796,18 +1853,18 @@ private: return; m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this)); } - void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeUse nodeUse, MacroAssembler::Jump jumpToFail) + void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail) { speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail); } // Add a set of speculation checks without additional recovery. void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail) { - Vector<MacroAssembler::Jump, 16> JumpVector = jumpsToFail.jumps(); - for (unsigned i = 0; i < JumpVector.size(); ++i) - speculationCheck(kind, jsValueSource, nodeIndex, JumpVector[i]); + Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps(); + for (unsigned i = 0; i < jumpVector.size(); ++i) + speculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i]); } - void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeUse nodeUse, MacroAssembler::JumpList& jumpsToFail) + void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail) { speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail); } @@ -1819,10 +1876,47 @@ private: m_jit.codeBlock()->appendSpeculationRecovery(recovery); m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_jit.codeBlock()->numberOfSpeculationRecoveries())); } - void speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeUse nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) + void speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) { speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery); } + void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery) + { + speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail); + + unsigned setLocalIndexInBlock = m_indexInBlock + 1; + + Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock)); + + if (setLocal->op() == Int32ToDouble) { + setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock)); + ASSERT(at(setLocal->child1()).child1() == m_compileIndex); + } else + ASSERT(setLocal->child1() == m_compileIndex); + + ASSERT(setLocal->op() == SetLocal); + ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin); + + Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1)); + if (nextNode->codeOrigin == at(m_compileIndex).codeOrigin) { + ASSERT(nextNode->op() == Flush); + nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 2)); + ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin); // duplicate the same assertion as below so that if we fail, we'll know we came down this path. + } + ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin); + + OSRExit& exit = m_jit.codeBlock()->lastOSRExit(); + exit.m_codeOrigin = nextNode->codeOrigin; + exit.m_lastSetOperand = setLocal->local(); + + exit.valueRecoveryForOperand(setLocal->local()) = valueRecovery; + } + void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery) + { + Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps(); + for (unsigned i = 0; i < jumpVector.size(); ++i) + forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i], valueRecovery); + } // Called when we statically determine that a speculation will fail. void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex) @@ -1835,7 +1929,7 @@ private: speculationCheck(kind, jsValueRegs, nodeIndex, m_jit.jump()); m_compileOkay = false; } - void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeUse nodeUse) + void terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse) { terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index()); } @@ -1934,7 +2028,7 @@ private: class IntegerOperand { public: - explicit IntegerOperand(SpeculativeJIT* jit, NodeUse use) + explicit IntegerOperand(SpeculativeJIT* jit, Edge use) : m_jit(jit) , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) @@ -1943,6 +2037,7 @@ public: #endif { ASSERT(m_jit); + ASSERT(use.useKind() != DoubleUse); if (jit->isFilled(m_index)) gpr(); } @@ -1986,12 +2081,21 @@ private: class DoubleOperand { public: - explicit DoubleOperand(SpeculativeJIT* jit, NodeUse use) + explicit DoubleOperand(SpeculativeJIT* jit, Edge use) : m_jit(jit) , m_index(use.index()) , m_fprOrInvalid(InvalidFPRReg) { ASSERT(m_jit); + + // This is counter-intuitive but correct. DoubleOperand is intended to + // be used only when you're a node that is happy to accept an untyped + // value, but will special-case for doubles (using DoubleOperand) if the + // value happened to already be represented as a double. The implication + // is that you will not try to force the value to become a double if it + // is not one already. + ASSERT(use.useKind() != DoubleUse); + if (jit->isFilledDouble(m_index)) fpr(); } @@ -2027,7 +2131,7 @@ private: class JSValueOperand { public: - explicit JSValueOperand(SpeculativeJIT* jit, NodeUse use) + explicit JSValueOperand(SpeculativeJIT* jit, Edge use) : m_jit(jit) , m_index(use.index()) #if USE(JSVALUE64) @@ -2037,6 +2141,7 @@ public: #endif { ASSERT(m_jit); + ASSERT(use.useKind() != DoubleUse); #if USE(JSVALUE64) if (jit->isFilled(m_index)) gpr(); @@ -2141,12 +2246,13 @@ private: class StorageOperand { public: - explicit StorageOperand(SpeculativeJIT* jit, NodeUse use) + explicit StorageOperand(SpeculativeJIT* jit, Edge use) : m_jit(jit) , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) { ASSERT(m_jit); + ASSERT(use.useKind() != DoubleUse); if (jit->isFilled(m_index)) gpr(); } @@ -2310,7 +2416,7 @@ private: class SpeculateIntegerOperand { public: - explicit SpeculateIntegerOperand(SpeculativeJIT* jit, NodeUse use) + explicit SpeculateIntegerOperand(SpeculativeJIT* jit, Edge use) : m_jit(jit) , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) @@ -2319,6 +2425,7 @@ public: #endif { ASSERT(m_jit); + ASSERT(use.useKind() != DoubleUse); if (jit->isFilled(m_index)) gpr(); } @@ -2357,12 +2464,13 @@ private: class SpeculateStrictInt32Operand { public: - explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, NodeUse use) + explicit SpeculateStrictInt32Operand(SpeculativeJIT* jit, Edge use) : m_jit(jit) , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) { ASSERT(m_jit); + ASSERT(use.useKind() != DoubleUse); if (jit->isFilled(m_index)) gpr(); } @@ -2398,12 +2506,13 @@ private: class SpeculateDoubleOperand { public: - explicit SpeculateDoubleOperand(SpeculativeJIT* jit, NodeUse use) + explicit SpeculateDoubleOperand(SpeculativeJIT* jit, Edge use) : m_jit(jit) , m_index(use.index()) , m_fprOrInvalid(InvalidFPRReg) { ASSERT(m_jit); + ASSERT(use.useKind() == DoubleUse); if (jit->isFilled(m_index)) fpr(); } @@ -2434,12 +2543,13 @@ private: class SpeculateCellOperand { public: - explicit SpeculateCellOperand(SpeculativeJIT* jit, NodeUse use) + explicit SpeculateCellOperand(SpeculativeJIT* jit, Edge use) : m_jit(jit) , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) { ASSERT(m_jit); + ASSERT(use.useKind() != DoubleUse); if (jit->isFilled(m_index)) gpr(); } @@ -2475,12 +2585,13 @@ private: class SpeculateBooleanOperand { public: - explicit SpeculateBooleanOperand(SpeculativeJIT* jit, NodeUse use) + explicit SpeculateBooleanOperand(SpeculativeJIT* jit, Edge use) : m_jit(jit) , m_index(use.index()) , m_gprOrInvalid(InvalidGPRReg) { ASSERT(m_jit); + ASSERT(use.useKind() != DoubleUse); if (jit->isFilled(m_index)) gpr(); } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp index b6814229c..c156e81d0 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp @@ -29,8 +29,6 @@ #if ENABLE(DFG_JIT) -#include "JSByteArray.h" - namespace JSC { namespace DFG { #if USE(JSVALUE32_64) @@ -495,10 +493,8 @@ void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node& node) JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseTagGPROrNone, GPRReg basePayloadGPR, GPRReg resultTagGPR, GPRReg resultPayloadGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode) { - m_jit.beginUninterruptedSequence(); JITCompiler::DataLabelPtr structureToCompare; - JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); - m_jit.endUninterruptedSequence(); + JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); m_jit.loadPtr(JITCompiler::Address(basePayloadGPR, JSObject::offsetOfPropertyStorage()), resultPayloadGPR); JITCompiler::DataLabelCompact tagLoadWithPatch = m_jit.load32WithCompactAddressOffsetPatch(JITCompiler::Address(resultPayloadGPR, OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)), resultTagGPR); @@ -506,7 +502,7 @@ JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg ba JITCompiler::Jump done = m_jit.jump(); - structureCheck.link(&m_jit); + structureCheck.m_jump.link(&m_jit); if (slowPathTarget.isSet()) slowPathTarget.link(&m_jit); @@ -532,12 +528,10 @@ JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg ba return functionCall; } -void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, NodeUse valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) +void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, GPRReg valueTagGPR, GPRReg valuePayloadGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) { - m_jit.beginUninterruptedSequence(); JITCompiler::DataLabelPtr structureToCompare; - JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); - m_jit.endUninterruptedSequence(); + JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(basePayloadGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); writeBarrier(basePayloadGPR, valueTagGPR, valueUse, WriteBarrierForPropertyAccess, scratchGPR); @@ -547,7 +541,7 @@ void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, JITCompiler::Jump done = m_jit.jump(); - structureCheck.link(&m_jit); + structureCheck.m_jump.link(&m_jit); if (slowPathTarget.isSet()) slowPathTarget.link(&m_jit); @@ -576,7 +570,7 @@ void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg basePayloadGPR, m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(tagStoreWithPatch.label()), JITCompiler::DataLabelCompact(payloadStoreWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(basePayloadGPR), safeCast<int8_t>(valueTagGPR), safeCast<int8_t>(valuePayloadGPR), safeCast<int8_t>(scratchGPR))); } -void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeUse operand, bool invert) +void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert) { JSValueOperand arg(this, operand); GPRReg argTagGPR = arg.tagGPR(); @@ -608,7 +602,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeUse operand, bool booleanResult(resultPayloadGPR, m_compileIndex); } -void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex branchNodeIndex, bool invert) +void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex branchNodeIndex, bool invert) { Node& branchNode = at(branchNodeIndex); BlockIndex taken = branchNode.takenBlockIndex(); @@ -650,7 +644,7 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex jump(notTaken); } -bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, NodeUse operand, bool invert) +bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, Edge operand, bool invert) { unsigned branchIndexInBlock = detectPeepHoleBranch(); if (branchIndexInBlock != UINT_MAX) { @@ -739,6 +733,9 @@ void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNo } jump(notTaken); + + m_indexInBlock = m_jit.graph().m_blocks[m_block]->size() - 1; + m_compileIndex = branchNodeIndex; } void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction) @@ -895,24 +892,24 @@ void SpeculativeJIT::emitCall(Node& node) { P_DFGOperation_E slowCallFunction; - if (node.op == Call) + if (node.op() == Call) slowCallFunction = operationLinkCall; else { - ASSERT(node.op == Construct); + ASSERT(node.op() == Construct); slowCallFunction = operationLinkConstruct; } // For constructors, the this argument is not passed but we have to make space // for it. - int dummyThisArgument = node.op == Call ? 0 : 1; + int dummyThisArgument = node.op() == Call ? 0 : 1; - CallLinkInfo::CallType callType = node.op == Call ? CallLinkInfo::Call : CallLinkInfo::Construct; + CallLinkInfo::CallType callType = node.op() == Call ? CallLinkInfo::Call : CallLinkInfo::Construct; - NodeUse calleeNodeUse = m_jit.graph().m_varArgChildren[node.firstChild()]; - JSValueOperand callee(this, calleeNodeUse); + Edge calleeEdge = m_jit.graph().m_varArgChildren[node.firstChild()]; + JSValueOperand callee(this, calleeEdge); GPRReg calleeTagGPR = callee.tagGPR(); GPRReg calleePayloadGPR = callee.payloadGPR(); - use(calleeNodeUse); + use(calleeEdge); // The call instruction's first child is either the function (normal call) or the // receiver (method call). subsequent children are the arguments. @@ -924,11 +921,11 @@ void SpeculativeJIT::emitCall(Node& node) m_jit.store32(calleeTagGPR, callFrameTagSlot(RegisterFile::Callee)); for (int i = 0; i < numPassedArgs; i++) { - NodeUse argNodeUse = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i]; - JSValueOperand arg(this, argNodeUse); + Edge argEdge = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i]; + JSValueOperand arg(this, argEdge); GPRReg argTagGPR = arg.tagGPR(); GPRReg argPayloadGPR = arg.payloadGPR(); - use(argNodeUse); + use(argEdge); m_jit.store32(argTagGPR, argumentTagSlot(i + dummyThisArgument)); m_jit.store32(argPayloadGPR, argumentPayloadSlot(i + dummyThisArgument)); @@ -953,7 +950,7 @@ void SpeculativeJIT::emitCall(Node& node) m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin; - CallBeginToken token = m_jit.beginJSCall(); + CallBeginToken token = m_jit.beginCall(); JITCompiler::Call fastCall = m_jit.nearCall(); m_jit.notifyCall(fastCall, codeOrigin, token); @@ -967,7 +964,7 @@ void SpeculativeJIT::emitCall(Node& node) JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction); m_jit.addFastExceptionCheck(slowCall, codeOrigin, token); m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); - token = m_jit.beginJSCall(); + token = m_jit.beginCall(); JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR); m_jit.notifyCall(theCall, codeOrigin, token); @@ -1285,15 +1282,15 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(NodeIndex nodeIndex) #if DFG_ENABLE(DEBUG_VERBOSE) dataLog("SpecBool@%d ", nodeIndex); #endif - if (isKnownNotBoolean(nodeIndex)) { + Node& node = m_jit.graph()[nodeIndex]; + VirtualRegister virtualRegister = node.virtualRegister(); + GenerationInfo& info = m_generationInfo[virtualRegister]; + if ((node.hasConstant() && !valueOfJSConstant(nodeIndex).isBoolean()) + || !(info.isJSBoolean() || info.isUnknownJS())) { terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); return allocate(); } - Node& node = at(nodeIndex); - VirtualRegister virtualRegister = node.virtualRegister(); - GenerationInfo& info = m_generationInfo[virtualRegister]; - switch (info.registerFormat()) { case DataFormatNone: { @@ -1399,6 +1396,147 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf booleanResult(resultPayloadGPR, m_compileIndex); } +void SpeculativeJIT::compileObjectToObjectOrOtherEquality( + Edge leftChild, Edge rightChild, + const ClassInfo* classInfo, PredictionChecker predictionCheck) +{ + SpeculateCellOperand op1(this, leftChild); + JSValueOperand op2(this, rightChild); + GPRTemporary result(this); + + GPRReg op1GPR = op1.gpr(); + GPRReg op2TagGPR = op2.tagGPR(); + GPRReg op2PayloadGPR = op2.payloadGPR(); + GPRReg resultGPR = result.gpr(); + + if (!predictionCheck(m_state.forNode(leftChild).m_type)) { + speculationCheck( + BadType, JSValueSource::unboxedCell(op1GPR), leftChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, + MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), + MacroAssembler::TrustedImmPtr(classInfo))); + } + + // It seems that most of the time when programs do a == b where b may be either null/undefined + // or an object, b is usually an object. Balance the branches to make that case fast. + MacroAssembler::Jump rightNotCell = + m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag)); + + // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the + // proof, when filtered on cell, demonstrates that we have an object of the desired type + // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the + // speculation. + if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) { + speculationCheck( + BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, + MacroAssembler::Address(op2PayloadGPR, JSCell::classInfoOffset()), + MacroAssembler::TrustedImmPtr(classInfo))); + } + + // At this point we know that we can perform a straight-forward equality comparison on pointer + // values because both left and right are pointers to objects that have no special equality + // protocols. + MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2PayloadGPR); + MacroAssembler::Jump trueCase = m_jit.jump(); + + rightNotCell.link(&m_jit); + + // We know that within this branch, rightChild must not be a cell. Check if that is enough to + // prove that it is either null or undefined. + if (!isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) { + m_jit.move(op2TagGPR, resultGPR); + m_jit.or32(TrustedImm32(1), resultGPR); + + speculationCheck( + BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(), + m_jit.branch32( + MacroAssembler::NotEqual, resultGPR, + MacroAssembler::TrustedImm32(JSValue::NullTag))); + } + + falseCase.link(&m_jit); + m_jit.move(TrustedImm32(0), resultGPR); + MacroAssembler::Jump done = m_jit.jump(); + trueCase.link(&m_jit); + m_jit.move(TrustedImm32(1), resultGPR); + done.link(&m_jit); + + booleanResult(resultGPR, m_compileIndex); +} + +void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality( + Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, + const ClassInfo* classInfo, PredictionChecker predictionCheck) +{ + Node& branchNode = at(branchNodeIndex); + BlockIndex taken = branchNode.takenBlockIndex(); + BlockIndex notTaken = branchNode.notTakenBlockIndex(); + + SpeculateCellOperand op1(this, leftChild); + JSValueOperand op2(this, rightChild); + GPRTemporary result(this); + + GPRReg op1GPR = op1.gpr(); + GPRReg op2TagGPR = op2.tagGPR(); + GPRReg op2PayloadGPR = op2.payloadGPR(); + GPRReg resultGPR = result.gpr(); + + if (!predictionCheck(m_state.forNode(leftChild).m_type)) { + speculationCheck( + BadType, JSValueSource::unboxedCell(op1GPR), leftChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, + MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), + MacroAssembler::TrustedImmPtr(classInfo))); + } + + // It seems that most of the time when programs do a == b where b may be either null/undefined + // or an object, b is usually an object. Balance the branches to make that case fast. + MacroAssembler::Jump rightNotCell = + m_jit.branch32(MacroAssembler::NotEqual, op2TagGPR, TrustedImm32(JSValue::CellTag)); + + // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the + // proof, when filtered on cell, demonstrates that we have an object of the desired type + // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the + // speculation. + if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) { + speculationCheck( + BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, + MacroAssembler::Address(op2PayloadGPR, JSCell::classInfoOffset()), + MacroAssembler::TrustedImmPtr(classInfo))); + } + + // At this point we know that we can perform a straight-forward equality comparison on pointer + // values because both left and right are pointers to objects that have no special equality + // protocols. + branch32(MacroAssembler::Equal, op1GPR, op2PayloadGPR, taken); + + // We know that within this branch, rightChild must not be a cell. Check if that is enough to + // prove that it is either null or undefined. + if (isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) + rightNotCell.link(&m_jit); + else { + jump(notTaken, ForceJump); + + rightNotCell.link(&m_jit); + m_jit.move(op2TagGPR, resultGPR); + m_jit.or32(TrustedImm32(1), resultGPR); + + speculationCheck( + BadType, JSValueRegs(op2TagGPR, op2PayloadGPR), rightChild.index(), + m_jit.branch32( + MacroAssembler::NotEqual, resultGPR, + MacroAssembler::TrustedImm32(JSValue::NullTag))); + } + + jump(notTaken); +} + void SpeculativeJIT::compileIntegerCompare(Node& node, MacroAssembler::RelationalCondition condition) { SpeculateIntegerOperand op1(this, node.child1()); @@ -1447,7 +1585,7 @@ void SpeculativeJIT::compileValueAdd(Node& node) jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex); } -void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeUse nodeUse, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse, const ClassInfo* classInfo, bool needSpeculationCheck) { JSValueOperand value(this, nodeUse); GPRTemporary resultPayload(this); @@ -1478,7 +1616,7 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeUse nodeUse, const Class void SpeculativeJIT::compileLogicalNot(Node& node) { - if (isKnownBoolean(node.child1().index()) || isBooleanPrediction(m_jit.getPrediction(node.child1().index()))) { + if (at(node.child1()).shouldSpeculateBoolean()) { SpeculateBooleanOperand value(this, node.child1()); GPRTemporary result(this, value); m_jit.xor32(TrustedImm32(1), value.gpr(), result.gpr()); @@ -1535,7 +1673,7 @@ void SpeculativeJIT::compileLogicalNot(Node& node) booleanResult(resultPayloadGPR, m_compileIndex, UseChildrenCalledExplicitly); } -void SpeculativeJIT::emitObjectOrOtherBranch(NodeUse nodeUse, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck) { JSValueOperand value(this, nodeUse); GPRTemporary scratch(this); @@ -1567,7 +1705,7 @@ void SpeculativeJIT::emitBranch(Node& node) BlockIndex taken = node.takenBlockIndex(); BlockIndex notTaken = node.notTakenBlockIndex(); - if (isKnownBoolean(node.child1().index())) { + if (at(node.child1()).shouldSpeculateBoolean()) { SpeculateBooleanOperand value(this, node.child1()); MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; @@ -1640,7 +1778,7 @@ void SpeculativeJIT::emitBranch(Node& node) void SpeculativeJIT::compile(Node& node) { - NodeType op = static_cast<NodeType>(node.op); + NodeType op = node.op(); switch (op) { case JSConstant: @@ -1658,7 +1796,7 @@ void SpeculativeJIT::compile(Node& node) // If we have no prediction for this local, then don't attempt to compile. if (prediction == PredictNone || value.isClear()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -1684,7 +1822,7 @@ void SpeculativeJIT::compile(Node& node) break; } - if (isArrayPrediction(prediction) || isByteArrayPrediction(prediction)) { + if (isArrayPrediction(prediction)) { GPRTemporary result(this); m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr()); @@ -1742,9 +1880,30 @@ void SpeculativeJIT::compile(Node& node) // SetLocal and whatever other DFG Nodes are associated with the same // bytecode index as the SetLocal. ASSERT(m_codeOriginForOSR == node.codeOrigin); - Node& nextNode = at(m_compileIndex + 1); - - m_codeOriginForOSR = nextNode.codeOrigin; + Node* nextNode = &at(block()->at(m_indexInBlock + 1)); + + // But even more oddly, we need to be super careful about the following + // sequence: + // + // a: Foo() + // b: SetLocal(@a) + // c: Flush(@b) + // + // This next piece of crazy takes care of this. + if (nextNode->op() == Flush && nextNode->child1() == m_compileIndex) + nextNode = &at(block()->at(m_indexInBlock + 2)); + + // Oddly, it's possible for the bytecode index for the next node to be + // equal to ours. This will happen for op_post_inc. And, even more oddly, + // this is just fine. Ordinarily, this wouldn't be fine, since if the + // next node failed OSR then we'd be OSR-ing with this SetLocal's local + // variable already set even though from the standpoint of the old JIT, + // this SetLocal should not have executed. But for op_post_inc, it's just + // fine, because this SetLocal's local (i.e. the LHS in a x = y++ + // statement) would be dead anyway - so the fact that DFG would have + // already made the assignment, and baked it into the register file during + // OSR exit, would not be visible to the old JIT in any way. + m_codeOriginForOSR = nextNode->codeOrigin; if (!m_jit.graph().isCaptured(node.local())) { if (node.variableAccessData()->shouldUseDoubleFormat()) { @@ -1757,7 +1916,7 @@ void SpeculativeJIT::compile(Node& node) valueSourceReferenceForOperand(node.local()) = ValueSource(DoubleInRegisterFile); break; } - PredictedType predictedType = node.variableAccessData()->prediction(); + PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction(); if (m_generationInfo[at(node.child1()).virtualRegister()].registerFormat() == DataFormatDouble) { DoubleOperand value(this, node.child1()); m_jit.storeDouble(value.fpr(), JITCompiler::addressFor(node.local())); @@ -1782,16 +1941,6 @@ void SpeculativeJIT::compile(Node& node) valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile); break; } - if (isByteArrayPrediction(predictedType)) { - SpeculateCellOperand cell(this, node.child1()); - GPRReg cellGPR = cell.gpr(); - if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); - m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local())); - noResult(m_compileIndex); - valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile); - break; - } if (isBooleanPrediction(predictedType)) { SpeculateBooleanOperand value(this, node.child1()); m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local())); @@ -1873,11 +2022,34 @@ void SpeculativeJIT::compile(Node& node) compileUInt32ToNumber(node); break; } + + case DoubleAsInt32: { + compileDoubleAsInt32(node); + break; + } case ValueToInt32: { compileValueToInt32(node); break; } + + case Int32ToDouble: { + compileInt32ToDouble(node); + break; + } + + case CheckNumber: { + if (!isNumberPrediction(m_state.forNode(node.child1()).m_type)) { + JSValueOperand op1(this, node.child1()); + JITCompiler::Jump isInteger = m_jit.branch32(MacroAssembler::Equal, op1.tagGPR(), TrustedImm32(JSValue::Int32Tag)); + speculationCheck( + BadType, JSValueRegs(op1.tagGPR(), op1.payloadGPR()), node.child1().index(), + m_jit.branch32(MacroAssembler::AboveOrEqual, op1.tagGPR(), TrustedImm32(JSValue::LowestTag))); + isInteger.link(&m_jit); + } + noResult(m_compileIndex); + break; + } case ValueAdd: case ArithAdd: @@ -1899,63 +2071,9 @@ void SpeculativeJIT::compile(Node& node) case ArithDiv: { if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) { #if CPU(X86) - SpeculateIntegerOperand op1(this, node.child1()); - SpeculateIntegerOperand op2(this, node.child2()); - GPRReg op1GPR = op1.gpr(); - GPRReg op2GPR = op2.gpr(); - - speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR)); - - // If the user cares about negative zero, then speculate that we're not about - // to produce negative zero. - if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) { - MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR); - speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0))); - numeratorNonZero.link(&m_jit); - } - - GPRTemporary eax(this, X86Registers::eax); - GPRTemporary edx(this, X86Registers::edx); - - GPRReg temp2 = InvalidGPRReg; - if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) { - temp2 = allocate(); - m_jit.move(op2GPR, temp2); - op2GPR = temp2; - } - - m_jit.move(op1GPR, eax.gpr()); - m_jit.assembler().cdq(); - m_jit.assembler().idivl_r(op2GPR); - - if (temp2 != InvalidGPRReg) - unlock(temp2); - - // Check that there was no remainder. If there had been, then we'd be obligated to - // produce a double result instead. - speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr())); - - integerResult(eax.gpr(), m_compileIndex); + compileIntegerArithDivForX86(node); #else // CPU(X86) -> so non-X86 code follows - SpeculateDoubleOperand op1(this, node.child1()); - SpeculateDoubleOperand op2(this, node.child2()); - FPRTemporary result(this); - FPRTemporary scratch(this); - GPRTemporary intResult(this); - - FPRReg op1FPR = op1.fpr(); - FPRReg op2FPR = op2.fpr(); - FPRReg resultFPR = result.fpr(); - FPRReg scratchFPR = scratch.fpr(); - GPRReg resultGPR = intResult.gpr(); - - m_jit.divDouble(op1FPR, op2FPR, resultFPR); - - JITCompiler::JumpList failureCases; - m_jit.branchConvertDoubleToInt32(resultFPR, resultGPR, failureCases, scratchFPR); - speculationCheck(Overflow, JSValueRegs(), NoNode, failureCases); - - integerResult(resultGPR, m_compileIndex); + ASSERT_NOT_REACHED(); // should have been coverted into a double divide. #endif // CPU(X86) break; } @@ -2121,7 +2239,7 @@ void SpeculativeJIT::compile(Node& node) case GetByVal: { if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -2148,13 +2266,6 @@ void SpeculativeJIT::compile(Node& node) break; } - if (at(node.child1()).shouldSpeculateByteArray()) { - compileGetByValOnByteArray(node); - if (!m_compileOkay) - return; - break; - } - if (at(node.child1()).shouldSpeculateInt8Array()) { compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); if (!m_compileOkay) @@ -2254,7 +2365,7 @@ void SpeculativeJIT::compile(Node& node) case PutByVal: { if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -2277,15 +2388,6 @@ void SpeculativeJIT::compile(Node& node) SpeculateCellOperand base(this, node.child1()); SpeculateStrictInt32Operand property(this, node.child2()); - if (at(node.child1()).shouldSpeculateByteArray()) { - compilePutByValForByteArray(base.gpr(), property.gpr(), node); - break; - } - if (at(node.child1()).shouldSpeculateByteArray()) { - compilePutByValForByteArray(base.gpr(), property.gpr(), node); - break; - } - if (at(node.child1()).shouldSpeculateInt8Array()) { compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); if (!m_compileOkay) @@ -2414,7 +2516,7 @@ void SpeculativeJIT::compile(Node& node) case PutByValAlias: { if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -2424,11 +2526,6 @@ void SpeculativeJIT::compile(Node& node) SpeculateCellOperand base(this, node.child1()); SpeculateStrictInt32Operand property(this, node.child2()); - if (at(node.child1()).shouldSpeculateByteArray()) { - compilePutByValForByteArray(base.gpr(), property.gpr(), node); - break; - } - if (at(node.child1()).shouldSpeculateInt8Array()) { compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), NoTypedArraySpecCheck, SignedTypedArray); if (!m_compileOkay) @@ -2515,6 +2612,55 @@ void SpeculativeJIT::compile(Node& node) break; } + case RegExpExec: { + if (compileRegExpExec(node)) + return; + + if (!node.adjustedRefCount()) { + SpeculateCellOperand base(this, node.child1()); + SpeculateCellOperand argument(this, node.child2()); + GPRReg baseGPR = base.gpr(); + GPRReg argumentGPR = argument.gpr(); + + flushRegisters(); + GPRResult result(this); + callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR); + + // Must use jsValueResult because otherwise we screw up register + // allocation, which thinks that this node has a result. + booleanResult(result.gpr(), m_compileIndex); + break; + } + + SpeculateCellOperand base(this, node.child1()); + SpeculateCellOperand argument(this, node.child2()); + GPRReg baseGPR = base.gpr(); + GPRReg argumentGPR = argument.gpr(); + + flushRegisters(); + GPRResult2 resultTag(this); + GPRResult resultPayload(this); + callOperation(operationRegExpExec, resultTag.gpr(), resultPayload.gpr(), baseGPR, argumentGPR); + + jsValueResult(resultTag.gpr(), resultPayload.gpr(), m_compileIndex); + break; + } + + case RegExpTest: { + SpeculateCellOperand base(this, node.child1()); + SpeculateCellOperand argument(this, node.child2()); + GPRReg baseGPR = base.gpr(); + GPRReg argumentGPR = argument.gpr(); + + flushRegisters(); + GPRResult result(this); + callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR); + + // If we add a DataFormatBool, we should use it here. + booleanResult(result.gpr(), m_compileIndex); + break; + } + case ArrayPush: { SpeculateCellOperand base(this, node.child1()); JSValueOperand value(this, node.child2()); @@ -2716,8 +2862,6 @@ void SpeculativeJIT::compile(Node& node) // FIXME: Add string speculation here. - bool wasPrimitive = isKnownNumeric(node.child1().index()) || isKnownBoolean(node.child1().index()); - JSValueOperand op1(this, node.child1()); GPRTemporary resultTag(this, op1); GPRTemporary resultPayload(this, op1, false); @@ -2729,7 +2873,7 @@ void SpeculativeJIT::compile(Node& node) op1.use(); - if (wasPrimitive) { + if (!(m_state.forNode(node.child1()).m_type & ~(PredictNumber | PredictBoolean))) { m_jit.move(op1TagGPR, resultTagGPR); m_jit.move(op1PayloadGPR, resultPayloadGPR); } else { @@ -3014,7 +3158,7 @@ void SpeculativeJIT::compile(Node& node) case GetById: { if (!node.prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -3068,7 +3212,7 @@ void SpeculativeJIT::compile(Node& node) case GetByIdFlush: { if (!node.prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -3152,22 +3296,6 @@ void SpeculativeJIT::compile(Node& node) break; } - case GetByteArrayLength: { - SpeculateCellOperand base(this, node.child1()); - GPRReg baseGPR = base.gpr(); - - if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); - - GPRTemporary result(this); - GPRReg resultGPR = result.gpr(); - - m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSByteArray::offsetOfStorage()), resultGPR); - m_jit.load32(MacroAssembler::Address(resultGPR, ByteArray::offsetOfSize()), resultGPR); - - integerResult(resultGPR, m_compileIndex); - break; - } case GetInt8ArrayLength: { compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type)); break; @@ -3411,6 +3539,85 @@ void SpeculativeJIT::compile(Node& node) break; } + case IsUndefined: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this); + + JITCompiler::Jump isCell = m_jit.branch32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::CellTag)); + + m_jit.compare32(JITCompiler::Equal, value.tagGPR(), TrustedImm32(JSValue::UndefinedTag), result.gpr()); + JITCompiler::Jump done = m_jit.jump(); + + isCell.link(&m_jit); + m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureOffset()), result.gpr()); + m_jit.test8(JITCompiler::NonZero, JITCompiler::Address(result.gpr(), Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), result.gpr()); + + done.link(&m_jit); + booleanResult(result.gpr(), m_compileIndex); + break; + } + + case IsBoolean: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value); + + m_jit.compare32(JITCompiler::Equal, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::BooleanTag), result.gpr()); + booleanResult(result.gpr(), m_compileIndex); + break; + } + + case IsNumber: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value); + + m_jit.add32(TrustedImm32(1), value.tagGPR(), result.gpr()); + m_jit.compare32(JITCompiler::Below, result.gpr(), JITCompiler::TrustedImm32(JSValue::LowestTag + 1), result.gpr()); + booleanResult(result.gpr(), m_compileIndex); + break; + } + + case IsString: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value); + + JITCompiler::Jump isNotCell = m_jit.branch32(JITCompiler::NotEqual, value.tagGPR(), JITCompiler::TrustedImm32(JSValue::CellTag)); + + m_jit.loadPtr(JITCompiler::Address(value.payloadGPR(), JSCell::structureOffset()), result.gpr()); + m_jit.compare8(JITCompiler::Equal, JITCompiler::Address(result.gpr(), Structure::typeInfoTypeOffset()), TrustedImm32(StringType), result.gpr()); + JITCompiler::Jump done = m_jit.jump(); + + isNotCell.link(&m_jit); + m_jit.move(TrustedImm32(0), result.gpr()); + + done.link(&m_jit); + booleanResult(result.gpr(), m_compileIndex); + break; + } + + case IsObject: { + JSValueOperand value(this, node.child1()); + GPRReg valueTagGPR = value.tagGPR(); + GPRReg valuePayloadGPR = value.payloadGPR(); + GPRResult result(this); + GPRReg resultGPR = result.gpr(); + flushRegisters(); + callOperation(operationIsObject, resultGPR, valueTagGPR, valuePayloadGPR); + booleanResult(result.gpr(), m_compileIndex); + break; + } + + case IsFunction: { + JSValueOperand value(this, node.child1()); + GPRReg valueTagGPR = value.tagGPR(); + GPRReg valuePayloadGPR = value.payloadGPR(); + GPRResult result(this); + GPRReg resultGPR = result.gpr(); + flushRegisters(); + callOperation(operationIsFunction, resultGPR, valueTagGPR, valuePayloadGPR); + booleanResult(result.gpr(), m_compileIndex); + break; + } + case Phi: case Flush: break; @@ -3567,7 +3774,7 @@ void SpeculativeJIT::compile(Node& node) break; case ForceOSRExit: { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp index 1597b1674..a46f8f262 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp @@ -26,8 +26,6 @@ #include "config.h" #include "DFGSpeculativeJIT.h" -#include "JSByteArray.h" - #if ENABLE(DFG_JIT) namespace JSC { namespace DFG { @@ -76,7 +74,7 @@ GPRReg SpeculativeJIT::fillInteger(NodeIndex nodeIndex, DataFormat& returnFormat info.fillJSValue(gpr, DataFormatJSInteger); unlock(gpr); } - + switch (info.registerFormat()) { case DataFormatNone: // Should have filled, above. @@ -409,7 +407,7 @@ void SpeculativeJIT::nonSpeculativeValueToInt32(Node& node) if (isKnownInteger(node.child1().index())) { IntegerOperand op1(this, node.child1()); GPRTemporary result(this, op1); - m_jit.move(op1.gpr(), result.gpr()); + m_jit.zeroExtend32ToPtr(op1.gpr(), result.gpr()); integerResult(result.gpr(), m_compileIndex); return; } @@ -480,14 +478,14 @@ void SpeculativeJIT::nonSpeculativeUInt32ToNumber(Node& node) JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg resultGPR, GPRReg scratchGPR, unsigned identifierNumber, JITCompiler::Jump slowPathTarget, SpillRegistersMode spillMode) { JITCompiler::DataLabelPtr structureToCompare; - JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); + JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); m_jit.loadPtr(JITCompiler::Address(baseGPR, JSObject::offsetOfPropertyStorage()), resultGPR); JITCompiler::DataLabelCompact loadWithPatch = m_jit.loadPtrWithCompactAddressOffsetPatch(JITCompiler::Address(resultGPR, 0), resultGPR); JITCompiler::Jump done = m_jit.jump(); - structureCheck.link(&m_jit); + structureCheck.m_jump.link(&m_jit); if (slowPathTarget.isSet()) slowPathTarget.link(&m_jit); @@ -512,11 +510,11 @@ JITCompiler::Call SpeculativeJIT::cachedGetById(CodeOrigin codeOrigin, GPRReg ba return functionCall; } -void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, NodeUse valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) +void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg valueGPR, Edge valueUse, GPRReg scratchGPR, unsigned identifierNumber, PutKind putKind, JITCompiler::Jump slowPathTarget) { JITCompiler::DataLabelPtr structureToCompare; - JITCompiler::Jump structureCheck = m_jit.branchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); + JITCompiler::PatchableJump structureCheck = m_jit.patchableBranchPtrWithPatch(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), structureToCompare, JITCompiler::TrustedImmPtr(reinterpret_cast<void*>(-1))); writeBarrier(baseGPR, valueGPR, valueUse, WriteBarrierForPropertyAccess, scratchGPR); @@ -525,7 +523,7 @@ void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg JITCompiler::Jump done = m_jit.jump(); - structureCheck.link(&m_jit); + structureCheck.m_jump.link(&m_jit); if (slowPathTarget.isSet()) slowPathTarget.link(&m_jit); @@ -554,7 +552,7 @@ void SpeculativeJIT::cachedPutById(CodeOrigin codeOrigin, GPRReg baseGPR, GPRReg m_jit.addPropertyAccess(PropertyAccessRecord(codeOrigin, structureToCompare, functionCall, structureCheck, JITCompiler::DataLabelCompact(storeWithPatch.label()), slowCase, doneLabel, safeCast<int8_t>(baseGPR), safeCast<int8_t>(valueGPR), safeCast<int8_t>(scratchGPR))); } -void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeUse operand, bool invert) +void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(Edge operand, bool invert) { JSValueOperand arg(this, operand); GPRReg argGPR = arg.gpr(); @@ -586,7 +584,7 @@ void SpeculativeJIT::nonSpeculativeNonPeepholeCompareNull(NodeUse operand, bool jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); } -void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex branchNodeIndex, bool invert) +void SpeculativeJIT::nonSpeculativePeepholeBranchNull(Edge operand, NodeIndex branchNodeIndex, bool invert) { Node& branchNode = at(branchNodeIndex); BlockIndex taken = branchNode.takenBlockIndex(); @@ -626,7 +624,7 @@ void SpeculativeJIT::nonSpeculativePeepholeBranchNull(NodeUse operand, NodeIndex jump(notTaken); } -bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, NodeUse operand, bool invert) +bool SpeculativeJIT::nonSpeculativeCompareNull(Node& node, Edge operand, bool invert) { unsigned branchIndexInBlock = detectPeepHoleBranch(); if (branchIndexInBlock != UINT_MAX) { @@ -713,6 +711,9 @@ void SpeculativeJIT::nonSpeculativePeepholeBranch(Node& node, NodeIndex branchNo } jump(notTaken); + + m_indexInBlock = m_jit.graph().m_blocks[m_block]->size() - 1; + m_compileIndex = branchNodeIndex; } void SpeculativeJIT::nonSpeculativeNonPeepholeCompare(Node& node, MacroAssembler::RelationalCondition cond, S_DFGOperation_EJJ helperFunction) @@ -916,23 +917,23 @@ void SpeculativeJIT::emitCall(Node& node) { P_DFGOperation_E slowCallFunction; - if (node.op == Call) + if (node.op() == Call) slowCallFunction = operationLinkCall; else { - ASSERT(node.op == Construct); + ASSERT(node.op() == Construct); slowCallFunction = operationLinkConstruct; } // For constructors, the this argument is not passed but we have to make space // for it. - int dummyThisArgument = node.op == Call ? 0 : 1; + int dummyThisArgument = node.op() == Call ? 0 : 1; - CallLinkInfo::CallType callType = node.op == Call ? CallLinkInfo::Call : CallLinkInfo::Construct; + CallLinkInfo::CallType callType = node.op() == Call ? CallLinkInfo::Call : CallLinkInfo::Construct; - NodeUse calleeNodeUse = m_jit.graph().m_varArgChildren[node.firstChild()]; - JSValueOperand callee(this, calleeNodeUse); + Edge calleeEdge = m_jit.graph().m_varArgChildren[node.firstChild()]; + JSValueOperand callee(this, calleeEdge); GPRReg calleeGPR = callee.gpr(); - use(calleeNodeUse); + use(calleeEdge); // The call instruction's first child is either the function (normal call) or the // receiver (method call). subsequent children are the arguments. @@ -943,10 +944,10 @@ void SpeculativeJIT::emitCall(Node& node) m_jit.storePtr(calleeGPR, callFrameSlot(RegisterFile::Callee)); for (int i = 0; i < numPassedArgs; i++) { - NodeUse argNodeUse = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i]; - JSValueOperand arg(this, argNodeUse); + Edge argEdge = m_jit.graph().m_varArgChildren[node.firstChild() + 1 + i]; + JSValueOperand arg(this, argEdge); GPRReg argGPR = arg.gpr(); - use(argNodeUse); + use(argEdge); m_jit.storePtr(argGPR, argumentSlot(i + dummyThisArgument)); } @@ -966,7 +967,7 @@ void SpeculativeJIT::emitCall(Node& node) m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); CodeOrigin codeOrigin = at(m_compileIndex).codeOrigin; - CallBeginToken token = m_jit.beginJSCall(); + CallBeginToken token = m_jit.beginCall(); JITCompiler::Call fastCall = m_jit.nearCall(); m_jit.notifyCall(fastCall, codeOrigin, token); @@ -979,7 +980,7 @@ void SpeculativeJIT::emitCall(Node& node) JITCompiler::Call slowCall = m_jit.appendCall(slowCallFunction); m_jit.addFastExceptionCheck(slowCall, codeOrigin, token); m_jit.addPtr(TrustedImm32(m_jit.codeBlock()->m_numCalleeRegisters * sizeof(Register)), GPRInfo::callFrameRegister); - token = m_jit.beginJSCall(); + token = m_jit.beginCall(); JITCompiler::Call theCall = m_jit.call(GPRInfo::returnValueGPR); m_jit.notifyCall(theCall, codeOrigin, token); @@ -1485,6 +1486,145 @@ void SpeculativeJIT::compileObjectEquality(Node& node, const ClassInfo* classInf jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); } +void SpeculativeJIT::compileObjectToObjectOrOtherEquality( + Edge leftChild, Edge rightChild, + const ClassInfo* classInfo, PredictionChecker predictionCheck) +{ + SpeculateCellOperand op1(this, leftChild); + JSValueOperand op2(this, rightChild); + GPRTemporary result(this); + + GPRReg op1GPR = op1.gpr(); + GPRReg op2GPR = op2.gpr(); + GPRReg resultGPR = result.gpr(); + + if (!predictionCheck(m_state.forNode(leftChild).m_type)) { + speculationCheck( + BadType, JSValueRegs(op1GPR), leftChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, + MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), + MacroAssembler::TrustedImmPtr(classInfo))); + } + + // It seems that most of the time when programs do a == b where b may be either null/undefined + // or an object, b is usually an object. Balance the branches to make that case fast. + MacroAssembler::Jump rightNotCell = + m_jit.branchTestPtr(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister); + + // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the + // proof, when filtered on cell, demonstrates that we have an object of the desired type + // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the + // speculation. + if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) { + speculationCheck( + BadType, JSValueRegs(op2GPR), rightChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, + MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), + MacroAssembler::TrustedImmPtr(classInfo))); + } + + // At this point we know that we can perform a straight-forward equality comparison on pointer + // values because both left and right are pointers to objects that have no special equality + // protocols. + MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR); + MacroAssembler::Jump trueCase = m_jit.jump(); + + rightNotCell.link(&m_jit); + + // We know that within this branch, rightChild must not be a cell. Check if that is enough to + // prove that it is either null or undefined. + if (!isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) { + m_jit.move(op2GPR, resultGPR); + m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); + + speculationCheck( + BadType, JSValueRegs(op2GPR), rightChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, resultGPR, + MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); + } + + falseCase.link(&m_jit); + m_jit.move(TrustedImm32(ValueFalse), resultGPR); + MacroAssembler::Jump done = m_jit.jump(); + trueCase.link(&m_jit); + m_jit.move(TrustedImm32(ValueTrue), resultGPR); + done.link(&m_jit); + + jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean); +} + +void SpeculativeJIT::compilePeepHoleObjectToObjectOrOtherEquality( + Edge leftChild, Edge rightChild, NodeIndex branchNodeIndex, + const ClassInfo* classInfo, PredictionChecker predictionCheck) +{ + Node& branchNode = at(branchNodeIndex); + BlockIndex taken = branchNode.takenBlockIndex(); + BlockIndex notTaken = branchNode.notTakenBlockIndex(); + + SpeculateCellOperand op1(this, leftChild); + JSValueOperand op2(this, rightChild); + GPRTemporary result(this); + + GPRReg op1GPR = op1.gpr(); + GPRReg op2GPR = op2.gpr(); + GPRReg resultGPR = result.gpr(); + + if (!predictionCheck(m_state.forNode(leftChild).m_type)) { + speculationCheck( + BadType, JSValueRegs(op1GPR), leftChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, + MacroAssembler::Address(op1GPR, JSCell::classInfoOffset()), + MacroAssembler::TrustedImmPtr(classInfo))); + } + + // It seems that most of the time when programs do a == b where b may be either null/undefined + // or an object, b is usually an object. Balance the branches to make that case fast. + MacroAssembler::Jump rightNotCell = + m_jit.branchTestPtr(MacroAssembler::NonZero, op2GPR, GPRInfo::tagMaskRegister); + + // We know that within this branch, rightChild must be a cell. If the CFA can tell us that the + // proof, when filtered on cell, demonstrates that we have an object of the desired type + // (predictionCheck() will test for FinalObject or Array, currently), then we can skip the + // speculation. + if (!predictionCheck(m_state.forNode(rightChild).m_type & PredictCell)) { + speculationCheck( + BadType, JSValueRegs(op2GPR), rightChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, + MacroAssembler::Address(op2GPR, JSCell::classInfoOffset()), + MacroAssembler::TrustedImmPtr(classInfo))); + } + + // At this point we know that we can perform a straight-forward equality comparison on pointer + // values because both left and right are pointers to objects that have no special equality + // protocols. + branchPtr(MacroAssembler::Equal, op1GPR, op2GPR, taken); + + // We know that within this branch, rightChild must not be a cell. Check if that is enough to + // prove that it is either null or undefined. + if (isOtherPrediction(m_state.forNode(rightChild).m_type & ~PredictCell)) + rightNotCell.link(&m_jit); + else { + jump(notTaken, ForceJump); + + rightNotCell.link(&m_jit); + m_jit.move(op2GPR, resultGPR); + m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR); + + speculationCheck( + BadType, JSValueRegs(op2GPR), rightChild.index(), + m_jit.branchPtr( + MacroAssembler::NotEqual, resultGPR, + MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull)))); + } + + jump(notTaken); +} + void SpeculativeJIT::compileIntegerCompare(Node& node, MacroAssembler::RelationalCondition condition) { SpeculateIntegerOperand op1(this, node.child1()); @@ -1531,7 +1671,7 @@ void SpeculativeJIT::compileValueAdd(Node& node) jsValueResult(result.gpr(), m_compileIndex); } -void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeUse nodeUse, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::compileObjectOrOtherLogicalNot(Edge nodeUse, const ClassInfo* classInfo, bool needSpeculationCheck) { JSValueOperand value(this, nodeUse); GPRTemporary result(this); @@ -1560,16 +1700,6 @@ void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeUse nodeUse, const Class void SpeculativeJIT::compileLogicalNot(Node& node) { - if (isKnownBoolean(node.child1().index())) { - SpeculateBooleanOperand value(this, node.child1()); - GPRTemporary result(this, value); - - m_jit.move(value.gpr(), result.gpr()); - m_jit.xorPtr(TrustedImm32(true), result.gpr()); - - jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); - return; - } if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) { compileObjectOrOtherLogicalNot(node.child1(), &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type)); return; @@ -1599,7 +1729,18 @@ void SpeculativeJIT::compileLogicalNot(Node& node) } PredictedType prediction = m_jit.getPrediction(node.child1()); - if (isBooleanPrediction(prediction) || !prediction) { + if (isBooleanPrediction(prediction)) { + if (isBooleanPrediction(m_state.forNode(node.child1()).m_type)) { + SpeculateBooleanOperand value(this, node.child1()); + GPRTemporary result(this, value); + + m_jit.move(value.gpr(), result.gpr()); + m_jit.xorPtr(TrustedImm32(true), result.gpr()); + + jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); + return; + } + JSValueOperand value(this, node.child1()); GPRTemporary result(this); // FIXME: We could reuse, but on speculation fail would need recovery to restore tag (akin to add). @@ -1635,7 +1776,7 @@ void SpeculativeJIT::compileLogicalNot(Node& node) jsValueResult(resultGPR, m_compileIndex, DataFormatJSBoolean, UseChildrenCalledExplicitly); } -void SpeculativeJIT::emitObjectOrOtherBranch(NodeUse nodeUse, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck) +void SpeculativeJIT::emitObjectOrOtherBranch(Edge nodeUse, BlockIndex taken, BlockIndex notTaken, const ClassInfo* classInfo, bool needSpeculationCheck) { JSValueOperand value(this, nodeUse); GPRTemporary scratch(this); @@ -1661,27 +1802,10 @@ void SpeculativeJIT::emitObjectOrOtherBranch(NodeUse nodeUse, BlockIndex taken, void SpeculativeJIT::emitBranch(Node& node) { - JSValueOperand value(this, node.child1()); - GPRReg valueGPR = value.gpr(); - BlockIndex taken = node.takenBlockIndex(); BlockIndex notTaken = node.notTakenBlockIndex(); - if (isKnownBoolean(node.child1().index())) { - MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; - - if (taken == (m_block + 1)) { - condition = MacroAssembler::Zero; - BlockIndex tmp = taken; - taken = notTaken; - notTaken = tmp; - } - - branchTest32(condition, valueGPR, TrustedImm32(true), taken); - jump(notTaken); - - noResult(m_compileIndex); - } else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) { + if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) { emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSFinalObject::s_info, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type)); } else if (at(node.child1()).shouldSpeculateArrayOrOther()) { emitObjectOrOtherBranch(node.child1(), taken, notTaken, &JSArray::s_info, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type)); @@ -1708,18 +1832,35 @@ void SpeculativeJIT::emitBranch(Node& node) noResult(m_compileIndex); } else { - GPRTemporary result(this); - GPRReg resultGPR = result.gpr(); + JSValueOperand value(this, node.child1()); + GPRReg valueGPR = value.gpr(); bool predictBoolean = isBooleanPrediction(m_jit.getPrediction(node.child1())); if (predictBoolean) { - branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), notTaken); - branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), taken); - - speculationCheck(BadType, JSValueRegs(valueGPR), node.child1(), m_jit.jump()); + if (isBooleanPrediction(m_state.forNode(node.child1()).m_type)) { + MacroAssembler::ResultCondition condition = MacroAssembler::NonZero; + + if (taken == (m_block + 1)) { + condition = MacroAssembler::Zero; + BlockIndex tmp = taken; + taken = notTaken; + notTaken = tmp; + } + + branchTest32(condition, valueGPR, TrustedImm32(true), taken); + jump(notTaken); + } else { + branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(false))), notTaken); + branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsBoolean(true))), taken); + + speculationCheck(BadType, JSValueRegs(valueGPR), node.child1(), m_jit.jump()); + } value.use(); } else { + GPRTemporary result(this); + GPRReg resultGPR = result.gpr(); + branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::TrustedImmPtr(JSValue::encode(jsNumber(0))), notTaken); branchPtr(MacroAssembler::AboveOrEqual, valueGPR, GPRInfo::tagTypeNumberRegister, taken); @@ -1744,7 +1885,7 @@ void SpeculativeJIT::emitBranch(Node& node) void SpeculativeJIT::compile(Node& node) { - NodeType op = static_cast<NodeType>(node.op); + NodeType op = node.op(); switch (op) { case JSConstant: @@ -1762,7 +1903,7 @@ void SpeculativeJIT::compile(Node& node) // If we have no prediction for this local, then don't attempt to compile. if (prediction == PredictNone || value.isClear()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -1823,7 +1964,18 @@ void SpeculativeJIT::compile(Node& node) // SetLocal and whatever other DFG Nodes are associated with the same // bytecode index as the SetLocal. ASSERT(m_codeOriginForOSR == node.codeOrigin); - Node& nextNode = at(m_compileIndex + 1); + Node* nextNode = &at(block()->at(m_indexInBlock + 1)); + + // But even more oddly, we need to be super careful about the following + // sequence: + // + // a: Foo() + // b: SetLocal(@a) + // c: Flush(@b) + // + // This next piece of crazy takes care of this. + if (nextNode->op() == Flush && nextNode->child1() == m_compileIndex) + nextNode = &at(block()->at(m_indexInBlock + 2)); // Oddly, it's possible for the bytecode index for the next node to be // equal to ours. This will happen for op_post_inc. And, even more oddly, @@ -1835,7 +1987,7 @@ void SpeculativeJIT::compile(Node& node) // statement) would be dead anyway - so the fact that DFG would have // already made the assignment, and baked it into the register file during // OSR exit, would not be visible to the old JIT in any way. - m_codeOriginForOSR = nextNode.codeOrigin; + m_codeOriginForOSR = nextNode->codeOrigin; if (!m_jit.graph().isCaptured(node.local())) { if (node.variableAccessData()->shouldUseDoubleFormat()) { @@ -1849,7 +2001,7 @@ void SpeculativeJIT::compile(Node& node) break; } - PredictedType predictedType = node.variableAccessData()->prediction(); + PredictedType predictedType = node.variableAccessData()->argumentAwarePrediction(); if (isInt32Prediction(predictedType)) { SpeculateIntegerOperand value(this, node.child1()); m_jit.store32(value.gpr(), JITCompiler::payloadFor(node.local())); @@ -1867,16 +2019,6 @@ void SpeculativeJIT::compile(Node& node) valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile); break; } - if (isByteArrayPrediction(predictedType)) { - SpeculateCellOperand cell(this, node.child1()); - GPRReg cellGPR = cell.gpr(); - if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueRegs(cellGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); - m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local())); - noResult(m_compileIndex); - valueSourceReferenceForOperand(node.local()) = ValueSource(CellInRegisterFile); - break; - } if (isBooleanPrediction(predictedType)) { SpeculateBooleanOperand boolean(this, node.child1()); m_jit.storePtr(boolean.gpr(), JITCompiler::addressFor(node.local())); @@ -1960,10 +2102,33 @@ void SpeculativeJIT::compile(Node& node) break; } + case DoubleAsInt32: { + compileDoubleAsInt32(node); + break; + } + case ValueToInt32: { compileValueToInt32(node); break; } + + case Int32ToDouble: { + compileInt32ToDouble(node); + break; + } + + case CheckNumber: { + if (!isNumberPrediction(m_state.forNode(node.child1()).m_type)) { + JSValueOperand op1(this, node.child1()); + JITCompiler::Jump isInteger = m_jit.branchPtr(MacroAssembler::AboveOrEqual, op1.gpr(), GPRInfo::tagTypeNumberRegister); + speculationCheck( + BadType, JSValueRegs(op1.gpr()), node.child1().index(), + m_jit.branchTestPtr(MacroAssembler::Zero, op1.gpr(), GPRInfo::tagTypeNumberRegister)); + isInteger.link(&m_jit); + } + noResult(m_compileIndex); + break; + } case ValueAdd: case ArithAdd: @@ -1984,42 +2149,7 @@ void SpeculativeJIT::compile(Node& node) case ArithDiv: { if (Node::shouldSpeculateInteger(at(node.child1()), at(node.child2())) && node.canSpeculateInteger()) { - SpeculateIntegerOperand op1(this, node.child1()); - SpeculateIntegerOperand op2(this, node.child2()); - GPRTemporary eax(this, X86Registers::eax); - GPRTemporary edx(this, X86Registers::edx); - GPRReg op1GPR = op1.gpr(); - GPRReg op2GPR = op2.gpr(); - - speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::Zero, op2GPR)); - - // If the user cares about negative zero, then speculate that we're not about - // to produce negative zero. - if (!nodeCanIgnoreNegativeZero(node.arithNodeFlags())) { - MacroAssembler::Jump numeratorNonZero = m_jit.branchTest32(MacroAssembler::NonZero, op1GPR); - speculationCheck(NegativeZero, JSValueRegs(), NoNode, m_jit.branch32(MacroAssembler::LessThan, op2GPR, TrustedImm32(0))); - numeratorNonZero.link(&m_jit); - } - - GPRReg temp2 = InvalidGPRReg; - if (op2GPR == X86Registers::eax || op2GPR == X86Registers::edx) { - temp2 = allocate(); - m_jit.move(op2GPR, temp2); - op2GPR = temp2; - } - - m_jit.move(op1GPR, eax.gpr()); - m_jit.assembler().cdq(); - m_jit.assembler().idivl_r(op2GPR); - - if (temp2 != InvalidGPRReg) - unlock(temp2); - - // Check that there was no remainder. If there had been, then we'd be obligated to - // produce a double result instead. - speculationCheck(Overflow, JSValueRegs(), NoNode, m_jit.branchTest32(JITCompiler::NonZero, edx.gpr())); - - integerResult(eax.gpr(), m_compileIndex); + compileIntegerArithDivForX86(node); break; } @@ -2184,7 +2314,7 @@ void SpeculativeJIT::compile(Node& node) case GetByVal: { if (!node.prediction() || !at(node.child1()).prediction() || !at(node.child2()).prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -2209,13 +2339,6 @@ void SpeculativeJIT::compile(Node& node) break; } - if (at(node.child1()).shouldSpeculateByteArray()) { - compileGetByValOnByteArray(node); - if (!m_compileOkay) - return; - break; - } - if (at(node.child1()).shouldSpeculateInt8Array()) { compileGetByValOnIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); if (!m_compileOkay) @@ -2309,7 +2432,7 @@ void SpeculativeJIT::compile(Node& node) case PutByVal: { if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -2330,11 +2453,6 @@ void SpeculativeJIT::compile(Node& node) SpeculateCellOperand base(this, node.child1()); SpeculateStrictInt32Operand property(this, node.child2()); - if (at(node.child1()).shouldSpeculateByteArray()) { - compilePutByValForByteArray(base.gpr(), property.gpr(), node); - break; - } - if (at(node.child1()).shouldSpeculateInt8Array()) { compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type) ? NoTypedArrayTypeSpecCheck : AllTypedArraySpecChecks, SignedTypedArray); if (!m_compileOkay) @@ -2459,7 +2577,7 @@ void SpeculativeJIT::compile(Node& node) case PutByValAlias: { if (!at(node.child1()).prediction() || !at(node.child2()).prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -2468,11 +2586,6 @@ void SpeculativeJIT::compile(Node& node) SpeculateCellOperand base(this, node.child1()); SpeculateStrictInt32Operand property(this, node.child2()); - if (at(node.child1()).shouldSpeculateByteArray()) { - compilePutByValForByteArray(base.gpr(), property.gpr(), node); - break; - } - if (at(node.child1()).shouldSpeculateInt8Array()) { compilePutByValForIntTypedArray(m_jit.globalData()->int8ArrayDescriptor(), base.gpr(), property.gpr(), node, sizeof(int8_t), NoTypedArraySpecCheck, SignedTypedArray); if (!m_compileOkay) @@ -2559,6 +2672,54 @@ void SpeculativeJIT::compile(Node& node) break; } + case RegExpExec: { + if (compileRegExpExec(node)) + return; + if (!node.adjustedRefCount()) { + SpeculateCellOperand base(this, node.child1()); + SpeculateCellOperand argument(this, node.child2()); + GPRReg baseGPR = base.gpr(); + GPRReg argumentGPR = argument.gpr(); + + flushRegisters(); + GPRResult result(this); + callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR); + + // Must use jsValueResult because otherwise we screw up register + // allocation, which thinks that this node has a result. + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + SpeculateCellOperand base(this, node.child1()); + SpeculateCellOperand argument(this, node.child2()); + GPRReg baseGPR = base.gpr(); + GPRReg argumentGPR = argument.gpr(); + + flushRegisters(); + GPRResult result(this); + callOperation(operationRegExpExec, result.gpr(), baseGPR, argumentGPR); + + jsValueResult(result.gpr(), m_compileIndex); + break; + } + + case RegExpTest: { + SpeculateCellOperand base(this, node.child1()); + SpeculateCellOperand argument(this, node.child2()); + GPRReg baseGPR = base.gpr(); + GPRReg argumentGPR = argument.gpr(); + + flushRegisters(); + GPRResult result(this); + callOperation(operationRegExpTest, result.gpr(), baseGPR, argumentGPR); + + // If we add a DataFormatBool, we should use it here. + m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); + jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); + break; + } + case ArrayPush: { SpeculateCellOperand base(this, node.child1()); JSValueOperand value(this, node.child2()); @@ -2741,8 +2902,6 @@ void SpeculativeJIT::compile(Node& node) // FIXME: Add string speculation here. - bool wasPrimitive = isKnownNumeric(node.child1().index()) || isKnownBoolean(node.child1().index()); - JSValueOperand op1(this, node.child1()); GPRTemporary result(this, op1); @@ -2751,7 +2910,7 @@ void SpeculativeJIT::compile(Node& node) op1.use(); - if (wasPrimitive) + if (!(m_state.forNode(node.child1()).m_type & ~(PredictNumber | PredictBoolean))) m_jit.move(op1GPR, resultGPR); else { MacroAssembler::JumpList alreadyPrimitive; @@ -3018,7 +3177,7 @@ void SpeculativeJIT::compile(Node& node) } case GetById: { if (!node.prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -3068,7 +3227,7 @@ void SpeculativeJIT::compile(Node& node) case GetByIdFlush: { if (!node.prediction()) { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } @@ -3147,22 +3306,6 @@ void SpeculativeJIT::compile(Node& node) break; } - case GetByteArrayLength: { - SpeculateCellOperand base(this, node.child1()); - GPRTemporary result(this); - - GPRReg baseGPR = base.gpr(); - GPRReg resultGPR = result.gpr(); - - if (!isByteArrayPrediction(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueRegs(baseGPR), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSByteArray::s_info))); - - m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSByteArray::offsetOfStorage()), resultGPR); - m_jit.load32(MacroAssembler::Address(resultGPR, ByteArray::offsetOfSize()), resultGPR); - - integerResult(resultGPR, m_compileIndex); - break; - } case GetInt8ArrayLength: { compileGetTypedArrayLength(m_jit.globalData()->int8ArrayDescriptor(), node, !isInt8ArrayPrediction(m_state.forNode(node.child1()).m_type)); break; @@ -3393,6 +3536,90 @@ void SpeculativeJIT::compile(Node& node) compileInstanceOf(node); break; } + + case IsUndefined: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this); + + JITCompiler::Jump isCell = m_jit.branchTestPtr(JITCompiler::Zero, value.gpr(), GPRInfo::tagMaskRegister); + + m_jit.comparePtr(JITCompiler::Equal, value.gpr(), TrustedImm32(ValueUndefined), result.gpr()); + JITCompiler::Jump done = m_jit.jump(); + + isCell.link(&m_jit); + m_jit.loadPtr(JITCompiler::Address(value.gpr(), JSCell::structureOffset()), result.gpr()); + m_jit.test8(JITCompiler::NonZero, JITCompiler::Address(result.gpr(), Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), result.gpr()); + + done.link(&m_jit); + m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); + jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); + break; + } + + case IsBoolean: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value); + + m_jit.move(value.gpr(), result.gpr()); + m_jit.xorPtr(JITCompiler::TrustedImm32(ValueFalse), result.gpr()); + m_jit.testPtr(JITCompiler::Zero, result.gpr(), JITCompiler::TrustedImm32(static_cast<int32_t>(~1)), result.gpr()); + m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); + jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); + break; + } + + case IsNumber: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value); + + m_jit.testPtr(JITCompiler::NonZero, value.gpr(), GPRInfo::tagTypeNumberRegister, result.gpr()); + m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); + jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); + break; + } + + case IsString: { + JSValueOperand value(this, node.child1()); + GPRTemporary result(this, value); + + JITCompiler::Jump isNotCell = m_jit.branchTestPtr(JITCompiler::NonZero, value.gpr(), GPRInfo::tagMaskRegister); + + m_jit.loadPtr(JITCompiler::Address(value.gpr(), JSCell::structureOffset()), result.gpr()); + m_jit.compare8(JITCompiler::Equal, JITCompiler::Address(result.gpr(), Structure::typeInfoTypeOffset()), TrustedImm32(StringType), result.gpr()); + m_jit.or32(TrustedImm32(ValueFalse), result.gpr()); + JITCompiler::Jump done = m_jit.jump(); + + isNotCell.link(&m_jit); + m_jit.move(TrustedImm32(ValueFalse), result.gpr()); + + done.link(&m_jit); + jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); + break; + } + + case IsObject: { + JSValueOperand value(this, node.child1()); + GPRReg valueGPR = value.gpr(); + GPRResult result(this); + GPRReg resultGPR = result.gpr(); + flushRegisters(); + callOperation(operationIsObject, resultGPR, valueGPR); + m_jit.or32(TrustedImm32(ValueFalse), resultGPR); + jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); + break; + } + + case IsFunction: { + JSValueOperand value(this, node.child1()); + GPRReg valueGPR = value.gpr(); + GPRResult result(this); + GPRReg resultGPR = result.gpr(); + flushRegisters(); + callOperation(operationIsFunction, resultGPR, valueGPR); + m_jit.or32(TrustedImm32(ValueFalse), resultGPR); + jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean); + break; + } case Flush: case Phi: @@ -3539,7 +3766,7 @@ void SpeculativeJIT::compile(Node& node) break; case ForceOSRExit: { - terminateSpeculativeExecution(Uncountable, JSValueRegs(), NoNode); + terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), NoNode); break; } diff --git a/Source/JavaScriptCore/dfg/DFGVariableAccessData.h b/Source/JavaScriptCore/dfg/DFGVariableAccessData.h index bd626f9fb..1d99ed516 100644 --- a/Source/JavaScriptCore/dfg/DFGVariableAccessData.h +++ b/Source/JavaScriptCore/dfg/DFGVariableAccessData.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2011, 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,11 +26,14 @@ #ifndef DFGVariableAccessData_h #define DFGVariableAccessData_h -#include "DFGOperands.h" +#include "DFGDoubleFormatState.h" +#include "DFGNodeFlags.h" +#include "Operands.h" #include "PredictedType.h" #include "VirtualRegister.h" #include <wtf/Platform.h> #include <wtf/UnionFind.h> +#include <wtf/Vector.h> namespace JSC { namespace DFG { @@ -41,7 +44,9 @@ public: VariableAccessData() : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min())) , m_prediction(PredictNone) - , m_shouldUseDoubleFormat(false) + , m_argumentAwarePrediction(PredictNone) + , m_flags(0) + , m_doubleFormatState(EmptyDoubleFormatState) { clearVotes(); } @@ -49,7 +54,9 @@ public: VariableAccessData(VirtualRegister local) : m_local(local) , m_prediction(PredictNone) - , m_shouldUseDoubleFormat(false) + , m_argumentAwarePrediction(PredictNone) + , m_flags(0) + , m_doubleFormatState(EmptyDoubleFormatState) { clearVotes(); } @@ -67,7 +74,11 @@ public: bool predict(PredictedType prediction) { - return mergePrediction(find()->m_prediction, prediction); + VariableAccessData* self = find(); + bool result = mergePrediction(self->m_prediction, prediction); + if (result) + mergePrediction(m_argumentAwarePrediction, m_prediction); + return result; } PredictedType nonUnifiedPrediction() @@ -80,6 +91,16 @@ public: return find()->m_prediction; } + PredictedType argumentAwarePrediction() + { + return find()->m_argumentAwarePrediction; + } + + bool mergeArgumentAwarePrediction(PredictedType prediction) + { + return mergePrediction(find()->m_argumentAwarePrediction, prediction); + } + void clearVotes() { ASSERT(find() == this); @@ -101,19 +122,51 @@ public: bool shouldUseDoubleFormatAccordingToVote() { + // We don't support this facility for arguments, yet. // FIXME: make this work for arguments. - return !operandIsArgument(operand()) && ((isNumberPrediction(prediction()) && doubleVoteRatio() >= Options::doubleVoteRatioForDoubleFormat) || isDoublePrediction(prediction())); + if (operandIsArgument(operand())) + return false; + + // If the variable is not a number prediction, then this doesn't + // make any sense. + if (!isNumberPrediction(prediction())) + return false; + + // If the variable is predicted to hold only doubles, then it's a + // no-brainer: it should be formatted as a double. + if (isDoublePrediction(prediction())) + return true; + + // If the variable is known to be used as an integer, then be safe - + // don't force it to be a double. + if (flags() & NodeUsedAsInt) + return false; + + // If the variable has been voted to become a double, then make it a + // double. + if (doubleVoteRatio() >= Options::doubleVoteRatioForDoubleFormat) + return true; + + return false; + } + + DoubleFormatState doubleFormatState() + { + return find()->m_doubleFormatState; } bool shouldUseDoubleFormat() { - ASSERT(find() == this); - return m_shouldUseDoubleFormat; + ASSERT(isRoot()); + return m_doubleFormatState == UsingDoubleFormat; } bool tallyVotesForShouldUseDoubleFormat() { - ASSERT(find() == this); + ASSERT(isRoot()); + + if (m_doubleFormatState == CantUseDoubleFormat) + return false; bool newValueOfShouldUseDoubleFormat = shouldUseDoubleFormatAccordingToVote(); if (!newValueOfShouldUseDoubleFormat) { @@ -122,11 +175,35 @@ public: return false; } - if (m_shouldUseDoubleFormat) + if (m_doubleFormatState == UsingDoubleFormat) return false; - m_shouldUseDoubleFormat = true; - mergePrediction(m_prediction, PredictDouble); + return DFG::mergeDoubleFormatState(m_doubleFormatState, UsingDoubleFormat); + } + + bool mergeDoubleFormatState(DoubleFormatState doubleFormatState) + { + return DFG::mergeDoubleFormatState(find()->m_doubleFormatState, doubleFormatState); + } + + bool makePredictionForDoubleFormat() + { + ASSERT(isRoot()); + + if (m_doubleFormatState != UsingDoubleFormat) + return false; + + return mergePrediction(m_prediction, PredictDouble); + } + + NodeFlags flags() const { return m_flags; } + + bool mergeFlags(NodeFlags newFlags) + { + newFlags |= m_flags; + if (newFlags == m_flags) + return false; + m_flags = newFlags; return true; } @@ -138,9 +215,11 @@ private: VirtualRegister m_local; PredictedType m_prediction; + PredictedType m_argumentAwarePrediction; + NodeFlags m_flags; float m_votes[2]; - bool m_shouldUseDoubleFormat; + DoubleFormatState m_doubleFormatState; }; } } // namespace JSC::DFG diff --git a/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp b/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp index 255003612..11ac69524 100644 --- a/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp +++ b/Source/JavaScriptCore/dfg/DFGVirtualRegisterAllocationPhase.cpp @@ -64,17 +64,17 @@ public: #endif Node& node = m_graph[nodeIndex]; - if (!node.shouldGenerate() || node.op == Phi || node.op == Flush) + if (!node.shouldGenerate() || node.op() == Phi || node.op() == Flush) continue; // GetLocal nodes are effectively phi nodes in the graph, referencing // results from prior blocks. - if (node.op != GetLocal) { + if (node.op() != GetLocal) { // First, call use on all of the current node's children, then // allocate a VirtualRegister for this node. We do so in this // order so that if a child is on its last use, and a // VirtualRegister is freed, then it may be reused for node. - if (node.flags & NodeHasVarArgs) { + if (node.flags() & NodeHasVarArgs) { for (unsigned childIdx = node.firstChild(); childIdx < node.firstChild() + node.numChildren(); childIdx++) scoreBoard.use(m_graph.m_varArgChildren[childIdx]); } else { @@ -109,6 +109,14 @@ public: // for the function (and checked for on entry). Since we perform a new and // different allocation of temporaries, more registers may now be required. unsigned calleeRegisters = scoreBoard.highWatermark() + m_graph.m_parameterSlots; + size_t inlineCallFrameCount = codeBlock()->inlineCallFrames().size(); + for (size_t i = 0; i < inlineCallFrameCount; i++) { + InlineCallFrame& inlineCallFrame = codeBlock()->inlineCallFrames()[i]; + CodeBlock* codeBlock = baselineCodeBlockForInlineCallFrame(&inlineCallFrame); + unsigned requiredCalleeRegisters = inlineCallFrame.stackOffset + codeBlock->m_numCalleeRegisters; + if (requiredCalleeRegisters > calleeRegisters) + calleeRegisters = requiredCalleeRegisters; + } if ((unsigned)codeBlock()->m_numCalleeRegisters < calleeRegisters) codeBlock()->m_numCalleeRegisters = calleeRegisters; #if DFG_ENABLE(DEBUG_VERBOSE) diff --git a/Source/JavaScriptCore/heap/BlockAllocator.cpp b/Source/JavaScriptCore/heap/BlockAllocator.cpp new file mode 100644 index 000000000..028c84c2d --- /dev/null +++ b/Source/JavaScriptCore/heap/BlockAllocator.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2012 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 "BlockAllocator.h" + +#include "MarkedBlock.h" +#include <wtf/CurrentTime.h> + +namespace JSC { + +BlockAllocator::BlockAllocator() + : m_numberOfFreeBlocks(0) + , m_blockFreeingThreadShouldQuit(false) + , m_blockFreeingThread(createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree")) +{ + ASSERT(m_blockFreeingThread); +} + +BlockAllocator::~BlockAllocator() +{ + releaseFreeBlocks(); + { + MutexLocker locker(m_freeBlockLock); + m_blockFreeingThreadShouldQuit = true; + m_freeBlockCondition.broadcast(); + } + waitForThreadCompletion(m_blockFreeingThread); +} + +void BlockAllocator::releaseFreeBlocks() +{ + while (true) { + MarkedBlock* block; + { + MutexLocker locker(m_freeBlockLock); + if (!m_numberOfFreeBlocks) + block = 0; + else { + // FIXME: How do we know this is a MarkedBlock? It could be a CopiedBlock. + block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead()); + ASSERT(block); + m_numberOfFreeBlocks--; + } + } + + if (!block) + break; + + MarkedBlock::destroy(block); + } +} + +void BlockAllocator::waitForRelativeTimeWhileHoldingLock(double relative) +{ + if (m_blockFreeingThreadShouldQuit) + return; + m_freeBlockCondition.timedWait(m_freeBlockLock, currentTime() + relative); +} + +void BlockAllocator::waitForRelativeTime(double relative) +{ + // If this returns early, that's fine, so long as it doesn't do it too + // frequently. It would only be a bug if this function failed to return + // when it was asked to do so. + + MutexLocker locker(m_freeBlockLock); + waitForRelativeTimeWhileHoldingLock(relative); +} + +void BlockAllocator::blockFreeingThreadStartFunc(void* blockAllocator) +{ + static_cast<BlockAllocator*>(blockAllocator)->blockFreeingThreadMain(); +} + +void BlockAllocator::blockFreeingThreadMain() +{ + while (!m_blockFreeingThreadShouldQuit) { + // Generally wait for one second before scavenging free blocks. This + // may return early, particularly when we're being asked to quit. + waitForRelativeTime(1.0); + if (m_blockFreeingThreadShouldQuit) + break; + + // Now process the list of free blocks. Keep freeing until half of the + // blocks that are currently on the list are gone. Assume that a size_t + // field can be accessed atomically. + size_t currentNumberOfFreeBlocks = m_numberOfFreeBlocks; + if (!currentNumberOfFreeBlocks) + continue; + + size_t desiredNumberOfFreeBlocks = currentNumberOfFreeBlocks / 2; + + while (!m_blockFreeingThreadShouldQuit) { + MarkedBlock* block; + { + MutexLocker locker(m_freeBlockLock); + if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks) + block = 0; + else { + // FIXME: How do we know this is a MarkedBlock? It could be a CopiedBlock. + block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead()); + ASSERT(block); + m_numberOfFreeBlocks--; + } + } + + if (!block) + break; + + MarkedBlock::destroy(block); + } + } +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/heap/BlockAllocator.h b/Source/JavaScriptCore/heap/BlockAllocator.h new file mode 100644 index 000000000..4b90d28b9 --- /dev/null +++ b/Source/JavaScriptCore/heap/BlockAllocator.h @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2012 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 BlockAllocator_h +#define BlockAllocator_h + +#include <wtf/DoublyLinkedList.h> +#include <wtf/Forward.h> +#include <wtf/Threading.h> + +namespace JSC { + +class HeapBlock; + +// Simple allocator to reduce VM cost by holding onto blocks of memory for +// short periods of time and then freeing them on a secondary thread. + +class BlockAllocator { +public: + BlockAllocator(); + ~BlockAllocator(); + + HeapBlock* allocate(); + void deallocate(HeapBlock*); + +private: + void waitForRelativeTimeWhileHoldingLock(double relative); + void waitForRelativeTime(double relative); + + void blockFreeingThreadMain(); + static void blockFreeingThreadStartFunc(void* heap); + + void releaseFreeBlocks(); + + DoublyLinkedList<HeapBlock> m_freeBlocks; + size_t m_numberOfFreeBlocks; + bool m_blockFreeingThreadShouldQuit; + Mutex m_freeBlockLock; + ThreadCondition m_freeBlockCondition; + ThreadIdentifier m_blockFreeingThread; +}; + +inline HeapBlock* BlockAllocator::allocate() +{ + MutexLocker locker(m_freeBlockLock); + if (!m_numberOfFreeBlocks) { + ASSERT(m_freeBlocks.isEmpty()); + return 0; + } + + ASSERT(!m_freeBlocks.isEmpty()); + m_numberOfFreeBlocks--; + return m_freeBlocks.removeHead(); +} + +inline void BlockAllocator::deallocate(HeapBlock* block) +{ + MutexLocker locker(m_freeBlockLock); + m_freeBlocks.push(block); + m_numberOfFreeBlocks++; +} + +} // namespace JSC + +#endif // BlockAllocator_h diff --git a/Source/JavaScriptCore/heap/CopiedAllocator.h b/Source/JavaScriptCore/heap/CopiedAllocator.h index dc3c5dfed..7455ec816 100644 --- a/Source/JavaScriptCore/heap/CopiedAllocator.h +++ b/Source/JavaScriptCore/heap/CopiedAllocator.h @@ -39,8 +39,7 @@ public: bool wasLastAllocation(void*, size_t); void startedCopying(); void resetCurrentBlock(CopiedBlock*); - void resetLastAllocation(void*); - size_t currentUtilization(); + size_t currentCapacity(); private: CopiedBlock* currentBlock() { return m_currentBlock; } @@ -92,14 +91,9 @@ inline void CopiedAllocator::resetCurrentBlock(CopiedBlock* newBlock) m_currentOffset = static_cast<char*>(newBlock->m_offset); } -inline size_t CopiedAllocator::currentUtilization() +inline size_t CopiedAllocator::currentCapacity() { - return static_cast<size_t>(m_currentOffset - m_currentBlock->payload()); -} - -inline void CopiedAllocator::resetLastAllocation(void* ptr) -{ - m_currentOffset = static_cast<char*>(ptr); + return m_currentBlock->capacity(); } } // namespace JSC diff --git a/Source/JavaScriptCore/heap/CopiedBlock.h b/Source/JavaScriptCore/heap/CopiedBlock.h index 387b2ddab..431b86c38 100644 --- a/Source/JavaScriptCore/heap/CopiedBlock.h +++ b/Source/JavaScriptCore/heap/CopiedBlock.h @@ -55,16 +55,30 @@ public: #endif } - char* payload() - { - return reinterpret_cast<char*>(this) + ((sizeof(CopiedBlock) + 7) & ~7); - } + char* payload(); + size_t size(); + size_t capacity(); private: void* m_offset; uintptr_t m_isPinned; }; +inline char* CopiedBlock::payload() +{ + return reinterpret_cast<char*>(this) + ((sizeof(CopiedBlock) + 7) & ~7); +} + +inline size_t CopiedBlock::size() +{ + return static_cast<size_t>(static_cast<char*>(m_offset) - payload()); +} + +inline size_t CopiedBlock::capacity() +{ + return m_allocation.size(); +} + } // namespace JSC #endif diff --git a/Source/JavaScriptCore/heap/CopiedSpace.cpp b/Source/JavaScriptCore/heap/CopiedSpace.cpp index c8470120f..063ea65a2 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.cpp +++ b/Source/JavaScriptCore/heap/CopiedSpace.cpp @@ -27,6 +27,7 @@ #include "CopiedSpace.h" #include "CopiedSpaceInlineMethods.h" +#include "GCActivityCallback.h" namespace JSC { @@ -34,8 +35,6 @@ CopiedSpace::CopiedSpace(Heap* heap) : m_heap(heap) , m_toSpace(0) , m_fromSpace(0) - , m_totalMemoryAllocated(0) - , m_totalMemoryUtilized(0) , m_inCopyingPhase(false) , m_numberOfLoanedBlocks(0) { @@ -46,8 +45,6 @@ void CopiedSpace::init() m_toSpace = &m_blocks1; m_fromSpace = &m_blocks2; - m_totalMemoryAllocated += HeapBlock::s_blockSize * s_initialBlockNum; - if (!addNewBlock()) CRASH(); } @@ -57,7 +54,8 @@ CheckedBoolean CopiedSpace::tryAllocateSlowCase(size_t bytes, void** outPtr) if (isOversize(bytes)) return tryAllocateOversize(bytes, outPtr); - m_totalMemoryUtilized += m_allocator.currentUtilization(); + m_heap->didAllocate(m_allocator.currentCapacity()); + if (!addNewBlock()) { *outPtr = 0; return false; @@ -71,22 +69,22 @@ CheckedBoolean CopiedSpace::tryAllocateOversize(size_t bytes, void** outPtr) { ASSERT(isOversize(bytes)); - size_t blockSize = WTF::roundUpToMultipleOf<s_pageSize>(sizeof(CopiedBlock) + bytes); - PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, s_pageSize, OSAllocator::JSGCHeapPages); + size_t blockSize = WTF::roundUpToMultipleOf(WTF::pageSize(), sizeof(CopiedBlock) + bytes); + + PageAllocationAligned allocation = PageAllocationAligned::allocate(blockSize, WTF::pageSize(), OSAllocator::JSGCHeapPages); if (!static_cast<bool>(allocation)) { *outPtr = 0; return false; } + CopiedBlock* block = new (NotNull, allocation.base()) CopiedBlock(allocation); m_oversizeBlocks.push(block); - ASSERT(is8ByteAligned(block->m_offset)); - m_oversizeFilter.add(reinterpret_cast<Bits>(block)); - m_totalMemoryAllocated += blockSize; - m_totalMemoryUtilized += bytes; + *outPtr = allocateFromBlock(block, bytes); + + m_heap->didAllocate(blockSize); - *outPtr = block->m_offset; return true; } @@ -102,13 +100,12 @@ CheckedBoolean CopiedSpace::tryReallocate(void** ptr, size_t oldSize, size_t new return tryReallocateOversize(ptr, oldSize, newSize); if (m_allocator.wasLastAllocation(oldPtr, oldSize)) { - m_allocator.resetLastAllocation(oldPtr); - if (m_allocator.fitsInCurrentBlock(newSize)) { - m_totalMemoryUtilized += newSize - oldSize; - return m_allocator.allocate(newSize); + size_t delta = newSize - oldSize; + if (m_allocator.fitsInCurrentBlock(delta)) { + (void)m_allocator.allocate(delta); + return true; } } - m_totalMemoryUtilized -= oldSize; void* result = 0; if (!tryAllocate(newSize, &result)) { @@ -132,17 +129,15 @@ CheckedBoolean CopiedSpace::tryReallocateOversize(void** ptr, size_t oldSize, si *ptr = 0; return false; } + memcpy(newPtr, oldPtr, oldSize); if (isOversize(oldSize)) { CopiedBlock* oldBlock = oversizeBlockFor(oldPtr); m_oversizeBlocks.remove(oldBlock); oldBlock->m_allocation.deallocate(); - m_totalMemoryAllocated -= oldSize + sizeof(CopiedBlock); } - m_totalMemoryUtilized -= oldSize; - *ptr = newPtr; return true; } @@ -166,11 +161,6 @@ void CopiedSpace::doneFillingBlock(CopiedBlock* block) } { - MutexLocker locker(m_memoryStatsLock); - m_totalMemoryUtilized += static_cast<size_t>(static_cast<char*>(block->m_offset) - block->payload()); - } - - { MutexLocker locker(m_loanedBlocksLock); ASSERT(m_numberOfLoanedBlocks > 0); m_numberOfLoanedBlocks--; @@ -198,11 +188,7 @@ void CopiedSpace::doneCopying() } m_toSpaceSet.remove(block); - { - MutexLocker locker(m_heap->m_freeBlockLock); - m_heap->m_freeBlocks.push(block); - m_heap->m_numberOfFreeBlocks++; - } + m_heap->blockAllocator().deallocate(block); } CopiedBlock* curr = static_cast<CopiedBlock*>(m_oversizeBlocks.head()); @@ -210,8 +196,6 @@ void CopiedSpace::doneCopying() CopiedBlock* next = static_cast<CopiedBlock*>(curr->next()); if (!curr->m_isPinned) { m_oversizeBlocks.remove(curr); - m_totalMemoryAllocated -= curr->m_allocation.size(); - m_totalMemoryUtilized -= curr->m_allocation.size() - sizeof(CopiedBlock); curr->m_allocation.deallocate(); } else curr->m_isPinned = false; @@ -227,16 +211,8 @@ void CopiedSpace::doneCopying() CheckedBoolean CopiedSpace::getFreshBlock(AllocationEffort allocationEffort, CopiedBlock** outBlock) { - HeapBlock* heapBlock = 0; CopiedBlock* block = 0; - { - MutexLocker locker(m_heap->m_freeBlockLock); - if (!m_heap->m_freeBlocks.isEmpty()) { - heapBlock = m_heap->m_freeBlocks.removeHead(); - m_heap->m_numberOfFreeBlocks--; - } - } - if (heapBlock) + if (HeapBlock* heapBlock = m_heap->blockAllocator().allocate()) block = new (NotNull, heapBlock) CopiedBlock(heapBlock->m_allocation); else if (allocationEffort == AllocationMustSucceed) { if (!allocateNewBlock(&block)) { @@ -246,7 +222,7 @@ CheckedBoolean CopiedSpace::getFreshBlock(AllocationEffort allocationEffort, Cop } } else { ASSERT(allocationEffort == AllocationCanFail); - if (m_heap->waterMark() >= m_heap->highWaterMark() && m_heap->m_isSafeToCollect) + if (m_heap->shouldCollect()) m_heap->collect(Heap::DoNotSweep); if (!getFreshBlock(AllocationMustSucceed, &block)) { @@ -261,4 +237,73 @@ CheckedBoolean CopiedSpace::getFreshBlock(AllocationEffort allocationEffort, Cop return true; } +void CopiedSpace::freeAllBlocks() +{ + while (!m_toSpace->isEmpty()) + m_heap->blockAllocator().deallocate(m_toSpace->removeHead()); + + while (!m_fromSpace->isEmpty()) + m_heap->blockAllocator().deallocate(m_fromSpace->removeHead()); + + while (!m_oversizeBlocks.isEmpty()) + m_oversizeBlocks.removeHead()->m_allocation.deallocate(); +} + +size_t CopiedSpace::size() +{ + size_t calculatedSize = 0; + + for (CopiedBlock* block = static_cast<CopiedBlock*>(m_toSpace->head()); block; block = static_cast<CopiedBlock*>(block->next())) + calculatedSize += block->size(); + + for (CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->head()); block; block = static_cast<CopiedBlock*>(block->next())) + calculatedSize += block->size(); + + for (CopiedBlock* block = static_cast<CopiedBlock*>(m_oversizeBlocks.head()); block; block = static_cast<CopiedBlock*>(block->next())) + calculatedSize += block->size(); + + return calculatedSize; +} + +size_t CopiedSpace::capacity() +{ + size_t calculatedCapacity = 0; + + for (CopiedBlock* block = static_cast<CopiedBlock*>(m_toSpace->head()); block; block = static_cast<CopiedBlock*>(block->next())) + calculatedCapacity += block->capacity(); + + for (CopiedBlock* block = static_cast<CopiedBlock*>(m_fromSpace->head()); block; block = static_cast<CopiedBlock*>(block->next())) + calculatedCapacity += block->capacity(); + + for (CopiedBlock* block = static_cast<CopiedBlock*>(m_oversizeBlocks.head()); block; block = static_cast<CopiedBlock*>(block->next())) + calculatedCapacity += block->capacity(); + + return calculatedCapacity; +} + +static bool isBlockListPagedOut(double deadline, DoublyLinkedList<HeapBlock>* list) +{ + unsigned itersSinceLastTimeCheck = 0; + HeapBlock* current = list->head(); + while (current) { + current = current->next(); + ++itersSinceLastTimeCheck; + if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) { + double currentTime = WTF::monotonicallyIncreasingTime(); + if (currentTime > deadline) + return true; + itersSinceLastTimeCheck = 0; + } + } + + return false; +} + +bool CopiedSpace::isPagedOut(double deadline) +{ + return isBlockListPagedOut(deadline, m_toSpace) + || isBlockListPagedOut(deadline, m_fromSpace) + || isBlockListPagedOut(deadline, &m_oversizeBlocks); +} + } // namespace JSC diff --git a/Source/JavaScriptCore/heap/CopiedSpace.h b/Source/JavaScriptCore/heap/CopiedSpace.h index e8fa80055..d3cc040a5 100644 --- a/Source/JavaScriptCore/heap/CopiedSpace.h +++ b/Source/JavaScriptCore/heap/CopiedSpace.h @@ -35,6 +35,7 @@ #include <wtf/HashSet.h> #include <wtf/OSAllocator.h> #include <wtf/PageAllocationAligned.h> +#include <wtf/PageBlock.h> #include <wtf/StdLibExtras.h> #include <wtf/ThreadingPrimitives.h> @@ -65,8 +66,11 @@ public: bool contains(void*, CopiedBlock*&); - size_t totalMemoryAllocated() { return m_totalMemoryAllocated; } - size_t totalMemoryUtilized() { return m_totalMemoryUtilized; } + size_t size(); + size_t capacity(); + + void freeAllBlocks(); + bool isPagedOut(double deadline); static CopiedBlock* blockFor(void*); @@ -97,7 +101,6 @@ private: HashSet<CopiedBlock*> m_toSpaceSet; Mutex m_toSpaceLock; - Mutex m_memoryStatsLock; DoublyLinkedList<HeapBlock>* m_toSpace; DoublyLinkedList<HeapBlock>* m_fromSpace; @@ -106,9 +109,6 @@ private: DoublyLinkedList<HeapBlock> m_blocks2; DoublyLinkedList<HeapBlock> m_oversizeBlocks; - size_t m_totalMemoryAllocated; - size_t m_totalMemoryUtilized; - bool m_inCopyingPhase; Mutex m_loanedBlocksLock; @@ -116,8 +116,6 @@ private: size_t m_numberOfLoanedBlocks; static const size_t s_maxAllocationSize = 32 * KB; - static const size_t s_pageSize = 4 * KB; - static const size_t s_pageMask = ~(s_pageSize - 1); static const size_t s_initialBlockNum = 16; static const size_t s_blockMask = ~(HeapBlock::s_blockSize - 1); }; diff --git a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h index 0b1b38d32..a8e45658b 100644 --- a/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h +++ b/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h @@ -56,8 +56,6 @@ inline void CopiedSpace::startedCopying() m_toSpaceFilter.reset(); m_allocator.startedCopying(); - m_totalMemoryUtilized = 0; - ASSERT(!m_inCopyingPhase); ASSERT(!m_numberOfLoanedBlocks); m_inCopyingPhase = true; @@ -65,11 +63,7 @@ inline void CopiedSpace::startedCopying() inline void CopiedSpace::recycleBlock(CopiedBlock* block) { - { - MutexLocker locker(m_heap->m_freeBlockLock); - m_heap->m_freeBlocks.push(block); - m_heap->m_numberOfFreeBlocks++; - } + m_heap->blockAllocator().deallocate(block); { MutexLocker locker(m_loanedBlocksLock); @@ -118,18 +112,13 @@ inline CheckedBoolean CopiedSpace::allocateNewBlock(CopiedBlock** outBlock) return false; } - { - MutexLocker locker(m_memoryStatsLock); - m_totalMemoryAllocated += HeapBlock::s_blockSize; - } - *outBlock = new (NotNull, allocation.base()) CopiedBlock(allocation); return true; } inline bool CopiedSpace::fitsInBlock(CopiedBlock* block, size_t bytes) { - return static_cast<char*>(block->m_offset) + bytes < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize && static_cast<char*>(block->m_offset) + bytes > block->m_offset; + return static_cast<char*>(block->m_offset) + bytes < reinterpret_cast<char*>(block) + block->capacity() && static_cast<char*>(block->m_offset) + bytes > block->m_offset; } inline CheckedBoolean CopiedSpace::tryAllocate(size_t bytes, void** outPtr) @@ -146,14 +135,13 @@ inline CheckedBoolean CopiedSpace::tryAllocate(size_t bytes, void** outPtr) inline void* CopiedSpace::allocateFromBlock(CopiedBlock* block, size_t bytes) { - ASSERT(!isOversize(bytes)); ASSERT(fitsInBlock(block, bytes)); ASSERT(is8ByteAligned(block->m_offset)); void* ptr = block->m_offset; - ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize); + ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + block->capacity()); block->m_offset = static_cast<void*>((static_cast<char*>(ptr) + bytes)); - ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + HeapBlock::s_blockSize); + ASSERT(block->m_offset >= block->payload() && block->m_offset < reinterpret_cast<char*>(block) + block->capacity()); ASSERT(is8ByteAligned(ptr)); return ptr; @@ -171,7 +159,7 @@ inline bool CopiedSpace::isPinned(void* ptr) inline CopiedBlock* CopiedSpace::oversizeBlockFor(void* ptr) { - return reinterpret_cast<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & s_pageMask); + return reinterpret_cast<CopiedBlock*>(reinterpret_cast<size_t>(ptr) & WTF::pageMask()); } inline CopiedBlock* CopiedSpace::blockFor(void* ptr) diff --git a/Source/JavaScriptCore/heap/Handle.h b/Source/JavaScriptCore/heap/Handle.h index 6f467743c..8bf2bd896 100644 --- a/Source/JavaScriptCore/heap/Handle.h +++ b/Source/JavaScriptCore/heap/Handle.h @@ -48,7 +48,7 @@ template<typename KeyType, typename MappedType, typename FinalizerCallback, type class HandleBase { template <typename T> friend class Weak; - friend class HandleHeap; + friend class HandleSet; friend struct JSCallbackObjectData; template <typename KeyType, typename MappedType, typename FinalizerCallback, typename HashArg, typename KeyTraitsArg> friend class WeakGCMap; @@ -59,6 +59,8 @@ public: typedef JSValue (HandleBase::*UnspecifiedBoolType); operator UnspecifiedBoolType*() const { return (m_slot && *m_slot) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } + HandleSlot slot() const { return m_slot; } + protected: HandleBase(HandleSlot slot) : m_slot(slot) @@ -67,7 +69,6 @@ protected: void swap(HandleBase& other) { std::swap(m_slot, other.m_slot); } - HandleSlot slot() const { return m_slot; } void setSlot(HandleSlot slot) { m_slot = slot; @@ -132,7 +133,8 @@ protected: } private: - friend class HandleHeap; + friend class HandleSet; + friend class WeakBlock; static Handle<T> wrapSlot(HandleSlot slot) { diff --git a/Source/JavaScriptCore/heap/HandleHeap.h b/Source/JavaScriptCore/heap/HandleHeap.h deleted file mode 100644 index c9ee11b2f..000000000 --- a/Source/JavaScriptCore/heap/HandleHeap.h +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (C) 2011 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 HandleHeap_h -#define HandleHeap_h - -#include <wtf/BlockStack.h> -#include "Handle.h" -#include <wtf/HashCountedSet.h> -#include <wtf/SentinelLinkedList.h> -#include <wtf/SinglyLinkedList.h> - -namespace JSC { - -class HandleHeap; -class HeapRootVisitor; -class JSGlobalData; -class JSValue; -class SlotVisitor; - -class JS_EXPORT_PRIVATE WeakHandleOwner { -public: - virtual ~WeakHandleOwner(); - virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, SlotVisitor&); - virtual void finalize(Handle<Unknown>, void* context); -}; - -class HandleHeap { -public: - static HandleHeap* heapFor(HandleSlot); - - HandleHeap(JSGlobalData*); - - JSGlobalData* globalData(); - - HandleSlot allocate(); - void deallocate(HandleSlot); - - void makeWeak(HandleSlot, WeakHandleOwner* = 0, void* context = 0); - HandleSlot copyWeak(HandleSlot); - - void visitStrongHandles(HeapRootVisitor&); - void visitWeakHandles(HeapRootVisitor&); - void finalizeWeakHandles(); - - JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&); - -#if !ASSERT_DISABLED - bool hasWeakOwner(HandleSlot, WeakHandleOwner*); - bool hasFinalizer(HandleSlot); -#endif - - unsigned protectedGlobalObjectCount(); - - template<typename Functor> void forEachStrongHandle(Functor&, const HashCountedSet<JSCell*>& skipSet); - -private: - class Node { - public: - Node(WTF::SentinelTag); - Node(HandleHeap*); - - HandleSlot slot(); - HandleHeap* handleHeap(); - - void makeWeak(WeakHandleOwner*, void* context); - bool isWeak(); - - WeakHandleOwner* weakOwner(); - void* weakOwnerContext(); - - void setPrev(Node*); - Node* prev(); - - void setNext(Node*); - Node* next(); - - private: - WeakHandleOwner* emptyWeakOwner(); - - JSValue m_value; - HandleHeap* m_handleHeap; - WeakHandleOwner* m_weakOwner; - void* m_weakOwnerContext; - Node* m_prev; - Node* m_next; - }; - - static HandleSlot toHandle(Node*); - static Node* toNode(HandleSlot); - - JS_EXPORT_PRIVATE void grow(); - -#if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED - bool isValidWeakNode(Node*); - bool isLiveNode(Node*); -#endif - - JSGlobalData* m_globalData; - BlockStack<Node> m_blockStack; - - SentinelLinkedList<Node> m_strongList; - SentinelLinkedList<Node> m_weakList; - SentinelLinkedList<Node> m_immediateList; - SinglyLinkedList<Node> m_freeList; - Node* m_nextToFinalize; -}; - -inline HandleHeap* HandleHeap::heapFor(HandleSlot handle) -{ - return toNode(handle)->handleHeap(); -} - -inline JSGlobalData* HandleHeap::globalData() -{ - return m_globalData; -} - -inline HandleSlot HandleHeap::toHandle(Node* node) -{ - return reinterpret_cast<HandleSlot>(node); -} - -inline HandleHeap::Node* HandleHeap::toNode(HandleSlot handle) -{ - return reinterpret_cast<Node*>(handle); -} - -inline HandleSlot HandleHeap::allocate() -{ - // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants. - // File a bug with stack trace if you hit this. - if (m_nextToFinalize) - CRASH(); - if (m_freeList.isEmpty()) - grow(); - - Node* node = m_freeList.pop(); - new (NotNull, node) Node(this); - m_immediateList.push(node); - return toHandle(node); -} - -inline void HandleHeap::deallocate(HandleSlot handle) -{ - Node* node = toNode(handle); - if (node == m_nextToFinalize) { - ASSERT(m_nextToFinalize->next()); - m_nextToFinalize = m_nextToFinalize->next(); - } - - SentinelLinkedList<Node>::remove(node); - m_freeList.push(node); -} - -inline HandleSlot HandleHeap::copyWeak(HandleSlot other) -{ - Node* node = toNode(allocate()); - node->makeWeak(toNode(other)->weakOwner(), toNode(other)->weakOwnerContext()); - writeBarrier(node->slot(), *other); - *node->slot() = *other; - return toHandle(node); -} - -inline void HandleHeap::makeWeak(HandleSlot handle, WeakHandleOwner* weakOwner, void* context) -{ - // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants. - // File a bug with stack trace if you hit this. - if (m_nextToFinalize) - CRASH(); - Node* node = toNode(handle); - node->makeWeak(weakOwner, context); - - SentinelLinkedList<Node>::remove(node); - if (!*handle || !handle->isCell()) { - m_immediateList.push(node); - return; - } - - m_weakList.push(node); -} - -#if !ASSERT_DISABLED -inline bool HandleHeap::hasWeakOwner(HandleSlot handle, WeakHandleOwner* weakOwner) -{ - return toNode(handle)->weakOwner() == weakOwner; -} - -inline bool HandleHeap::hasFinalizer(HandleSlot handle) -{ - return toNode(handle)->weakOwner(); -} -#endif - -inline HandleHeap::Node::Node(HandleHeap* handleHeap) - : m_handleHeap(handleHeap) - , m_weakOwner(0) - , m_weakOwnerContext(0) - , m_prev(0) - , m_next(0) -{ -} - -inline HandleHeap::Node::Node(WTF::SentinelTag) - : m_handleHeap(0) - , m_weakOwner(0) - , m_weakOwnerContext(0) - , m_prev(0) - , m_next(0) -{ -} - -inline HandleSlot HandleHeap::Node::slot() -{ - return &m_value; -} - -inline HandleHeap* HandleHeap::Node::handleHeap() -{ - return m_handleHeap; -} - -inline void HandleHeap::Node::makeWeak(WeakHandleOwner* weakOwner, void* context) -{ - m_weakOwner = weakOwner ? weakOwner : emptyWeakOwner(); - m_weakOwnerContext = context; -} - -inline bool HandleHeap::Node::isWeak() -{ - return m_weakOwner; // True for emptyWeakOwner(). -} - -inline WeakHandleOwner* HandleHeap::Node::weakOwner() -{ - return m_weakOwner == emptyWeakOwner() ? 0 : m_weakOwner; // 0 for emptyWeakOwner(). -} - -inline void* HandleHeap::Node::weakOwnerContext() -{ - ASSERT(weakOwner()); - return m_weakOwnerContext; -} - -inline void HandleHeap::Node::setPrev(Node* prev) -{ - m_prev = prev; -} - -inline HandleHeap::Node* HandleHeap::Node::prev() -{ - return m_prev; -} - -inline void HandleHeap::Node::setNext(Node* next) -{ - m_next = next; -} - -inline HandleHeap::Node* HandleHeap::Node::next() -{ - return m_next; -} - -// Sentinel to indicate that a node is weak, but its owner has no meaningful -// callbacks. This allows us to optimize by skipping such nodes. -inline WeakHandleOwner* HandleHeap::Node::emptyWeakOwner() -{ - return reinterpret_cast<WeakHandleOwner*>(-1); -} - -template<typename Functor> void HandleHeap::forEachStrongHandle(Functor& functor, const HashCountedSet<JSCell*>& skipSet) -{ - Node* end = m_strongList.end(); - for (Node* node = m_strongList.begin(); node != end; node = node->next()) { - JSValue value = *node->slot(); - if (!value || !value.isCell()) - continue; - if (skipSet.contains(value.asCell())) - continue; - functor(value.asCell()); - } -} - -} - -#endif diff --git a/Source/JavaScriptCore/heap/HandleHeap.cpp b/Source/JavaScriptCore/heap/HandleSet.cpp index 2402f7efb..a6ccf29eb 100644 --- a/Source/JavaScriptCore/heap/HandleHeap.cpp +++ b/Source/JavaScriptCore/heap/HandleSet.cpp @@ -24,34 +24,21 @@ */ #include "config.h" -#include "HandleHeap.h" +#include "HandleSet.h" #include "HeapRootVisitor.h" #include "JSObject.h" namespace JSC { -WeakHandleOwner::~WeakHandleOwner() -{ -} - -bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, SlotVisitor&) -{ - return false; -} - -void WeakHandleOwner::finalize(Handle<Unknown>, void*) -{ -} - -HandleHeap::HandleHeap(JSGlobalData* globalData) +HandleSet::HandleSet(JSGlobalData* globalData) : m_globalData(globalData) , m_nextToFinalize(0) { grow(); } -void HandleHeap::grow() +void HandleSet::grow() { Node* block = m_blockStack.grow(); for (int i = m_blockStack.blockLength - 1; i >= 0; --i) { @@ -61,7 +48,7 @@ void HandleHeap::grow() } } -void HandleHeap::visitStrongHandles(HeapRootVisitor& heapRootVisitor) +void HandleSet::visitStrongHandles(HeapRootVisitor& heapRootVisitor) { Node* end = m_strongList.end(); for (Node* node = m_strongList.begin(); node != end; node = node->next()) { @@ -73,63 +60,7 @@ void HandleHeap::visitStrongHandles(HeapRootVisitor& heapRootVisitor) } } -void HandleHeap::visitWeakHandles(HeapRootVisitor& heapRootVisitor) -{ - SlotVisitor& visitor = heapRootVisitor.visitor(); - - Node* end = m_weakList.end(); - for (Node* node = m_weakList.begin(); node != end; node = node->next()) { -#if ENABLE(GC_VALIDATION) - if (!isValidWeakNode(node)) - CRASH(); -#endif - JSCell* cell = node->slot()->asCell(); - if (Heap::isMarked(cell)) - continue; - - WeakHandleOwner* weakOwner = node->weakOwner(); - if (!weakOwner) - continue; - - if (!weakOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext(), visitor)) - continue; - - heapRootVisitor.visit(node->slot()); - } -} - -void HandleHeap::finalizeWeakHandles() -{ - Node* end = m_weakList.end(); - for (Node* node = m_weakList.begin(); node != end; node = m_nextToFinalize) { - m_nextToFinalize = node->next(); -#if ENABLE(GC_VALIDATION) - if (!isValidWeakNode(node)) - CRASH(); -#endif - - JSCell* cell = node->slot()->asCell(); - if (Heap::isMarked(cell)) - continue; - - if (WeakHandleOwner* weakOwner = node->weakOwner()) { - weakOwner->finalize(Handle<Unknown>::wrapSlot(node->slot()), node->weakOwnerContext()); - if (m_nextToFinalize != node->next()) // Owner deallocated node. - continue; - } -#if ENABLE(GC_VALIDATION) - if (!isLiveNode(node)) - CRASH(); -#endif - *node->slot() = JSValue(); - SentinelLinkedList<Node>::remove(node); - m_immediateList.push(node); - } - - m_nextToFinalize = 0; -} - -void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value) +void HandleSet::writeBarrier(HandleSlot slot, const JSValue& value) { // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants. // File a bug with stack trace if you hit this. @@ -150,15 +81,6 @@ void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value) return; } - if (node->isWeak()) { - m_weakList.push(node); -#if ENABLE(GC_VALIDATION) - if (!isLiveNode(node)) - CRASH(); -#endif - return; - } - m_strongList.push(node); #if ENABLE(GC_VALIDATION) if (!isLiveNode(node)) @@ -166,7 +88,7 @@ void HandleHeap::writeBarrier(HandleSlot slot, const JSValue& value) #endif } -unsigned HandleHeap::protectedGlobalObjectCount() +unsigned HandleSet::protectedGlobalObjectCount() { unsigned count = 0; Node* end = m_strongList.end(); @@ -179,7 +101,7 @@ unsigned HandleHeap::protectedGlobalObjectCount() } #if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED -bool HandleHeap::isLiveNode(Node* node) +bool HandleSet::isLiveNode(Node* node) { if (node->prev()->next() != node) return false; @@ -188,24 +110,6 @@ bool HandleHeap::isLiveNode(Node* node) return true; } - -bool HandleHeap::isValidWeakNode(Node* node) -{ - if (!isLiveNode(node)) - return false; - if (!node->isWeak()) - return false; - - JSValue value = *node->slot(); - if (!value || !value.isCell()) - return false; - - JSCell* cell = value.asCell(); - if (!cell || !cell->structure()) - return false; - - return true; -} #endif } // namespace JSC diff --git a/Source/JavaScriptCore/heap/HandleSet.h b/Source/JavaScriptCore/heap/HandleSet.h new file mode 100644 index 000000000..c22ffa418 --- /dev/null +++ b/Source/JavaScriptCore/heap/HandleSet.h @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2011 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 HandleSet_h +#define HandleSet_h + +#include <wtf/BlockStack.h> +#include "Handle.h" +#include <wtf/HashCountedSet.h> +#include <wtf/SentinelLinkedList.h> +#include <wtf/SinglyLinkedList.h> + +namespace JSC { + +class HandleSet; +class HeapRootVisitor; +class JSGlobalData; +class JSValue; +class SlotVisitor; + +class HandleSet { +public: + static HandleSet* heapFor(HandleSlot); + + HandleSet(JSGlobalData*); + + JSGlobalData* globalData(); + + HandleSlot allocate(); + void deallocate(HandleSlot); + + void visitStrongHandles(HeapRootVisitor&); + + JS_EXPORT_PRIVATE void writeBarrier(HandleSlot, const JSValue&); + + unsigned protectedGlobalObjectCount(); + + template<typename Functor> void forEachStrongHandle(Functor&, const HashCountedSet<JSCell*>& skipSet); + +private: + class Node { + public: + Node(WTF::SentinelTag); + Node(HandleSet*); + + HandleSlot slot(); + HandleSet* handleSet(); + + void setPrev(Node*); + Node* prev(); + + void setNext(Node*); + Node* next(); + + private: + JSValue m_value; + HandleSet* m_handleSet; + Node* m_prev; + Node* m_next; + }; + + static HandleSlot toHandle(Node*); + static Node* toNode(HandleSlot); + + JS_EXPORT_PRIVATE void grow(); + +#if ENABLE(GC_VALIDATION) || !ASSERT_DISABLED + bool isLiveNode(Node*); +#endif + + JSGlobalData* m_globalData; + BlockStack<Node> m_blockStack; + + SentinelLinkedList<Node> m_strongList; + SentinelLinkedList<Node> m_immediateList; + SinglyLinkedList<Node> m_freeList; + Node* m_nextToFinalize; +}; + +inline HandleSet* HandleSet::heapFor(HandleSlot handle) +{ + return toNode(handle)->handleSet(); +} + +inline JSGlobalData* HandleSet::globalData() +{ + return m_globalData; +} + +inline HandleSlot HandleSet::toHandle(Node* node) +{ + return reinterpret_cast<HandleSlot>(node); +} + +inline HandleSet::Node* HandleSet::toNode(HandleSlot handle) +{ + return reinterpret_cast<Node*>(handle); +} + +inline HandleSlot HandleSet::allocate() +{ + // Forbid assignment to handles during the finalization phase, since it would violate many GC invariants. + // File a bug with stack trace if you hit this. + if (m_nextToFinalize) + CRASH(); + if (m_freeList.isEmpty()) + grow(); + + Node* node = m_freeList.pop(); + new (NotNull, node) Node(this); + m_immediateList.push(node); + return toHandle(node); +} + +inline void HandleSet::deallocate(HandleSlot handle) +{ + Node* node = toNode(handle); + if (node == m_nextToFinalize) { + ASSERT(m_nextToFinalize->next()); + m_nextToFinalize = m_nextToFinalize->next(); + } + + SentinelLinkedList<Node>::remove(node); + m_freeList.push(node); +} + +inline HandleSet::Node::Node(HandleSet* handleSet) + : m_handleSet(handleSet) + , m_prev(0) + , m_next(0) +{ +} + +inline HandleSet::Node::Node(WTF::SentinelTag) + : m_handleSet(0) + , m_prev(0) + , m_next(0) +{ +} + +inline HandleSlot HandleSet::Node::slot() +{ + return &m_value; +} + +inline HandleSet* HandleSet::Node::handleSet() +{ + return m_handleSet; +} + +inline void HandleSet::Node::setPrev(Node* prev) +{ + m_prev = prev; +} + +inline HandleSet::Node* HandleSet::Node::prev() +{ + return m_prev; +} + +inline void HandleSet::Node::setNext(Node* next) +{ + m_next = next; +} + +inline HandleSet::Node* HandleSet::Node::next() +{ + return m_next; +} + +template<typename Functor> void HandleSet::forEachStrongHandle(Functor& functor, const HashCountedSet<JSCell*>& skipSet) +{ + Node* end = m_strongList.end(); + for (Node* node = m_strongList.begin(); node != end; node = node->next()) { + JSValue value = *node->slot(); + if (!value || !value.isCell()) + continue; + if (skipSet.contains(value.asCell())) + continue; + functor(value.asCell()); + } +} + +} + +#endif diff --git a/Source/JavaScriptCore/heap/Heap.cpp b/Source/JavaScriptCore/heap/Heap.cpp index a5d4a063f..d0dbc3172 100644 --- a/Source/JavaScriptCore/heap/Heap.cpp +++ b/Source/JavaScriptCore/heap/Heap.cpp @@ -33,6 +33,7 @@ #include "JSLock.h" #include "JSONObject.h" #include "Tracing.h" +#include "WeakSetInlines.h" #include <algorithm> #include <wtf/CurrentTime.h> @@ -312,144 +313,65 @@ inline PassOwnPtr<TypeCountSet> RecordType::returnValue() Heap::Heap(JSGlobalData* globalData, HeapSize heapSize) : m_heapSize(heapSize) , m_minBytesPerCycle(heapSizeForHint(heapSize)) - , m_lastFullGCSize(0) - , m_waterMark(0) - , m_highWaterMark(m_minBytesPerCycle) + , m_sizeAfterLastCollect(0) + , m_bytesAllocatedLimit(m_minBytesPerCycle) + , m_bytesAllocated(0) + , m_bytesAbandoned(0) , m_operationInProgress(NoOperation) , m_objectSpace(this) , m_storageSpace(this) - , m_blockFreeingThreadShouldQuit(false) - , m_extraCost(0) , m_markListSet(0) , m_activityCallback(DefaultGCActivityCallback::create(this)) , m_machineThreads(this) , m_sharedData(globalData) , m_slotVisitor(m_sharedData) - , m_handleHeap(globalData) + , m_weakSet(this) + , m_handleSet(globalData) , m_isSafeToCollect(false) , m_globalData(globalData) , m_lastGCLength(0) + , m_lastCodeDiscardTime(WTF::currentTime()) { - (*m_activityCallback)(); - m_numberOfFreeBlocks = 0; - m_blockFreeingThread = createThread(blockFreeingThreadStartFunc, this, "JavaScriptCore::BlockFree"); - - ASSERT(m_blockFreeingThread); m_storageSpace.init(); } Heap::~Heap() { - // Destroy our block freeing thread. - { - MutexLocker locker(m_freeBlockLock); - m_blockFreeingThreadShouldQuit = true; - m_freeBlockCondition.broadcast(); - } - waitForThreadCompletion(m_blockFreeingThread); + delete m_markListSet; + + m_objectSpace.shrink(); + m_storageSpace.freeAllBlocks(); - // The destroy function must already have been called, so assert this. - ASSERT(!m_globalData); + ASSERT(!size()); + ASSERT(!capacity()); } -void Heap::destroy() +bool Heap::isPagedOut(double deadline) { - JSLock lock(SilenceAssertionsOnly); - - if (!m_globalData) - return; + return m_objectSpace.isPagedOut(deadline) || m_storageSpace.isPagedOut(deadline); +} +// The JSGlobalData is being destroyed and the collector will never run again. +// Run all pending finalizers now because we won't get another chance. +void Heap::lastChanceToFinalize() +{ ASSERT(!m_globalData->dynamicGlobalObject); ASSERT(m_operationInProgress == NoOperation); - - // The global object is not GC protected at this point, so sweeping may delete it - // (and thus the global data) before other objects that may use the global data. - RefPtr<JSGlobalData> protect(m_globalData); -#if ENABLE(JIT) - m_globalData->jitStubs->clearHostFunctionStubs(); -#endif - - delete m_markListSet; - m_markListSet = 0; + // FIXME: Make this a release-mode crash once we're sure no one's doing this. + if (size_t size = m_protectedValues.size()) + WTFLogAlways("ERROR: JavaScriptCore heap deallocated while %ld values were still protected", static_cast<unsigned long>(size)); + m_weakSet.finalizeAll(); canonicalizeCellLivenessData(); clearMarks(); - - m_handleHeap.finalizeWeakHandles(); + sweep(); m_globalData->smallStrings.finalizeSmallStrings(); - shrink(); - ASSERT(!size()); - + #if ENABLE(SIMPLE_HEAP_PROFILING) m_slotVisitor.m_visitedTypeCounts.dump(WTF::dataFile(), "Visited Type Counts"); m_destroyedTypeCounts.dump(WTF::dataFile(), "Destroyed Type Counts"); #endif - - releaseFreeBlocks(); - - m_globalData = 0; -} - -void Heap::waitForRelativeTimeWhileHoldingLock(double relative) -{ - if (m_blockFreeingThreadShouldQuit) - return; - m_freeBlockCondition.timedWait(m_freeBlockLock, currentTime() + relative); -} - -void Heap::waitForRelativeTime(double relative) -{ - // If this returns early, that's fine, so long as it doesn't do it too - // frequently. It would only be a bug if this function failed to return - // when it was asked to do so. - - MutexLocker locker(m_freeBlockLock); - waitForRelativeTimeWhileHoldingLock(relative); -} - -void Heap::blockFreeingThreadStartFunc(void* heap) -{ - static_cast<Heap*>(heap)->blockFreeingThreadMain(); -} - -void Heap::blockFreeingThreadMain() -{ - while (!m_blockFreeingThreadShouldQuit) { - // Generally wait for one second before scavenging free blocks. This - // may return early, particularly when we're being asked to quit. - waitForRelativeTime(1.0); - if (m_blockFreeingThreadShouldQuit) - break; - - // Now process the list of free blocks. Keep freeing until half of the - // blocks that are currently on the list are gone. Assume that a size_t - // field can be accessed atomically. - size_t currentNumberOfFreeBlocks = m_numberOfFreeBlocks; - if (!currentNumberOfFreeBlocks) - continue; - - size_t desiredNumberOfFreeBlocks = currentNumberOfFreeBlocks / 2; - - while (!m_blockFreeingThreadShouldQuit) { - MarkedBlock* block; - { - MutexLocker locker(m_freeBlockLock); - if (m_numberOfFreeBlocks <= desiredNumberOfFreeBlocks) - block = 0; - else { - block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead()); - ASSERT(block); - m_numberOfFreeBlocks--; - } - } - - if (!block) - break; - - MarkedBlock::destroy(block); - } - } } void Heap::reportExtraMemoryCostSlowCase(size_t cost) @@ -465,9 +387,28 @@ void Heap::reportExtraMemoryCostSlowCase(size_t cost) // if a large value survives one garbage collection, there is not much point to // collecting more frequently as long as it stays alive. - if (m_extraCost > maxExtraCost && m_extraCost > highWaterMark() / 2) - collectAllGarbage(); - m_extraCost += cost; + didAllocate(cost); + if (shouldCollect()) + collect(DoNotSweep); +} + +void Heap::reportAbandonedObjectGraph() +{ + // Our clients don't know exactly how much memory they + // are abandoning so we just guess for them. + double abandonedBytes = 0.10 * m_sizeAfterLastCollect; + + // We want to accelerate the next collection. Because memory has just + // been abandoned, the next collection has the potential to + // be more profitable. Since allocation is the trigger for collection, + // we hasten the next collection by pretending that we've allocated more memory. + didAbandon(abandonedBytes); +} + +void Heap::didAbandon(size_t bytes) +{ + m_activityCallback->didAllocate(m_bytesAllocated + m_bytesAbandoned); + m_bytesAbandoned += bytes; } void Heap::protect(JSValue k) @@ -662,7 +603,7 @@ void Heap::markRoots(bool fullGC) { GCPHASE(VisitStrongHandles); - m_handleHeap.visitStrongHandles(heapRootVisitor); + m_handleSet.visitStrongHandles(heapRootVisitor); visitor.donateAndDrain(); } @@ -686,12 +627,12 @@ void Heap::markRoots(bool fullGC) #endif } - // Weak handles must be marked last, because their owners use the set of - // opaque roots to determine reachability. + // Weak references must be marked last because their liveness depends on + // the liveness of the rest of the object graph. { - GCPHASE(VisitingWeakHandles); + GCPHASE(VisitingLiveWeakHandles); while (true) { - m_handleHeap.visitWeakHandles(heapRootVisitor); + m_weakSet.visitLiveWeakImpls(heapRootVisitor); harvestWeakReferences(); if (visitor.isEmpty()) break; @@ -704,6 +645,12 @@ void Heap::markRoots(bool fullGC) } } } + + { + GCPHASE(VisitingDeadWeakHandles); + m_weakSet.visitDeadWeakImpls(heapRootVisitor); + } + GCCOUNTER(VisitedValueCount, visitor.visitCount()); visitor.doneCopying(); @@ -731,12 +678,12 @@ size_t Heap::objectCount() size_t Heap::size() { - return m_objectSpace.forEachBlock<Size>(); + return m_objectSpace.forEachBlock<Size>() + m_storageSpace.size(); } size_t Heap::capacity() { - return m_objectSpace.forEachBlock<Capacity>(); + return m_objectSpace.forEachBlock<Capacity>() + m_storageSpace.capacity(); } size_t Heap::protectedGlobalObjectCount() @@ -764,16 +711,27 @@ PassOwnPtr<TypeCountSet> Heap::objectTypeCounts() return m_objectSpace.forEachCell<RecordType>(); } +void Heap::discardAllCompiledCode() +{ + // If JavaScript is running, it's not safe to recompile, since we'll end + // up throwing away code that is live on the stack. + if (m_globalData->dynamicGlobalObject) + return; + + for (FunctionExecutable* current = m_functions.head(); current; current = current->next()) + current->discardCode(); +} + void Heap::collectAllGarbage() { if (!m_isSafeToCollect) return; - if (!m_globalData->dynamicGlobalObject) - m_globalData->recompileAllJSFunctions(); collect(DoSweep); } +static double minute = 60.0; + void Heap::collect(SweepToggle sweepToggle) { SamplingRegion samplingRegion("Garbage Collection"); @@ -782,11 +740,19 @@ void Heap::collect(SweepToggle sweepToggle) ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); ASSERT(m_isSafeToCollect); JAVASCRIPTCORE_GC_BEGIN(); + + m_activityCallback->willCollect(); + double lastGCStartTime = WTF::currentTime(); + if (lastGCStartTime - m_lastCodeDiscardTime > minute) { + discardAllCompiledCode(); + m_lastCodeDiscardTime = WTF::currentTime(); + } + #if ENABLE(GGC) bool fullGC = sweepToggle == DoSweep; if (!fullGC) - fullGC = (capacity() > 4 * m_lastFullGCSize); + fullGC = (capacity() > 4 * m_sizeAfterLastCollect); #else bool fullGC = true; #endif @@ -804,7 +770,7 @@ void Heap::collect(SweepToggle sweepToggle) { GCPHASE(FinalizeWeakHandles); - m_handleHeap.finalizeWeakHandles(); + m_weakSet.sweep(); m_globalData->smallStrings.finalizeSmallStrings(); } @@ -824,24 +790,25 @@ void Heap::collect(SweepToggle sweepToggle) SamplingRegion samplingRegion("Garbage Collection: Sweeping"); GCPHASE(Sweeping); sweep(); - shrink(); + m_objectSpace.shrink(); + m_weakSet.shrink(); + m_bytesAbandoned = 0; } - // To avoid pathological GC churn in large heaps, we set the allocation high - // water mark to be proportional to the current size of the heap. The exact - // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size : + // To avoid pathological GC churn in large heaps, we set the new allocation + // limit to be the current size of the heap. This heuristic + // is a bit arbitrary. Using the current size of the heap after this + // collection gives us a 2X multiplier, which is a 1:1 (heap size : // new bytes allocated) proportion, and seems to work well in benchmarks. - size_t newSize = size() + m_storageSpace.totalMemoryUtilized(); - size_t proportionalBytes = 2 * newSize; + size_t newSize = size(); if (fullGC) { - m_lastFullGCSize = newSize; - setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle)); + m_sizeAfterLastCollect = newSize; + m_bytesAllocatedLimit = max(newSize, m_minBytesPerCycle); } + m_bytesAllocated = 0; double lastGCEndTime = WTF::currentTime(); m_lastGCLength = lastGCEndTime - lastGCStartTime; JAVASCRIPTCORE_GC_END(); - - (*m_activityCallback)(); } void Heap::canonicalizeCellLivenessData() @@ -851,8 +818,8 @@ void Heap::canonicalizeCellLivenessData() void Heap::resetAllocators() { - m_extraCost = 0; m_objectSpace.resetAllocators(); + m_weakSet.resetAllocator(); } void Heap::setActivityCallback(PassOwnPtr<GCActivityCallback> activityCallback) @@ -865,6 +832,12 @@ GCActivityCallback* Heap::activityCallback() return m_activityCallback.get(); } +void Heap::didAllocate(size_t bytes) +{ + m_activityCallback->didAllocate(m_bytesAllocated + m_bytesAbandoned); + m_bytesAllocated += bytes; +} + bool Heap::isValidAllocation(size_t bytes) { if (!isValidThreadState(m_globalData)) @@ -879,49 +852,27 @@ bool Heap::isValidAllocation(size_t bytes) return true; } -void Heap::freeBlocks(MarkedBlock* head) -{ - m_objectSpace.freeBlocks(head); -} - -void Heap::shrink() +void Heap::addFinalizer(JSCell* cell, Finalizer finalizer) { - m_objectSpace.shrink(); + WeakSet::allocate(cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer)); // Balanced by FinalizerOwner::finalize(). } -void Heap::releaseFreeBlocks() +void Heap::FinalizerOwner::finalize(Handle<Unknown> handle, void* context) { - while (true) { - MarkedBlock* block; - { - MutexLocker locker(m_freeBlockLock); - if (!m_numberOfFreeBlocks) - block = 0; - else { - block = static_cast<MarkedBlock*>(m_freeBlocks.removeHead()); - ASSERT(block); - m_numberOfFreeBlocks--; - } - } - - if (!block) - break; - - MarkedBlock::destroy(block); - } + HandleSlot slot = handle.slot(); + Finalizer finalizer = reinterpret_cast<Finalizer>(context); + finalizer(slot->asCell()); + WeakSet::deallocate(WeakImpl::asWeakImpl(slot)); } -void Heap::addFinalizer(JSCell* cell, Finalizer finalizer) +void Heap::addFunctionExecutable(FunctionExecutable* executable) { - Weak<JSCell> weak(*globalData(), cell, &m_finalizerOwner, reinterpret_cast<void*>(finalizer)); - weak.leakHandle(); // Balanced by FinalizerOwner::finalize(). + m_functions.append(executable); } -void Heap::FinalizerOwner::finalize(Handle<Unknown> handle, void* context) +void Heap::removeFunctionExecutable(FunctionExecutable* executable) { - Weak<JSCell> weak(Weak<JSCell>::Adopt, handle); - Finalizer finalizer = reinterpret_cast<Finalizer>(context); - finalizer(weak.get()); + m_functions.remove(executable); } } // namespace JSC diff --git a/Source/JavaScriptCore/heap/Heap.h b/Source/JavaScriptCore/heap/Heap.h index 09a95882b..10fdb07be 100644 --- a/Source/JavaScriptCore/heap/Heap.h +++ b/Source/JavaScriptCore/heap/Heap.h @@ -22,17 +22,18 @@ #ifndef Heap_h #define Heap_h +#include "BlockAllocator.h" #include "DFGCodeBlocks.h" -#include "HandleHeap.h" +#include "HandleSet.h" #include "HandleStack.h" #include "MarkedAllocator.h" #include "MarkedBlock.h" #include "MarkedBlockSet.h" #include "MarkedSpace.h" #include "SlotVisitor.h" +#include "WeakHandleOwner.h" +#include "WeakSet.h" #include "WriteBarrierSupport.h" -#include <wtf/DoublyLinkedList.h> -#include <wtf/Forward.h> #include <wtf/HashCountedSet.h> #include <wtf/HashSet.h> @@ -42,6 +43,7 @@ namespace JSC { class CopiedSpace; class CodeBlock; + class FunctionExecutable; class GCActivityCallback; class GlobalCodeBlock; class Heap; @@ -71,8 +73,14 @@ namespace JSC { public: friend class JIT; friend class MarkStackThreadSharedData; - static Heap* heap(JSValue); // 0 for immediate values - static Heap* heap(JSCell*); + static Heap* heap(const JSValue); // 0 for immediate values + static Heap* heap(const JSCell*); + + // This constant determines how many blocks we iterate between checks of our + // deadline when calling Heap::isPagedOut. Decreasing it will cause us to detect + // overstepping our deadline more quickly, while increasing it will cause + // our scan to run faster. + static const unsigned s_timeCheckResolution = 16; static bool isMarked(const void*); static bool testAndSetMarked(const void*); @@ -84,7 +92,7 @@ namespace JSC { Heap(JSGlobalData*, HeapSize); ~Heap(); - JS_EXPORT_PRIVATE void destroy(); // JSGlobalData must call destroy() before ~Heap(). + JS_EXPORT_PRIVATE void lastChanceToFinalize(); JSGlobalData* globalData() const { return m_globalData; } MarkedSpace& objectSpace() { return m_objectSpace; } @@ -105,11 +113,18 @@ namespace JSC { typedef void (*Finalizer)(JSCell*); JS_EXPORT_PRIVATE void addFinalizer(JSCell*, Finalizer); + void addFunctionExecutable(FunctionExecutable*); + void removeFunctionExecutable(FunctionExecutable*); void notifyIsSafeToCollect() { m_isSafeToCollect = true; } + JS_EXPORT_PRIVATE void collectAllGarbage(); + enum SweepToggle { DoNotSweep, DoSweep }; + bool shouldCollect(); + void collect(SweepToggle); void reportExtraMemoryCost(size_t cost); + JS_EXPORT_PRIVATE void reportAbandonedObjectGraph(); JS_EXPORT_PRIVATE void protect(JSValue); JS_EXPORT_PRIVATE bool unprotect(JSValue); // True when the protect count drops to 0. @@ -133,12 +148,21 @@ namespace JSC { template<typename Functor> typename Functor::ReturnType forEachProtectedCell(Functor&); template<typename Functor> typename Functor::ReturnType forEachProtectedCell(); - HandleHeap* handleHeap() { return &m_handleHeap; } + WeakSet* weakSet() { return &m_weakSet; } + HandleSet* handleSet() { return &m_handleSet; } HandleStack* handleStack() { return &m_handleStack; } void getConservativeRegisterRoots(HashSet<JSCell*>& roots); double lastGCLength() { return m_lastGCLength; } + void increaseLastGCLength(double amount) { m_lastGCLength += amount; } + + JS_EXPORT_PRIVATE void discardAllCompiledCode(); + + void didAllocate(size_t); + void didAbandon(size_t); + + bool isPagedOut(double deadline); private: friend class CodeBlock; @@ -153,10 +177,6 @@ namespace JSC { void* allocateWithDestructor(size_t); void* allocateWithoutDestructor(size_t); - size_t waterMark(); - size_t highWaterMark(); - void setHighWaterMark(size_t); - static const size_t minExtraCost = 256; static const size_t maxExtraCost = 1024 * 1024; @@ -173,7 +193,6 @@ namespace JSC { void canonicalizeCellLivenessData(); void resetAllocators(); - void freeBlocks(MarkedBlock*); void clearMarks(); void markRoots(bool fullGC); @@ -182,43 +201,29 @@ namespace JSC { void harvestWeakReferences(); void finalizeUnconditionalFinalizers(); - enum SweepToggle { DoNotSweep, DoSweep }; - void collect(SweepToggle); - void shrink(); - void releaseFreeBlocks(); void sweep(); RegisterFile& registerFile(); + BlockAllocator& blockAllocator(); - void waitForRelativeTimeWhileHoldingLock(double relative); - void waitForRelativeTime(double relative); - void blockFreeingThreadMain(); - static void blockFreeingThreadStartFunc(void* heap); - const HeapSize m_heapSize; const size_t m_minBytesPerCycle; - size_t m_lastFullGCSize; - size_t m_waterMark; - size_t m_highWaterMark; + size_t m_sizeAfterLastCollect; + + size_t m_bytesAllocatedLimit; + size_t m_bytesAllocated; + size_t m_bytesAbandoned; OperationInProgress m_operationInProgress; MarkedSpace m_objectSpace; CopiedSpace m_storageSpace; - DoublyLinkedList<HeapBlock> m_freeBlocks; - size_t m_numberOfFreeBlocks; - - ThreadIdentifier m_blockFreeingThread; - Mutex m_freeBlockLock; - ThreadCondition m_freeBlockCondition; - bool m_blockFreeingThreadShouldQuit; + BlockAllocator m_blockAllocator; #if ENABLE(SIMPLE_HEAP_PROFILING) VTableSpectrum m_destroyedTypeCounts; #endif - size_t m_extraCost; - ProtectCountSet m_protectedValues; Vector<Vector<ValueStringPair>* > m_tempSortingVectors; HashSet<MarkedArgumentBuffer*>* m_markListSet; @@ -230,7 +235,8 @@ namespace JSC { MarkStackThreadSharedData m_sharedData; SlotVisitor m_slotVisitor; - HandleHeap m_handleHeap; + WeakSet m_weakSet; + HandleSet m_handleSet; HandleStack m_handleStack; DFGCodeBlocks m_dfgCodeBlocks; FinalizerOwner m_finalizerOwner; @@ -239,19 +245,31 @@ namespace JSC { JSGlobalData* m_globalData; double m_lastGCLength; + double m_lastCodeDiscardTime; + + DoublyLinkedList<FunctionExecutable> m_functions; }; + inline bool Heap::shouldCollect() + { +#if ENABLE(GGC) + return m_objectSpace.nurseryWaterMark() >= m_minBytesPerCycle && m_isSafeToCollect; +#else + return m_bytesAllocated > m_bytesAllocatedLimit && m_isSafeToCollect; +#endif + } + bool Heap::isBusy() { return m_operationInProgress != NoOperation; } - inline Heap* Heap::heap(JSCell* cell) + inline Heap* Heap::heap(const JSCell* cell) { return MarkedBlock::blockFor(cell)->heap(); } - inline Heap* Heap::heap(JSValue v) + inline Heap* Heap::heap(const JSValue v) { if (!v.isCell()) return 0; @@ -273,21 +291,6 @@ namespace JSC { MarkedBlock::blockFor(cell)->setMarked(cell); } - inline size_t Heap::waterMark() - { - return m_objectSpace.waterMark() + m_storageSpace.totalMemoryUtilized(); - } - - inline size_t Heap::highWaterMark() - { - return m_highWaterMark; - } - - inline void Heap::setHighWaterMark(size_t newHighWaterMark) - { - m_highWaterMark = newHighWaterMark; - } - #if ENABLE(GGC) inline uint8_t* Heap::addressOfCardFor(JSCell* cell) { @@ -334,7 +337,7 @@ namespace JSC { ProtectCountSet::iterator end = m_protectedValues.end(); for (ProtectCountSet::iterator it = m_protectedValues.begin(); it != end; ++it) functor(it->first); - m_handleHeap.forEachStrongHandle(functor, m_protectedValues); + m_handleSet.forEachStrongHandle(functor, m_protectedValues); return functor.returnValue(); } @@ -367,6 +370,11 @@ namespace JSC { return m_storageSpace.tryReallocate(ptr, oldSize, newSize); } + inline BlockAllocator& Heap::blockAllocator() + { + return m_blockAllocator; + } + } // namespace JSC #endif // Heap_h diff --git a/Source/JavaScriptCore/heap/Local.h b/Source/JavaScriptCore/heap/Local.h index afcfe42b8..5d1f06439 100644 --- a/Source/JavaScriptCore/heap/Local.h +++ b/Source/JavaScriptCore/heap/Local.h @@ -102,7 +102,7 @@ template <typename T, unsigned inlineCapacity = 0> class LocalStack { typedef typename Handle<T>::ExternalType ExternalType; public: LocalStack(JSGlobalData& globalData) - : m_globalData(&globalData) + : m_globalData(globalData) , m_count(0) { } @@ -122,7 +122,7 @@ public: void push(ExternalType value) { if (m_count == m_stack.size()) - m_stack.append(Local<T>(*m_globalData, value)); + m_stack.append(Local<T>(m_globalData, value)); else m_stack[m_count] = value; m_count++; @@ -132,7 +132,7 @@ public: unsigned size() const { return m_count; } private: - RefPtr<JSGlobalData> m_globalData; + JSGlobalData& m_globalData; Vector<Local<T>, inlineCapacity> m_stack; unsigned m_count; }; diff --git a/Source/JavaScriptCore/heap/MachineStackMarker.cpp b/Source/JavaScriptCore/heap/MachineStackMarker.cpp index fd828d5de..30915eaf8 100644 --- a/Source/JavaScriptCore/heap/MachineStackMarker.cpp +++ b/Source/JavaScriptCore/heap/MachineStackMarker.cpp @@ -96,6 +96,7 @@ typedef HANDLE PlatformThread; typedef pthread_t PlatformThread; static const int SigThreadSuspendResume = SIGUSR2; +#if defined(SA_RESTART) static void pthreadSignalHandlerSuspendResume(int signo) { sigset_t signalSet; @@ -104,6 +105,7 @@ static void pthreadSignalHandlerSuspendResume(int signo) sigsuspend(&signalSet); } #endif +#endif class MachineThreads::Thread { public: diff --git a/Source/JavaScriptCore/heap/MarkStack.cpp b/Source/JavaScriptCore/heap/MarkStack.cpp index 129a7ab67..cf6e3513c 100644 --- a/Source/JavaScriptCore/heap/MarkStack.cpp +++ b/Source/JavaScriptCore/heap/MarkStack.cpp @@ -486,16 +486,6 @@ void* SlotVisitor::allocateNewSpace(void* ptr, size_t bytes) return CopiedSpace::allocateFromBlock(m_copyBlock, bytes); } -void SlotVisitor::copy(void** ptr, size_t bytes) -{ - void* newPtr = 0; - if (!(newPtr = allocateNewSpace(*ptr, bytes))) - return; - - memcpy(newPtr, *ptr, bytes); - *ptr = newPtr; -} - void SlotVisitor::copyAndAppend(void** ptr, size_t bytes, JSValue* values, unsigned length) { void* oldPtr = *ptr; @@ -503,7 +493,7 @@ void SlotVisitor::copyAndAppend(void** ptr, size_t bytes, JSValue* values, unsig if (newPtr) { size_t jsValuesOffset = static_cast<size_t>(reinterpret_cast<char*>(values) - static_cast<char*>(oldPtr)); - JSValue* newValues = reinterpret_cast<JSValue*>(static_cast<char*>(newPtr) + jsValuesOffset); + JSValue* newValues = reinterpret_cast_ptr<JSValue*>(static_cast<char*>(newPtr) + jsValuesOffset); for (unsigned i = 0; i < length; i++) { JSValue& value = values[i]; newValues[i] = value; diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.cpp b/Source/JavaScriptCore/heap/MarkedAllocator.cpp index eb6d2c691..b5e5fff77 100644 --- a/Source/JavaScriptCore/heap/MarkedAllocator.cpp +++ b/Source/JavaScriptCore/heap/MarkedAllocator.cpp @@ -1,29 +1,48 @@ #include "config.h" #include "MarkedAllocator.h" +#include "GCActivityCallback.h" #include "Heap.h" +#include <wtf/CurrentTime.h> namespace JSC { +bool MarkedAllocator::isPagedOut(double deadline) +{ + unsigned itersSinceLastTimeCheck = 0; + HeapBlock* block = m_blockList.head(); + while (block) { + block = block->next(); + ++itersSinceLastTimeCheck; + if (itersSinceLastTimeCheck >= Heap::s_timeCheckResolution) { + double currentTime = WTF::monotonicallyIncreasingTime(); + if (currentTime > deadline) + return true; + itersSinceLastTimeCheck = 0; + } + } + + return false; +} + inline void* MarkedAllocator::tryAllocateHelper() { - MarkedBlock::FreeCell* firstFreeCell = m_firstFreeCell; - if (!firstFreeCell) { + if (!m_freeList.head) { for (MarkedBlock*& block = m_currentBlock; block; block = static_cast<MarkedBlock*>(block->next())) { - firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList); - if (firstFreeCell) + m_freeList = block->sweep(MarkedBlock::SweepToFreeList); + if (m_freeList.head) break; - m_markedSpace->didConsumeFreeList(block); block->didConsumeFreeList(); } - if (!firstFreeCell) + if (!m_freeList.head) return 0; } - ASSERT(firstFreeCell); - m_firstFreeCell = firstFreeCell->next; - return firstFreeCell; + MarkedBlock::FreeCell* head = m_freeList.head; + m_freeList.head = head->next; + ASSERT(head); + return head; } inline void* MarkedAllocator::tryAllocate() @@ -41,6 +60,9 @@ void* MarkedAllocator::allocateSlowCase() ASSERT(m_heap->m_operationInProgress == NoOperation); #endif + ASSERT(!m_freeList.head); + m_heap->didAllocate(m_freeList.bytes); + void* result = tryAllocate(); if (LIKELY(result != 0)) @@ -48,16 +70,10 @@ void* MarkedAllocator::allocateSlowCase() AllocationEffort allocationEffort; - if (( -#if ENABLE(GGC) - nurseryWaterMark() < m_heap->m_minBytesPerCycle -#else - m_heap->waterMark() < m_heap->highWaterMark() -#endif - ) || !m_heap->m_isSafeToCollect) - allocationEffort = AllocationMustSucceed; - else + if (m_heap->shouldCollect()) allocationEffort = AllocationCanFail; + else + allocationEffort = AllocationMustSucceed; MarkedBlock* block = allocateBlock(allocationEffort); if (block) { @@ -74,7 +90,7 @@ void* MarkedAllocator::allocateSlowCase() if (result) return result; - ASSERT(m_heap->waterMark() < m_heap->highWaterMark()); + ASSERT(!m_heap->shouldCollect()); addBlock(allocateBlock(AllocationMustSucceed)); @@ -85,17 +101,7 @@ void* MarkedAllocator::allocateSlowCase() MarkedBlock* MarkedAllocator::allocateBlock(AllocationEffort allocationEffort) { - MarkedBlock* block; - - { - MutexLocker locker(m_heap->m_freeBlockLock); - if (m_heap->m_numberOfFreeBlocks) { - block = static_cast<MarkedBlock*>(m_heap->m_freeBlocks.removeHead()); - ASSERT(block); - m_heap->m_numberOfFreeBlocks--; - } else - block = 0; - } + MarkedBlock* block = static_cast<MarkedBlock*>(m_heap->blockAllocator().allocate()); if (block) block = MarkedBlock::recycle(block, m_heap, m_cellSize, m_cellsNeedDestruction); else if (allocationEffort == AllocationCanFail) @@ -111,11 +117,11 @@ MarkedBlock* MarkedAllocator::allocateBlock(AllocationEffort allocationEffort) void MarkedAllocator::addBlock(MarkedBlock* block) { ASSERT(!m_currentBlock); - ASSERT(!m_firstFreeCell); + ASSERT(!m_freeList.head); m_blockList.append(block); m_currentBlock = block; - m_firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList); + m_freeList = block->sweep(MarkedBlock::SweepToFreeList); } void MarkedAllocator::removeBlock(MarkedBlock* block) diff --git a/Source/JavaScriptCore/heap/MarkedAllocator.h b/Source/JavaScriptCore/heap/MarkedAllocator.h index 1c6af77a2..8ad7e925f 100644 --- a/Source/JavaScriptCore/heap/MarkedAllocator.h +++ b/Source/JavaScriptCore/heap/MarkedAllocator.h @@ -32,7 +32,9 @@ public: void addBlock(MarkedBlock*); void removeBlock(MarkedBlock*); void init(Heap*, MarkedSpace*, size_t cellSize, bool cellsNeedDestruction); - + + bool isPagedOut(double deadline); + private: friend class LLIntOffsetsExtractor; @@ -41,7 +43,7 @@ private: void* tryAllocateHelper(); MarkedBlock* allocateBlock(AllocationEffort); - MarkedBlock::FreeCell* m_firstFreeCell; + MarkedBlock::FreeList m_freeList; MarkedBlock* m_currentBlock; DoublyLinkedList<HeapBlock> m_blockList; size_t m_cellSize; @@ -51,8 +53,7 @@ private: }; inline MarkedAllocator::MarkedAllocator() - : m_firstFreeCell(0) - , m_currentBlock(0) + : m_currentBlock(0) , m_cellSize(0) , m_cellsNeedDestruction(true) , m_heap(0) @@ -70,13 +71,13 @@ inline void MarkedAllocator::init(Heap* heap, MarkedSpace* markedSpace, size_t c inline void* MarkedAllocator::allocate() { - MarkedBlock::FreeCell* firstFreeCell = m_firstFreeCell; + MarkedBlock::FreeCell* head = m_freeList.head; // This is a light-weight fast path to cover the most common case. - if (UNLIKELY(!firstFreeCell)) + if (UNLIKELY(!head)) return allocateSlowCase(); - m_firstFreeCell = firstFreeCell->next; - return firstFreeCell; + m_freeList.head = head->next; + return head; } inline void MarkedAllocator::reset() @@ -87,12 +88,12 @@ inline void MarkedAllocator::reset() inline void MarkedAllocator::zapFreeList() { if (!m_currentBlock) { - ASSERT(!m_firstFreeCell); + ASSERT(!m_freeList.head); return; } - m_currentBlock->zapFreeList(m_firstFreeCell); - m_firstFreeCell = 0; + m_currentBlock->zapFreeList(m_freeList); + m_freeList = MarkedBlock::FreeList(); } template <typename Functor> inline void MarkedAllocator::forEachBlock(Functor& functor) diff --git a/Source/JavaScriptCore/heap/MarkedBlock.cpp b/Source/JavaScriptCore/heap/MarkedBlock.cpp index 75c21e7dd..3a58b5a42 100644 --- a/Source/JavaScriptCore/heap/MarkedBlock.cpp +++ b/Source/JavaScriptCore/heap/MarkedBlock.cpp @@ -77,7 +77,7 @@ inline void MarkedBlock::callDestructor(JSCell* cell) } template<MarkedBlock::BlockState blockState, MarkedBlock::SweepMode sweepMode, bool destructorCallNeeded> -MarkedBlock::FreeCell* MarkedBlock::specializedSweep() +MarkedBlock::FreeList MarkedBlock::specializedSweep() { ASSERT(blockState != Allocated && blockState != FreeListed); ASSERT(destructorCallNeeded || sweepMode != SweepOnly); @@ -86,6 +86,7 @@ MarkedBlock::FreeCell* MarkedBlock::specializedSweep() // This is fine, since the allocation code makes no assumptions about the // order of the free list. FreeCell* head = 0; + size_t count = 0; for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { if (blockState == Marked && m_marks.get(i)) continue; @@ -101,19 +102,20 @@ MarkedBlock::FreeCell* MarkedBlock::specializedSweep() FreeCell* freeCell = reinterpret_cast<FreeCell*>(cell); freeCell->next = head; head = freeCell; + ++count; } } m_state = ((sweepMode == SweepToFreeList) ? FreeListed : Zapped); - return head; + return FreeList(head, count * cellSize()); } -MarkedBlock::FreeCell* MarkedBlock::sweep(SweepMode sweepMode) +MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode) { HEAP_LOG_BLOCK_STATE_TRANSITION(this); if (sweepMode == SweepOnly && !m_cellsNeedDestruction) - return 0; + return FreeList(); if (m_cellsNeedDestruction) return sweepHelper<true>(sweepMode); @@ -121,7 +123,7 @@ MarkedBlock::FreeCell* MarkedBlock::sweep(SweepMode sweepMode) } template<bool destructorCallNeeded> -MarkedBlock::FreeCell* MarkedBlock::sweepHelper(SweepMode sweepMode) +MarkedBlock::FreeList MarkedBlock::sweepHelper(SweepMode sweepMode) { switch (m_state) { case New: @@ -130,10 +132,10 @@ MarkedBlock::FreeCell* MarkedBlock::sweepHelper(SweepMode sweepMode) case FreeListed: // Happens when a block transitions to fully allocated. ASSERT(sweepMode == SweepToFreeList); - return 0; + return FreeList(); case Allocated: ASSERT_NOT_REACHED(); - return 0; + return FreeList(); case Marked: return sweepMode == SweepToFreeList ? specializedSweep<Marked, SweepToFreeList, destructorCallNeeded>() @@ -145,12 +147,13 @@ MarkedBlock::FreeCell* MarkedBlock::sweepHelper(SweepMode sweepMode) } ASSERT_NOT_REACHED(); - return 0; + return FreeList(); } -void MarkedBlock::zapFreeList(FreeCell* firstFreeCell) +void MarkedBlock::zapFreeList(const FreeList& freeList) { HEAP_LOG_BLOCK_STATE_TRANSITION(this); + FreeCell* head = freeList.head; if (m_state == Marked) { // If the block is in the Marked state then we know that: @@ -159,7 +162,7 @@ void MarkedBlock::zapFreeList(FreeCell* firstFreeCell) // fact that their mark bits are unset. // Hence if the block is Marked we need to leave it Marked. - ASSERT(!firstFreeCell); + ASSERT(!head); return; } @@ -176,7 +179,7 @@ void MarkedBlock::zapFreeList(FreeCell* firstFreeCell) // dead objects will have 0 in their vtables and live objects will have // non-zero vtables, which is consistent with the block being zapped. - ASSERT(!firstFreeCell); + ASSERT(!head); return; } @@ -188,7 +191,7 @@ void MarkedBlock::zapFreeList(FreeCell* firstFreeCell) // way to tell what's live vs dead. We use zapping for that. FreeCell* next; - for (FreeCell* current = firstFreeCell; current; current = next) { + for (FreeCell* current = head; current; current = next) { next = current->next; reinterpret_cast<JSCell*>(current)->zap(); } diff --git a/Source/JavaScriptCore/heap/MarkedBlock.h b/Source/JavaScriptCore/heap/MarkedBlock.h index 3d0182eb8..429b7c08e 100644 --- a/Source/JavaScriptCore/heap/MarkedBlock.h +++ b/Source/JavaScriptCore/heap/MarkedBlock.h @@ -87,6 +87,14 @@ namespace JSC { FreeCell* next; }; + struct FreeList { + FreeCell* head; + size_t bytes; + + FreeList(); + FreeList(FreeCell*, size_t); + }; + struct VoidFunctor { typedef void ReturnType; void returnValue() { } @@ -105,13 +113,13 @@ namespace JSC { void* allocate(); enum SweepMode { SweepOnly, SweepToFreeList }; - FreeCell* sweep(SweepMode = SweepOnly); + FreeList sweep(SweepMode = SweepOnly); // While allocating from a free list, MarkedBlock temporarily has bogus // cell liveness data. To restore accurate cell liveness data, call one // of these functions: void didConsumeFreeList(); // Call this once you've allocated all the items in the free list. - void zapFreeList(FreeCell* firstFreeCell); // Call this to undo the free list. + void zapFreeList(const FreeList&); // Call this to undo the free list. void clearMarks(); size_t markCount(); @@ -163,7 +171,7 @@ namespace JSC { static const size_t atomAlignmentMask = atomSize - 1; // atomSize must be a power of two. enum BlockState { New, FreeListed, Allocated, Marked, Zapped }; - template<bool destructorCallNeeded> FreeCell* sweepHelper(SweepMode = SweepOnly); + template<bool destructorCallNeeded> FreeList sweepHelper(SweepMode = SweepOnly); typedef char Atom[atomSize]; @@ -171,7 +179,7 @@ namespace JSC { Atom* atoms(); size_t atomNumber(const void*); void callDestructor(JSCell*); - template<BlockState, SweepMode, bool destructorCallNeeded> FreeCell* specializedSweep(); + template<BlockState, SweepMode, bool destructorCallNeeded> FreeList specializedSweep(); #if ENABLE(GGC) CardSet<bytesPerCard, blockSize> m_cards; @@ -189,6 +197,18 @@ namespace JSC { Heap* m_heap; }; + inline MarkedBlock::FreeList::FreeList() + : head(0) + , bytes(0) + { + } + + inline MarkedBlock::FreeList::FreeList(FreeCell* head, size_t bytes) + : head(head) + , bytes(bytes) + { + } + inline size_t MarkedBlock::firstAtom() { return WTF::roundUpToMultipleOf<atomSize>(sizeof(MarkedBlock)) / atomSize; diff --git a/Source/JavaScriptCore/heap/MarkedSpace.cpp b/Source/JavaScriptCore/heap/MarkedSpace.cpp index bf839011d..405ed571a 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.cpp +++ b/Source/JavaScriptCore/heap/MarkedSpace.cpp @@ -31,9 +31,7 @@ namespace JSC { class Structure; MarkedSpace::MarkedSpace(Heap* heap) - : m_waterMark(0) - , m_nurseryWaterMark(0) - , m_heap(heap) + : m_heap(heap) { for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { allocatorFor(cellSize).init(heap, this, cellSize, false); @@ -48,9 +46,6 @@ MarkedSpace::MarkedSpace(Heap* heap) void MarkedSpace::resetAllocators() { - m_waterMark = 0; - m_nurseryWaterMark = 0; - for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { allocatorFor(cellSize).reset(); destructorAllocatorFor(cellSize).reset(); @@ -75,6 +70,20 @@ void MarkedSpace::canonicalizeCellLivenessData() } } +bool MarkedSpace::isPagedOut(double deadline) +{ + for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) { + if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline)) + return true; + } + + for (size_t cellSize = impreciseStep; cellSize <= impreciseCutoff; cellSize += impreciseStep) { + if (allocatorFor(cellSize).isPagedOut(deadline) || destructorAllocatorFor(cellSize).isPagedOut(deadline)) + return true; + } + + return false; +} void MarkedSpace::freeBlocks(MarkedBlock* head) { @@ -84,9 +93,8 @@ void MarkedSpace::freeBlocks(MarkedBlock* head) m_blocks.remove(block); block->sweep(); - MutexLocker locker(m_heap->m_freeBlockLock); - m_heap->m_freeBlocks.append(block); - m_heap->m_numberOfFreeBlocks++; + + m_heap->blockAllocator().deallocate(block); } } diff --git a/Source/JavaScriptCore/heap/MarkedSpace.h b/Source/JavaScriptCore/heap/MarkedSpace.h index b553eb1b1..19061a12b 100644 --- a/Source/JavaScriptCore/heap/MarkedSpace.h +++ b/Source/JavaScriptCore/heap/MarkedSpace.h @@ -65,9 +65,6 @@ public: void canonicalizeCellLivenessData(); - size_t waterMark(); - size_t nurseryWaterMark(); - typedef HashSet<MarkedBlock*>::iterator BlockIterator; template<typename Functor> typename Functor::ReturnType forEachCell(Functor&); @@ -77,9 +74,12 @@ public: void shrink(); void freeBlocks(MarkedBlock* head); + void didAddBlock(MarkedBlock*); void didConsumeFreeList(MarkedBlock*); + bool isPagedOut(double deadline); + private: friend class LLIntOffsetsExtractor; @@ -101,22 +101,10 @@ private: Subspace m_destructorSpace; Subspace m_normalSpace; - size_t m_waterMark; - size_t m_nurseryWaterMark; Heap* m_heap; MarkedBlockSet m_blocks; }; -inline size_t MarkedSpace::waterMark() -{ - return m_waterMark; -} - -inline size_t MarkedSpace::nurseryWaterMark() -{ - return m_nurseryWaterMark; -} - template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachCell(Functor& functor) { canonicalizeCellLivenessData(); @@ -197,12 +185,6 @@ inline void MarkedSpace::didAddBlock(MarkedBlock* block) m_blocks.add(block); } -inline void MarkedSpace::didConsumeFreeList(MarkedBlock* block) -{ - m_nurseryWaterMark += block->capacity() - block->size(); - m_waterMark += block->capacity(); -} - } // namespace JSC #endif // MarkedSpace_h diff --git a/Source/JavaScriptCore/heap/PassWeak.h b/Source/JavaScriptCore/heap/PassWeak.h index 0d86e6c65..8c6364e4b 100644 --- a/Source/JavaScriptCore/heap/PassWeak.h +++ b/Source/JavaScriptCore/heap/PassWeak.h @@ -26,8 +26,9 @@ #ifndef PassWeak_h #define PassWeak_h +#include "JSCell.h" +#include "WeakSetInlines.h" #include <wtf/Assertions.h> -#include "Handle.h" #include <wtf/NullPtr.h> #include <wtf/TypeTraits.h> @@ -35,61 +36,136 @@ namespace JSC { template<typename T> class Weak; template<typename T> class PassWeak; -template<typename T> PassWeak<T> adoptWeak(HandleSlot); - -template<typename T> class PassWeak : public Handle<T> { - using Handle<T>::slot; - using Handle<T>::setSlot; +template<typename T> PassWeak<T> adoptWeak(WeakImpl*); +template<typename Base, typename T> class WeakImplAccessor { public: - typedef typename Handle<T>::ExternalType ExternalType; + typedef T* GetType; + + T* operator->() const; + T& operator*() const; + GetType get() const; + +#if !ASSERT_DISABLED + bool was(GetType) const; +#endif +}; - PassWeak() : Handle<T>() { } - PassWeak(std::nullptr_t) : Handle<T>() { } +template<typename T> class PassWeak : public WeakImplAccessor<PassWeak<T>, T> { +public: + friend class WeakImplAccessor<PassWeak<T>, T>; + typedef typename WeakImplAccessor<PassWeak<T>, T>::GetType GetType; - PassWeak(JSGlobalData& globalData, ExternalType externalType = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0) - : Handle<T>(globalData.heap.handleHeap()->allocate()) - { - HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context); - JSValue value = HandleTypes<T>::toJSValue(externalType); - HandleHeap::heapFor(slot())->writeBarrier(slot(), value); - *slot() = value; - } + PassWeak(); + PassWeak(std::nullptr_t); + PassWeak(GetType, WeakHandleOwner* = 0, void* context = 0); // It somewhat breaks the type system to allow transfer of ownership out of // a const PassWeak. However, it makes it much easier to work with PassWeak // temporaries, and we don't have a need to use real const PassWeaks anyway. - PassWeak(const PassWeak& o) : Handle<T>(o.leakHandle()) { } - template<typename U> PassWeak(const PassWeak<U>& o) : Handle<T>(o.leakHandle()) { } + PassWeak(const PassWeak&); + template<typename U> PassWeak(const PassWeak<U>&); + + ~PassWeak(); - ~PassWeak() - { - if (!slot()) - return; - HandleHeap::heapFor(slot())->deallocate(slot()); - setSlot(0); - } + bool operator!() const; - ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); } + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef JSValue (PassWeak::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const; - HandleSlot leakHandle() const WARN_UNUSED_RETURN; + WeakImpl* leakImpl() const WARN_UNUSED_RETURN; private: - friend PassWeak adoptWeak<T>(HandleSlot); + friend PassWeak adoptWeak<T>(WeakImpl*); + explicit PassWeak(WeakImpl*); - explicit PassWeak(HandleSlot slot) : Handle<T>(slot) { } + WeakImpl* m_impl; }; -template<typename T> inline HandleSlot PassWeak<T>::leakHandle() const +template<typename Base, typename T> inline T* WeakImplAccessor<Base, T>::operator->() const +{ + ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live); + return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()); +} + +template<typename Base, typename T> inline T& WeakImplAccessor<Base, T>::operator*() const +{ + ASSERT(static_cast<const Base*>(this)->m_impl && static_cast<const Base*>(this)->m_impl->state() == WeakImpl::Live); + return *jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()); +} + +template<typename Base, typename T> inline typename WeakImplAccessor<Base, T>::GetType WeakImplAccessor<Base, T>::get() const +{ + if (!static_cast<const Base*>(this)->m_impl || static_cast<const Base*>(this)->m_impl->state() != WeakImpl::Live) + return GetType(); + return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()); +} + +#if !ASSERT_DISABLED +template<typename Base, typename T> inline bool WeakImplAccessor<Base, T>::was(typename WeakImplAccessor<Base, T>::GetType other) const +{ + return jsCast<T*>(static_cast<const Base*>(this)->m_impl->jsValue().asCell()) == other; +} +#endif + +template<typename T> inline PassWeak<T>::PassWeak() + : m_impl(0) +{ +} + +template<typename T> inline PassWeak<T>::PassWeak(std::nullptr_t) + : m_impl(0) +{ +} + +template<typename T> inline PassWeak<T>::PassWeak(typename PassWeak<T>::GetType getType, WeakHandleOwner* weakOwner, void* context) + : m_impl(getType ? WeakSet::allocate(getType, weakOwner, context) : 0) +{ +} + +template<typename T> inline PassWeak<T>::PassWeak(const PassWeak& o) + : m_impl(o.leakImpl()) +{ +} + +template<typename T> template<typename U> inline PassWeak<T>::PassWeak(const PassWeak<U>& o) + : m_impl(o.leakImpl()) +{ +} + +template<typename T> inline PassWeak<T>::~PassWeak() +{ + if (!m_impl) + return; + WeakSet::deallocate(m_impl); +} + +template<typename T> inline bool PassWeak<T>::operator!() const +{ + return !m_impl || m_impl->state() != WeakImpl::Live || !m_impl->jsValue(); +} + +template<typename T> inline PassWeak<T>::operator UnspecifiedBoolType*() const +{ + return reinterpret_cast<UnspecifiedBoolType*>(!!*this); +} + +template<typename T> inline PassWeak<T>::PassWeak(WeakImpl* impl) +: m_impl(impl) +{ +} + +template<typename T> inline WeakImpl* PassWeak<T>::leakImpl() const { - HandleSlot slot = this->slot(); - const_cast<PassWeak<T>*>(this)->setSlot(0); - return slot; + WeakImpl* tmp = 0; + std::swap(tmp, const_cast<WeakImpl*&>(m_impl)); + return tmp; } -template<typename T> PassWeak<T> adoptWeak(HandleSlot slot) +template<typename T> PassWeak<T> inline adoptWeak(WeakImpl* impl) { - return PassWeak<T>(slot); + return PassWeak<T>(impl); } template<typename T, typename U> inline bool operator==(const PassWeak<T>& a, const PassWeak<U>& b) diff --git a/Source/JavaScriptCore/heap/SlotVisitor.h b/Source/JavaScriptCore/heap/SlotVisitor.h index 6584db703..01eb219fc 100644 --- a/Source/JavaScriptCore/heap/SlotVisitor.h +++ b/Source/JavaScriptCore/heap/SlotVisitor.h @@ -62,7 +62,6 @@ public: void finalizeUnconditionalFinalizers(); void startCopying(); - void copy(void**, size_t); void copyAndAppend(void**, size_t, JSValue*, unsigned); void doneCopying(); diff --git a/Source/JavaScriptCore/heap/Strong.h b/Source/JavaScriptCore/heap/Strong.h index d2f2a2278..7fafaeab5 100644 --- a/Source/JavaScriptCore/heap/Strong.h +++ b/Source/JavaScriptCore/heap/Strong.h @@ -28,7 +28,7 @@ #include <wtf/Assertions.h> #include "Handle.h" -#include "HandleHeap.h" +#include "HandleSet.h" namespace JSC { @@ -56,7 +56,7 @@ public: { if (!other.slot()) return; - setSlot(HandleHeap::heapFor(other.slot())->allocate()); + setSlot(HandleSet::heapFor(other.slot())->allocate()); set(other.get()); } @@ -65,7 +65,7 @@ public: { if (!other.slot()) return; - setSlot(HandleHeap::heapFor(other.slot())->allocate()); + setSlot(HandleSet::heapFor(other.slot())->allocate()); set(other.get()); } @@ -81,11 +81,19 @@ public: clear(); } + bool operator!() const { return !slot() || !*slot(); } + + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef JSValue (HandleBase::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const { return !!*this ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; } + void swap(Strong& other) { Handle<T>::swap(other); } + ExternalType get() const { return HandleTypes<T>::getFromSlot(this->slot()); } + void set(JSGlobalData&, ExternalType); template <typename U> Strong& operator=(const Strong<U>& other) @@ -95,7 +103,7 @@ public: return *this; } - set(*HandleHeap::heapFor(other.slot())->globalData(), other.get()); + set(*HandleSet::heapFor(other.slot())->globalData(), other.get()); return *this; } @@ -106,7 +114,7 @@ public: return *this; } - set(*HandleHeap::heapFor(other.slot())->globalData(), other.get()); + set(*HandleSet::heapFor(other.slot())->globalData(), other.get()); return *this; } @@ -114,7 +122,7 @@ public: { if (!slot()) return; - HandleHeap::heapFor(slot())->deallocate(slot()); + HandleSet::heapFor(slot())->deallocate(slot()); setSlot(0); } @@ -125,7 +133,7 @@ private: { ASSERT(slot()); JSValue value = HandleTypes<T>::toJSValue(externalType); - HandleHeap::heapFor(slot())->writeBarrier(slot(), value); + HandleSet::heapFor(slot())->writeBarrier(slot(), value); *slot() = value; } }; diff --git a/Source/JavaScriptCore/heap/StrongInlines.h b/Source/JavaScriptCore/heap/StrongInlines.h index 46049096a..2308bf6f6 100644 --- a/Source/JavaScriptCore/heap/StrongInlines.h +++ b/Source/JavaScriptCore/heap/StrongInlines.h @@ -26,18 +26,20 @@ #ifndef StrongInlines_h #define StrongInlines_h +#include "JSGlobalData.h" + namespace JSC { template <typename T> inline Strong<T>::Strong(JSGlobalData& globalData, ExternalType value) - : Handle<T>(globalData.heap.handleHeap()->allocate()) + : Handle<T>(globalData.heap.handleSet()->allocate()) { set(value); } template <typename T> inline Strong<T>::Strong(JSGlobalData& globalData, Handle<T> handle) - : Handle<T>(globalData.heap.handleHeap()->allocate()) + : Handle<T>(globalData.heap.handleSet()->allocate()) { set(handle.get()); } @@ -46,7 +48,7 @@ template <typename T> inline void Strong<T>::set(JSGlobalData& globalData, ExternalType value) { if (!slot()) - setSlot(globalData.heap.handleHeap()->allocate()); + setSlot(globalData.heap.handleSet()->allocate()); set(value); } diff --git a/Source/JavaScriptCore/heap/Weak.h b/Source/JavaScriptCore/heap/Weak.h index 8291e4440..0938249b8 100644 --- a/Source/JavaScriptCore/heap/Weak.h +++ b/Source/JavaScriptCore/heap/Weak.h @@ -27,109 +27,129 @@ #define Weak_h #include <wtf/Assertions.h> -#include "Handle.h" -#include "HandleHeap.h" -#include "JSGlobalData.h" #include "PassWeak.h" +#include "WeakSetInlines.h" namespace JSC { -// A weakly referenced handle that becomes 0 when the value it points to is garbage collected. -template <typename T> class Weak : public Handle<T> { +template<typename T> class Weak : public WeakImplAccessor<Weak<T>, T> { WTF_MAKE_NONCOPYABLE(Weak); - - using Handle<T>::slot; - using Handle<T>::setSlot; - public: - typedef typename Handle<T>::ExternalType ExternalType; - - Weak() - : Handle<T>() - { - } - - Weak(std::nullptr_t) - : Handle<T>() - { - } - - Weak(JSGlobalData& globalData, ExternalType externalType = ExternalType(), WeakHandleOwner* weakOwner = 0, void* context = 0) - : Handle<T>(globalData.heap.handleHeap()->allocate()) - { - HandleHeap::heapFor(slot())->makeWeak(slot(), weakOwner, context); - JSValue value = HandleTypes<T>::toJSValue(externalType); - HandleHeap::heapFor(slot())->writeBarrier(slot(), value); - *slot() = value; - } - - enum AdoptTag { Adopt }; - template<typename U> Weak(AdoptTag, Handle<U> handle) - : Handle<T>(handle.slot()) - { - validateCell(get()); - } + friend class WeakImplAccessor<Weak<T>, T>; + typedef typename WeakImplAccessor<Weak<T>, T>::GetType GetType; + + Weak(); + Weak(std::nullptr_t); + Weak(GetType, WeakHandleOwner* = 0, void* context = 0); enum HashTableDeletedValueTag { HashTableDeletedValue }; - bool isHashTableDeletedValue() const { return slot() == hashTableDeletedValue(); } - Weak(HashTableDeletedValueTag) - : Handle<T>(hashTableDeletedValue()) - { - } - - template<typename U> Weak(const PassWeak<U>& other) - : Handle<T>(other.leakHandle()) - { - } - - ~Weak() - { - clear(); - } - - void swap(Weak& other) - { - Handle<T>::swap(other); - } + bool isHashTableDeletedValue() const; + Weak(HashTableDeletedValueTag); - Weak& operator=(const PassWeak<T>&); + template<typename U> Weak(const PassWeak<U>&); - ExternalType get() const { return HandleTypes<T>::getFromSlot(slot()); } - - PassWeak<T> release() { PassWeak<T> tmp = adoptWeak<T>(slot()); setSlot(0); return tmp; } - - void clear() - { - if (!slot()) - return; - HandleHeap::heapFor(slot())->deallocate(slot()); - setSlot(0); - } + ~Weak(); + + void swap(Weak&); + Weak& operator=(const PassWeak<T>&); - HandleSlot leakHandle() - { - ASSERT(HandleHeap::heapFor(slot())->hasFinalizer(slot())); - HandleSlot result = slot(); - setSlot(0); - return result; - } + bool operator!() const; + // This conversion operator allows implicit conversion to bool but not to other integer types. + typedef JSValue (HandleBase::*UnspecifiedBoolType); + operator UnspecifiedBoolType*() const; + + PassWeak<T> release(); + void clear(); + private: - static HandleSlot hashTableDeletedValue() { return reinterpret_cast<HandleSlot>(-1); } + static WeakImpl* hashTableDeletedValue(); + + WeakImpl* m_impl; }; +template<typename T> inline Weak<T>::Weak() + : m_impl(0) +{ +} + +template<typename T> inline Weak<T>::Weak(std::nullptr_t) + : m_impl(0) +{ +} + +template<typename T> inline Weak<T>::Weak(typename Weak<T>::GetType getType, WeakHandleOwner* weakOwner, void* context) + : m_impl(getType ? WeakSet::allocate(getType, weakOwner, context) : 0) +{ +} + +template<typename T> inline bool Weak<T>::isHashTableDeletedValue() const +{ + return m_impl == hashTableDeletedValue(); +} + +template<typename T> inline Weak<T>::Weak(typename Weak<T>::HashTableDeletedValueTag) + : m_impl(hashTableDeletedValue()) +{ +} + +template<typename T> template<typename U> inline Weak<T>::Weak(const PassWeak<U>& other) + : m_impl(other.leakImpl()) +{ +} + +template<typename T> inline Weak<T>::~Weak() +{ + clear(); +} + template<class T> inline void swap(Weak<T>& a, Weak<T>& b) { a.swap(b); } +template<typename T> inline void Weak<T>::swap(Weak& other) +{ + std::swap(m_impl, other.m_impl); +} + template<typename T> inline Weak<T>& Weak<T>::operator=(const PassWeak<T>& o) { clear(); - setSlot(o.leakHandle()); + m_impl = o.leakImpl(); return *this; } +template<typename T> inline bool Weak<T>::operator!() const +{ + return !m_impl || !m_impl->jsValue() || m_impl->state() != WeakImpl::Live; +} + +template<typename T> inline Weak<T>::operator UnspecifiedBoolType*() const +{ + return reinterpret_cast<UnspecifiedBoolType*>(!!*this); +} + +template<typename T> inline PassWeak<T> Weak<T>::release() +{ + PassWeak<T> tmp = adoptWeak<T>(m_impl); + m_impl = 0; + return tmp; +} + +template<typename T> inline void Weak<T>::clear() +{ + if (!m_impl) + return; + WeakSet::deallocate(m_impl); + m_impl = 0; +} + +template<typename T> inline WeakImpl* Weak<T>::hashTableDeletedValue() +{ + return reinterpret_cast<WeakImpl*>(-1); +} + } // namespace JSC namespace WTF { @@ -151,7 +171,7 @@ template<typename T> struct HashTraits<JSC::Weak<T> > : SimpleClassHashTraits<JS static PassOutType passOut(StorageType& value) { return value.release(); } static PassOutType passOut(EmptyValueType) { return PassOutType(); } - typedef typename StorageType::ExternalType PeekType; + typedef typename StorageType::GetType PeekType; static PeekType peek(const StorageType& value) { return value.get(); } static PeekType peek(EmptyValueType) { return PeekType(); } }; diff --git a/Source/JavaScriptCore/heap/WeakBlock.cpp b/Source/JavaScriptCore/heap/WeakBlock.cpp new file mode 100644 index 000000000..f307e111e --- /dev/null +++ b/Source/JavaScriptCore/heap/WeakBlock.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2012 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 "WeakBlock.h" + +#include "Heap.h" +#include "HeapRootVisitor.h" +#include "JSObject.h" +#include "ScopeChain.h" +#include "Structure.h" + +namespace JSC { + +WeakBlock* WeakBlock::create() +{ + PageAllocation allocation = PageAllocation::allocate(blockSize, OSAllocator::JSGCHeapPages); + if (!static_cast<bool>(allocation)) + CRASH(); + return new (NotNull, allocation.base()) WeakBlock(allocation); +} + +void WeakBlock::destroy(WeakBlock* block) +{ + block->m_allocation.deallocate(); +} + +WeakBlock::WeakBlock(PageAllocation& allocation) + : m_allocation(allocation) +{ + for (size_t i = 0; i < weakImplCount(); ++i) { + WeakImpl* weakImpl = &weakImpls()[i]; + new (NotNull, weakImpl) WeakImpl; + addToFreeList(&m_sweepResult.freeList, weakImpl); + } + + ASSERT(!m_sweepResult.isNull() && m_sweepResult.blockIsFree); +} + +void WeakBlock::finalizeAll() +{ + for (size_t i = 0; i < weakImplCount(); ++i) { + WeakImpl* weakImpl = &weakImpls()[i]; + if (weakImpl->state() >= WeakImpl::Finalized) + continue; + weakImpl->setState(WeakImpl::Dead); + finalize(weakImpl); + } +} + +void WeakBlock::sweep() +{ + if (!m_sweepResult.isNull()) + return; + + SweepResult sweepResult; + for (size_t i = 0; i < weakImplCount(); ++i) { + WeakImpl* weakImpl = &weakImpls()[i]; + if (weakImpl->state() == WeakImpl::Dead) + finalize(weakImpl); + if (weakImpl->state() == WeakImpl::Deallocated) + addToFreeList(&sweepResult.freeList, weakImpl); + else + sweepResult.blockIsFree = false; + } + + m_sweepResult = sweepResult; + ASSERT(!m_sweepResult.isNull()); +} + +void WeakBlock::visitLiveWeakImpls(HeapRootVisitor& heapRootVisitor) +{ + // If a block is completely empty, a visit won't have any effect. + if (!m_sweepResult.isNull() && m_sweepResult.blockIsFree) + return; + + SlotVisitor& visitor = heapRootVisitor.visitor(); + + for (size_t i = 0; i < weakImplCount(); ++i) { + WeakImpl* weakImpl = &weakImpls()[i]; + if (weakImpl->state() != WeakImpl::Live) + continue; + + const JSValue& jsValue = weakImpl->jsValue(); + if (Heap::isMarked(jsValue.asCell())) + continue; + + WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner(); + if (!weakHandleOwner) + continue; + + if (!weakHandleOwner->isReachableFromOpaqueRoots(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(jsValue)), weakImpl->context(), visitor)) + continue; + + heapRootVisitor.visit(&const_cast<JSValue&>(jsValue)); + } +} + +void WeakBlock::visitDeadWeakImpls(HeapRootVisitor&) +{ + // If a block is completely empty, a visit won't have any effect. + if (!m_sweepResult.isNull() && m_sweepResult.blockIsFree) + return; + + for (size_t i = 0; i < weakImplCount(); ++i) { + WeakImpl* weakImpl = &weakImpls()[i]; + if (weakImpl->state() > WeakImpl::Dead) + continue; + + if (Heap::isMarked(weakImpl->jsValue().asCell())) + continue; + + weakImpl->setState(WeakImpl::Dead); + } +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/heap/WeakBlock.h b/Source/JavaScriptCore/heap/WeakBlock.h new file mode 100644 index 000000000..9e546ea32 --- /dev/null +++ b/Source/JavaScriptCore/heap/WeakBlock.h @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2012 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 WeakBlock_h +#define WeakBlock_h + +#include "HeapBlock.h" +#include "WeakHandleOwner.h" +#include "WeakImpl.h" +#include <wtf/DoublyLinkedList.h> +#include <wtf/PageAllocation.h> +#include <wtf/StdLibExtras.h> + +namespace JSC { + +class HeapRootVisitor; +class JSValue; +class WeakHandleOwner; + +class WeakBlock : public DoublyLinkedListNode<WeakBlock> { +public: + friend class WTF::DoublyLinkedListNode<WeakBlock>; + static const size_t blockSize = 4 * KB; + + struct FreeCell { + FreeCell* next; + }; + + struct SweepResult { + SweepResult(); + bool isNull() const; + + bool blockIsFree; + FreeCell* freeList; + }; + + static WeakBlock* create(); + static void destroy(WeakBlock*); + + static WeakImpl* asWeakImpl(FreeCell*); + + void sweep(); + const SweepResult& sweepResult(); + SweepResult takeSweepResult(); + + void visitLiveWeakImpls(HeapRootVisitor&); + void visitDeadWeakImpls(HeapRootVisitor&); + + void finalizeAll(); + +private: + static FreeCell* asFreeCell(WeakImpl*); + + WeakBlock(PageAllocation&); + WeakImpl* firstWeakImpl(); + void finalize(WeakImpl*); + WeakImpl* weakImpls(); + size_t weakImplCount(); + void addToFreeList(FreeCell**, WeakImpl*); + + PageAllocation m_allocation; + WeakBlock* m_prev; + WeakBlock* m_next; + SweepResult m_sweepResult; +}; + +inline WeakBlock::SweepResult::SweepResult() + : blockIsFree(true) + , freeList(0) +{ + ASSERT(isNull()); +} + +inline bool WeakBlock::SweepResult::isNull() const +{ + return blockIsFree && !freeList; // This state is impossible, so we can use it to mean null. +} + +inline WeakImpl* WeakBlock::asWeakImpl(FreeCell* freeCell) +{ + return reinterpret_cast<WeakImpl*>(freeCell); +} + +inline WeakBlock::SweepResult WeakBlock::takeSweepResult() +{ + SweepResult tmp; + std::swap(tmp, m_sweepResult); + ASSERT(m_sweepResult.isNull()); + return tmp; +} + +inline const WeakBlock::SweepResult& WeakBlock::sweepResult() +{ + return m_sweepResult; +} + +inline WeakBlock::FreeCell* WeakBlock::asFreeCell(WeakImpl* weakImpl) +{ + return reinterpret_cast<FreeCell*>(weakImpl); +} + +inline void WeakBlock::finalize(WeakImpl* weakImpl) +{ + ASSERT(weakImpl->state() == WeakImpl::Dead); + weakImpl->setState(WeakImpl::Finalized); + WeakHandleOwner* weakHandleOwner = weakImpl->weakHandleOwner(); + if (!weakHandleOwner) + return; + weakHandleOwner->finalize(Handle<Unknown>::wrapSlot(&const_cast<JSValue&>(weakImpl->jsValue())), weakImpl->context()); +} + +inline WeakImpl* WeakBlock::weakImpls() +{ + return reinterpret_cast<WeakImpl*>(this) + ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl)); +} + +inline size_t WeakBlock::weakImplCount() +{ + return (blockSize / sizeof(WeakImpl)) - ((sizeof(WeakBlock) + sizeof(WeakImpl) - 1) / sizeof(WeakImpl)); +} + +inline void WeakBlock::addToFreeList(FreeCell** freeList, WeakImpl* weakImpl) +{ + ASSERT(weakImpl->state() == WeakImpl::Deallocated); + FreeCell* freeCell = asFreeCell(weakImpl); + ASSERT(!*freeList || ((char*)*freeList > (char*)this && (char*)*freeList < (char*)this + blockSize)); + ASSERT((char*)freeCell > (char*)this && (char*)freeCell < (char*)this + blockSize); + freeCell->next = *freeList; + *freeList = freeCell; +} + +} // namespace JSC + +#endif // WeakBlock_h diff --git a/Source/JavaScriptCore/wtf/PageBlock.cpp b/Source/JavaScriptCore/heap/WeakHandleOwner.cpp index f7c546356..67e1774df 100644 --- a/Source/JavaScriptCore/wtf/PageBlock.cpp +++ b/Source/JavaScriptCore/heap/WeakHandleOwner.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -24,47 +24,24 @@ */ #include "config.h" -#include "PageBlock.h" +#include "WeakHandleOwner.h" -#if OS(UNIX) -#include <unistd.h> -#endif +namespace JSC { -#if OS(WINDOWS) -#include <malloc.h> -#include <windows.h> -#endif +class SlotVisitor; +template<typename T> class Handle; -namespace WTF { - -static size_t s_pageSize; - -#if OS(UNIX) - -inline size_t systemPageSize() +WeakHandleOwner::~WeakHandleOwner() { - return getpagesize(); } -#elif OS(WINDOWS) - -inline size_t systemPageSize() +bool WeakHandleOwner::isReachableFromOpaqueRoots(Handle<Unknown>, void*, SlotVisitor&) { - static size_t size = 0; - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - size = system_info.dwPageSize; - return size; + return false; } -#endif - -size_t pageSize() +void WeakHandleOwner::finalize(Handle<Unknown>, void*) { - if (!s_pageSize) - s_pageSize = systemPageSize(); - ASSERT(isPowerOfTwo(s_pageSize)); - return s_pageSize; } -} // namespace WTF +} // namespace JSC diff --git a/Source/JavaScriptCore/wtf/FixedArray.h b/Source/JavaScriptCore/heap/WeakHandleOwner.h index c67d18cda..6304dd20b 100644 --- a/Source/JavaScriptCore/wtf/FixedArray.h +++ b/Source/JavaScriptCore/heap/WeakHandleOwner.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Apple Inc. All rights reserved. + * Copyright (C) 2012 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,36 +23,22 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef FixedArray_h -#define FixedArray_h +#ifndef WeakHandleOwner_h +#define WeakHandleOwner_h -#include <wtf/Assertions.h> +#include "Handle.h" -namespace WTF { +namespace JSC { -template <typename T, size_t Size> class FixedArray { -public: - T& operator[](size_t i) - { - ASSERT(i < Size); - return m_data[i]; - } - - const T& operator[](size_t i) const - { - ASSERT(i < Size); - return m_data[i]; - } - - T* data() { return m_data; } - size_t size() const { return Size; } +class SlotVisitor; -private: - T m_data[Size]; +class JS_EXPORT_PRIVATE WeakHandleOwner { +public: + virtual ~WeakHandleOwner(); + virtual bool isReachableFromOpaqueRoots(Handle<Unknown>, void* context, SlotVisitor&); + virtual void finalize(Handle<Unknown>, void* context); }; -} // namespace WTF - -using WTF::FixedArray; +} // namespace JSC -#endif // FixedArray_h +#endif // WeakHandleOwner_h diff --git a/Source/JavaScriptCore/heap/WeakImpl.h b/Source/JavaScriptCore/heap/WeakImpl.h new file mode 100644 index 000000000..9924923f9 --- /dev/null +++ b/Source/JavaScriptCore/heap/WeakImpl.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2012 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 WeakImpl_h +#define WeakImpl_h + +#include "JSValue.h" + +namespace JSC { + +class WeakHandleOwner; + +class WeakImpl { +public: + enum State { + Live = 0x0, + Dead = 0x1, + Finalized = 0x2, + Deallocated = 0x3 + }; + + enum { + StateMask = 0x3 + }; + + WeakImpl(); + WeakImpl(JSValue, WeakHandleOwner*, void* context); + + State state(); + void setState(State); + + const JSValue& jsValue(); + WeakHandleOwner* weakHandleOwner(); + void* context(); + + static WeakImpl* asWeakImpl(JSValue*); + +private: + const JSValue m_jsValue; + WeakHandleOwner* m_weakHandleOwner; + void* m_context; +}; + +inline WeakImpl::WeakImpl() + : m_weakHandleOwner(0) + , m_context(0) +{ + setState(Deallocated); +} + +inline WeakImpl::WeakImpl(JSValue jsValue, WeakHandleOwner* weakHandleOwner, void* context) + : m_jsValue(jsValue) + , m_weakHandleOwner(weakHandleOwner) + , m_context(context) +{ + ASSERT(state() == Live); + ASSERT(m_jsValue && m_jsValue.isCell()); +} + +inline WeakImpl::State WeakImpl::state() +{ + return static_cast<State>(reinterpret_cast<uintptr_t>(m_weakHandleOwner) & StateMask); +} + +inline void WeakImpl::setState(WeakImpl::State state) +{ + ASSERT(state >= this->state()); + m_weakHandleOwner = reinterpret_cast<WeakHandleOwner*>((reinterpret_cast<uintptr_t>(m_weakHandleOwner) & ~StateMask) | state); +} + +inline const JSValue& WeakImpl::jsValue() +{ + return m_jsValue; +} + +inline WeakHandleOwner* WeakImpl::weakHandleOwner() +{ + return reinterpret_cast<WeakHandleOwner*>((reinterpret_cast<uintptr_t>(m_weakHandleOwner) & ~StateMask)); +} + +inline void* WeakImpl::context() +{ + return m_context; +} + +inline WeakImpl* WeakImpl::asWeakImpl(JSValue* slot) +{ + return reinterpret_cast<WeakImpl*>(reinterpret_cast<char*>(slot) + OBJECT_OFFSETOF(WeakImpl, m_jsValue)); +} + +} // namespace JSC + +#endif // WeakImpl_h diff --git a/Source/JavaScriptCore/heap/WeakSet.cpp b/Source/JavaScriptCore/heap/WeakSet.cpp new file mode 100644 index 000000000..d9c773cef --- /dev/null +++ b/Source/JavaScriptCore/heap/WeakSet.cpp @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2012 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 "WeakSet.h" + +#include "Heap.h" + +namespace JSC { + +WeakSet::~WeakSet() +{ + WeakBlock* next = 0; + for (WeakBlock* block = m_blocks.head(); block; block = next) { + next = block->next(); + WeakBlock::destroy(block); + } + m_blocks.clear(); +} + +void WeakSet::finalizeAll() +{ + for (WeakBlock* block = m_blocks.head(); block; block = block->next()) + block->finalizeAll(); +} + +void WeakSet::visitLiveWeakImpls(HeapRootVisitor& visitor) +{ + for (WeakBlock* block = m_blocks.head(); block; block = block->next()) + block->visitLiveWeakImpls(visitor); +} + +void WeakSet::visitDeadWeakImpls(HeapRootVisitor& visitor) +{ + for (WeakBlock* block = m_blocks.head(); block; block = block->next()) + block->visitDeadWeakImpls(visitor); +} + +void WeakSet::sweep() +{ + WeakBlock* next; + for (WeakBlock* block = m_blocks.head(); block; block = next) { + next = block->next(); + + // If a block is completely empty, a new sweep won't have any effect. + if (!block->sweepResult().isNull() && block->sweepResult().blockIsFree) + continue; + + block->takeSweepResult(); // Force a new sweep by discarding the last sweep. + block->sweep(); + } +} + +void WeakSet::shrink() +{ + WeakBlock* next; + for (WeakBlock* block = m_blocks.head(); block; block = next) { + next = block->next(); + + if (!block->sweepResult().isNull() && block->sweepResult().blockIsFree) + removeAllocator(block); + } +} + +void WeakSet::resetAllocator() +{ + m_allocator = 0; + m_nextAllocator = m_blocks.head(); +} + +WeakBlock::FreeCell* WeakSet::findAllocator() +{ + if (WeakBlock::FreeCell* allocator = tryFindAllocator()) + return allocator; + + return addAllocator(); +} + +WeakBlock::FreeCell* WeakSet::tryFindAllocator() +{ + while (m_nextAllocator) { + WeakBlock* block = m_nextAllocator; + m_nextAllocator = m_nextAllocator->next(); + + block->sweep(); + WeakBlock::SweepResult sweepResult = block->takeSweepResult(); + if (sweepResult.freeList) + return sweepResult.freeList; + } + + return 0; +} + +WeakBlock::FreeCell* WeakSet::addAllocator() +{ + WeakBlock* block = WeakBlock::create(); + m_heap->didAllocate(WeakBlock::blockSize); + m_blocks.append(block); + WeakBlock::SweepResult sweepResult = block->takeSweepResult(); + ASSERT(!sweepResult.isNull() && sweepResult.freeList); + return sweepResult.freeList; +} + +void WeakSet::removeAllocator(WeakBlock* block) +{ + m_blocks.remove(block); + WeakBlock::destroy(block); +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/wtf/SinglyLinkedList.h b/Source/JavaScriptCore/heap/WeakSet.h index c00bf3687..0a683bd5f 100644 --- a/Source/JavaScriptCore/wtf/SinglyLinkedList.h +++ b/Source/JavaScriptCore/heap/WeakSet.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2012 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,50 +23,57 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef SinglyLinkedList_h -#define SinglyLinkedList_h +#ifndef WeakSet_h +#define WeakSet_h -namespace WTF { +#include "WeakBlock.h" -template <typename Node> class SinglyLinkedList { +namespace JSC { + +class Heap; +class WeakImpl; + +class WeakSet { public: - SinglyLinkedList(); - - bool isEmpty(); + WeakSet(Heap*); + void finalizeAll(); + ~WeakSet(); - void push(Node*); - Node* pop(); + static WeakImpl* allocate(JSValue, WeakHandleOwner* = 0, void* context = 0); + static void deallocate(WeakImpl*); -private: - Node* m_head; -}; + void visitLiveWeakImpls(HeapRootVisitor&); + void visitDeadWeakImpls(HeapRootVisitor&); -template <typename Node> inline SinglyLinkedList<Node>::SinglyLinkedList() - : m_head(0) -{ -} + void sweep(); + void resetAllocator(); -template <typename Node> inline bool SinglyLinkedList<Node>::isEmpty() -{ - return !m_head; -} + void shrink(); -template <typename Node> inline void SinglyLinkedList<Node>::push(Node* node) -{ - ASSERT(node); - node->setNext(m_head); - m_head = node; -} +private: + JS_EXPORT_PRIVATE WeakBlock::FreeCell* findAllocator(); + WeakBlock::FreeCell* tryFindAllocator(); + WeakBlock::FreeCell* addAllocator(); + void removeAllocator(WeakBlock*); -template <typename Node> inline Node* SinglyLinkedList<Node>::pop() + WeakBlock::FreeCell* m_allocator; + WeakBlock* m_nextAllocator; + DoublyLinkedList<WeakBlock> m_blocks; + Heap* m_heap; +}; + +inline WeakSet::WeakSet(Heap* heap) + : m_allocator(0) + , m_nextAllocator(0) + , m_heap(heap) { - Node* tmp = m_head; - m_head = m_head->next(); - return tmp; } +inline void WeakSet::deallocate(WeakImpl* weakImpl) +{ + weakImpl->setState(WeakImpl::Deallocated); } -using WTF::SinglyLinkedList; +} // namespace JSC -#endif +#endif // WeakSet_h diff --git a/Source/JavaScriptCore/wtf/threads/BinarySemaphore.h b/Source/JavaScriptCore/heap/WeakSetInlines.h index 8e82207e9..0515904fc 100644 --- a/Source/JavaScriptCore/wtf/threads/BinarySemaphore.h +++ b/Source/JavaScriptCore/heap/WeakSetInlines.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010, 2011 Apple Inc. All rights reserved. + * Copyright (C) 2012 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,41 +23,25 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef BinarySemaphore_h -#define BinarySemaphore_h +#ifndef WeakSetInlines_h +#define WeakSetInlines_h -#include <wtf/Noncopyable.h> -#include <wtf/ThreadingPrimitives.h> +#include "WeakSet.h" -namespace WTF { +namespace JSC { -class BinarySemaphore { - WTF_MAKE_NONCOPYABLE(BinarySemaphore); +inline WeakImpl* WeakSet::allocate(JSValue jsValue, WeakHandleOwner* weakHandleOwner, void* context) +{ + WeakSet& weakSet = *Heap::heap(jsValue.asCell())->weakSet(); + WeakBlock::FreeCell* allocator = weakSet.m_allocator; + if (UNLIKELY(!allocator)) + allocator = weakSet.findAllocator(); + weakSet.m_allocator = allocator->next; -public: - BinarySemaphore(); - ~BinarySemaphore(); + WeakImpl* weakImpl = WeakBlock::asWeakImpl(allocator); + return new (NotNull, weakImpl) WeakImpl(jsValue, weakHandleOwner, context); +} - void signal(); - bool wait(double absoluteTime); +} // namespace JSC -#if PLATFORM(WIN) - HANDLE event() const { return m_event; } -#endif - -private: -#if PLATFORM(WIN) - HANDLE m_event; -#else - bool m_isSet; - - Mutex m_mutex; - ThreadCondition m_condition; -#endif -}; - -} // namespace WTF - -using WTF::BinarySemaphore; - -#endif // BinarySemaphore_h +#endif // WeakSetInlines_h diff --git a/Source/JavaScriptCore/interpreter/CallFrame.cpp b/Source/JavaScriptCore/interpreter/CallFrame.cpp index b0e5ea0f6..a5ffaee8d 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.cpp +++ b/Source/JavaScriptCore/interpreter/CallFrame.cpp @@ -81,7 +81,7 @@ bool CallFrame::isInlineCallFrameSlow() JSCell* calleeAsFunctionCell = getJSFunction(callee()); if (!calleeAsFunctionCell) return false; - JSFunction* calleeAsFunction = asFunction(calleeAsFunctionCell); + JSFunction* calleeAsFunction = jsCast<JSFunction*>(calleeAsFunctionCell); return calleeAsFunction->executable() != codeBlock()->ownerExecutable(); } @@ -183,4 +183,11 @@ CallFrame* CallFrame::trueCallerFrame() } #endif +Register* CallFrame::frameExtentInternal() +{ + CodeBlock* codeBlock = this->codeBlock(); + ASSERT(codeBlock); + return registers() + codeBlock->m_numCalleeRegisters; +} + } diff --git a/Source/JavaScriptCore/interpreter/CallFrame.h b/Source/JavaScriptCore/interpreter/CallFrame.h index 5bf2b9488..4ec3de7f3 100644 --- a/Source/JavaScriptCore/interpreter/CallFrame.h +++ b/Source/JavaScriptCore/interpreter/CallFrame.h @@ -125,6 +125,15 @@ namespace JSC { } #endif + Register* frameExtent() + { + if (!codeBlock()) + return registers(); + return frameExtentInternal(); + } + + Register* frameExtentInternal(); + #if ENABLE(DFG_JIT) InlineCallFrame* inlineCallFrame() const { return this[RegisterFile::ReturnPC].asInlineCallFrame(); } unsigned codeOriginIndexForDFG() const { return this[RegisterFile::ArgumentCount].tag(); } diff --git a/Source/JavaScriptCore/interpreter/Interpreter.cpp b/Source/JavaScriptCore/interpreter/Interpreter.cpp index a74d3de89..1cd5719ff 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.cpp +++ b/Source/JavaScriptCore/interpreter/Interpreter.cpp @@ -45,7 +45,6 @@ #include "JSActivation.h" #include "JSArray.h" #include "JSBoundFunction.h" -#include "JSByteArray.h" #include "JSNotAnObject.h" #include "JSPropertyNameIterator.h" #include "LiteralParser.h" @@ -65,6 +64,7 @@ #include <limits.h> #include <stdio.h> #include <wtf/Threading.h> +#include <wtf/text/StringBuilder.h> #if ENABLE(JIT) #include "JIT.h" @@ -421,7 +421,8 @@ JSValue eval(CallFrame* callFrame) JSValue program = callFrame->argument(0); if (!program.isString()) return program; - + + TopCallFrameSetter topCallFrame(callFrame->globalData(), callFrame); UString programSource = asString(program)->value(callFrame); if (callFrame->hadException()) return JSValue(); @@ -952,14 +953,14 @@ static StackFrameCodeType getStackFrameCodeType(CallFrame* callFrame) return StackFrameGlobalCode; } -void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<StackFrame>& results) +void Interpreter::getStackTrace(JSGlobalData* globalData, Vector<StackFrame>& results) { - CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag()->trueCallFrameFromVMCode(); + CallFrame* callFrame = globalData->topCallFrame->removeHostCallFrameFlag(); if (!callFrame || callFrame == CallFrame::noCaller()) return; + int line = getLineNumberForCallFrame(globalData, callFrame); - if (line == -1) - line = getLineNumberForCallFrame(globalData, callFrame); + callFrame = callFrame->trueCallFrameFromVMCode(); while (callFrame && callFrame != CallFrame::noCaller()) { UString sourceURL; @@ -975,11 +976,46 @@ void Interpreter::getStackTrace(JSGlobalData* globalData, int line, Vector<Stack } } +void Interpreter::addStackTraceIfNecessary(CallFrame* callFrame, JSObject* error) +{ + JSGlobalData* globalData = &callFrame->globalData(); + ASSERT(callFrame == globalData->topCallFrame || callFrame == callFrame->lexicalGlobalObject()->globalExec() || callFrame == callFrame->dynamicGlobalObject()->globalExec()); + if (error->hasProperty(callFrame, globalData->propertyNames->stack)) + return; + + Vector<StackFrame> stackTrace; + getStackTrace(&callFrame->globalData(), stackTrace); + + if (stackTrace.isEmpty()) + return; + + JSGlobalObject* globalObject = 0; + if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error)) + globalObject = globalData->dynamicGlobalObject; + else + globalObject = error->globalObject(); + StringBuilder builder; + for (unsigned i = 0; i < stackTrace.size(); i++) { + builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl())); + if (i != stackTrace.size() - 1) + builder.append('\n'); + } + + error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, UString(builder.toString().impl())), ReadOnly | DontDelete); +} + NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSValue& exceptionValue, unsigned bytecodeOffset) { CodeBlock* codeBlock = callFrame->codeBlock(); bool isInterrupt = false; + ASSERT(!exceptionValue.isEmpty()); + ASSERT(!exceptionValue.isCell() || exceptionValue.asCell()); + // This shouldn't be possible (hence the assertions), but we're already in the slowest of + // slow cases, so let's harden against it anyway to be safe. + if (exceptionValue.isEmpty() || (exceptionValue.isCell() && !exceptionValue.asCell())) + exceptionValue = jsNull(); + // Set up the exception object if (exceptionValue.isObject()) { JSObject* exception = asObject(exceptionValue); @@ -990,12 +1026,9 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV // Using hasExpressionInfo to imply we are interested in rich exception info. if (codeBlock->hasExpressionInfo() && !hasErrorInfo(callFrame, exception)) { ASSERT(codeBlock->hasLineInfo()); - // FIXME: should only really be adding these properties to VM generated exceptions, // but the inspector currently requires these for all thrown objects. - Vector<StackFrame> stackTrace; - getStackTrace(&callFrame->globalData(), codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), stackTrace); - addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source(), stackTrace); + addErrorInfo(callFrame, exception, codeBlock->lineNumberForBytecodeOffset(bytecodeOffset), codeBlock->ownerExecutable()->source()); } isInterrupt = isInterruptedExecutionException(exception) || isTerminatedExecutionException(exception); @@ -1013,9 +1046,11 @@ NEVER_INLINE HandlerInfo* Interpreter::throwException(CallFrame*& callFrame, JSV if (!unwindCallFrame(callFrame, exceptionValue, bytecodeOffset, codeBlock)) { if (Profiler* profiler = *Profiler::enabledProfilerReference()) profiler->exceptionUnwind(callFrame); + callFrame->globalData().topCallFrame = callFrame; return 0; } } + callFrame->globalData().topCallFrame = callFrame; if (Profiler* profiler = *Profiler::enabledProfilerReference()) profiler->exceptionUnwind(callFrame); @@ -1223,6 +1258,7 @@ JSValue Interpreter::executeCall(CallFrame* callFrame, JSObject* function, CallT return checkedReturn(throwStackOverflowError(callFrame)); Register* oldEnd = m_registerFile.end(); + ASSERT(callFrame->frameExtent() <= oldEnd || callFrame == callFrame->scopeChain()->globalObject->globalExec()); int argCount = 1 + args.size(); // implicit "this" parameter size_t registerOffset = argCount + RegisterFile::CallFrameHeaderSize; @@ -1514,7 +1550,7 @@ JSValue Interpreter::execute(EvalExecutable* eval, CallFrame* callFrame, JSValue for (ScopeChainNode* node = scopeChain; ; node = node->next.get()) { ASSERT(node); if (node->object->isVariableObject() && !node->object->isStaticScopeObject()) { - variableObject = static_cast<JSVariableObject*>(node->object.get()); + variableObject = jsCast<JSVariableObject*>(node->object.get()); break; } } @@ -1831,6 +1867,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* } + StructureChain* prototypeChain = structure->prototypeChain(callFrame); switch (slot.cachedPropertyType()) { case PropertySlot::Getter: vPC[0] = getOpcode(op_get_by_id_getter_chain); @@ -1846,7 +1883,7 @@ NEVER_INLINE void Interpreter::tryCacheGetByID(CallFrame* callFrame, CodeBlock* break; } vPC[4].u.structure.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure); - vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), structure->prototypeChain(callFrame)); + vPC[5].u.structureChain.set(callFrame->globalData(), codeBlock->ownerExecutable(), prototypeChain); vPC[6] = count; } @@ -2352,7 +2389,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = vPC[1].u.operand; JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow + if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() + src2.asInt32()); else { JSValue result = jsAdd(callFrame, src1, src2); @@ -2371,7 +2408,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = vPC[1].u.operand; JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32() >> 15)) // no overflow + if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | src2.asInt32()) >> 15) // no overflow callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() * src2.asInt32()); else { JSValue result = jsNumber(src1.toNumber(callFrame) * src2.toNumber(callFrame)); @@ -2439,7 +2476,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi int dst = vPC[1].u.operand; JSValue src1 = callFrame->r(vPC[2].u.operand).jsValue(); JSValue src2 = callFrame->r(vPC[3].u.operand).jsValue(); - if (src1.isInt32() && src2.isInt32() && !(src1.asInt32() | (src2.asInt32() & 0xc0000000))) // no overflow + if (src1.isInt32() && src2.isInt32() && !((src1.asInt32() | src2.asInt32()) & 0xc0000000)) // no overflow callFrame->uncheckedR(dst) = jsNumber(src1.asInt32() - src2.asInt32()); else { JSValue result = jsNumber(src1.toNumber(callFrame) - src2.toNumber(callFrame)); @@ -2883,7 +2920,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi ASSERT_UNUSED(end, iter != end); } ASSERT((*iter)->isVariableObject()); - JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get()); + JSVariableObject* scope = jsCast<JSVariableObject*>(iter->get()); callFrame->uncheckedR(dst) = scope->registerAt(index).get(); ASSERT(callFrame->r(dst).jsValue()); vPC += OPCODE_LENGTH(op_get_scoped_var); @@ -2914,7 +2951,7 @@ JSValue Interpreter::privateExecute(ExecutionFlag flag, RegisterFile* registerFi } ASSERT((*iter)->isVariableObject()); - JSVariableObject* scope = static_cast<JSVariableObject*>(iter->get()); + JSVariableObject* scope = jsCast<JSVariableObject*>(iter->get()); ASSERT(callFrame->r(value).jsValue()); scope->registerAt(index).set(*globalData, scope, callFrame->r(value).jsValue()); vPC += OPCODE_LENGTH(op_put_scoped_var); @@ -3738,8 +3775,6 @@ skip_id_custom_self: result = jsArray->JSArray::get(callFrame, i); } else if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) result = asString(baseValue)->getIndex(callFrame, i); - else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) - result = asByteArray(baseValue)->getIndex(callFrame, i); else result = baseValue.get(callFrame, i); } else { @@ -3778,15 +3813,6 @@ skip_id_custom_self: jsArray->setIndex(*globalData, i, callFrame->r(value).jsValue()); else jsArray->JSArray::putByIndex(jsArray, callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode()); - } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { - JSByteArray* jsByteArray = asByteArray(baseValue); - JSValue jsValue = callFrame->r(value).jsValue(); - if (jsValue.isInt32()) - jsByteArray->setIndex(i, jsValue.asInt32()); - else if (jsValue.isDouble()) - jsByteArray->setIndex(i, jsValue.asDouble()); - else - baseValue.putByIndex(callFrame, i, jsValue, codeBlock->isStrictMode()); } else baseValue.putByIndex(callFrame, i, callFrame->r(value).jsValue(), codeBlock->isStrictMode()); } else { @@ -4443,7 +4469,7 @@ skip_id_custom_self: if (isHostFunction(funcVal, globalFuncEval)) { CallFrame* newCallFrame = CallFrame::create(callFrame->registers() + registerOffset); - newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_eval), callFrame->scopeChain(), callFrame, argCount, asFunction(funcVal)); + newCallFrame->init(0, vPC + OPCODE_LENGTH(op_call_eval), callFrame->scopeChain(), callFrame, argCount, jsCast<JSFunction*>(funcVal)); JSValue result = eval(newCallFrame); if ((exceptionValue = globalData->exception)) @@ -4496,7 +4522,7 @@ skip_id_custom_self: goto vm_throw; } - callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, asFunction(v)); + callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call), callDataScopeChain, previousCallFrame, argCount, jsCast<JSFunction*>(v)); codeBlock = newCodeBlock; ASSERT(codeBlock == callFrame->codeBlock()); *topCallFrameSlot = callFrame; @@ -4574,7 +4600,7 @@ skip_id_custom_self: goto vm_throw; } - newCallFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, callFrame, argCount, asFunction(v)); + newCallFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_call_varargs), callDataScopeChain, callFrame, argCount, jsCast<JSFunction*>(v)); codeBlock = newCodeBlock; callFrame = newCallFrame; ASSERT(codeBlock == callFrame->codeBlock()); @@ -4785,7 +4811,7 @@ skip_id_custom_self: int thisRegister = vPC[1].u.operand; int protoRegister = vPC[2].u.operand; - JSFunction* constructor = asFunction(callFrame->callee()); + JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee()); #if !ASSERT_DISABLED ConstructData constructData; ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS); @@ -4895,7 +4921,7 @@ skip_id_custom_self: goto vm_throw; } - callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, asFunction(v)); + callFrame->init(newCodeBlock, vPC + OPCODE_LENGTH(op_construct), callDataScopeChain, previousCallFrame, argCount, jsCast<JSFunction*>(v)); codeBlock = newCodeBlock; *topCallFrameSlot = callFrame; vPC = newCodeBlock->instructions().begin(); @@ -5186,30 +5212,6 @@ skip_id_custom_self: vPC++; NEXT_INSTRUCTION(); } - DEFINE_OPCODE(op_jsr) { - /* jsr retAddrDst(r) target(offset) - - Places the address of the next instruction into the retAddrDst - register and jumps to offset target from the current instruction. - */ - int retAddrDst = vPC[1].u.operand; - int target = vPC[2].u.operand; - callFrame->r(retAddrDst) = vPC + OPCODE_LENGTH(op_jsr); - - vPC += target; - NEXT_INSTRUCTION(); - } - DEFINE_OPCODE(op_sret) { - /* sret retAddrSrc(r) - - Jumps to the address stored in the retAddrSrc register. This - differs from op_jmp because the target address is stored in a - register, not as an immediate. - */ - int retAddrSrc = vPC[1].u.operand; - vPC = callFrame->r(retAddrSrc).vPC(); - NEXT_INSTRUCTION(); - } DEFINE_OPCODE(op_debug) { /* debug debugHookID(n) firstLine(n) lastLine(n) diff --git a/Source/JavaScriptCore/interpreter/Interpreter.h b/Source/JavaScriptCore/interpreter/Interpreter.h index 51881a565..adb23f237 100644 --- a/Source/JavaScriptCore/interpreter/Interpreter.h +++ b/Source/JavaScriptCore/interpreter/Interpreter.h @@ -222,7 +222,8 @@ namespace JSC { NEVER_INLINE HandlerInfo* throwException(CallFrame*&, JSValue&, unsigned bytecodeOffset); NEVER_INLINE void debug(CallFrame*, DebugHookID, int firstLine, int lastLine); static const UString getTraceLine(CallFrame*, StackFrameCodeType, const UString&, int); - JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, int line, Vector<StackFrame>& results); + JS_EXPORT_PRIVATE static void getStackTrace(JSGlobalData*, Vector<StackFrame>& results); + static void addStackTraceIfNecessary(CallFrame*, JSObject* error); void dumpSampleData(ExecState* exec); void startSampling(); diff --git a/Source/JavaScriptCore/interpreter/Register.h b/Source/JavaScriptCore/interpreter/Register.h index f3b2125cb..a4a76b865 100644 --- a/Source/JavaScriptCore/interpreter/Register.h +++ b/Source/JavaScriptCore/interpreter/Register.h @@ -86,7 +86,7 @@ namespace JSC { return r; } - static inline Register withCallee(JSObject* callee); + static Register withCallee(JSObject* callee); private: union { diff --git a/Source/JavaScriptCore/jit/ExecutableAllocator.cpp b/Source/JavaScriptCore/jit/ExecutableAllocator.cpp index 5912f8652..e30c892e3 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocator.cpp +++ b/Source/JavaScriptCore/jit/ExecutableAllocator.cpp @@ -29,7 +29,6 @@ #if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) #include "CodeProfiling.h" -#include <wtf/DataLog.h> #include <wtf/HashSet.h> #include <wtf/MetaAllocator.h> #include <wtf/PageReservation.h> @@ -197,16 +196,21 @@ bool ExecutableAllocator::underMemoryPressure() double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage) { + double result; #ifdef EXECUTABLE_MEMORY_LIMIT size_t bytesAllocated = DemandExecutableAllocator::bytesAllocatedByAllAllocators() + addedMemoryUsage; if (bytesAllocated >= EXECUTABLE_MEMORY_LIMIT) bytesAllocated = EXECUTABLE_MEMORY_LIMIT; - return static_cast<double>(EXECUTABLE_MEMORY_LIMIT) / + result = static_cast<double>(EXECUTABLE_MEMORY_LIMIT) / (EXECUTABLE_MEMORY_LIMIT - bytesAllocated); #else UNUSED_PARAM(addedMemoryUsage); - return 1.0; + result = 1.0; #endif + if (result < 1.0) + result = 1.0; + return result; + } PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData&, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort) diff --git a/Source/JavaScriptCore/jit/ExecutableAllocator.h b/Source/JavaScriptCore/jit/ExecutableAllocator.h index 8a14ac67e..1ddf011cb 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocator.h +++ b/Source/JavaScriptCore/jit/ExecutableAllocator.h @@ -94,7 +94,7 @@ namespace JSC { typedef WTF::MetaAllocatorHandle ExecutableMemoryHandle; -#if ENABLE(JIT) && ENABLE(ASSEMBLER) +#if ENABLE(ASSEMBLER) #if ENABLE(EXECUTABLE_ALLOCATOR_DEMAND) class DemandExecutableAllocator; @@ -194,18 +194,24 @@ public: #elif CPU(ARM_TRADITIONAL) && OS(LINUX) && COMPILER(GCC) static void cacheFlush(void* code, size_t size) { - asm volatile ( - "push {r7}\n" - "mov r0, %0\n" - "mov r1, %1\n" - "mov r7, #0xf0000\n" - "add r7, r7, #0x2\n" - "mov r2, #0x0\n" - "svc 0x0\n" - "pop {r7}\n" - : - : "r" (code), "r" (reinterpret_cast<char*>(code) + size) - : "r0", "r1", "r2"); + uintptr_t currentPage = reinterpret_cast<uintptr_t>(code) & ~(pageSize() - 1); + uintptr_t lastPage = (reinterpret_cast<uintptr_t>(code) + size) & ~(pageSize() - 1); + + do { + asm volatile ( + "push {r7}\n" + "mov r0, %0\n" + "mov r1, %1\n" + "mov r7, #0xf0000\n" + "add r7, r7, #0x2\n" + "mov r2, #0x0\n" + "svc 0x0\n" + "pop {r7}\n" + : + : "r" (currentPage), "r" (currentPage + pageSize()) + : "r0", "r1", "r2"); + currentPage += pageSize(); + } while (lastPage >= currentPage); } #elif OS(WINCE) static void cacheFlush(void* code, size_t size) diff --git a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp index 959ea744b..b4422c3df 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp +++ b/Source/JavaScriptCore/jit/ExecutableAllocatorFixedVMPool.cpp @@ -59,7 +59,7 @@ public: : MetaAllocator(32) // round up all allocations to 32 bytes { m_reservation = PageReservation::reserveWithGuardPages(fixedPoolSize, OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true); -#if !ENABLE(CLASSIC_INTERPRETER) +#if !(ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) if (!m_reservation) CRASH(); #endif @@ -126,8 +126,13 @@ double ExecutableAllocator::memoryPressureMultiplier(size_t addedMemoryUsage) size_t bytesAllocated = statistics.bytesAllocated + addedMemoryUsage; if (bytesAllocated >= statistics.bytesReserved) bytesAllocated = statistics.bytesReserved; - return static_cast<double>(statistics.bytesReserved) / - (statistics.bytesReserved - bytesAllocated); + double result = 1.0; + size_t divisor = statistics.bytesReserved - bytesAllocated; + if (divisor) + result = static_cast<double>(statistics.bytesReserved) / divisor; + if (result < 1.0) + result = 1.0; + return result; } PassRefPtr<ExecutableMemoryHandle> ExecutableAllocator::allocate(JSGlobalData& globalData, size_t sizeInBytes, void* ownerUID, JITCompilationEffort effort) diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp index 541cc896a..01b1260c9 100644 --- a/Source/JavaScriptCore/jit/JIT.cpp +++ b/Source/JavaScriptCore/jit/JIT.cpp @@ -229,12 +229,8 @@ void JIT::privateCompileMainPass() DEFINE_BINARY_OP(op_lesseq) DEFINE_BINARY_OP(op_greater) DEFINE_BINARY_OP(op_greatereq) - DEFINE_UNARY_OP(op_is_boolean) DEFINE_UNARY_OP(op_is_function) - DEFINE_UNARY_OP(op_is_number) DEFINE_UNARY_OP(op_is_object) - DEFINE_UNARY_OP(op_is_string) - DEFINE_UNARY_OP(op_is_undefined) DEFINE_UNARY_OP(op_typeof) DEFINE_OP(op_add) @@ -269,6 +265,10 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_get_scoped_var) DEFINE_OP(op_check_has_instance) DEFINE_OP(op_instanceof) + DEFINE_OP(op_is_undefined) + DEFINE_OP(op_is_boolean) + DEFINE_OP(op_is_number) + DEFINE_OP(op_is_string) DEFINE_OP(op_jeq_null) DEFINE_OP(op_jfalse) DEFINE_OP(op_jmp) @@ -283,7 +283,6 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_jnlesseq) DEFINE_OP(op_jngreater) DEFINE_OP(op_jngreatereq) - DEFINE_OP(op_jsr) DEFINE_OP(op_jtrue) DEFINE_OP(op_loop) DEFINE_OP(op_loop_hint) @@ -340,7 +339,6 @@ void JIT::privateCompileMainPass() DEFINE_OP(op_ret_object_or_this) DEFINE_OP(op_rshift) DEFINE_OP(op_urshift) - DEFINE_OP(op_sret) DEFINE_OP(op_strcat) DEFINE_OP(op_stricteq) DEFINE_OP(op_sub) @@ -519,6 +517,48 @@ void JIT::privateCompileSlowCases() #endif } +ALWAYS_INLINE void PropertyStubCompilationInfo::copyToStubInfo(StructureStubInfo& info, LinkBuffer &linkBuffer) +{ + ASSERT(bytecodeIndex != std::numeric_limits<unsigned>::max()); + info.bytecodeIndex = bytecodeIndex; + info.callReturnLocation = linkBuffer.locationOf(callReturnLocation); + info.hotPathBegin = linkBuffer.locationOf(hotPathBegin); + + switch (m_type) { + case MethodCheck: { + CodeLocationDataLabelPtr structureToCompareLocation = linkBuffer.locationOf(methodCheckStructureToCompare); + info.patch.baseline.methodCheckProtoObj = MacroAssembler::differenceBetweenCodePtr(structureToCompareLocation, linkBuffer.locationOf(methodCheckProtoObj)); + info.patch.baseline.methodCheckProtoStructureToCompare = MacroAssembler::differenceBetweenCodePtr(structureToCompareLocation, linkBuffer.locationOf(methodCheckProtoStructureToCompare)); + info.patch.baseline.methodCheckPutFunction = MacroAssembler::differenceBetweenCodePtr(structureToCompareLocation, linkBuffer.locationOf(methodCheckPutFunction)); + // No break - fall through to GetById. + } + case GetById: { + CodeLocationLabel hotPathBeginLocation = linkBuffer.locationOf(hotPathBegin); + info.patch.baseline.u.get.structureToCompare = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getStructureToCompare)); + info.patch.baseline.u.get.structureCheck = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getStructureCheck)); +#if USE(JSVALUE64) + info.patch.baseline.u.get.displacementLabel = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getDisplacementLabel)); +#else + info.patch.baseline.u.get.displacementLabel1 = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getDisplacementLabel1)); + info.patch.baseline.u.get.displacementLabel2 = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getDisplacementLabel2)); +#endif + info.patch.baseline.u.get.putResult = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(getPutResult)); + info.patch.baseline.u.get.coldPathBegin = MacroAssembler::differenceBetweenCodePtr(linkBuffer.locationOf(getColdPathBegin), linkBuffer.locationOf(callReturnLocation)); + break; + } + case PutById: + CodeLocationLabel hotPathBeginLocation = linkBuffer.locationOf(hotPathBegin); + info.patch.baseline.u.put.structureToCompare = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(putStructureToCompare)); +#if USE(JSVALUE64) + info.patch.baseline.u.put.displacementLabel = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(putDisplacementLabel)); +#else + info.patch.baseline.u.put.displacementLabel1 = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(putDisplacementLabel1)); + info.patch.baseline.u.put.displacementLabel2 = MacroAssembler::differenceBetweenCodePtr(hotPathBeginLocation, linkBuffer.locationOf(putDisplacementLabel2)); +#endif + break; + } +} + JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffort effort) { #if ENABLE(JIT_VERBOSE_OSR) @@ -665,18 +705,9 @@ JITCode JIT::privateCompile(CodePtr* functionEntryArityCheck, JITCompilationEffo m_codeBlock->callReturnIndexVector().append(CallReturnOffsetToBytecodeOffset(patchBuffer.returnAddressOffset(iter->from), iter->bytecodeOffset)); } - // Link absolute addresses for jsr - for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter) - patchBuffer.patch(iter->storeLocation, patchBuffer.locationOf(iter->target).executableAddress()); - m_codeBlock->setNumberOfStructureStubInfos(m_propertyAccessCompilationInfo.size()); - for (unsigned i = 0; i < m_propertyAccessCompilationInfo.size(); ++i) { - StructureStubInfo& info = m_codeBlock->structureStubInfo(i); - ASSERT(m_propertyAccessCompilationInfo[i].bytecodeIndex != std::numeric_limits<unsigned>::max()); - info.bytecodeIndex = m_propertyAccessCompilationInfo[i].bytecodeIndex; - info.callReturnLocation = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].callReturnLocation); - info.hotPathBegin = patchBuffer.locationOf(m_propertyAccessCompilationInfo[i].hotPathBegin); - } + for (unsigned i = 0; i < m_propertyAccessCompilationInfo.size(); ++i) + m_propertyAccessCompilationInfo[i].copyToStubInfo(m_codeBlock->structureStubInfo(i), patchBuffer); m_codeBlock->setNumberOfCallLinkInfos(m_callStructureStubCompilationInfo.size()); for (unsigned i = 0; i < m_codeBlock->numberOfCallLinkInfos(); ++i) { CallLinkInfo& info = m_codeBlock->callLinkInfo(i); diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h index 2d2841baf..af5076fb5 100644 --- a/Source/JavaScriptCore/jit/JIT.h +++ b/Source/JavaScriptCore/jit/JIT.h @@ -41,7 +41,6 @@ #define JIT_CLASS_ALIGNMENT #endif -#define ASSERT_JIT_OFFSET_UNUSED(variable, actual, expected) ASSERT_WITH_MESSAGE_UNUSED(variable, actual == expected, "JIT Offset \"%s\" should be %d, not %d.\n", #expected, static_cast<int>(expected), static_cast<int>(actual)); #define ASSERT_JIT_OFFSET(actual, expected) ASSERT_WITH_MESSAGE(actual == expected, "JIT Offset \"%s\" should be %d, not %d.\n", #expected, static_cast<int>(expected), static_cast<int>(actual)); #include "CodeBlock.h" @@ -147,17 +146,108 @@ namespace JSC { } }; + enum PropertyStubGetById_T { PropertyStubGetById }; + enum PropertyStubPutById_T { PropertyStubPutById }; + struct PropertyStubCompilationInfo { + enum Type { GetById, PutById, MethodCheck } m_type; + unsigned bytecodeIndex; MacroAssembler::Call callReturnLocation; MacroAssembler::Label hotPathBegin; - + MacroAssembler::DataLabelPtr getStructureToCompare; + MacroAssembler::PatchableJump getStructureCheck; +#if USE(JSVALUE64) + MacroAssembler::DataLabelCompact getDisplacementLabel; +#else + MacroAssembler::DataLabelCompact getDisplacementLabel1; + MacroAssembler::DataLabelCompact getDisplacementLabel2; +#endif + MacroAssembler::Label getPutResult; + MacroAssembler::Label getColdPathBegin; + MacroAssembler::DataLabelPtr putStructureToCompare; +#if USE(JSVALUE64) + MacroAssembler::DataLabel32 putDisplacementLabel; +#else + MacroAssembler::DataLabel32 putDisplacementLabel1; + MacroAssembler::DataLabel32 putDisplacementLabel2; +#endif + MacroAssembler::DataLabelPtr methodCheckStructureToCompare; + MacroAssembler::DataLabelPtr methodCheckProtoObj; + MacroAssembler::DataLabelPtr methodCheckProtoStructureToCompare; + MacroAssembler::DataLabelPtr methodCheckPutFunction; + #if !ASSERT_DISABLED PropertyStubCompilationInfo() : bytecodeIndex(std::numeric_limits<unsigned>::max()) { } #endif + + + PropertyStubCompilationInfo(PropertyStubGetById_T, unsigned bytecodeIndex, MacroAssembler::Label hotPathBegin, +#if USE(JSVALUE64) + MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::PatchableJump structureCheck, MacroAssembler::DataLabelCompact displacementLabel, MacroAssembler::Label putResult) +#else + MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::PatchableJump structureCheck, MacroAssembler::DataLabelCompact displacementLabel1, MacroAssembler::DataLabelCompact displacementLabel2, MacroAssembler::Label putResult) +#endif + : m_type(GetById) + , bytecodeIndex(bytecodeIndex) + , hotPathBegin(hotPathBegin) + , getStructureToCompare(structureToCompare) + , getStructureCheck(structureCheck) +#if USE(JSVALUE64) + , getDisplacementLabel(displacementLabel) +#else + , getDisplacementLabel1(displacementLabel1) + , getDisplacementLabel2(displacementLabel2) +#endif + , getPutResult(putResult) + { + } + + PropertyStubCompilationInfo(PropertyStubPutById_T, unsigned bytecodeIndex, MacroAssembler::Label hotPathBegin, +#if USE(JSVALUE64) + MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::DataLabel32 displacementLabel) +#else + MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::DataLabel32 displacementLabel1, MacroAssembler::DataLabel32 displacementLabel2) +#endif + : m_type(PutById) + , bytecodeIndex(bytecodeIndex) + , hotPathBegin(hotPathBegin) + , putStructureToCompare(structureToCompare) +#if USE(JSVALUE64) + , putDisplacementLabel(displacementLabel) +#else + , putDisplacementLabel1(displacementLabel1) + , putDisplacementLabel2(displacementLabel2) +#endif + { + } + + void slowCaseInfo(PropertyStubGetById_T, MacroAssembler::Label coldPathBegin, MacroAssembler::Call call) + { + ASSERT(m_type == GetById || m_type == MethodCheck); + callReturnLocation = call; + getColdPathBegin = coldPathBegin; + } + + void slowCaseInfo(PropertyStubPutById_T, MacroAssembler::Call call) + { + ASSERT(m_type == PutById); + callReturnLocation = call; + } + + void addMethodCheckInfo(MacroAssembler::DataLabelPtr structureToCompare, MacroAssembler::DataLabelPtr protoObj, MacroAssembler::DataLabelPtr protoStructureToCompare, MacroAssembler::DataLabelPtr putFunction) + { + m_type = MethodCheck; + methodCheckStructureToCompare = structureToCompare; + methodCheckProtoObj = protoObj; + methodCheckProtoStructureToCompare = protoStructureToCompare; + methodCheckPutFunction = putFunction; + } + + void copyToStubInfo(StructureStubInfo& info, LinkBuffer &patchBuffer); }; struct StructureStubCompilationInfo { @@ -187,6 +277,7 @@ namespace JSC { class JIT : private JSInterfaceJIT { friend class JITStubCall; + friend struct PropertyStubCompilationInfo; using MacroAssembler::Jump; using MacroAssembler::JumpList; @@ -269,7 +360,7 @@ namespace JSC { static void resetPatchPutById(RepatchBuffer&, StructureStubInfo*); static void patchGetByIdSelf(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress); static void patchPutByIdReplace(CodeBlock* codeblock, StructureStubInfo*, Structure*, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct); - static void patchMethodCallProto(JSGlobalData&, CodeBlock* codeblock, MethodCallLinkInfo&, JSObject*, Structure*, JSObject*, ReturnAddressPtr); + static void patchMethodCallProto(JSGlobalData&, CodeBlock* codeblock, MethodCallLinkInfo&, StructureStubInfo&, JSObject*, Structure*, JSObject*, ReturnAddressPtr); static void compilePatchGetArrayLength(JSGlobalData* globalData, CodeBlock* codeBlock, ReturnAddressPtr returnAddress) { @@ -280,17 +371,6 @@ namespace JSC { static void linkFor(JSFunction* callee, CodeBlock* callerCodeBlock, CodeBlock* calleeCodeBlock, CodePtr, CallLinkInfo*, JSGlobalData*, CodeSpecializationKind); private: - struct JSRInfo { - DataLabelPtr storeLocation; - Label target; - - JSRInfo(DataLabelPtr storeLocation, Label targetLocation) - : storeLocation(storeLocation) - , target(targetLocation) - { - } - }; - JIT(JSGlobalData*, CodeBlock* = 0); void privateCompileMainPass(); @@ -399,49 +479,7 @@ namespace JSC { void emitSub32Constant(unsigned dst, unsigned op, int32_t constant, ResultType opType); void emitBinaryDoubleOp(OpcodeID, unsigned dst, unsigned op1, unsigned op2, OperandTypes, JumpList& notInt32Op1, JumpList& notInt32Op2, bool op1IsInRegisters = true, bool op2IsInRegisters = true); -#if CPU(X86) - // These architecture specific value are used to enable patching - see comment on op_put_by_id. - static const int patchOffsetPutByIdStructure = 7; - static const int patchOffsetPutByIdPropertyMapOffset1 = 22; - static const int patchOffsetPutByIdPropertyMapOffset2 = 28; - // These architecture specific value are used to enable patching - see comment on op_get_by_id. - static const int patchOffsetGetByIdStructure = 7; - static const int patchOffsetGetByIdBranchToSlowCase = 13; - static const int patchOffsetGetByIdPropertyMapOffset1 = 19; - static const int patchOffsetGetByIdPropertyMapOffset2 = 22; - static const int patchOffsetGetByIdPutResult = 22; -#if ENABLE(OPCODE_SAMPLING) - static const int patchOffsetGetByIdSlowCaseCall = 44; -#else - static const int patchOffsetGetByIdSlowCaseCall = 40; -#endif - static const int patchOffsetOpCallCompareToJump = 6; - - static const int patchOffsetMethodCheckProtoObj = 11; - static const int patchOffsetMethodCheckProtoStruct = 18; - static const int patchOffsetMethodCheckPutFunction = 29; -#elif CPU(ARM_TRADITIONAL) - // These architecture specific value are used to enable patching - see comment on op_put_by_id. - static const int patchOffsetPutByIdStructure = 4; - static const int patchOffsetPutByIdPropertyMapOffset1 = 20; - static const int patchOffsetPutByIdPropertyMapOffset2 = 28; - // These architecture specific value are used to enable patching - see comment on op_get_by_id. - static const int patchOffsetGetByIdStructure = 4; - static const int patchOffsetGetByIdBranchToSlowCase = 16; - static const int patchOffsetGetByIdPropertyMapOffset1 = 20; - static const int patchOffsetGetByIdPropertyMapOffset2 = 28; - static const int patchOffsetGetByIdPutResult = 36; -#if ENABLE(OPCODE_SAMPLING) - #error "OPCODE_SAMPLING is not yet supported" -#else - static const int patchOffsetGetByIdSlowCaseCall = 48; -#endif - static const int patchOffsetOpCallCompareToJump = 12; - - static const int patchOffsetMethodCheckProtoObj = 12; - static const int patchOffsetMethodCheckProtoStruct = 20; - static const int patchOffsetMethodCheckPutFunction = 32; - +#if CPU(ARM_TRADITIONAL) // sequenceOpCall static const int sequenceOpCallInstructionSpace = 12; static const int sequenceOpCallConstantSpace = 2; @@ -452,96 +490,12 @@ namespace JSC { static const int sequenceGetByIdHotPathInstructionSpace = 36; static const int sequenceGetByIdHotPathConstantSpace = 4; // sequenceGetByIdSlowCase - static const int sequenceGetByIdSlowCaseInstructionSpace = 56; - static const int sequenceGetByIdSlowCaseConstantSpace = 3; + static const int sequenceGetByIdSlowCaseInstructionSpace = 64; + static const int sequenceGetByIdSlowCaseConstantSpace = 4; // sequencePutById static const int sequencePutByIdInstructionSpace = 36; static const int sequencePutByIdConstantSpace = 4; -#elif CPU(ARM_THUMB2) - // These architecture specific value are used to enable patching - see comment on op_put_by_id. - static const int patchOffsetPutByIdStructure = 10; - static const int patchOffsetPutByIdPropertyMapOffset1 = 36; - static const int patchOffsetPutByIdPropertyMapOffset2 = 48; - // These architecture specific value are used to enable patching - see comment on op_get_by_id. - static const int patchOffsetGetByIdStructure = 10; - static const int patchOffsetGetByIdBranchToSlowCase = 26; - static const int patchOffsetGetByIdPropertyMapOffset1 = 28; - static const int patchOffsetGetByIdPropertyMapOffset2 = 30; - static const int patchOffsetGetByIdPutResult = 32; -#if ENABLE(OPCODE_SAMPLING) - #error "OPCODE_SAMPLING is not yet supported" -#else - static const int patchOffsetGetByIdSlowCaseCall = 52; -#endif - static const int patchOffsetOpCallCompareToJump = 16; - - static const int patchOffsetMethodCheckProtoObj = 24; - static const int patchOffsetMethodCheckProtoStruct = 34; - static const int patchOffsetMethodCheckPutFunction = 58; - - // sequenceOpCall - static const int sequenceOpCallInstructionSpace = 12; - static const int sequenceOpCallConstantSpace = 2; - // sequenceMethodCheck - static const int sequenceMethodCheckInstructionSpace = 40; - static const int sequenceMethodCheckConstantSpace = 6; - // sequenceGetByIdHotPath - static const int sequenceGetByIdHotPathInstructionSpace = 36; - static const int sequenceGetByIdHotPathConstantSpace = 4; - // sequenceGetByIdSlowCase - static const int sequenceGetByIdSlowCaseInstructionSpace = 40; - static const int sequenceGetByIdSlowCaseConstantSpace = 2; - // sequencePutById - static const int sequencePutByIdInstructionSpace = 36; - static const int sequencePutByIdConstantSpace = 4; -#elif CPU(MIPS) -#if WTF_MIPS_ISA(1) - static const int patchOffsetPutByIdStructure = 16; - static const int patchOffsetPutByIdPropertyMapOffset1 = 56; - static const int patchOffsetPutByIdPropertyMapOffset2 = 72; - static const int patchOffsetGetByIdStructure = 16; - static const int patchOffsetGetByIdBranchToSlowCase = 48; - static const int patchOffsetGetByIdPropertyMapOffset1 = 56; - static const int patchOffsetGetByIdPropertyMapOffset2 = 76; - static const int patchOffsetGetByIdPutResult = 96; -#if ENABLE(OPCODE_SAMPLING) - #error "OPCODE_SAMPLING is not yet supported" -#else - static const int patchOffsetGetByIdSlowCaseCall = 68; -#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 patchOffsetPutByIdPropertyMapOffset1 = 48; - static const int patchOffsetPutByIdPropertyMapOffset2 = 64; - static const int patchOffsetGetByIdStructure = 12; - static const int patchOffsetGetByIdBranchToSlowCase = 44; - static const int patchOffsetGetByIdPropertyMapOffset1 = 48; - static const int patchOffsetGetByIdPropertyMapOffset2 = 64; - static const int patchOffsetGetByIdPutResult = 80; -#if ENABLE(OPCODE_SAMPLING) - #error "OPCODE_SAMPLING is not yet supported" -#else - static const int patchOffsetGetByIdSlowCaseCall = 68; -#endif - static const int patchOffsetOpCallCompareToJump = 32; - static const int patchOffsetMethodCheckProtoObj = 32; - static const int patchOffsetMethodCheckProtoStruct = 52; - static const int patchOffsetMethodCheckPutFunction = 84; -#endif #elif CPU(SH4) - // These architecture specific value are used to enable patching - see comment on op_put_by_id. - static const int patchOffsetGetByIdStructure = 6; - static const int patchOffsetPutByIdPropertyMapOffset = 24; - static const int patchOffsetPutByIdStructure = 6; - // These architecture specific value are used to enable patching - see comment on op_get_by_id. - static const int patchOffsetGetByIdBranchToSlowCase = 10; - static const int patchOffsetGetByIdPropertyMapOffset = 24; - static const int patchOffsetGetByIdPutResult = 24; - // sequenceOpCall static const int sequenceOpCallInstructionSpace = 12; static const int sequenceOpCallConstantSpace = 2; @@ -552,30 +506,11 @@ namespace JSC { static const int sequenceGetByIdHotPathInstructionSpace = 36; static const int sequenceGetByIdHotPathConstantSpace = 5; // sequenceGetByIdSlowCase - static const int sequenceGetByIdSlowCaseInstructionSpace = 30; - static const int sequenceGetByIdSlowCaseConstantSpace = 3; + static const int sequenceGetByIdSlowCaseInstructionSpace = 38; + static const int sequenceGetByIdSlowCaseConstantSpace = 4; // sequencePutById static const int sequencePutByIdInstructionSpace = 36; static const int sequencePutByIdConstantSpace = 5; - - static const int patchOffsetGetByIdPropertyMapOffset1 = 20; - static const int patchOffsetGetByIdPropertyMapOffset2 = 22; - - static const int patchOffsetPutByIdPropertyMapOffset1 = 20; - static const int patchOffsetPutByIdPropertyMapOffset2 = 26; - -#if ENABLE(OPCODE_SAMPLING) - static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE -#else - static const int patchOffsetGetByIdSlowCaseCall = 26; -#endif - static const int patchOffsetOpCallCompareToJump = 4; - - static const int patchOffsetMethodCheckProtoObj = 12; - static const int patchOffsetMethodCheckProtoStruct = 20; - static const int patchOffsetMethodCheckPutFunction = 32; -#else -#error "JSVALUE32_64 not supported on this platform." #endif #else // USE(JSVALUE32_64) @@ -597,17 +532,6 @@ namespace JSC { Jump emitJumpIfNotJSCell(RegisterID); void emitJumpSlowCaseIfNotJSCell(RegisterID); void emitJumpSlowCaseIfNotJSCell(RegisterID, int VReg); -#if USE(JSVALUE32_64) - JIT::Jump emitJumpIfImmediateNumber(RegisterID reg) - { - return emitJumpIfImmediateInteger(reg); - } - - JIT::Jump emitJumpIfNotImmediateNumber(RegisterID reg) - { - return emitJumpIfNotImmediateInteger(reg); - } -#endif Jump emitJumpIfImmediateInteger(RegisterID); Jump emitJumpIfNotImmediateInteger(RegisterID); Jump emitJumpIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID); @@ -615,20 +539,12 @@ namespace JSC { void emitJumpSlowCaseIfNotImmediateNumber(RegisterID); void emitJumpSlowCaseIfNotImmediateIntegers(RegisterID, RegisterID, RegisterID); -#if USE(JSVALUE32_64) - void emitFastArithDeTagImmediate(RegisterID); - Jump emitFastArithDeTagImmediateJumpIfZero(RegisterID); -#endif void emitFastArithReTagImmediate(RegisterID src, RegisterID dest); void emitFastArithIntToImmNoCheck(RegisterID src, RegisterID dest); void emitTagAsBoolImmediate(RegisterID reg); void compileBinaryArithOp(OpcodeID, unsigned dst, unsigned src1, unsigned src2, OperandTypes opi); -#if USE(JSVALUE64) void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes, bool op1HasImmediateIntFastCase, bool op2HasImmediateIntFastCase); -#else - void compileBinaryArithOpSlowCase(OpcodeID, Vector<SlowCaseEntry>::iterator&, unsigned dst, unsigned src1, unsigned src2, OperandTypes); -#endif void compileGetByIdHotPath(int baseVReg, Identifier*); void compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident, Vector<SlowCaseEntry>::iterator& iter, bool isMethodCheck = false); @@ -637,133 +553,6 @@ namespace JSC { void compileGetDirectOffset(RegisterID base, RegisterID result, RegisterID offset, RegisterID scratch); void compilePutDirectOffset(RegisterID base, RegisterID value, size_t cachedOffset); -#if CPU(X86_64) - // These architecture specific value are used to enable patching - see comment on op_put_by_id. - static const int patchOffsetPutByIdStructure = 10; - static const int patchOffsetPutByIdPropertyMapOffset = 31; - // These architecture specific value are used to enable patching - see comment on op_get_by_id. - static const int patchOffsetGetByIdStructure = 10; - static const int patchOffsetGetByIdBranchToSlowCase = 20; - static const int patchOffsetGetByIdPropertyMapOffset = 28; - static const int patchOffsetGetByIdPutResult = 28; -#if ENABLE(OPCODE_SAMPLING) - static const int patchOffsetGetByIdSlowCaseCall = 72; -#else - static const int patchOffsetGetByIdSlowCaseCall = 62; -#endif - static const int patchOffsetOpCallCompareToJump = 9; - - static const int patchOffsetMethodCheckProtoObj = 20; - static const int patchOffsetMethodCheckProtoStruct = 30; - static const int patchOffsetMethodCheckPutFunction = 50; -#elif CPU(X86) - // These architecture specific value are used to enable patching - see comment on op_put_by_id. - static const int patchOffsetPutByIdStructure = 7; - static const int patchOffsetPutByIdPropertyMapOffset = 22; - // These architecture specific value are used to enable patching - see comment on op_get_by_id. - static const int patchOffsetGetByIdStructure = 7; - static const int patchOffsetGetByIdBranchToSlowCase = 13; - static const int patchOffsetGetByIdPropertyMapOffset = 22; - static const int patchOffsetGetByIdPutResult = 22; -#if ENABLE(OPCODE_SAMPLING) - static const int patchOffsetGetByIdSlowCaseCall = 33; -#else - static const int patchOffsetGetByIdSlowCaseCall = 23; -#endif - static const int patchOffsetOpCallCompareToJump = 6; - - static const int patchOffsetMethodCheckProtoObj = 11; - static const int patchOffsetMethodCheckProtoStruct = 18; - static const int patchOffsetMethodCheckPutFunction = 29; -#elif CPU(ARM_THUMB2) - // These architecture specific value are used to enable patching - see comment on op_put_by_id. - static const int patchOffsetPutByIdStructure = 10; - static const int patchOffsetPutByIdPropertyMapOffset = 46; - // These architecture specific value are used to enable patching - see comment on op_get_by_id. - static const int patchOffsetGetByIdStructure = 10; - static const int patchOffsetGetByIdBranchToSlowCase = 26; - static const int patchOffsetGetByIdPropertyMapOffset = 46; - static const int patchOffsetGetByIdPutResult = 50; -#if ENABLE(OPCODE_SAMPLING) - static const int patchOffsetGetByIdSlowCaseCall = 0; // FIMXE -#else - static const int patchOffsetGetByIdSlowCaseCall = 28; -#endif - static const int patchOffsetOpCallCompareToJump = 16; - - static const int patchOffsetMethodCheckProtoObj = 24; - static const int patchOffsetMethodCheckProtoStruct = 34; - static const int patchOffsetMethodCheckPutFunction = 58; -#elif CPU(ARM_TRADITIONAL) - // These architecture specific value are used to enable patching - see comment on op_put_by_id. - static const int patchOffsetPutByIdStructure = 4; - static const int patchOffsetPutByIdPropertyMapOffset = 20; - // These architecture specific value are used to enable patching - see comment on op_get_by_id. - static const int patchOffsetGetByIdStructure = 4; - static const int patchOffsetGetByIdBranchToSlowCase = 16; - static const int patchOffsetGetByIdPropertyMapOffset = 20; - static const int patchOffsetGetByIdPutResult = 28; -#if ENABLE(OPCODE_SAMPLING) - #error "OPCODE_SAMPLING is not yet supported" -#else - static const int patchOffsetGetByIdSlowCaseCall = 28; -#endif - static const int patchOffsetOpCallCompareToJump = 12; - - static const int patchOffsetMethodCheckProtoObj = 12; - static const int patchOffsetMethodCheckProtoStruct = 20; - static const int patchOffsetMethodCheckPutFunction = 32; - - // sequenceOpCall - static const int sequenceOpCallInstructionSpace = 12; - static const int sequenceOpCallConstantSpace = 2; - // sequenceMethodCheck - static const int sequenceMethodCheckInstructionSpace = 40; - static const int sequenceMethodCheckConstantSpace = 6; - // sequenceGetByIdHotPath - static const int sequenceGetByIdHotPathInstructionSpace = 28; - static const int sequenceGetByIdHotPathConstantSpace = 3; - // sequenceGetByIdSlowCase - static const int sequenceGetByIdSlowCaseInstructionSpace = 32; - static const int sequenceGetByIdSlowCaseConstantSpace = 2; - // 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 patchOffsetPutByIdPropertyMapOffset = 68; - static const int patchOffsetGetByIdStructure = 16; - static const int patchOffsetGetByIdBranchToSlowCase = 48; - 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 patchOffsetPutByIdPropertyMapOffset = 60; - static const int patchOffsetGetByIdStructure = 12; - static const int patchOffsetGetByIdBranchToSlowCase = 44; - 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) #if (defined(ASSEMBLER_HAS_CONSTANT_POOL) && ASSEMBLER_HAS_CONSTANT_POOL) @@ -775,9 +564,9 @@ namespace JSC { void endUninterruptedSequence(int, int, int); #else -#define BEGIN_UNINTERRUPTED_SEQUENCE(name) do { beginUninterruptedSequence(); } while (false) -#define END_UNINTERRUPTED_SEQUENCE(name) do { endUninterruptedSequence(); } while (false) -#define END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, dst) do { endUninterruptedSequence(); } while (false) +#define BEGIN_UNINTERRUPTED_SEQUENCE(name) +#define END_UNINTERRUPTED_SEQUENCE(name) +#define END_UNINTERRUPTED_SEQUENCE_FOR_PUT(name, dst) #endif void emit_compareAndJump(OpcodeID, unsigned op1, unsigned op2, unsigned target, RelationalCondition); @@ -815,6 +604,10 @@ namespace JSC { void emit_op_init_lazy_reg(Instruction*); void emit_op_check_has_instance(Instruction*); void emit_op_instanceof(Instruction*); + void emit_op_is_undefined(Instruction*); + void emit_op_is_boolean(Instruction*); + void emit_op_is_number(Instruction*); + void emit_op_is_string(Instruction*); void emit_op_jeq_null(Instruction*); void emit_op_jfalse(Instruction*); void emit_op_jmp(Instruction*); @@ -829,7 +622,6 @@ namespace JSC { void emit_op_jnlesseq(Instruction*); void emit_op_jngreater(Instruction*); void emit_op_jngreatereq(Instruction*); - void emit_op_jsr(Instruction*); void emit_op_jtrue(Instruction*); void emit_op_loop(Instruction*); void emit_op_loop_hint(Instruction*); @@ -883,7 +675,6 @@ namespace JSC { void emit_op_ret(Instruction*); void emit_op_ret_object_or_this(Instruction*); void emit_op_rshift(Instruction*); - void emit_op_sret(Instruction*); void emit_op_strcat(Instruction*); void emit_op_stricteq(Instruction*); void emit_op_sub(Instruction*); @@ -898,9 +689,6 @@ namespace JSC { void emit_op_to_primitive(Instruction*); void emit_op_unexpected_load(Instruction*); void emit_op_urshift(Instruction*); -#if ENABLE(JIT_USE_SOFT_MODULO) - void softModulo(); -#endif void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&); void emitSlow_op_bitand(Instruction*, Vector<SlowCaseEntry>::iterator&); @@ -1069,7 +857,6 @@ namespace JSC { Vector<JumpTable> m_jmpTable; unsigned m_bytecodeOffset; - Vector<JSRInfo> m_jsrSites; Vector<SlowCaseEntry> m_slowCases; Vector<SwitchRecord> m_switches; diff --git a/Source/JavaScriptCore/jit/JITArithmetic.cpp b/Source/JavaScriptCore/jit/JITArithmetic.cpp index 1b32e3bcf..a9390e35f 100644 --- a/Source/JavaScriptCore/jit/JITArithmetic.cpp +++ b/Source/JavaScriptCore/jit/JITArithmetic.cpp @@ -732,7 +732,7 @@ void JIT::emitSlow_op_pre_dec(Instruction* currentInstruction, Vector<SlowCaseEn /* ------------------------------ BEGIN: OP_MOD ------------------------------ */ -#if CPU(X86) || CPU(X86_64) || CPU(MIPS) +#if CPU(X86) || CPU(X86_64) void JIT::emit_op_mod(Instruction* currentInstruction) { @@ -740,20 +740,25 @@ void JIT::emit_op_mod(Instruction* currentInstruction) unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; -#if CPU(X86) || CPU(X86_64) // Make sure registers are correct for x86 IDIV instructions. ASSERT(regT0 == X86Registers::eax); ASSERT(regT1 == X86Registers::edx); ASSERT(regT2 == X86Registers::ecx); -#endif - emitGetVirtualRegisters(op1, regT0, op2, regT2); - emitJumpSlowCaseIfNotImmediateInteger(regT0); + emitGetVirtualRegisters(op1, regT3, op2, regT2); + emitJumpSlowCaseIfNotImmediateInteger(regT3); emitJumpSlowCaseIfNotImmediateInteger(regT2); - addSlowCase(branchPtr(Equal, regT2, TrustedImmPtr(JSValue::encode(jsNumber(0))))); + move(regT3, regT0); + addSlowCase(branchTest32(Zero, regT2)); + Jump denominatorNotNeg1 = branch32(NotEqual, regT2, TrustedImm32(-1)); + addSlowCase(branch32(Equal, regT0, TrustedImm32(-2147483647-1))); + denominatorNotNeg1.link(this); m_assembler.cdq(); m_assembler.idivl_r(regT2); + Jump numeratorPositive = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0)); + addSlowCase(branchTest32(Zero, regT1)); + numeratorPositive.link(this); emitFastArithReTagImmediate(regT1, regT0); emitPutVirtualRegister(result); } @@ -765,13 +770,15 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry> linkSlowCase(iter); linkSlowCase(iter); linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); JITStubCall stubCall(this, cti_op_mod); - stubCall.addArgument(regT0); + stubCall.addArgument(regT3); stubCall.addArgument(regT2); stubCall.call(result); } -#else // CPU(X86) || CPU(X86_64) || CPU(MIPS) +#else // CPU(X86) || CPU(X86_64) void JIT::emit_op_mod(Instruction* currentInstruction) { @@ -787,20 +794,7 @@ void JIT::emit_op_mod(Instruction* currentInstruction) void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { -#if ENABLE(JIT_USE_SOFT_MODULO) - unsigned result = currentInstruction[1].u.operand; - unsigned op1 = currentInstruction[2].u.operand; - unsigned op2 = currentInstruction[3].u.operand; - linkSlowCase(iter); - linkSlowCase(iter); - linkSlowCase(iter); - JITStubCall stubCall(this, cti_op_mod); - stubCall.addArgument(op1, regT2); - stubCall.addArgument(op2, regT2); - stubCall.call(result); -#else ASSERT_NOT_REACHED(); -#endif } #endif // CPU(X86) || CPU(X86_64) diff --git a/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp b/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp index 11a758103..62a359eeb 100644 --- a/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp +++ b/Source/JavaScriptCore/jit/JITArithmetic32_64.cpp @@ -1202,25 +1202,28 @@ void JIT::emit_op_mod(Instruction* currentInstruction) unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; -#if ENABLE(JIT_USE_SOFT_MODULO) - #if CPU(X86) || CPU(X86_64) // Make sure registers are correct for x86 IDIV instructions. ASSERT(regT0 == X86Registers::eax); ASSERT(regT1 == X86Registers::edx); ASSERT(regT2 == X86Registers::ecx); ASSERT(regT3 == X86Registers::ebx); -#endif - emitLoad2(op1, regT1, regT0, op2, regT3, regT2); + emitLoad2(op1, regT0, regT3, op2, regT1, regT2); addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag))); - addSlowCase(branch32(NotEqual, regT3, TrustedImm32(JSValue::Int32Tag))); - - addSlowCase(branch32(Equal, regT2, TrustedImm32(0))); - - emitNakedCall(m_globalData->jitStubs->ctiSoftModulo()); - - emitStoreInt32(dst, regT0, (op1 == dst || op2 == dst)); + addSlowCase(branch32(NotEqual, regT0, TrustedImm32(JSValue::Int32Tag))); + + move(regT3, regT0); + addSlowCase(branchTest32(Zero, regT2)); + Jump denominatorNotNeg1 = branch32(NotEqual, regT2, TrustedImm32(-1)); + addSlowCase(branch32(Equal, regT0, TrustedImm32(-2147483647-1))); + denominatorNotNeg1.link(this); + m_assembler.cdq(); + m_assembler.idivl_r(regT2); + Jump numeratorPositive = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0)); + addSlowCase(branchTest32(Zero, regT1)); + numeratorPositive.link(this); + emitStoreInt32(dst, regT1, (op1 == dst || op2 == dst)); #else JITStubCall stubCall(this, cti_op_mod); stubCall.addArgument(op1); @@ -1231,13 +1234,15 @@ void JIT::emit_op_mod(Instruction* currentInstruction) void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { -#if ENABLE(JIT_USE_SOFT_MODULO) +#if CPU(X86) || CPU(X86_64) unsigned result = currentInstruction[1].u.operand; unsigned op1 = currentInstruction[2].u.operand; unsigned op2 = currentInstruction[3].u.operand; linkSlowCase(iter); linkSlowCase(iter); linkSlowCase(iter); + linkSlowCase(iter); + linkSlowCase(iter); JITStubCall stubCall(this, cti_op_mod); stubCall.addArgument(op1); stubCall.addArgument(op2); @@ -1245,7 +1250,9 @@ void JIT::emitSlow_op_mod(Instruction* currentInstruction, Vector<SlowCaseEntry> #else UNUSED_PARAM(currentInstruction); UNUSED_PARAM(iter); - ASSERT_NOT_REACHED(); + // We would have really useful assertions here if it wasn't for the compiler's + // insistence on attribute noreturn. + // ASSERT_NOT_REACHED(); #endif } diff --git a/Source/JavaScriptCore/jit/JITCall.cpp b/Source/JavaScriptCore/jit/JITCall.cpp index 73d017d05..7664eb746 100644 --- a/Source/JavaScriptCore/jit/JITCall.cpp +++ b/Source/JavaScriptCore/jit/JITCall.cpp @@ -161,8 +161,10 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca int registerOffset = instruction[3].u.operand; addPtr(TrustedImm32(registerOffset * sizeof(Register)), callFrameRegister, regT1); - store32(TrustedImm32(argCount), Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)))); + store32(TrustedImm32(argCount), Address(regT1, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload))); } // regT1 holds newCallFrame with ArgumentCount initialized. + + store32(TrustedImm32(instruction - m_codeBlock->instructions().begin()), Address(callFrameRegister, RegisterFile::ArgumentCount * static_cast<int>(sizeof(Register)) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag))); emitGetVirtualRegister(callee, regT0); // regT0 holds callee. storePtr(callFrameRegister, Address(regT1, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register)))); @@ -180,7 +182,6 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca END_UNINTERRUPTED_SEQUENCE(sequenceOpCall); addSlowCase(slowCase); - ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, slowCase), patchOffsetOpCallCompareToJump); ASSERT(m_callStructureStubCompilationInfo.size() == callLinkInfoIndex); m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo()); m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck; diff --git a/Source/JavaScriptCore/jit/JITCall32_64.cpp b/Source/JavaScriptCore/jit/JITCall32_64.cpp index 7fb6c78b9..81266052b 100644 --- a/Source/JavaScriptCore/jit/JITCall32_64.cpp +++ b/Source/JavaScriptCore/jit/JITCall32_64.cpp @@ -245,6 +245,8 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca store32(TrustedImm32(argCount), payloadFor(RegisterFile::ArgumentCount, regT3)); } // regT3 holds newCallFrame with ArgumentCount initialized. + + storePtr(TrustedImmPtr(instruction), tagFor(RegisterFile::ArgumentCount, callFrameRegister)); emitLoad(callee, regT1, regT0); // regT1, regT0 holds callee. storePtr(callFrameRegister, Address(regT3, RegisterFile::CallerFrame * static_cast<int>(sizeof(Register)))); @@ -264,7 +266,6 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca addSlowCase(slowCase); addSlowCase(branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag))); - ASSERT_JIT_OFFSET(differenceBetween(addressOfLinkedFunctionCheck, slowCase), patchOffsetOpCallCompareToJump); ASSERT(m_callStructureStubCompilationInfo.size() == callLinkInfoIndex); m_callStructureStubCompilationInfo.append(StructureStubCompilationInfo()); m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathBegin = addressOfLinkedFunctionCheck; diff --git a/Source/JavaScriptCore/jit/JITExceptions.cpp b/Source/JavaScriptCore/jit/JITExceptions.cpp index ab1180716..2955fac8d 100644 --- a/Source/JavaScriptCore/jit/JITExceptions.cpp +++ b/Source/JavaScriptCore/jit/JITExceptions.cpp @@ -32,7 +32,7 @@ #include "JSGlobalData.h" #include "JSValue.h" -#if ENABLE(ASSEMBLER) +#if ENABLE(JIT) namespace JSC { diff --git a/Source/JavaScriptCore/jit/JITInlineMethods.h b/Source/JavaScriptCore/jit/JITInlineMethods.h index 998d5ac18..cd33821f2 100644 --- a/Source/JavaScriptCore/jit/JITInlineMethods.h +++ b/Source/JavaScriptCore/jit/JITInlineMethods.h @@ -132,7 +132,6 @@ ALWAYS_INLINE bool JIT::atJumpTarget() ALWAYS_INLINE void JIT::beginUninterruptedSequence(int insnSpace, int constSpace) { - JSInterfaceJIT::beginUninterruptedSequence(); #if CPU(ARM_TRADITIONAL) #ifndef NDEBUG // Ensure the label after the sequence can also fit @@ -182,7 +181,6 @@ ALWAYS_INLINE void JIT::endUninterruptedSequence(int insnSpace, int constSpace, ASSERT(differenceBetween(m_uninterruptedInstructionSequenceBegin, label()) <= insnSpace); ASSERT(sizeOfConstantPool() - m_uninterruptedConstantSequenceBegin <= constSpace); #endif - JSInterfaceJIT::endUninterruptedSequence(); } #endif @@ -414,12 +412,12 @@ template <typename ClassType, bool destructor, typename StructureType> inline vo allocator = &m_globalData->heap.allocatorForObjectWithDestructor(sizeof(ClassType)); else allocator = &m_globalData->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType)); - loadPtr(&allocator->m_firstFreeCell, result); + loadPtr(&allocator->m_freeList.head, result); addSlowCase(branchTestPtr(Zero, result)); // remove the object from the free list loadPtr(Address(result), storagePtr); - storePtr(storagePtr, &allocator->m_firstFreeCell); + storePtr(storagePtr, &allocator->m_freeList.head); // initialize the object's structure storePtr(structure, Address(result, JSCell::structureOffset())); @@ -485,12 +483,13 @@ inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, R unsigned initialLength = std::max(length, 4U); size_t initialStorage = JSArray::storageSize(initialLength); + // We allocate the backing store first to ensure that garbage collection + // doesn't happen during JSArray initialization. + emitAllocateBasicStorage(initialStorage, storageResult, storagePtr); + // Allocate the cell for the array. emitAllocateBasicJSObject<JSArray, false>(TrustedImmPtr(m_codeBlock->globalObject()->arrayStructure()), cellResult, storagePtr); - // Allocate the backing store for the array. - emitAllocateBasicStorage(initialStorage, storageResult, storagePtr); - // Store all the necessary info in the ArrayStorage. storePtr(storageResult, Address(storageResult, ArrayStorage::allocBaseOffset())); store32(Imm32(length), Address(storageResult, ArrayStorage::lengthOffset())); @@ -503,8 +502,7 @@ inline void JIT::emitAllocateJSArray(unsigned valuesRegister, unsigned length, R store32(Imm32(initialLength), Address(cellResult, JSArray::vectorLengthOffset())); store32(TrustedImm32(0), Address(cellResult, JSArray::indexBiasOffset())); - // Initialize the subclass data and the sparse value map. - storePtr(TrustedImmPtr(0), Address(cellResult, JSArray::subclassDataOffset())); + // Initialize the sparse value map. storePtr(TrustedImmPtr(0), Address(cellResult, JSArray::sparseValueMapOffset())); // Store the values we have. diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp index 2db82bf4a..d68f4109d 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp @@ -232,6 +232,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon Label nativeCallThunk = align(); emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); + storePtr(callFrameRegister, &m_globalData->topCallFrame); #if CPU(X86_64) // Load caller frame's scope chain into this callframe so that whatever we call can @@ -465,6 +466,69 @@ void JIT::emit_op_instanceof(Instruction* currentInstruction) emitPutVirtualRegister(dst); } +void JIT::emit_op_is_undefined(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + + emitGetVirtualRegister(value, regT0); + Jump isCell = emitJumpIfJSCell(regT0); + + comparePtr(Equal, regT0, TrustedImm32(ValueUndefined), regT0); + Jump done = jump(); + + isCell.link(this); + loadPtr(Address(regT0, JSCell::structureOffset()), regT1); + test8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0); + + done.link(this); + emitTagAsBoolImmediate(regT0); + emitPutVirtualRegister(dst); +} + +void JIT::emit_op_is_boolean(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + + emitGetVirtualRegister(value, regT0); + xorPtr(TrustedImm32(static_cast<int32_t>(ValueFalse)), regT0); + testPtr(Zero, regT0, TrustedImm32(static_cast<int32_t>(~1)), regT0); + emitTagAsBoolImmediate(regT0); + emitPutVirtualRegister(dst); +} + +void JIT::emit_op_is_number(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + + emitGetVirtualRegister(value, regT0); + testPtr(NonZero, regT0, tagTypeNumberRegister, regT0); + emitTagAsBoolImmediate(regT0); + emitPutVirtualRegister(dst); +} + +void JIT::emit_op_is_string(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + + emitGetVirtualRegister(value, regT0); + Jump isNotCell = emitJumpIfNotJSCell(regT0); + + loadPtr(Address(regT0, JSCell::structureOffset()), regT1); + compare8(Equal, Address(regT1, Structure::typeInfoTypeOffset()), TrustedImm32(StringType), regT0); + emitTagAsBoolImmediate(regT0); + Jump done = jump(); + + isNotCell.link(this); + move(TrustedImm32(ValueFalse), regT0); + + done.link(this); + emitPutVirtualRegister(dst); +} + void JIT::emit_op_call(Instruction* currentInstruction) { compileOpCall(op_call, currentInstruction, m_callLinkInfoIndex++); @@ -742,22 +806,6 @@ void JIT::emit_op_jneq_ptr(Instruction* currentInstruction) addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(JSValue::encode(JSValue(ptr)))), target); } -void JIT::emit_op_jsr(Instruction* currentInstruction) -{ - int retAddrDst = currentInstruction[1].u.operand; - int target = currentInstruction[2].u.operand; - DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst)); - addJump(jump(), target); - m_jsrSites.append(JSRInfo(storeLocation, label())); - killLastResultRegister(); -} - -void JIT::emit_op_sret(Instruction* currentInstruction) -{ - jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand)); - killLastResultRegister(); -} - void JIT::emit_op_eq(Instruction* currentInstruction) { emitGetVirtualRegisters(currentInstruction[2].u.operand, regT0, currentInstruction[3].u.operand, regT1); @@ -1662,11 +1710,14 @@ void JIT::emit_op_new_array(Instruction* currentInstruction) void JIT::emitSlow_op_new_array(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) { + // If the allocation would be oversize, we will already make the proper stub call above in + // emit_op_new_array. int length = currentInstruction[3].u.operand; if (CopiedSpace::isOversize(JSArray::storageSize(length))) return; - linkSlowCase(iter); // Not enough space in MarkedSpace for cell. linkSlowCase(iter); // Not enough space in CopiedSpace for storage. + linkSlowCase(iter); // Not enough space in MarkedSpace for cell. + JITStubCall stubCall(this, cti_op_new_array); stubCall.addArgument(TrustedImm32(currentInstruction[2].u.operand)); stubCall.addArgument(TrustedImm32(currentInstruction[3].u.operand)); diff --git a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp index b67696f35..76e11e48c 100644 --- a/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp +++ b/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp @@ -42,10 +42,6 @@ namespace JSC { PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGlobalData* globalData, TrampolineStructure *trampolines) { -#if ENABLE(JIT_USE_SOFT_MODULO) - Label softModBegin = align(); - softModulo(); -#endif // (1) This function provides fast property access for string length Label stringLengthBegin = align(); @@ -222,10 +218,6 @@ PassRefPtr<ExecutableMemoryHandle> JIT::privateCompileCTIMachineTrampolines(JSGl trampolines->ctiNativeConstruct = patchBuffer.trampolineAt(nativeConstructThunk); trampolines->ctiStringLengthTrampoline = patchBuffer.trampolineAt(stringLengthBegin); -#if ENABLE(JIT_USE_SOFT_MODULO) - trampolines->ctiSoftModulo = patchBuffer.trampolineAt(softModBegin); -#endif - return executableMemory.release(); } @@ -236,6 +228,7 @@ JIT::Label JIT::privateCompileCTINativeCall(JSGlobalData* globalData, bool isCon Label nativeCallThunk = align(); emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); + storePtr(callFrameRegister, &m_globalData->topCallFrame); #if CPU(X86) // Load caller frame's scope chain into this callframe so that whatever we call can @@ -370,6 +363,7 @@ JIT::CodeRef JIT::privateCompileCTINativeCall(JSGlobalData* globalData, NativeFu Call nativeCall; emitPutImmediateToCallFrameHeader(0, RegisterFile::CodeBlock); + storePtr(callFrameRegister, &m_globalData->topCallFrame); #if CPU(X86) // Load caller frame's scope chain into this callframe so that whatever we call can @@ -639,6 +633,65 @@ void JIT::emitSlow_op_instanceof(Instruction* currentInstruction, Vector<SlowCas stubCall.call(dst); } +void JIT::emit_op_is_undefined(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + + emitLoad(value, regT1, regT0); + Jump isCell = branch32(Equal, regT1, TrustedImm32(JSValue::CellTag)); + + compare32(Equal, regT1, TrustedImm32(JSValue::UndefinedTag), regT0); + Jump done = jump(); + + isCell.link(this); + loadPtr(Address(regT0, JSCell::structureOffset()), regT1); + test8(NonZero, Address(regT1, Structure::typeInfoFlagsOffset()), TrustedImm32(MasqueradesAsUndefined), regT0); + + done.link(this); + emitStoreBool(dst, regT0); +} + +void JIT::emit_op_is_boolean(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + + emitLoadTag(value, regT0); + compare32(Equal, regT0, TrustedImm32(JSValue::BooleanTag), regT0); + emitStoreBool(dst, regT0); +} + +void JIT::emit_op_is_number(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + + emitLoadTag(value, regT0); + add32(TrustedImm32(1), regT0); + compare32(Below, regT0, TrustedImm32(JSValue::LowestTag + 1), regT0); + emitStoreBool(dst, regT0); +} + +void JIT::emit_op_is_string(Instruction* currentInstruction) +{ + unsigned dst = currentInstruction[1].u.operand; + unsigned value = currentInstruction[2].u.operand; + + emitLoad(value, regT1, regT0); + Jump isNotCell = branch32(NotEqual, regT1, TrustedImm32(JSValue::CellTag)); + + loadPtr(Address(regT0, JSCell::structureOffset()), regT1); + compare8(Equal, Address(regT1, Structure::typeInfoTypeOffset()), TrustedImm32(StringType), regT0); + Jump done = jump(); + + isNotCell.link(this); + move(TrustedImm32(0), regT0); + + done.link(this); + emitStoreBool(dst, regT0); +} + void JIT::emit_op_tear_off_activation(Instruction* currentInstruction) { unsigned activation = currentInstruction[1].u.operand; @@ -929,20 +982,6 @@ void JIT::emit_op_jneq_ptr(Instruction* currentInstruction) addJump(branchPtr(NotEqual, regT0, TrustedImmPtr(ptr)), target); } -void JIT::emit_op_jsr(Instruction* currentInstruction) -{ - int retAddrDst = currentInstruction[1].u.operand; - int target = currentInstruction[2].u.operand; - DataLabelPtr storeLocation = storePtrWithPatch(TrustedImmPtr(0), Address(callFrameRegister, sizeof(Register) * retAddrDst)); - addJump(jump(), target); - m_jsrSites.append(JSRInfo(storeLocation, label())); -} - -void JIT::emit_op_sret(Instruction* currentInstruction) -{ - jump(Address(callFrameRegister, sizeof(Register) * currentInstruction[1].u.operand)); -} - void JIT::emit_op_eq(Instruction* currentInstruction) { unsigned dst = currentInstruction[1].u.operand; @@ -1642,99 +1681,6 @@ void JIT::emitSlow_op_get_argument_by_val(Instruction* currentInstruction, Vecto stubCall.call(dst); } -#if ENABLE(JIT_USE_SOFT_MODULO) -void JIT::softModulo() -{ - move(regT2, regT3); - move(regT0, regT2); - move(TrustedImm32(0), regT1); - JumpList exitBranch; - - // Check for negative result reminder - Jump positiveRegT3 = branch32(GreaterThanOrEqual, regT3, TrustedImm32(0)); - neg32(regT3); - xor32(TrustedImm32(1), regT1); - positiveRegT3.link(this); - - Jump positiveRegT2 = branch32(GreaterThanOrEqual, regT2, TrustedImm32(0)); - neg32(regT2); - xor32(TrustedImm32(2), regT1); - positiveRegT2.link(this); - - // Save the condition for negative reminder - push(regT1); - - exitBranch.append(branch32(LessThan, regT2, regT3)); - - // Power of two fast case - move(regT3, regT0); - sub32(TrustedImm32(1), regT0); - Jump notPowerOfTwo = branchTest32(NonZero, regT0, regT3); - and32(regT0, regT2); - exitBranch.append(jump()); - - notPowerOfTwo.link(this); - -#if CPU(X86) || CPU(X86_64) - move(regT2, regT0); - m_assembler.cdq(); - m_assembler.idivl_r(regT3); - move(regT1, regT2); -#elif CPU(MIPS) - m_assembler.div(regT2, regT3); - m_assembler.mfhi(regT2); -#else - countLeadingZeros32(regT2, regT0); - countLeadingZeros32(regT3, regT1); - sub32(regT0, regT1); - - Jump useFullTable = branch32(Equal, regT1, TrustedImm32(31)); - - neg32(regT1); - add32(TrustedImm32(31), regT1); - - int elementSizeByShift = -1; -#if CPU(ARM) - elementSizeByShift = 3; -#else -#error "JIT_USE_SOFT_MODULO not yet supported on this platform." -#endif - relativeTableJump(regT1, elementSizeByShift); - - useFullTable.link(this); - // Modulo table - for (int i = 31; i > 0; --i) { -#if CPU(ARM_TRADITIONAL) - m_assembler.cmp_r(regT2, m_assembler.lsl(regT3, i)); - m_assembler.sub_r(regT2, regT2, m_assembler.lsl(regT3, i), ARMAssembler::CS); -#elif CPU(ARM_THUMB2) - ShiftTypeAndAmount shift(SRType_LSL, i); - m_assembler.sub_S(regT1, regT2, regT3, shift); - m_assembler.it(ARMv7Assembler::ConditionCS); - m_assembler.mov(regT2, regT1); -#else -#error "JIT_USE_SOFT_MODULO not yet supported on this platform." -#endif - } - - Jump lower = branch32(Below, regT2, regT3); - sub32(regT3, regT2); - lower.link(this); -#endif - - exitBranch.link(this); - - // Check for negative reminder - pop(regT1); - Jump positiveResult = branch32(Equal, regT1, TrustedImm32(0)); - neg32(regT2); - positiveResult.link(this); - - move(regT2, regT0); - ret(); -} -#endif // ENABLE(JIT_USE_SOFT_MODULO) - } // namespace JSC #endif // USE(JSVALUE32_64) diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp index 99c038e55..8c7148c9d 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess.cpp @@ -310,10 +310,6 @@ void JIT::emit_op_method_check(Instruction* currentInstruction) Jump match = jump(); - ASSERT_JIT_OFFSET_UNUSED(protoObj, differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj); - ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoStructureToCompare), patchOffsetMethodCheckProtoStruct); - ASSERT_JIT_OFFSET_UNUSED(putFunction, differenceBetween(info.structureToCompare, putFunction), patchOffsetMethodCheckPutFunction); - // Link the failure cases here. notCell.link(this); structureCheck.link(this); @@ -329,6 +325,8 @@ void JIT::emit_op_method_check(Instruction* currentInstruction) // We've already generated the following get_by_id, so make sure it's skipped over. m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id); + + m_propertyAccessCompilationInfo.last().addMethodCheckInfo(info.structureToCompare, protoObj, protoStructureToCompare, putFunction); } void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -369,25 +367,19 @@ void JIT::compileGetByIdHotPath(int baseVReg, Identifier*) BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath); Label hotPathBegin(this); - m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo()); - m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset; - m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin; DataLabelPtr structureToCompare; - Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); + PatchableJump structureCheck = patchableBranchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); addSlowCase(structureCheck); - ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure); - ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase) loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT0); DataLabelCompact displacementLabel = loadPtrWithCompactAddressOffsetPatch(Address(regT0, patchGetByIdDefaultOffset), regT0); - ASSERT_JIT_OFFSET_UNUSED(displacementLabel, differenceBetween(hotPathBegin, displacementLabel), patchOffsetGetByIdPropertyMapOffset); Label putResult(this); END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath); - ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, putResult), patchOffsetGetByIdPutResult); + m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo(PropertyStubGetById, m_bytecodeOffset, hotPathBegin, structureToCompare, structureCheck, displacementLabel, putResult)); } void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -413,9 +405,7 @@ void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase); -#ifndef NDEBUG Label coldPathBegin(this); -#endif JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id); stubCall.addArgument(regT0); stubCall.addArgument(TrustedImmPtr(ident)); @@ -423,10 +413,8 @@ void JIT::compileGetByIdSlowCase(int resultVReg, int baseVReg, Identifier* ident END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase); - ASSERT_JIT_OFFSET(differenceBetween(coldPathBegin, call), patchOffsetGetByIdSlowCaseCall); - // Track the location of the call; this will be used to recover patch information. - m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].callReturnLocation = call; + m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].slowCaseInfo(PropertyStubGetById, coldPathBegin, call); } void JIT::emit_op_put_by_id(Instruction* currentInstruction) @@ -446,14 +434,10 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById); Label hotPathBegin(this); - m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo()); - m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset; - m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin; // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over. DataLabelPtr structureToCompare; addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)))); - ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure); loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT2); DataLabel32 displacementLabel = storePtrWithAddressOffsetPatch(regT1, Address(regT2, patchPutByIdDefaultOffset)); @@ -462,7 +446,7 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) emitWriteBarrier(regT0, regT1, regT2, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess); - ASSERT_JIT_OFFSET_UNUSED(displacementLabel, differenceBetween(hotPathBegin, displacementLabel), patchOffsetPutByIdPropertyMapOffset); + m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo(PropertyStubPutById, m_bytecodeOffset, hotPathBegin, structureToCompare, displacementLabel)); } void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -481,7 +465,7 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase Call call = stubCall.call(); // Track the location of the call; this will be used to recover patch information. - m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].callReturnLocation = call; + m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].slowCaseInfo(PropertyStubPutById, call); } // Compile a store into an object's property storage. May overwrite the @@ -595,8 +579,8 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St int offset = sizeof(JSValue) * cachedOffset; // Patch the offset into the propoerty map to load from, then patch the Structure to look for. - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset), offset); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.get.structureToCompare), structure); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel), offset); } void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct) @@ -610,8 +594,8 @@ void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, int offset = sizeof(JSValue) * cachedOffset; // Patch the offset into the propoerty map to load from, then patch the Structure to look for. - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset), offset); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.put.structureToCompare), structure); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel), offset); } void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) @@ -632,18 +616,18 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock); // Use the patch information to link the failure cases back to the original slow case routine. - CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall); + CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin); patchBuffer.link(failureCases1, slowCaseBegin); patchBuffer.link(failureCases2, slowCaseBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); // Track the stub we have created so that it will be deleted later. stubInfo->stubRoutine = patchBuffer.finalizeCode(); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code())); @@ -689,12 +673,12 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock); // Use the patch information to link the failure cases back to the original slow case routine. - CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall); + CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin); patchBuffer.link(failureCases1, slowCaseBegin); patchBuffer.link(failureCases2, slowCaseBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); if (needsStubLink) { for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { @@ -706,7 +690,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str stubInfo->stubRoutine = patchBuffer.finalizeCode(); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code())); @@ -753,19 +737,19 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructures->list[currentIndex - 1].stubRoutine.code()); if (!lastProtoBegin) - lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall); + lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin); patchBuffer.link(failureCase, lastProtoBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode(); polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, isDirect); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubCode.code())); } @@ -824,13 +808,13 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi patchBuffer.link(failureCases2, lastProtoBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); MacroAssemblerCodeRef stubCode = patchBuffer.finalizeCode(); prototypeStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubCode, structure, prototypeStructure, isDirect); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubCode.code())); } @@ -893,7 +877,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi patchBuffer.link(bucketsOfFail, lastProtoBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); CodeRef stubRoutine = patchBuffer.finalizeCode(); @@ -901,7 +885,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code())); } @@ -956,17 +940,17 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str } // Use the patch information to link the failure cases back to the original slow case routine. - patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall)); + patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin)); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); // Track the stub we have created so that it will be deleted later. CodeRef stubRoutine = patchBuffer.finalizeCode(); stubInfo->stubRoutine = stubRoutine; // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code())); @@ -1048,9 +1032,9 @@ void JIT::emit_op_put_global_var(Instruction* currentInstruction) void JIT::resetPatchGetById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo) { repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_get_by_id); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), reinterpret_cast<void*>(-1)); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset), 0); - repatchBuffer.relink(stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase), stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall)); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.get.structureToCompare), reinterpret_cast<void*>(-1)); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel), 0); + repatchBuffer.relink(stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck), stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin)); } void JIT::resetPatchPutById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo) @@ -1059,8 +1043,8 @@ void JIT::resetPatchPutById(RepatchBuffer& repatchBuffer, StructureStubInfo* stu repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_put_by_id_direct); else repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_put_by_id); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), reinterpret_cast<void*>(-1)); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetPutByIdPropertyMapOffset), 0); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.put.structureToCompare), reinterpret_cast<void*>(-1)); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.put.displacementLabel), 0); } #endif // USE(JSVALUE64) @@ -1135,7 +1119,7 @@ void JIT::testPrototype(JSValue prototype, JumpList& failureCases) failureCases.append(branchPtr(NotEqual, Address(regT3, JSCell::structureOffset()), TrustedImmPtr(prototype.asCell()->structure()))); } -void JIT::patchMethodCallProto(JSGlobalData& globalData, CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, JSObject* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress) +void JIT::patchMethodCallProto(JSGlobalData& globalData, CodeBlock* codeBlock, MethodCallLinkInfo& methodCallLinkInfo, StructureStubInfo& stubInfo, JSObject* callee, Structure* structure, JSObject* proto, ReturnAddressPtr returnAddress) { RepatchBuffer repatchBuffer(codeBlock); @@ -1143,9 +1127,9 @@ void JIT::patchMethodCallProto(JSGlobalData& globalData, CodeBlock* codeBlock, M methodCallLinkInfo.cachedStructure.set(globalData, structureLocation, codeBlock->ownerExecutable(), structure); Structure* prototypeStructure = proto->structure(); - methodCallLinkInfo.cachedPrototypeStructure.set(globalData, structureLocation.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoStruct), codeBlock->ownerExecutable(), prototypeStructure); - methodCallLinkInfo.cachedPrototype.set(globalData, structureLocation.dataLabelPtrAtOffset(patchOffsetMethodCheckProtoObj), codeBlock->ownerExecutable(), proto); - methodCallLinkInfo.cachedFunction.set(globalData, structureLocation.dataLabelPtrAtOffset(patchOffsetMethodCheckPutFunction), codeBlock->ownerExecutable(), callee); + methodCallLinkInfo.cachedPrototypeStructure.set(globalData, structureLocation.dataLabelPtrAtOffset(stubInfo.patch.baseline.methodCheckProtoStructureToCompare), codeBlock->ownerExecutable(), prototypeStructure); + methodCallLinkInfo.cachedPrototype.set(globalData, structureLocation.dataLabelPtrAtOffset(stubInfo.patch.baseline.methodCheckProtoObj), codeBlock->ownerExecutable(), proto); + methodCallLinkInfo.cachedFunction.set(globalData, structureLocation.dataLabelPtrAtOffset(stubInfo.patch.baseline.methodCheckPutFunction), codeBlock->ownerExecutable(), callee); repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(cti_op_get_by_id_method_check_update)); } diff --git a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp index 19abdbd89..550ad0b2e 100644 --- a/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp +++ b/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp @@ -120,10 +120,6 @@ void JIT::emit_op_method_check(Instruction* currentInstruction) move(TrustedImm32(JSValue::CellTag), regT1); Jump match = jump(); - ASSERT_JIT_OFFSET_UNUSED(protoObj, differenceBetween(info.structureToCompare, protoObj), patchOffsetMethodCheckProtoObj); - ASSERT_JIT_OFFSET(differenceBetween(info.structureToCompare, protoStructureToCompare), patchOffsetMethodCheckProtoStruct); - ASSERT_JIT_OFFSET_UNUSED(putFunction, differenceBetween(info.structureToCompare, putFunction), patchOffsetMethodCheckPutFunction); - // Link the failure cases here. structureCheck.link(this); protoStructureCheck.link(this); @@ -139,6 +135,8 @@ void JIT::emit_op_method_check(Instruction* currentInstruction) // We've already generated the following get_by_id, so make sure it's skipped over. m_bytecodeOffset += OPCODE_LENGTH(op_get_by_id); + + m_propertyAccessCompilationInfo.last().addMethodCheckInfo(info.structureToCompare, protoObj, protoStructureToCompare, putFunction); } void JIT::emitSlow_op_method_check(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -329,26 +327,20 @@ void JIT::compileGetByIdHotPath() BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath); Label hotPathBegin(this); - m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo()); - m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset; - m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin; DataLabelPtr structureToCompare; - Jump structureCheck = branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); + PatchableJump structureCheck = patchableBranchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure))); addSlowCase(structureCheck); - ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetGetByIdStructure); - ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureCheck), patchOffsetGetByIdBranchToSlowCase); loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT2); DataLabelCompact displacementLabel1 = loadPtrWithCompactAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT0); // payload - ASSERT_JIT_OFFSET_UNUSED(displacementLabel1, differenceBetween(hotPathBegin, displacementLabel1), patchOffsetGetByIdPropertyMapOffset1); DataLabelCompact displacementLabel2 = loadPtrWithCompactAddressOffsetPatch(Address(regT2, patchGetByIdDefaultOffset), regT1); // tag - ASSERT_JIT_OFFSET_UNUSED(displacementLabel2, differenceBetween(hotPathBegin, displacementLabel2), patchOffsetGetByIdPropertyMapOffset2); Label putResult(this); - ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, putResult), patchOffsetGetByIdPutResult); END_UNINTERRUPTED_SEQUENCE(sequenceGetByIdHotPath); + + m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo(PropertyStubGetById, m_bytecodeOffset, hotPathBegin, structureToCompare, structureCheck, displacementLabel1, displacementLabel2, putResult)); } void JIT::emitSlow_op_get_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -373,9 +365,7 @@ void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<Sl BEGIN_UNINTERRUPTED_SEQUENCE(sequenceGetByIdSlowCase); -#ifndef NDEBUG Label coldPathBegin(this); -#endif JITStubCall stubCall(this, isMethodCheck ? cti_op_get_by_id_method_check : cti_op_get_by_id); stubCall.addArgument(regT1, regT0); stubCall.addArgument(TrustedImmPtr(ident)); @@ -383,10 +373,8 @@ void JIT::compileGetByIdSlowCase(int dst, int base, Identifier* ident, Vector<Sl END_UNINTERRUPTED_SEQUENCE_FOR_PUT(sequenceGetByIdSlowCase, dst); - ASSERT_JIT_OFFSET(differenceBetween(coldPathBegin, call), patchOffsetGetByIdSlowCaseCall); - // Track the location of the call; this will be used to recover patch information. - m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].callReturnLocation = call; + m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].slowCaseInfo(PropertyStubGetById, coldPathBegin, call); } void JIT::emit_op_put_by_id(Instruction* currentInstruction) @@ -405,14 +393,10 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) BEGIN_UNINTERRUPTED_SEQUENCE(sequencePutById); Label hotPathBegin(this); - m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo()); - m_propertyAccessCompilationInfo.last().bytecodeIndex = m_bytecodeOffset; - m_propertyAccessCompilationInfo.last().hotPathBegin = hotPathBegin; // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over. DataLabelPtr structureToCompare; addSlowCase(branchPtrWithPatch(NotEqual, Address(regT0, JSCell::structureOffset()), structureToCompare, TrustedImmPtr(reinterpret_cast<void*>(patchGetByIdDefaultStructure)))); - ASSERT_JIT_OFFSET(differenceBetween(hotPathBegin, structureToCompare), patchOffsetPutByIdStructure); loadPtr(Address(regT0, JSObject::offsetOfPropertyStorage()), regT1); DataLabel32 displacementLabel1 = storePtrWithAddressOffsetPatch(regT2, Address(regT1, patchPutByIdDefaultOffset)); // payload @@ -421,9 +405,8 @@ void JIT::emit_op_put_by_id(Instruction* currentInstruction) END_UNINTERRUPTED_SEQUENCE(sequencePutById); emitWriteBarrier(regT0, regT2, regT1, regT2, ShouldFilterImmediates, WriteBarrierForPropertyAccess); - - ASSERT_JIT_OFFSET_UNUSED(displacementLabel1, differenceBetween(hotPathBegin, displacementLabel1), patchOffsetPutByIdPropertyMapOffset1); - ASSERT_JIT_OFFSET_UNUSED(displacementLabel2, differenceBetween(hotPathBegin, displacementLabel2), patchOffsetPutByIdPropertyMapOffset2); + + m_propertyAccessCompilationInfo.append(PropertyStubCompilationInfo(PropertyStubPutById, m_bytecodeOffset, hotPathBegin, structureToCompare, displacementLabel1, displacementLabel2)); } void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCaseEntry>::iterator& iter) @@ -442,7 +425,7 @@ void JIT::emitSlow_op_put_by_id(Instruction* currentInstruction, Vector<SlowCase Call call = stubCall.call(); // Track the location of the call; this will be used to recover patch information. - m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].callReturnLocation = call; + m_propertyAccessCompilationInfo[m_propertyAccessInstructionIndex++].slowCaseInfo(PropertyStubPutById, call); } // Compile a store into an object's property storage. May overwrite base. @@ -577,9 +560,9 @@ void JIT::patchGetByIdSelf(CodeBlock* codeBlock, StructureStubInfo* stubInfo, St int offset = sizeof(JSValue) * cachedOffset; // Patch the offset into the propoerty map to load from, then patch the Structure to look for. - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), structure); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.get.structureToCompare), structure); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag } void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, Structure* structure, size_t cachedOffset, ReturnAddressPtr returnAddress, bool direct) @@ -593,9 +576,9 @@ void JIT::patchPutByIdReplace(CodeBlock* codeBlock, StructureStubInfo* stubInfo, int offset = sizeof(JSValue) * cachedOffset; // Patch the offset into the propoerty map to load from, then patch the Structure to look for. - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), structure); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.put.structureToCompare), structure); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel1), offset + OBJECT_OFFSETOF(JSValue, u.asBits.payload)); // payload + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel2), offset + OBJECT_OFFSETOF(JSValue, u.asBits.tag)); // tag } void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) @@ -619,18 +602,18 @@ void JIT::privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress) LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock); // Use the patch information to link the failure cases back to the original slow case routine. - CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall); + CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin); patchBuffer.link(failureCases1, slowCaseBegin); patchBuffer.link(failureCases2, slowCaseBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); // Track the stub we have created so that it will be deleted later. stubInfo->stubRoutine = patchBuffer.finalizeCode(); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code())); @@ -678,12 +661,12 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str LinkBuffer patchBuffer(*m_globalData, this, m_codeBlock); // Use the patch information to link the failure cases back to the original slow case routine. - CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall); + CodeLocationLabel slowCaseBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin); patchBuffer.link(failureCases1, slowCaseBegin); patchBuffer.link(failureCases2, slowCaseBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); if (needsStubLink) { for (Vector<CallRecord>::iterator iter = m_calls.begin(); iter != m_calls.end(); ++iter) { @@ -696,7 +679,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str stubInfo->stubRoutine = patchBuffer.finalizeCode(); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubInfo->stubRoutine.code())); @@ -744,19 +727,19 @@ void JIT::privateCompileGetByIdSelfList(StructureStubInfo* stubInfo, Polymorphic // Use the patch information to link the failure cases back to the original slow case routine. CodeLocationLabel lastProtoBegin = CodeLocationLabel(polymorphicStructures->list[currentIndex - 1].stubRoutine.code()); if (!lastProtoBegin) - lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall); + lastProtoBegin = stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin); patchBuffer.link(failureCase, lastProtoBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); CodeRef stubRoutine = patchBuffer.finalizeCode(); polymorphicStructures->list[currentIndex].set(*m_globalData, m_codeBlock->ownerExecutable(), stubRoutine, structure, isDirect); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code())); } @@ -814,14 +797,14 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi patchBuffer.link(failureCases2, lastProtoBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); CodeRef stubRoutine = patchBuffer.finalizeCode(); prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, prototypeStructure, isDirect); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code())); } @@ -884,7 +867,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi patchBuffer.link(bucketsOfFail, lastProtoBegin); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); CodeRef stubRoutine = patchBuffer.finalizeCode(); @@ -892,7 +875,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi prototypeStructures->list[currentIndex].set(callFrame->globalData(), m_codeBlock->ownerExecutable(), stubRoutine, structure, chain, isDirect); // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code())); } @@ -946,17 +929,17 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str } } // Use the patch information to link the failure cases back to the original slow case routine. - patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall)); + patchBuffer.link(bucketsOfFail, stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin)); // 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)); + patchBuffer.link(success, stubInfo->hotPathBegin.labelAtOffset(stubInfo->patch.baseline.u.get.putResult)); // Track the stub we have created so that it will be deleted later. CodeRef stubRoutine = patchBuffer.finalizeCode(); stubInfo->stubRoutine = stubRoutine; // Finally patch the jump to slow case back in the hot path to jump here instead. - CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase); + CodeLocationJump jumpLocation = stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck); RepatchBuffer repatchBuffer(m_codeBlock); repatchBuffer.relink(jumpLocation, CodeLocationLabel(stubRoutine.code())); @@ -1109,10 +1092,10 @@ void JIT::emit_op_put_global_var(Instruction* currentInstruction) void JIT::resetPatchGetById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo) { repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_get_by_id); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetGetByIdStructure), reinterpret_cast<void*>(-1)); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset1), 0); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(patchOffsetGetByIdPropertyMapOffset2), 0); - repatchBuffer.relink(stubInfo->hotPathBegin.jumpAtOffset(patchOffsetGetByIdBranchToSlowCase), stubInfo->callReturnLocation.labelAtOffset(-patchOffsetGetByIdSlowCaseCall)); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.get.structureToCompare), reinterpret_cast<void*>(-1)); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel1), 0); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelCompactAtOffset(stubInfo->patch.baseline.u.get.displacementLabel2), 0); + repatchBuffer.relink(stubInfo->hotPathBegin.jumpAtOffset(stubInfo->patch.baseline.u.get.structureCheck), stubInfo->callReturnLocation.labelAtOffset(-stubInfo->patch.baseline.u.get.coldPathBegin)); } void JIT::resetPatchPutById(RepatchBuffer& repatchBuffer, StructureStubInfo* stubInfo) @@ -1121,9 +1104,9 @@ void JIT::resetPatchPutById(RepatchBuffer& repatchBuffer, StructureStubInfo* stu repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_put_by_id_direct); else repatchBuffer.relink(stubInfo->callReturnLocation, cti_op_put_by_id); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(patchOffsetPutByIdStructure), reinterpret_cast<void*>(-1)); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset1), 0); - repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(patchOffsetPutByIdPropertyMapOffset2), 0); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabelPtrAtOffset(stubInfo->patch.baseline.u.put.structureToCompare), reinterpret_cast<void*>(-1)); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel1), 0); + repatchBuffer.repatch(stubInfo->hotPathBegin.dataLabel32AtOffset(stubInfo->patch.baseline.u.put.displacementLabel2), 0); } } // namespace JSC diff --git a/Source/JavaScriptCore/jit/JITStubs.cpp b/Source/JavaScriptCore/jit/JITStubs.cpp index eebe90427..d81e68aae 100644 --- a/Source/JavaScriptCore/jit/JITStubs.cpp +++ b/Source/JavaScriptCore/jit/JITStubs.cpp @@ -48,7 +48,6 @@ #include "JITExceptions.h" #include "JSActivation.h" #include "JSArray.h" -#include "JSByteArray.h" #include "JSFunction.h" #include "JSGlobalObjectFunctions.h" #include "JSNotAnObject.h" @@ -1281,7 +1280,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_create_this) STUB_INIT_STACK_FRAME(stackFrame); CallFrame* callFrame = stackFrame.callFrame; - JSFunction* constructor = asFunction(callFrame->callee()); + JSFunction* constructor = jsCast<JSFunction*>(callFrame->callee()); #if !ASSERT_DISABLED ConstructData constructData; ASSERT(constructor->methodTable()->getConstructData(constructor, constructData) == ConstructTypeJS); @@ -1498,7 +1497,9 @@ DEFINE_STUB_FUNCTION(JSObject*, op_put_by_id_transition_realloc) ASSERT(baseValue.isObject()); JSObject* base = asObject(baseValue); - base->allocatePropertyStorage(*stackFrame.globalData, oldSize, newSize); + JSGlobalData& globalData = *stackFrame.globalData; + PropertyStorage newStorage = base->growPropertyStorage(globalData, oldSize, newSize); + base->setPropertyStorage(globalData, newStorage, newStructure); return base; } @@ -1517,6 +1518,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check) CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS); + StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS); if (!methodCallLinkInfo.seenOnce()) { methodCallLinkInfo.setSeen(); @@ -1555,7 +1557,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check) // Check to see if the function is on the object's prototype. Patch up the code to optimize. if (slot.slotBase() == structure->prototypeForLookup(callFrame)) { - JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS); + JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS); return JSValue::encode(result); } @@ -1566,7 +1568,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check) // for now. For now it performs a check on a special object on the global object only used for this // purpose. The object is in no way exposed, and as such the check will always pass. if (slot.slotBase() == baseValue) { - JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS); + JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS); return JSValue::encode(result); } } @@ -1590,6 +1592,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_update) CodeBlock* codeBlock = stackFrame.callFrame->codeBlock(); MethodCallLinkInfo& methodCallLinkInfo = codeBlock->getMethodCallLinkInfo(STUB_RETURN_ADDRESS); + StructureStubInfo& stubInfo = codeBlock->getStubInfo(STUB_RETURN_ADDRESS); ASSERT(methodCallLinkInfo.seenOnce()); @@ -1650,7 +1653,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_update) // Check to see if the function is on the object's prototype. Patch up the code to optimize. if (slot.slotBase() == proto) { - JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS); + JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, slotBaseObject, STUB_RETURN_ADDRESS); return JSValue::encode(result); } @@ -1661,7 +1664,7 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_id_method_check_update) // useful. We could try to nop it out altogether, but that's a little messy, so lets do something simpler // for now. For now it performs a check on a special object on the global object only used for this // purpose. The object is in no way exposed, and as such the check will always pass. - JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS); + JIT::patchMethodCallProto(callFrame->globalData(), codeBlock, methodCallLinkInfo, stubInfo, callee, structure, callFrame->scopeChain()->globalObject->methodCallDummy(), STUB_RETURN_ADDRESS); return JSValue::encode(result); } @@ -2149,7 +2152,7 @@ DEFINE_STUB_FUNCTION(JSObject*, op_new_func) inline void* jitCompileFor(CallFrame* callFrame, CodeSpecializationKind kind) { - JSFunction* function = asFunction(callFrame->callee()); + JSFunction* function = jsCast<JSFunction*>(callFrame->callee()); ASSERT(!function->isHostFunction()); FunctionExecutable* executable = function->jsExecutable(); ScopeChainNode* callDataScopeChain = function->scope(); @@ -2183,7 +2186,7 @@ DEFINE_STUB_FUNCTION(void*, op_construct_jitCompile) #if !ASSERT_DISABLED ConstructData constructData; - ASSERT(asFunction(stackFrame.callFrame->callee())->methodTable()->getConstructData(stackFrame.callFrame->callee(), constructData) == ConstructTypeJS); + ASSERT(jsCast<JSFunction*>(stackFrame.callFrame->callee())->methodTable()->getConstructData(stackFrame.callFrame->callee(), constructData) == ConstructTypeJS); #endif CallFrame* callFrame = stackFrame.callFrame; @@ -2222,7 +2225,7 @@ DEFINE_STUB_FUNCTION(void*, op_construct_arityCheck) inline void* lazyLinkFor(CallFrame* callFrame, CodeSpecializationKind kind) { - JSFunction* callee = asFunction(callFrame->callee()); + JSFunction* callee = jsCast<JSFunction*>(callFrame->callee()); ExecutableBase* executable = callee->executable(); MacroAssemblerCodePtr codePtr; @@ -2233,9 +2236,10 @@ inline void* lazyLinkFor(CallFrame* callFrame, CodeSpecializationKind kind) codePtr = executable->generatedJITCodeFor(kind).addressForCall(); else { FunctionExecutable* functionExecutable = static_cast<FunctionExecutable*>(executable); - JSObject* error = functionExecutable->compileFor(callFrame, callee->scope(), kind); - if (error) + if (JSObject* error = functionExecutable->compileFor(callFrame, callee->scope(), kind)) { + callFrame->globalData().exception = error; return 0; + } codeBlock = &functionExecutable->generatedBytecodeFor(kind); if (callFrame->argumentCountIncludingThis() < static_cast<size_t>(codeBlock->numParameters()) || callLinkInfo->callType == CallLinkInfo::CallVarargs) @@ -2444,11 +2448,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val) CHECK_FOR_EXCEPTION(); return JSValue::encode(result); } - if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { - // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. - ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val_byte_array)); - return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i)); - } JSValue result = baseValue.get(callFrame, i); CHECK_FOR_EXCEPTION(); return JSValue::encode(result); @@ -2489,36 +2488,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_string) return JSValue::encode(result); } -DEFINE_STUB_FUNCTION(EncodedJSValue, op_get_by_val_byte_array) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - CallFrame* callFrame = stackFrame.callFrame; - - JSValue baseValue = stackFrame.args[0].jsValue(); - JSValue subscript = stackFrame.args[1].jsValue(); - - JSValue result; - - if (LIKELY(subscript.isUInt32())) { - uint32_t i = subscript.asUInt32(); - if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { - // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. - return JSValue::encode(asByteArray(baseValue)->getIndex(callFrame, i)); - } - - result = baseValue.get(callFrame, i); - if (!isJSByteArray(baseValue)) - ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_get_by_val)); - } else { - Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); - result = baseValue.get(callFrame, property); - } - - CHECK_FOR_EXCEPTION_AT_END(); - return JSValue::encode(result); -} - DEFINE_STUB_FUNCTION(EncodedJSValue, op_sub) { STUB_INIT_STACK_FRAME(stackFrame); @@ -2554,21 +2523,6 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val) jsArray->setIndex(*globalData, i, value); else JSArray::putByIndex(jsArray, callFrame, i, value, callFrame->codeBlock()->isStrictMode()); - } else if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { - JSByteArray* jsByteArray = asByteArray(baseValue); - ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val_byte_array)); - // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. - if (value.isInt32()) { - jsByteArray->setIndex(i, value.asInt32()); - return; - } else { - if (value.isNumber()) { - jsByteArray->setIndex(i, value.asNumber()); - return; - } - } - - baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode()); } else baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode()); } else { @@ -2582,47 +2536,6 @@ DEFINE_STUB_FUNCTION(void, op_put_by_val) CHECK_FOR_EXCEPTION_AT_END(); } -DEFINE_STUB_FUNCTION(void, op_put_by_val_byte_array) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - CallFrame* callFrame = stackFrame.callFrame; - - JSValue baseValue = stackFrame.args[0].jsValue(); - JSValue subscript = stackFrame.args[1].jsValue(); - JSValue value = stackFrame.args[2].jsValue(); - - if (LIKELY(subscript.isUInt32())) { - uint32_t i = subscript.asUInt32(); - if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) { - JSByteArray* jsByteArray = asByteArray(baseValue); - - // All fast byte array accesses are safe from exceptions so return immediately to avoid exception checks. - if (value.isInt32()) { - jsByteArray->setIndex(i, value.asInt32()); - return; - } else { - if (value.isNumber()) { - jsByteArray->setIndex(i, value.asNumber()); - return; - } - } - } - - if (!isJSByteArray(baseValue)) - ctiPatchCallByReturnAddress(callFrame->codeBlock(), STUB_RETURN_ADDRESS, FunctionPtr(cti_op_put_by_val)); - baseValue.putByIndex(callFrame, i, value, callFrame->codeBlock()->isStrictMode()); - } else { - Identifier property(callFrame, subscript.toString(callFrame)->value(callFrame)); - if (!stackFrame.globalData->exception) { // Don't put to an object if toString threw an exception. - PutPropertySlot slot(callFrame->codeBlock()->isStrictMode()); - baseValue.put(callFrame, property, value, slot); - } - } - - CHECK_FOR_EXCEPTION_AT_END(); -} - DEFINE_STUB_FUNCTION(EncodedJSValue, op_less) { STUB_INIT_STACK_FRAME(stackFrame); @@ -2949,20 +2862,20 @@ DEFINE_STUB_FUNCTION(int, op_eq) if (cell1->isString()) { if (src2.isInt32()) - return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32(); + return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asInt32(); if (src2.isDouble()) - return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble(); + return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == src2.asDouble(); if (src2.isTrue()) - return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0; + return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 1.0; if (src2.isFalse()) - return jsToNumber(static_cast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0; + return jsToNumber(jsCast<JSString*>(cell1)->value(stackFrame.callFrame)) == 0.0; JSCell* cell2 = src2.asCell(); if (cell2->isString()) - return static_cast<JSString*>(cell1)->value(stackFrame.callFrame) == static_cast<JSString*>(cell2)->value(stackFrame.callFrame); + return jsCast<JSString*>(cell1)->value(stackFrame.callFrame) == jsCast<JSString*>(cell2)->value(stackFrame.callFrame); src2 = asObject(cell2)->toPrimitive(stackFrame.callFrame); CHECK_FOR_EXCEPTION(); @@ -3252,35 +3165,6 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, op_typeof) return JSValue::encode(jsTypeStringForValue(stackFrame.callFrame, stackFrame.args[0].jsValue())); } -DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_undefined) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - JSValue v = stackFrame.args[0].jsValue(); - return JSValue::encode(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined())); -} - -DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_boolean) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isBoolean())); -} - -DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_number) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - return JSValue::encode(jsBoolean(stackFrame.args[0].jsValue().isNumber())); -} - -DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_string) -{ - STUB_INIT_STACK_FRAME(stackFrame); - - return JSValue::encode(jsBoolean(isJSString(stackFrame.args[0].jsValue()))); -} - DEFINE_STUB_FUNCTION(EncodedJSValue, op_is_object) { STUB_INIT_STACK_FRAME(stackFrame); @@ -3558,24 +3442,24 @@ DEFINE_STUB_FUNCTION(EncodedJSValue, to_object) MacroAssemblerCodeRef JITThunks::ctiStub(JSGlobalData* globalData, ThunkGenerator generator) { - std::pair<CTIStubMap::iterator, bool> entry = m_ctiStubMap.add(generator, MacroAssemblerCodeRef()); - if (entry.second) - entry.first->second = generator(globalData); - return entry.first->second; + CTIStubMap::AddResult entry = m_ctiStubMap.add(generator, MacroAssemblerCodeRef()); + if (entry.isNewEntry) + entry.iterator->second = generator(globalData); + return entry.iterator->second; } NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, NativeFunction constructor) { - std::pair<HostFunctionStubMap::iterator, bool> result = m_hostFunctionStubMap->add(function, PassWeak<NativeExecutable>()); - if (!result.first->second) - result.first->second = PassWeak<NativeExecutable>(*globalData, NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, function), function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), constructor, NoIntrinsic)); - return result.first->second.get(); + HostFunctionStubMap::AddResult result = m_hostFunctionStubMap->add(function, PassWeak<NativeExecutable>()); + if (!result.iterator->second) + result.iterator->second = PassWeak<NativeExecutable>(NativeExecutable::create(*globalData, JIT::compileCTINativeCall(globalData, function), function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), constructor, NoIntrinsic)); + return result.iterator->second.get(); } NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFunction function, ThunkGenerator generator, Intrinsic intrinsic) { - std::pair<HostFunctionStubMap::iterator, bool> entry = m_hostFunctionStubMap->add(function, PassWeak<NativeExecutable>()); - if (!*entry.first->second) { + HostFunctionStubMap::AddResult entry = m_hostFunctionStubMap->add(function, PassWeak<NativeExecutable>()); + if (!entry.iterator->second) { MacroAssemblerCodeRef code; if (generator) { if (globalData->canUseJIT()) @@ -3584,9 +3468,9 @@ NativeExecutable* JITThunks::hostFunctionStub(JSGlobalData* globalData, NativeFu code = MacroAssemblerCodeRef(); } else code = JIT::compileCTINativeCall(globalData, function); - entry.first->second = PassWeak<NativeExecutable>(*globalData, NativeExecutable::create(*globalData, code, function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), callHostFunctionAsConstructor, intrinsic)); + entry.iterator->second = PassWeak<NativeExecutable>(NativeExecutable::create(*globalData, code, function, MacroAssemblerCodeRef::createSelfManagedCodeRef(ctiNativeConstruct()), callHostFunctionAsConstructor, intrinsic)); } - return entry.first->second.get(); + return entry.iterator->second.get(); } void JITThunks::clearHostFunctionStubs() diff --git a/Source/JavaScriptCore/jit/JITStubs.h b/Source/JavaScriptCore/jit/JITStubs.h index 49f666465..786353df5 100644 --- a/Source/JavaScriptCore/jit/JITStubs.h +++ b/Source/JavaScriptCore/jit/JITStubs.h @@ -92,7 +92,6 @@ namespace JSC { MacroAssemblerCodePtr ctiVirtualConstruct; MacroAssemblerCodePtr ctiNativeCall; MacroAssemblerCodePtr ctiNativeConstruct; - MacroAssemblerCodePtr ctiSoftModulo; }; #if CPU(X86_64) @@ -323,7 +322,6 @@ namespace JSC { #endif return m_trampolineStructure.ctiNativeConstruct; } - MacroAssemblerCodePtr ctiSoftModulo() { return m_trampolineStructure.ctiSoftModulo; } MacroAssemblerCodeRef ctiStub(JSGlobalData*, ThunkGenerator); @@ -369,7 +367,6 @@ extern "C" { EncodedJSValue JIT_STUB cti_op_get_by_id_self_fail(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_get_by_id_string_fail(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_get_by_val(STUB_ARGS_DECLARATION); - EncodedJSValue JIT_STUB cti_op_get_by_val_byte_array(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_get_by_val_string(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_in(STUB_ARGS_DECLARATION); EncodedJSValue JIT_STUB cti_op_instanceof(STUB_ARGS_DECLARATION); @@ -447,7 +444,6 @@ extern "C" { void JIT_STUB cti_op_put_by_id_direct_generic(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_put_by_index(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_put_by_val(STUB_ARGS_DECLARATION); - void JIT_STUB cti_op_put_by_val_byte_array(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_put_getter_setter(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_tear_off_activation(STUB_ARGS_DECLARATION); void JIT_STUB cti_op_tear_off_arguments(STUB_ARGS_DECLARATION); diff --git a/Source/JavaScriptCore/jsc.cpp b/Source/JavaScriptCore/jsc.cpp index 3d9d1d33e..665333d64 100644 --- a/Source/JavaScriptCore/jsc.cpp +++ b/Source/JavaScriptCore/jsc.cpp @@ -24,7 +24,7 @@ #include "BytecodeGenerator.h" #include "Completion.h" -#include "CurrentTime.h" +#include <wtf/CurrentTime.h> #include "ExceptionHelpers.h" #include "InitializeThreading.h" #include "Interpreter.h" @@ -33,7 +33,7 @@ #include "JSFunction.h" #include "JSLock.h" #include "JSString.h" -#include "MainThread.h" +#include <wtf/MainThread.h> #include "SamplingTool.h" #include <math.h> #include <stdio.h> @@ -72,10 +72,14 @@ #include <QDateTime> #endif +#if PLATFORM(IOS) +#include <fenv.h> +#include <arm/arch.h> +#endif + using namespace JSC; using namespace WTF; -static void cleanupGlobalData(JSGlobalData*); static bool fillBufferWithContentsOfFile(const UString& fileName, Vector<char>& buffer); static EncodedJSValue JSC_HOST_CALL functionPrint(ExecState*); @@ -195,8 +199,8 @@ protected: addFunction(globalData, "clearSamplingFlags", functionClearSamplingFlags, 1); #endif -#if ENABLE(COMMANDLINE_TYPEDARRAYS) addConstructableFunction(globalData, "Uint8Array", constructJSUint8Array, 1); + addConstructableFunction(globalData, "Uint8ClampedArray", constructJSUint8ClampedArray, 1); addConstructableFunction(globalData, "Uint16Array", constructJSUint16Array, 1); addConstructableFunction(globalData, "Uint32Array", constructJSUint32Array, 1); addConstructableFunction(globalData, "Int8Array", constructJSInt8Array, 1); @@ -204,7 +208,6 @@ protected: addConstructableFunction(globalData, "Int32Array", constructJSInt32Array, 1); addConstructableFunction(globalData, "Float32Array", constructJSFloat32Array, 1); addConstructableFunction(globalData, "Float64Array", constructJSFloat64Array, 1); -#endif JSArray* array = constructEmptyArray(globalExec()); for (size_t i = 0; i < arguments.size(); ++i) @@ -221,7 +224,7 @@ protected: void addConstructableFunction(JSGlobalData& globalData, const char* name, NativeFunction function, unsigned arguments) { Identifier identifier(globalExec(), name); - putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier, function, function)); + putDirect(globalData, identifier, JSFunction::create(globalExec(), this, arguments, identifier, function, NoIntrinsic, function)); } }; COMPILE_ASSERT(!IsInteger<GlobalObject>::value, WTF_IsInteger_GlobalObject_false); @@ -277,7 +280,7 @@ EncodedJSValue JSC_HOST_CALL functionJSCStack(ExecState* exec) { String trace = "--> Stack trace:\n"; Vector<StackFrame> stackTrace; - Interpreter::getStackTrace(&exec->globalData(), -1, stackTrace); + Interpreter::getStackTrace(&exec->globalData(), stackTrace); int i = 0; for (Vector<StackFrame>::iterator iter = stackTrace.begin(); iter < stackTrace.end(); iter++) { @@ -321,11 +324,17 @@ EncodedJSValue JSC_HOST_CALL functionRun(ExecState* exec) GlobalObject* globalObject = GlobalObject::create(exec->globalData(), GlobalObject::createStructure(exec->globalData(), jsNull()), Vector<UString>()); + JSValue exception; StopWatch stopWatch; stopWatch.start(); - evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(script.data(), fileName)); + evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(script.data(), fileName), JSValue(), &exception); stopWatch.stop(); + if (!!exception) { + throwError(globalObject->globalExec(), exception); + return JSValue::encode(jsUndefined()); + } + return JSValue::encode(jsNumber(stopWatch.getElapsedMS())); } @@ -407,14 +416,8 @@ EncodedJSValue JSC_HOST_CALL functionPreciseTime(ExecState*) return JSValue::encode(jsNumber(currentTime())); } -EncodedJSValue JSC_HOST_CALL functionQuit(ExecState* exec) +EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*) { - // Technically, destroying the heap in the middle of JS execution is a no-no, - // but we want to maintain compatibility with the Mozilla test suite, so - // we pretend that execution has terminated to avoid ASSERTs, then tear down the heap. - exec->globalData().dynamicGlobalObject = 0; - - cleanupGlobalData(&exec->globalData()); exit(EXIT_SUCCESS); #if COMPILER(MSVC) && OS(WINCE) @@ -436,10 +439,18 @@ EncodedJSValue JSC_HOST_CALL functionQuit(ExecState* exec) #define EXCEPT(x) #endif -int jscmain(int argc, char** argv, JSGlobalData*); +int jscmain(int argc, char** argv); int main(int argc, char** argv) { +#if PLATFORM(IOS) + // Enabled IEEE754 denormal support. + fenv_t env; + fegetenv( &env ); + env.__fpscr &= ~0x01000000u; + fesetenv( &env ); +#endif + #if OS(WINDOWS) #if !OS(WINCE) // Cygwin calls ::SetErrorMode(SEM_FAILCRITICALERRORS), which we will inherit. This is bad for @@ -473,23 +484,12 @@ 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(ThreadStackTypeLarge, LargeHeap).leakRef(); TRY - res = jscmain(argc, argv, globalData); + res = jscmain(argc, argv); EXCEPT(res = 3) - - cleanupGlobalData(globalData); return res; } -static void cleanupGlobalData(JSGlobalData* globalData) -{ - JSLock lock(SilenceAssertionsOnly); - globalData->clearBuiltinStructures(); - globalData->heap.destroy(); - globalData->deref(); -} - static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scripts, bool dump) { const char* script; @@ -522,11 +522,14 @@ static bool runWithScripts(GlobalObject* globalObject, const Vector<Script>& scr JSValue evaluationException; JSValue returnValue = evaluate(globalObject->globalExec(), globalObject->globalScopeChain(), jscSource(script, fileName), JSValue(), &evaluationException); success = success && !evaluationException; - if (dump) { - if (evaluationException) - printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data()); - else - printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data()); + if (dump && !evaluationException) + printf("End: %s\n", returnValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data()); + if (evaluationException) { + printf("Exception: %s\n", evaluationException.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data()); + Identifier stackID(globalObject->globalExec(), "stack"); + JSValue stackValue = evaluationException.get(globalObject->globalExec(), stackID); + if (!stackValue.isUndefinedOrNull()) + printf("%s\n", stackValue.toString(globalObject->globalExec())->value(globalObject->globalExec()).utf8().data()); } globalData.stopSampling(); @@ -592,7 +595,7 @@ static void runInteractive(GlobalObject* globalObject) printf("\n"); } -static NO_RETURN void printUsageStatement(JSGlobalData* globalData, bool help = false) +static NO_RETURN void printUsageStatement(bool help = false) { fprintf(stderr, "Usage: jsc [options] [files] [-- arguments]\n"); fprintf(stderr, " -d Dumps bytecode (debug builds only)\n"); @@ -604,24 +607,23 @@ static NO_RETURN void printUsageStatement(JSGlobalData* globalData, bool help = fprintf(stderr, " -s Installs signal handlers that exit on a crash (Unix platforms only)\n"); #endif - cleanupGlobalData(globalData); exit(help ? EXIT_SUCCESS : EXIT_FAILURE); } -static void parseArguments(int argc, char** argv, CommandLine& options, JSGlobalData* globalData) +static void parseArguments(int argc, char** argv, CommandLine& options) { int i = 1; for (; i < argc; ++i) { const char* arg = argv[i]; if (!strcmp(arg, "-f")) { if (++i == argc) - printUsageStatement(globalData); + printUsageStatement(); options.scripts.append(Script(true, argv[i])); continue; } if (!strcmp(arg, "-e")) { if (++i == argc) - printUsageStatement(globalData); + printUsageStatement(); options.scripts.append(Script(false, argv[i])); continue; } @@ -647,7 +649,7 @@ static void parseArguments(int argc, char** argv, CommandLine& options, JSGlobal break; } if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) - printUsageStatement(globalData, true); + printUsageStatement(true); options.scripts.append(Script(true, argv[i])); } @@ -658,12 +660,14 @@ static void parseArguments(int argc, char** argv, CommandLine& options, JSGlobal options.arguments.append(argv[i]); } -int jscmain(int argc, char** argv, JSGlobalData* globalData) +int jscmain(int argc, char** argv) { JSLock lock(SilenceAssertionsOnly); + RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap); + CommandLine options; - parseArguments(argc, argv, options, globalData); + parseArguments(argc, argv, options); GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments); bool success = runWithScripts(globalObject, options.scripts, options.dump); diff --git a/Source/JavaScriptCore/llint/LLIntExceptions.cpp b/Source/JavaScriptCore/llint/LLIntExceptions.cpp index a7d1a965a..20b0db3d9 100644 --- a/Source/JavaScriptCore/llint/LLIntExceptions.cpp +++ b/Source/JavaScriptCore/llint/LLIntExceptions.cpp @@ -40,6 +40,7 @@ namespace JSC { namespace LLInt { void interpreterThrowInCaller(ExecState* exec, ReturnAddressPtr pc) { JSGlobalData* globalData = &exec->globalData(); + NativeCallFrameTracer tracer(globalData, exec); #if LLINT_SLOW_PATH_TRACING dataLog("Throwing exception %s.\n", globalData->exception.description()); #endif @@ -56,6 +57,7 @@ Instruction* returnToThrowForThrownException(ExecState* exec) Instruction* returnToThrow(ExecState* exec, Instruction* pc) { JSGlobalData* globalData = &exec->globalData(); + NativeCallFrameTracer tracer(globalData, exec); #if LLINT_SLOW_PATH_TRACING dataLog("Throwing exception %s (returnToThrow).\n", globalData->exception.description()); #endif @@ -67,6 +69,7 @@ Instruction* returnToThrow(ExecState* exec, Instruction* pc) void* callToThrow(ExecState* exec, Instruction* pc) { JSGlobalData* globalData = &exec->globalData(); + NativeCallFrameTracer tracer(globalData, exec); #if LLINT_SLOW_PATH_TRACING dataLog("Throwing exception %s (callToThrow).\n", globalData->exception.description()); #endif diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp index b6bb664bc..2b5161f7b 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp @@ -37,7 +37,6 @@ #include "JIT.h" #include "JITDriver.h" #include "JSActivation.h" -#include "JSByteArray.h" #include "JSGlobalObjectFunctions.h" #include "JSPropertyNameIterator.h" #include "JSStaticScopeObject.h" @@ -189,7 +188,7 @@ LLINT_SLOW_PATH_DECL(trace_prologue) static void traceFunctionPrologue(ExecState* exec, const char* comment, CodeSpecializationKind kind) { - JSFunction* callee = asFunction(exec->callee()); + JSFunction* callee = jsCast<JSFunction*>(exec->callee()); FunctionExecutable* executable = callee->jsExecutable(); CodeBlock* codeBlock = &executable->generatedBytecodeFor(kind); dataLog("%p / %p: in %s of function %p, executable %p; numVars = %u, numParameters = %u, numCalleeRegisters = %u, caller = %p.\n", @@ -316,22 +315,22 @@ LLINT_SLOW_PATH_DECL(entry_osr) LLINT_SLOW_PATH_DECL(entry_osr_function_for_call) { - return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call", Prologue); + return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call", Prologue); } LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct) { - return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct", Prologue); + return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct", Prologue); } LLINT_SLOW_PATH_DECL(entry_osr_function_for_call_arityCheck) { - return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call_arityCheck", ArityCheck); + return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForCall), "entry_osr_function_for_call_arityCheck", ArityCheck); } LLINT_SLOW_PATH_DECL(entry_osr_function_for_construct_arityCheck) { - return entryOSR(exec, pc, &asFunction(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct_arityCheck", ArityCheck); + return entryOSR(exec, pc, &jsCast<JSFunction*>(exec->callee())->jsExecutable()->generatedBytecodeFor(CodeForConstruct), "entry_osr_function_for_construct_arityCheck", ArityCheck); } LLINT_SLOW_PATH_DECL(loop_osr) @@ -452,7 +451,7 @@ LLINT_SLOW_PATH_DECL(slow_path_create_arguments) LLINT_SLOW_PATH_DECL(slow_path_create_this) { LLINT_BEGIN(); - JSFunction* constructor = asFunction(exec->callee()); + JSFunction* constructor = jsCast<JSFunction*>(exec->callee()); #if !ASSERT_DISABLED ConstructData constructData; @@ -702,31 +701,6 @@ LLINT_SLOW_PATH_DECL(slow_path_typeof) LLINT_RETURN(jsTypeStringForValue(exec, LLINT_OP_C(2).jsValue())); } -LLINT_SLOW_PATH_DECL(slow_path_is_undefined) -{ - LLINT_BEGIN(); - JSValue v = LLINT_OP_C(2).jsValue(); - LLINT_RETURN(jsBoolean(v.isCell() ? v.asCell()->structure()->typeInfo().masqueradesAsUndefined() : v.isUndefined())); -} - -LLINT_SLOW_PATH_DECL(slow_path_is_boolean) -{ - LLINT_BEGIN(); - LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isBoolean())); -} - -LLINT_SLOW_PATH_DECL(slow_path_is_number) -{ - LLINT_BEGIN(); - LLINT_RETURN(jsBoolean(LLINT_OP_C(2).jsValue().isNumber())); -} - -LLINT_SLOW_PATH_DECL(slow_path_is_string) -{ - LLINT_BEGIN(); - LLINT_RETURN(jsBoolean(isJSString(LLINT_OP_C(2).jsValue()))); -} - LLINT_SLOW_PATH_DECL(slow_path_is_object) { LLINT_BEGIN(); @@ -982,9 +956,6 @@ inline JSValue getByVal(ExecState* exec, JSValue baseValue, JSValue subscript) if (isJSString(baseValue) && asString(baseValue)->canGetIndex(i)) return asString(baseValue)->getIndex(exec, i); - if (isJSByteArray(baseValue) && asByteArray(baseValue)->canAccessIndex(i)) - return asByteArray(baseValue)->getIndex(exec, i); - return baseValue.get(exec, i); } @@ -1015,7 +986,7 @@ LLINT_SLOW_PATH_DECL(slow_path_get_argument_by_val) LLINT_SLOW_PATH_DECL(slow_path_get_by_pname) { LLINT_BEGIN(); - LLINT_RETURN(getByVal(exec, LLINT_OP(2).jsValue(), LLINT_OP(3).jsValue())); + LLINT_RETURN(getByVal(exec, LLINT_OP_C(2).jsValue(), LLINT_OP_C(3).jsValue())); } LLINT_SLOW_PATH_DECL(slow_path_put_by_val) @@ -1036,18 +1007,6 @@ LLINT_SLOW_PATH_DECL(slow_path_put_by_val) JSArray::putByIndex(jsArray, exec, i, value, exec->codeBlock()->isStrictMode()); LLINT_END(); } - if (isJSByteArray(baseValue) - && asByteArray(baseValue)->canAccessIndex(i)) { - JSByteArray* jsByteArray = asByteArray(baseValue); - if (value.isInt32()) { - jsByteArray->setIndex(i, value.asInt32()); - LLINT_END(); - } - if (value.isNumber()) { - jsByteArray->setIndex(i, value.asNumber()); - LLINT_END(); - } - } baseValue.putByIndex(exec, i, value, exec->codeBlock()->isStrictMode()); LLINT_END(); } @@ -1254,7 +1213,7 @@ static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, { ExecState* exec = execCallee->callerFrame(); JSGlobalData& globalData = exec->globalData(); - + execCallee->setScopeChain(exec->scopeChain()); execCallee->setCodeBlock(0); execCallee->clearReturnPC(); @@ -1266,6 +1225,8 @@ static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, ASSERT(callType != CallTypeJS); if (callType == CallTypeHost) { + NativeCallFrameTracer tracer(&globalData, execCallee); + execCallee->setCallee(asObject(callee)); globalData.hostCallReturnValue = JSValue::decode(callData.native.function(execCallee)); LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue)); @@ -1287,6 +1248,8 @@ static SlowPathReturnType handleHostCall(ExecState* execCallee, Instruction* pc, ASSERT(constructType != ConstructTypeJS); if (constructType == ConstructTypeHost) { + NativeCallFrameTracer tracer(&globalData, execCallee); + execCallee->setCallee(asObject(callee)); globalData.hostCallReturnValue = JSValue::decode(constructData.native.function(execCallee)); LLINT_CALL_RETURN(execCallee, pc, reinterpret_cast<void*>(getHostCallReturnValue)); @@ -1310,7 +1273,7 @@ inline SlowPathReturnType setUpCall(ExecState* execCallee, Instruction* pc, Code if (!calleeAsFunctionCell) return handleHostCall(execCallee, pc, calleeAsValue, kind); - JSFunction* callee = asFunction(calleeAsFunctionCell); + JSFunction* callee = jsCast<JSFunction*>(calleeAsFunctionCell); ScopeChainNode* scope = callee->scopeUnchecked(); JSGlobalData& globalData = *scope->globalData; execCallee->setScopeChain(scope); diff --git a/Source/JavaScriptCore/llint/LLIntSlowPaths.h b/Source/JavaScriptCore/llint/LLIntSlowPaths.h index 334070a07..a91cf797e 100644 --- a/Source/JavaScriptCore/llint/LLIntSlowPaths.h +++ b/Source/JavaScriptCore/llint/LLIntSlowPaths.h @@ -39,20 +39,20 @@ struct Instruction; namespace LLInt { #if USE(JSVALUE64) +// According to C++ rules, a type used for the return signature of function with C linkage (i.e. +// 'extern "C"') needs to be POD; hence putting any constructors into it could cause either compiler +// warnings, or worse, a change in the ABI used to return these types. struct SlowPathReturnType { void* a; void* b; - - SlowPathReturnType(void* a, void* b) - : a(a) - , b(b) - { - } }; inline SlowPathReturnType encodeResult(void* a, void* b) { - return SlowPathReturnType(a, b); + SlowPathReturnType result; + result.a = a; + result.b = b; + return result; } #else typedef int64_t SlowPathReturnType; @@ -132,10 +132,6 @@ LLINT_SLOW_PATH_DECL(slow_path_bitxor); LLINT_SLOW_PATH_DECL(slow_path_check_has_instance); LLINT_SLOW_PATH_DECL(slow_path_instanceof); LLINT_SLOW_PATH_DECL(slow_path_typeof); -LLINT_SLOW_PATH_DECL(slow_path_is_undefined); -LLINT_SLOW_PATH_DECL(slow_path_is_boolean); -LLINT_SLOW_PATH_DECL(slow_path_is_number); -LLINT_SLOW_PATH_DECL(slow_path_is_string); LLINT_SLOW_PATH_DECL(slow_path_is_object); LLINT_SLOW_PATH_DECL(slow_path_is_function); LLINT_SLOW_PATH_DECL(slow_path_in); diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm index 9af91bef2..bbfa859f2 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter.asm @@ -291,17 +291,21 @@ macro allocateBasicJSObject(sizeClassIndex, classInfoOffset, structure, result, MarkedSpace::Subspace::preciseAllocators + sizeClassIndex * sizeof MarkedAllocator + const offsetOfFirstFreeCell = + MarkedAllocator::m_freeList + + MarkedBlock::FreeList::head + # FIXME: we can get the global data in one load from the stack. loadp CodeBlock[cfr], scratch1 loadp CodeBlock::m_globalData[scratch1], scratch1 - # Get the object from the free list. - loadp offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1], result + # Get the object from the free list. + loadp offsetOfMySizeClass + offsetOfFirstFreeCell[scratch1], result btpz result, slowCase # Remove the object from the free list. loadp [result], scratch2 - storep scratch2, offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1] + storep scratch2, offsetOfMySizeClass + offsetOfFirstFreeCell[scratch1] # Initialize the object. loadp classInfoOffset[scratch1], scratch2 @@ -423,30 +427,6 @@ _llint_op_typeof: dispatch(3) -_llint_op_is_undefined: - traceExecution() - callSlowPath(_llint_slow_path_is_undefined) - dispatch(3) - - -_llint_op_is_boolean: - traceExecution() - callSlowPath(_llint_slow_path_is_boolean) - dispatch(3) - - -_llint_op_is_number: - traceExecution() - callSlowPath(_llint_slow_path_is_number) - dispatch(3) - - -_llint_op_is_string: - traceExecution() - callSlowPath(_llint_slow_path_is_string) - dispatch(3) - - _llint_op_is_object: traceExecution() callSlowPath(_llint_slow_path_is_object) diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm index 46c6226e5..42ab4c1e4 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm @@ -200,6 +200,19 @@ macro loadConstantOrVariable(index, tag, payload) .done: end +macro loadConstantOrVariableTag(index, tag) + bigteq index, FirstConstantRegisterIndex, .constant + loadi TagOffset[cfr, index, 8], tag + jmp .done +.constant: + loadp CodeBlock[cfr], tag + loadp CodeBlock::m_constantRegisters + VectorBufferOffset[tag], tag + # There is a bit of evil here: if the index contains a value >= FirstConstantRegisterIndex, + # then value << 3 will be equal to (value - FirstConstantRegisterIndex) << 3. + loadp TagOffset[tag, index, 8], tag +.done: +end + # Index and payload may be the same register. Index may be clobbered. macro loadConstantOrVariable2Reg(index, tag, payload) bigteq index, FirstConstantRegisterIndex, .constant @@ -862,6 +875,62 @@ _llint_op_instanceof: dispatch(5) +_llint_op_is_undefined: + traceExecution() + loadi 8[PC], t1 + loadi 4[PC], t0 + loadConstantOrVariable(t1, t2, t3) + storei BooleanTag, TagOffset[cfr, t0, 8] + bieq t2, CellTag, .opIsUndefinedCell + cieq t2, UndefinedTag, t3 + storei t3, PayloadOffset[cfr, t0, 8] + dispatch(3) +.opIsUndefinedCell: + loadp JSCell::m_structure[t3], t1 + tbnz Structure::m_typeInfo + TypeInfo::m_flags[t1], MasqueradesAsUndefined, t1 + storei t1, PayloadOffset[cfr, t0, 8] + dispatch(3) + + +_llint_op_is_boolean: + traceExecution() + loadi 8[PC], t1 + loadi 4[PC], t2 + loadConstantOrVariableTag(t1, t0) + cieq t0, BooleanTag, t0 + storei BooleanTag, TagOffset[cfr, t2, 8] + storei t0, PayloadOffset[cfr, t2, 8] + dispatch(3) + + +_llint_op_is_number: + traceExecution() + loadi 8[PC], t1 + loadi 4[PC], t2 + loadConstantOrVariableTag(t1, t0) + storei BooleanTag, TagOffset[cfr, t2, 8] + addi 1, t0 + cib t0, LowestTag + 1, t1 + storei t1, PayloadOffset[cfr, t2, 8] + dispatch(3) + + +_llint_op_is_string: + traceExecution() + loadi 8[PC], t1 + loadi 4[PC], t2 + loadConstantOrVariable(t1, t0, t3) + storei BooleanTag, TagOffset[cfr, t2, 8] + bineq t0, CellTag, .opIsStringNotCell + loadp JSCell::m_structure[t3], t0 + cbeq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, t1 + storei t1, PayloadOffset[cfr, t2, 8] + dispatch(3) +.opIsStringNotCell: + storep 0, PayloadOffset[cfr, t2, 8] + dispatch(3) + + macro resolveGlobal(size, slow) # Operands are as follows: # 4[PC] Destination for the load. @@ -1571,21 +1640,6 @@ _llint_op_catch: dispatch(2) -_llint_op_jsr: - traceExecution() - loadi 4[PC], t0 - addi 3 * 4, PC, t1 - storei t1, [cfr, t0, 8] - dispatchBranch(8[PC]) - - -_llint_op_sret: - traceExecution() - loadi 4[PC], t0 - loadp [cfr, t0, 8], PC - dispatch(0) - - _llint_op_end: traceExecution() checkSwitchToJITForEpilogue() @@ -1619,6 +1673,8 @@ macro nativeCallTrampoline(executableOffsetToFunction) storei CellTag, ScopeChain + TagOffset[cfr] storei t1, ScopeChain + PayloadOffset[cfr] if X86 + loadp JITStackFrame::globalData + 4[sp], t0 # Additional offset for return address + storep cfr, JSGlobalData::topCallFrame[t0] peek 0, t1 storep t1, ReturnPC[cfr] move cfr, t2 # t2 = ecx @@ -1630,6 +1686,8 @@ macro nativeCallTrampoline(executableOffsetToFunction) addp 16 - 4, sp loadp JITStackFrame::globalData + 4[sp], t3 elsif ARMv7 + loadp JITStackFrame::globalData[sp], t1 + storep cfr, JSGlobalData::topCallFrame[t1] move t0, t2 preserveReturnAddressAfterCall(t3) storep t3, ReturnPC[cfr] @@ -1647,6 +1705,7 @@ macro nativeCallTrampoline(executableOffsetToFunction) ret .exception: preserveReturnAddressAfterCall(t1) # This is really only needed on X86 + loadi ArgumentCount + TagOffset[cfr], PC callSlowPath(_llint_throw_from_native_call) jmp _llint_throw_from_slow_path_trampoline end diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm index d8c931fa0..b28051f33 100644 --- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm +++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm @@ -117,7 +117,8 @@ macro checkSwitchToJITForLoop() btpz t0, .recover jmp t0 .recover: - loadp ArgumentCount + TagOffset[cfr], PC + move t3, PB + loadi ArgumentCount + TagOffset[cfr], PC end) end @@ -594,6 +595,9 @@ _llint_op_div: macro (left, right, slow, index) # Assume t3 is scratchable. btiz left, slow + bineq left, -1, .notNeg2TwoThe31DivByNeg1 + bieq right, -2147483648, .slow + .notNeg2TwoThe31DivByNeg1: btinz right, .intOK bilt left, 0, slow .intOK: @@ -728,6 +732,63 @@ _llint_op_instanceof: dispatch(5) +_llint_op_is_undefined: + traceExecution() + loadis 16[PB, PC, 8], t1 + loadis 8[PB, PC, 8], t2 + loadConstantOrVariable(t1, t0) + btpz t0, tagMask, .opIsUndefinedCell + cpeq t0, ValueUndefined, t3 + orp ValueFalse, t3 + storep t3, [cfr, t2, 8] + dispatch(3) +.opIsUndefinedCell: + loadp JSCell::m_structure[t0], t0 + tbnz Structure::m_typeInfo + TypeInfo::m_flags[t0], MasqueradesAsUndefined, t1 + orp ValueFalse, t1 + storep t1, [cfr, t2, 8] + dispatch(3) + + +_llint_op_is_boolean: + traceExecution() + loadis 16[PB, PC, 8], t1 + loadis 8[PB, PC, 8], t2 + loadConstantOrVariable(t1, t0) + xorp ValueFalse, t0 + tpz t0, ~1, t0 + orp ValueFalse, t0 + storep t0, [cfr, t2, 8] + dispatch(3) + + +_llint_op_is_number: + traceExecution() + loadis 16[PB, PC, 8], t1 + loadis 8[PB, PC, 8], t2 + loadConstantOrVariable(t1, t0) + tpnz t0, tagTypeNumber, t1 + orp ValueFalse, t1 + storep t1, [cfr, t2, 8] + dispatch(3) + + +_llint_op_is_string: + traceExecution() + loadis 16[PB, PC, 8], t1 + loadis 8[PB, PC, 8], t2 + loadConstantOrVariable(t1, t0) + btpnz t0, tagMask, .opIsStringNotCell + loadp JSCell::m_structure[t0], t0 + cbeq Structure::m_typeInfo + TypeInfo::m_type[t0], StringType, t1 + orp ValueFalse, t1 + storep t1, [cfr, t2, 8] + dispatch(3) +.opIsStringNotCell: + storep ValueFalse, [cfr, t2, 8] + dispatch(3) + + macro resolveGlobal(size, slow) # Operands are as follows: # 8[PB, PC, 8] Destination for the load. @@ -1425,21 +1486,6 @@ _llint_op_catch: dispatch(2) -_llint_op_jsr: - traceExecution() - loadis 8[PB, PC, 8], t0 - addi 3, PC, t1 - storei t1, [cfr, t0, 8] - dispatchInt(16[PB, PC, 8]) - - -_llint_op_sret: - traceExecution() - loadis 8[PB, PC, 8], t0 - loadi [cfr, t0, 8], PC - dispatch(0) - - _llint_op_end: traceExecution() checkSwitchToJITForEpilogue() @@ -1467,6 +1513,8 @@ _llint_throw_during_call_trampoline: macro nativeCallTrampoline(executableOffsetToFunction) storep 0, CodeBlock[cfr] + loadp JITStackFrame::globalData + 8[sp], t0 + storep cfr, JSGlobalData::topCallFrame[t0] loadp CallerFrame[cfr], t0 loadp ScopeChain[t0], t1 storep t1, ScopeChain[cfr] @@ -1484,6 +1532,11 @@ macro nativeCallTrampoline(executableOffsetToFunction) ret .exception: preserveReturnAddressAfterCall(t1) + loadi ArgumentCount + TagOffset[cfr], PC + loadp CodeBlock[cfr], PB + loadp CodeBlock::m_instructions[PB], PB + loadp JITStackFrame::globalData[sp], t0 + storep cfr, JSGlobalData::topCallFrame[t0] callSlowPath(_llint_throw_from_native_call) jmp _llint_throw_from_slow_path_trampoline end diff --git a/Source/JavaScriptCore/offlineasm/armv7.rb b/Source/JavaScriptCore/offlineasm/armv7.rb index ed7db5618..69df51a45 100644 --- a/Source/JavaScriptCore/offlineasm/armv7.rb +++ b/Source/JavaScriptCore/offlineasm/armv7.rb @@ -70,7 +70,7 @@ class RegisterID when "t3" "r4" when "t4" - "r7" + "r10" when "cfr" "r5" when "lr" @@ -522,11 +522,11 @@ def armV7LowerMisplacedAddresses(list) node.opcode, armV7AsRegisters(newList, postInstructions, node.operands, "i")) when "bbeq", "bbneq", "bba", "bbaeq", "bbb", "bbbeq", "btbo", "btbz", "btbnz", "tbz", "tbnz", - "tbo" + "tbo", "cbeq", "cbneq", "cba", "cbaeq", "cbb", "cbbeq" newList << Instruction.new(node.codeOrigin, node.opcode, armV7AsRegisters(newList, postInstructions, node.operands, "b")) - when "bbgt", "bbgteq", "bblt", "bblteq", "btbs", "tbs" + when "bbgt", "bbgteq", "bblt", "bblteq", "btbs", "tbs", "cbgt", "cbgteq", "cblt", "cblteq" newList << Instruction.new(node.codeOrigin, node.opcode, armV7AsRegisters(newList, postInstructions, node.operands, "bs")) @@ -568,7 +568,8 @@ def armV7LowerRegisterReuse(list) case node.opcode when "cieq", "cineq", "cia", "ciaeq", "cib", "cibeq", "cigt", "cigteq", "cilt", "cilteq", "cpeq", "cpneq", "cpa", "cpaeq", "cpb", "cpbeq", "cpgt", "cpgteq", "cplt", "cplteq", - "tio", "tis", "tiz", "tinz", "tbo", "tbs", "tbz", "tbnz" + "tio", "tis", "tiz", "tinz", "tbo", "tbs", "tbz", "tbnz", "tpo", "tps", "tpz", "tpnz", + "cbeq", "cbneq", "cba", "cbaeq", "cbb", "cbbeq", "cbgt", "cbgteq", "cblt", "cblteq" if node.operands.size == 2 if node.operands[0] == node.operands[1] tmp = Tmp.new(node.codeOrigin, :gpr) @@ -777,12 +778,7 @@ class Instruction when "urshifti", "urshiftp" emitArmV7Compact("lsrs", "lsrs", operands) when "muli", "mulp" - if operands.size == 2 or operands[0] == operands[2] or operands[1] == operands[2] - emitArmV7("muls", operands) - else - $asm.puts "mov #{operands[2].armV7Operand}, #{operands[0].armV7Operand}" - $asm.puts "muls #{operands[2].armV7Operand}, #{operands[2].armV7Operand}, #{operands[1].armV7Operand}" - end + emitArmV7("mul", operands) when "subi", "subp", "subis" emitArmV7Compact("subs", "subs", operands) when "negi", "negp" @@ -950,36 +946,36 @@ class Instruction $asm.puts "blx #{operands[0].armV7Operand}" end when "break" - $asm.puts "bkpt" + $asm.puts "bkpt #0" when "ret" $asm.puts "bx lr" - when "cieq", "cpeq" + when "cieq", "cpeq", "cbeq" emitArmV7Compare(operands, "eq") - when "cineq", "cpneq" + when "cineq", "cpneq", "cbneq" emitArmV7Compare(operands, "ne") - when "cia", "cpa" + when "cia", "cpa", "cba" emitArmV7Compare(operands, "hi") - when "ciaeq", "cpaeq" + when "ciaeq", "cpaeq", "cbaeq" emitArmV7Compare(operands, "hs") - when "cib", "cpb" + when "cib", "cpb", "cbb" emitArmV7Compare(operands, "lo") - when "cibeq", "cpbeq" + when "cibeq", "cpbeq", "cbbeq" emitArmV7Compare(operands, "ls") - when "cigt", "cpgt" + when "cigt", "cpgt", "cbgt" emitArmV7Compare(operands, "gt") - when "cigteq", "cpgteq" + when "cigteq", "cpgteq", "cbgteq" emitArmV7Compare(operands, "ge") - when "cilt", "cplt" + when "cilt", "cplt", "cblt" emitArmV7Compare(operands, "lt") - when "cilteq", "cplteq" + when "cilteq", "cplteq", "cblteq" emitArmV7Compare(operands, "le") - when "tio", "tbo" + when "tio", "tbo", "tpo" emitArmV7TestSet(operands, "vs") - when "tis", "tbs" + when "tis", "tbs", "tps" emitArmV7TestSet(operands, "mi") - when "tiz", "tbz" + when "tiz", "tbz", "tpz" emitArmV7TestSet(operands, "eq") - when "tinz", "tbnz" + when "tinz", "tbnz", "tpnz" emitArmV7TestSet(operands, "ne") when "peek" $asm.puts "ldr #{operands[1].armV7Operand}, [sp, \##{operands[0].value * 4}]" diff --git a/Source/JavaScriptCore/offlineasm/instructions.rb b/Source/JavaScriptCore/offlineasm/instructions.rb index cc7e0c6a5..67cec6d96 100644 --- a/Source/JavaScriptCore/offlineasm/instructions.rb +++ b/Source/JavaScriptCore/offlineasm/instructions.rb @@ -133,6 +133,16 @@ MACRO_INSTRUCTIONS = "break", "call", "ret", + "cbeq", + "cbneq", + "cba", + "cbaeq", + "cbb", + "cbbeq", + "cbgt", + "cbgteq", + "cblt", + "cblteq", "cieq", "cineq", "cia", @@ -151,6 +161,10 @@ MACRO_INSTRUCTIONS = "tbs", "tbz", "tbnz", + "tpo", + "tps", + "tpz", + "tpnz", "peek", "poke", "bpeq", diff --git a/Source/JavaScriptCore/offlineasm/x86.rb b/Source/JavaScriptCore/offlineasm/x86.rb index 4416ec909..e6a5c92ca 100644 --- a/Source/JavaScriptCore/offlineasm/x86.rb +++ b/Source/JavaScriptCore/offlineasm/x86.rb @@ -897,42 +897,62 @@ class Instruction $asm.puts "ret" when "cieq" handleX86IntCompareSet("sete", :int) + when "cbeq" + handleX86IntCompareSet("sete", :byte) when "cpeq" handleX86IntCompareSet("sete", :ptr) when "cineq" handleX86IntCompareSet("setne", :int) + when "cbneq" + handleX86IntCompareSet("setne", :byte) when "cpneq" handleX86IntCompareSet("setne", :ptr) when "cia" handleX86IntCompareSet("seta", :int) + when "cba" + handleX86IntCompareSet("seta", :byte) when "cpa" handleX86IntCompareSet("seta", :ptr) when "ciaeq" handleX86IntCompareSet("setae", :int) + when "cbaeq" + handleX86IntCompareSet("setae", :byte) when "cpaeq" handleX86IntCompareSet("setae", :ptr) when "cib" handleX86IntCompareSet("setb", :int) + when "cbb" + handleX86IntCompareSet("setb", :byte) when "cpb" handleX86IntCompareSet("setb", :ptr) when "cibeq" handleX86IntCompareSet("setbe", :int) + when "cbbeq" + handleX86IntCompareSet("setbe", :byte) when "cpbeq" handleX86IntCompareSet("setbe", :ptr) when "cigt" handleX86IntCompareSet("setg", :int) + when "cbgt" + handleX86IntCompareSet("setg", :byte) when "cpgt" handleX86IntCompareSet("setg", :ptr) when "cigteq" handleX86IntCompareSet("setge", :int) + when "cbgteq" + handleX86IntCompareSet("setge", :byte) when "cpgteq" handleX86IntCompareSet("setge", :ptr) when "cilt" handleX86IntCompareSet("setl", :int) + when "cblt" + handleX86IntCompareSet("setl", :byte) when "cplt" handleX86IntCompareSet("setl", :ptr) when "cilteq" handleX86IntCompareSet("setle", :int) + when "cblteq" + handleX86IntCompareSet("setle", :byte) when "cplteq" handleX86IntCompareSet("setle", :ptr) when "tio" @@ -943,6 +963,14 @@ class Instruction handleX86SetTest("setz", :int) when "tinz" handleX86SetTest("setnz", :int) + when "tpo" + handleX86SetTest("seto", :ptr) + when "tps" + handleX86SetTest("sets", :ptr) + when "tpz" + handleX86SetTest("setz", :ptr) + when "tpnz" + handleX86SetTest("setnz", :ptr) when "tbo" handleX86SetTest("seto", :byte) when "tbs" diff --git a/Source/JavaScriptCore/os-win32/WinMain.cpp b/Source/JavaScriptCore/os-win32/WinMain.cpp index 17800d005..d4ff3e657 100644 --- a/Source/JavaScriptCore/os-win32/WinMain.cpp +++ b/Source/JavaScriptCore/os-win32/WinMain.cpp @@ -19,7 +19,7 @@ */ #include "config.h" -#include "Vector.h" +#include <wtf/Vector.h> #include <winbase.h> #include <winnls.h> #include <wtf/UnusedParam.h> diff --git a/Source/JavaScriptCore/parser/Keywords.table b/Source/JavaScriptCore/parser/Keywords.table index 27c4e53a2..527eada60 100644 --- a/Source/JavaScriptCore/parser/Keywords.table +++ b/Source/JavaScriptCore/parser/Keywords.table @@ -43,12 +43,10 @@ extends RESERVED import RESERVED super RESERVED -# technically RESERVED_IF_STRICT in ES5, but may be reserved in ES6. -let RESERVED - # Reserved for future use in strict code. implements RESERVED_IF_STRICT interface RESERVED_IF_STRICT +let RESERVED_IF_STRICT package RESERVED_IF_STRICT private RESERVED_IF_STRICT protected RESERVED_IF_STRICT diff --git a/Source/JavaScriptCore/parser/Lexer.cpp b/Source/JavaScriptCore/parser/Lexer.cpp index 8d50afc54..3b020f4f2 100644 --- a/Source/JavaScriptCore/parser/Lexer.cpp +++ b/Source/JavaScriptCore/parser/Lexer.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All Rights Reserved. + * Copyright (C) 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All Rights Reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu) * Copyright (C) 2012 Mathias Bynens (mathias@qiwi.be) @@ -368,7 +368,7 @@ Lexer<T>::~Lexer() } template <typename T> -UString Lexer<T>::getInvalidCharMessage() +UString Lexer<T>::invalidCharacterMessage() const { switch (m_current) { case 0: @@ -386,7 +386,7 @@ UString Lexer<T>::getInvalidCharMessage() case 96: return "Invalid character: '`'"; default: - return String::format("Invalid character '\\u%04u'", m_current).impl(); + return String::format("Invalid character '\\u%04u'", static_cast<unsigned>(m_current)).impl(); } } @@ -403,7 +403,6 @@ void Lexer<T>::setCode(const SourceCode& source, ParserArena* arena) m_arena = &arena->identifierArena(); m_lineNumber = source.firstLine(); - m_delimited = false; m_lastToken = -1; const StringImpl* sourceString = source.provider()->data(); @@ -426,7 +425,7 @@ void Lexer<T>::setCode(const SourceCode& source, ParserArena* arena) if (LIKELY(m_code < m_codeEnd)) m_current = *m_code; else - m_current = -1; + m_current = 0; ASSERT(currentOffset() == source.startOffset()); } @@ -440,29 +439,34 @@ template <int shiftAmount> ALWAYS_INLINE void Lexer<T>::internalShift() template <typename T> ALWAYS_INLINE void Lexer<T>::shift() { - // Faster than an if-else sequence - ASSERT(m_current != -1); - m_current = -1; - m_code++; + // At one point timing showed that setting m_current to 0 unconditionally was faster than an if-else sequence. + m_current = 0; + ++m_code; if (LIKELY(m_code < m_codeEnd)) m_current = *m_code; } template <typename T> -ALWAYS_INLINE int Lexer<T>::peek(int offset) +ALWAYS_INLINE bool Lexer<T>::atEnd() const +{ + ASSERT(!m_current || m_code < m_codeEnd); + return UNLIKELY(UNLIKELY(!m_current) && m_code == m_codeEnd); +} + +template <typename T> +ALWAYS_INLINE T Lexer<T>::peek(int offset) const { - // Only use if necessary ASSERT(offset > 0 && offset < 5); const T* code = m_code + offset; - return (code < m_codeEnd) ? *code : -1; + return (code < m_codeEnd) ? *code : 0; } template <typename T> -int Lexer<T>::getUnicodeCharacter() +int Lexer<T>::parseFourDigitUnicodeHex() { - int char1 = peek(1); - int char2 = peek(2); - int char3 = peek(3); + T char1 = peek(1); + T char2 = peek(2); + T char3 = peek(3); if (UNLIKELY(!isASCIIHexDigit(m_current) || !isASCIIHexDigit(char1) || !isASCIIHexDigit(char2) || !isASCIIHexDigit(char3))) return -1; @@ -478,13 +482,13 @@ int Lexer<T>::getUnicodeCharacter() template <typename T> void Lexer<T>::shiftLineTerminator() { - ASSERT(isLineTerminator(static_cast<T>(m_current))); + ASSERT(isLineTerminator(m_current)); - int m_prev = m_current; + T prev = m_current; shift(); // Allow both CRLF and LFCR. - if (m_prev + m_current == '\n' + '\r') + if (prev + m_current == '\n' + '\r') shift(); ++m_lineNumber; @@ -629,12 +633,12 @@ template <typename T> inline void Lexer<T>::record16(int c) { ASSERT(c >= 0); - ASSERT(c <= USHRT_MAX); + ASSERT(c <= static_cast<int>(USHRT_MAX)); m_buffer16.append(static_cast<UChar>(c)); } template <> - template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::parseIdentifier(JSTokenData* tokenData, unsigned lexerFlags, bool strictMode) +template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<LChar>::parseIdentifier(JSTokenData* tokenData, unsigned lexerFlags, bool strictMode) { const ptrdiff_t remaining = m_codeEnd - m_code; if ((remaining >= maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords)) { @@ -647,7 +651,7 @@ template <> const LChar* identifierStart = currentCharacter(); - while (m_current != -1 && isIdentPart(static_cast<LChar>(m_current))) + while (isIdentPart(m_current)) shift(); if (UNLIKELY(m_current == '\\')) { @@ -665,8 +669,6 @@ template <> } else tokenData->ident = 0; - m_delimited = false; - if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) { ASSERT(shouldCreateIdentifier); if (remaining < maxTokenLength) { @@ -694,11 +696,12 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p return keyword == RESERVED_IF_STRICT && !strictMode ? IDENT : keyword; } } + const UChar* identifierStart = currentCharacter(); UChar orAllChars = 0; - while (m_current != -1 && isIdentPart(static_cast<UChar>(m_current))) { + while (isIdentPart(m_current)) { orAllChars |= m_current; shift(); } @@ -726,8 +729,6 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p } else tokenData->ident = 0; - m_delimited = false; - if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords))) { ASSERT(shouldCreateIdentifier); if (remaining < maxTokenLength) { @@ -752,7 +753,7 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow bool bufferRequired = false; while (true) { - if (LIKELY(m_current != -1 && isIdentPart(static_cast<T>(m_current)))) { + if (LIKELY(isIdentPart(m_current))) { shift(); continue; } @@ -767,7 +768,7 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow if (UNLIKELY(m_current != 'u')) return ERRORTOK; shift(); - int character = getUnicodeCharacter(); + int character = parseFourDigitUnicodeHex(); if (UNLIKELY(character == -1)) return ERRORTOK; UChar ucharacter = static_cast<UChar>(character); @@ -794,8 +795,6 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow } else tokenData->ident = 0; - m_delimited = false; - if (LIKELY(!bufferRequired && !(lexerFlags & LexerFlagsIgnoreReservedWords))) { ASSERT(shouldCreateIdentifier); // Keywords must not be recognized if there was an \uXXXX in the identifier. @@ -814,18 +813,28 @@ template <bool shouldCreateIdentifier> JSTokenType Lexer<T>::parseIdentifierSlow return IDENT; } +static ALWAYS_INLINE bool characterRequiresParseStringSlowCase(LChar character) +{ + return character < 0xE; +} + +static ALWAYS_INLINE bool characterRequiresParseStringSlowCase(UChar character) +{ + return character < 0xE || character > 0xFF; +} + template <typename T> template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTokenData* tokenData, bool strictMode) { int startingOffset = currentOffset(); int startingLineNumber = lineNumber(); - int stringQuoteCharacter = m_current; + T stringQuoteCharacter = m_current; shift(); const T* stringStart = currentCharacter(); while (m_current != stringQuoteCharacter) { - if (UNLIKELY((m_current == '\\'))) { + if (UNLIKELY(m_current == '\\')) { if (stringStart != currentCharacter() && shouldBuildStrings) append8(stringStart, currentCharacter() - stringStart); shift(); @@ -845,7 +854,7 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTo m_lexErrorMessage = "\\x can only be followed by a hex character sequence"; return false; } - int prev = m_current; + T prev = m_current; shift(); if (shouldBuildStrings) record8(convertHex(prev, m_current)); @@ -860,7 +869,7 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTo continue; } - if (UNLIKELY(((m_current > 0xff) || (m_current < 0xe)))) { + if (UNLIKELY(characterRequiresParseStringSlowCase(m_current))) { setOffset(startingOffset); setLineNumber(startingLineNumber); m_buffer8.resize(0); @@ -884,7 +893,7 @@ template <bool shouldBuildStrings> ALWAYS_INLINE bool Lexer<T>::parseString(JSTo template <typename T> template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenData* tokenData, bool strictMode) { - int stringQuoteCharacter = m_current; + T stringQuoteCharacter = m_current; shift(); const T* stringStart = currentCharacter(); @@ -902,7 +911,7 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat if (shouldBuildStrings) record16(escape); shift(); - } else if (UNLIKELY(isLineTerminator(static_cast<T>(m_current)))) + } else if (UNLIKELY(isLineTerminator(m_current))) shiftLineTerminator(); else if (m_current == 'x') { shift(); @@ -910,14 +919,14 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat m_lexErrorMessage = "\\x can only be followed by a hex character sequence"; return false; } - int prev = m_current; + T prev = m_current; shift(); if (shouldBuildStrings) record16(convertHex(prev, m_current)); shift(); } else if (m_current == 'u') { shift(); - int character = getUnicodeCharacter(); + int character = parseFourDigitUnicodeHex(); if (character != -1) { if (shouldBuildStrings) record16(character); @@ -940,11 +949,11 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat record16(0); } else if (!strictMode && isASCIIOctalDigit(m_current)) { // Octal character sequences - int character1 = m_current; + T character1 = m_current; shift(); if (isASCIIOctalDigit(m_current)) { // Two octal characters - int character2 = m_current; + T character2 = m_current; shift(); if (character1 >= '0' && character1 <= '3' && isASCIIOctalDigit(m_current)) { if (shouldBuildStrings) @@ -958,7 +967,7 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat if (shouldBuildStrings) record16(character1 - '0'); } - } else if (m_current != -1) { + } else if (!atEnd()) { if (shouldBuildStrings) record16(m_current); shift(); @@ -971,11 +980,11 @@ template <bool shouldBuildStrings> bool Lexer<T>::parseStringSlowCase(JSTokenDat continue; } // Fast check for characters that require special handling. - // Catches -1, \n, \r, 0x2028, and 0x2029 as efficiently + // Catches 0, \n, \r, 0x2028, and 0x2029 as efficiently // as possible, and lets through all common ASCII characters. if (UNLIKELY(((static_cast<unsigned>(m_current) - 0xE) & 0x2000))) { // New-line or end of input is not allowed - if (UNLIKELY(m_current == -1) || UNLIKELY(isLineTerminator(static_cast<T>(m_current)))) { + if (atEnd() || isLineTerminator(m_current)) { m_lexErrorMessage = "Unexpected EOF"; return false; } @@ -1152,10 +1161,10 @@ ALWAYS_INLINE bool Lexer<T>::parseMultilineComment() } } - if (UNLIKELY(m_current == -1)) + if (atEnd()) return false; - if (isLineTerminator(static_cast<T>(m_current))) { + if (isLineTerminator(m_current)) { shiftLineTerminator(); m_terminator = true; } else @@ -1184,22 +1193,20 @@ JSTokenType Lexer<T>::lex(JSTokenData* tokenData, JSTokenInfo* tokenInfo, unsign m_terminator = false; start: - while (m_current != -1 && isWhiteSpace(static_cast<T>(m_current))) + while (isWhiteSpace(m_current)) shift(); - int startOffset = currentOffset(); - - if (UNLIKELY(m_current == -1)) + if (atEnd()) return EOFTOK; - - m_delimited = false; + + tokenInfo->startOffset = currentOffset(); CharacterType type; - if (LIKELY(isLatin1(static_cast<T>(m_current)))) + if (LIKELY(isLatin1(m_current))) type = static_cast<CharacterType>(typesOfLatin1Characters[m_current]); else if (isNonLatin1IdentStart(m_current)) type = CharacterIdentifierStart; - else if (isLineTerminator(static_cast<T>(m_current))) + else if (isLineTerminator(m_current)) type = CharacterLineTerminator; else type = CharacterInvalid; @@ -1425,7 +1432,6 @@ start: shift(); break; case CharacterSemicolon: - m_delimited = true; shift(); token = SEMICOLON; break; @@ -1436,7 +1442,6 @@ start: break; case CharacterCloseBrace: tokenData->intValue = currentOffset(); - m_delimited = true; shift(); token = CLOSEBRACE; break; @@ -1473,25 +1478,24 @@ start: inNumberAfterDecimalPoint: parseNumberAfterDecimalPoint(); } - if ((m_current | 0x20) == 'e') + if ((m_current | 0x20) == 'e') { if (!parseNumberAfterExponentIndicator()) { m_lexErrorMessage = "Non-number found after exponent indicator"; goto returnError; } - // Null-terminate string for strtod. - m_buffer8.append('\0'); - tokenData->doubleValue = WTF::strtod<WTF::AllowTrailingJunk>(reinterpret_cast<const char*>(m_buffer8.data()), 0); + } + size_t parsedLength; + tokenData->doubleValue = parseDouble(m_buffer8.data(), m_buffer8.size(), parsedLength); } token = NUMBER; } // No identifiers allowed directly after numeric literal, e.g. "3in" is bad. - if (UNLIKELY(m_current != -1 && isIdentStart(static_cast<T>(m_current)))) { + if (UNLIKELY(isIdentStart(m_current))) { m_lexErrorMessage = "At least one digit must occur after a decimal point"; goto returnError; } m_buffer8.resize(0); - m_delimited = false; break; case CharacterQuote: if (lexerFlags & LexerFlagsDontBuildStrings) { @@ -1502,11 +1506,10 @@ inNumberAfterDecimalPoint: goto returnError; } shift(); - m_delimited = false; token = STRING; break; case CharacterIdentifierStart: - ASSERT(isIdentStart(static_cast<T>(m_current))); + ASSERT(isIdentStart(m_current)); // Fall through into CharacterBackSlash. case CharacterBackSlash: if (lexerFlags & LexexFlagsDontBuildKeywords) @@ -1515,13 +1518,13 @@ inNumberAfterDecimalPoint: token = parseIdentifier<true>(tokenData, lexerFlags, strictMode); break; case CharacterLineTerminator: - ASSERT(isLineTerminator(static_cast<T>(m_current))); + ASSERT(isLineTerminator(m_current)); shiftLineTerminator(); m_atLineStart = true; m_terminator = true; goto start; case CharacterInvalid: - m_lexErrorMessage = getInvalidCharMessage(); + m_lexErrorMessage = invalidCharacterMessage(); goto returnError; default: ASSERT_NOT_REACHED(); @@ -1533,8 +1536,8 @@ inNumberAfterDecimalPoint: goto returnToken; inSingleLineComment: - while (!isLineTerminator(static_cast<T>(m_current))) { - if (UNLIKELY(m_current == -1)) + while (!isLineTerminator(m_current)) { + if (atEnd()) return EOFTOK; shift(); } @@ -1545,12 +1548,10 @@ inSingleLineComment: goto start; token = SEMICOLON; - m_delimited = true; // Fall through into returnToken. returnToken: tokenInfo->line = m_lineNumber; - tokenInfo->startOffset = startOffset; tokenInfo->endOffset = currentOffset(); m_lastToken = token; return token; @@ -1558,7 +1559,6 @@ returnToken: returnError: m_error = true; tokenInfo->line = m_lineNumber; - tokenInfo->startOffset = startOffset; tokenInfo->endOffset = currentOffset(); return ERRORTOK; } @@ -1579,26 +1579,26 @@ bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags, } while (true) { - int current = m_current; - - if (isLineTerminator(static_cast<T>(current)) || current == -1) { + if (isLineTerminator(m_current) || atEnd()) { m_buffer16.resize(0); return false; } + T prev = m_current; + shift(); - if (current == '/' && !lastWasEscape && !inBrackets) + if (prev == '/' && !lastWasEscape && !inBrackets) break; - record16(current); + record16(prev); if (lastWasEscape) { lastWasEscape = false; continue; } - switch (current) { + switch (prev) { case '[': inBrackets = true; break; @@ -1614,7 +1614,7 @@ bool Lexer<T>::scanRegExp(const Identifier*& pattern, const Identifier*& flags, pattern = makeIdentifier(m_buffer16.data(), m_buffer16.size()); m_buffer16.resize(0); - while (m_current != -1 && isIdentPart(static_cast<T>(m_current))) { + while (isIdentPart(m_current)) { record16(m_current); shift(); } @@ -1632,14 +1632,14 @@ bool Lexer<T>::skipRegExp() bool inBrackets = false; while (true) { - int current = m_current; - - if (isLineTerminator(static_cast<T>(current)) || current == -1) + if (isLineTerminator(m_current) || atEnd()) return false; + T prev = m_current; + shift(); - if (current == '/' && !lastWasEscape && !inBrackets) + if (prev == '/' && !lastWasEscape && !inBrackets) break; if (lastWasEscape) { @@ -1647,7 +1647,7 @@ bool Lexer<T>::skipRegExp() continue; } - switch (current) { + switch (prev) { case '[': inBrackets = true; break; @@ -1660,7 +1660,7 @@ bool Lexer<T>::skipRegExp() } } - while (m_current != -1 && isIdentPart(static_cast<T>(m_current))) + while (isIdentPart(m_current)) shift(); return true; diff --git a/Source/JavaScriptCore/parser/Lexer.h b/Source/JavaScriptCore/parser/Lexer.h index 81558fa96..41f1f8553 100644 --- a/Source/JavaScriptCore/parser/Lexer.h +++ b/Source/JavaScriptCore/parser/Lexer.h @@ -1,6 +1,6 @@ /* * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2011, 2012 Apple Inc. All rights reserved. * Copyright (C) 2010 Zoltan Herczeg (zherczeg@inf.u-szeged.hu) * * This library is free software; you can redistribute it and/or @@ -67,8 +67,6 @@ enum LexerFlags { LexexFlagsDontBuildKeywords = 4 }; -class RegExp; - template <typename T> class Lexer { WTF_MAKE_NONCOPYABLE(Lexer); @@ -110,10 +108,10 @@ public: m_code = m_codeStart + offset; m_buffer8.resize(0); m_buffer16.resize(0); - // Faster than an if-else sequence - m_current = -1; if (LIKELY(m_code < m_codeEnd)) m_current = *m_code; + else + m_current = 0; } void setLineNumber(int line) { @@ -133,11 +131,12 @@ private: void append16(const UChar* characters, size_t length) { m_buffer16.append(characters, length); } ALWAYS_INLINE void shift(); - ALWAYS_INLINE int peek(int offset); - int getUnicodeCharacter(); + ALWAYS_INLINE bool atEnd() const; + ALWAYS_INLINE T peek(int offset) const; + int parseFourDigitUnicodeHex(); void shiftLineTerminator(); - UString getInvalidCharMessage(); + UString invalidCharacterMessage() const; ALWAYS_INLINE const T* currentCharacter() const; ALWAYS_INLINE int currentOffset() const { return m_code - m_codeStart; } ALWAYS_INLINE void setOffsetFromCharOffset(const T* charOffset) { setOffset(charOffset - m_codeStart); } @@ -171,7 +170,6 @@ private: Vector<LChar> m_buffer8; Vector<UChar> m_buffer16; bool m_terminator; - bool m_delimited; // encountered delimiter like "'" and "}" on last run int m_lastToken; const SourceCode* m_source; @@ -183,8 +181,7 @@ private: bool m_error; UString m_lexErrorMessage; - // current and following unicode characters (int to allow for -1 for end-of-file marker) - int m_current; + T m_current; IdentifierArena* m_arena; @@ -285,7 +282,7 @@ ALWAYS_INLINE JSTokenType Lexer<T>::lexExpectIdentifier(JSTokenData* tokenData, goto slowCase; m_current = *ptr; } else - m_current = -1; + m_current = 0; m_code = ptr; diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp index f58847fd2..a03af24df 100644 --- a/Source/JavaScriptCore/parser/Parser.cpp +++ b/Source/JavaScriptCore/parser/Parser.cpp @@ -1256,6 +1256,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLitera unsigned oldLineNumber = m_lexer->lineNumber(); consumeOrFailWithFlags(OPENBRACE, TreeBuilder::DontBuildStrings); + int oldNonLHSCount = m_nonLHSCount; + if (match(CLOSEBRACE)) { next(); return context.createObjectLiteral(m_lexer->lastLineNumber()); @@ -1291,6 +1293,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseObjectLitera consumeOrFail(CLOSEBRACE); + m_nonLHSCount = oldNonLHSCount; + return context.createObjectLiteral(m_lexer->lastLineNumber(), propertyList); } @@ -1299,6 +1303,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObject { consumeOrFail(OPENBRACE); + int oldNonLHSCount = m_nonLHSCount; + if (match(CLOSEBRACE)) { next(); return context.createObjectLiteral(m_lexer->lastLineNumber()); @@ -1323,19 +1329,21 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseStrictObject property = parseProperty<true>(context); failIfFalse(property); if (!m_syntaxAlreadyValidated) { - std::pair<ObjectValidationMap::iterator, bool> propertyEntryIter = objectValidator.add(context.getName(property).impl(), context.getType(property)); - if (!propertyEntryIter.second) { - failIfTrue(propertyEntryIter.first->second == PropertyNode::Constant); + ObjectValidationMap::AddResult propertyEntry = objectValidator.add(context.getName(property).impl(), context.getType(property)); + if (!propertyEntry.isNewEntry) { + failIfTrue(propertyEntry.iterator->second == PropertyNode::Constant); failIfTrue(context.getType(property) == PropertyNode::Constant); - failIfTrue(context.getType(property) & propertyEntryIter.first->second); - propertyEntryIter.first->second |= context.getType(property); + failIfTrue(context.getType(property) & propertyEntry.iterator->second); + propertyEntry.iterator->second |= context.getType(property); } } tail = context.createPropertyList(m_lexer->lastLineNumber(), property, tail); } consumeOrFail(CLOSEBRACE); - + + m_nonLHSCount = oldNonLHSCount; + return context.createObjectLiteral(m_lexer->lastLineNumber(), propertyList); } @@ -1344,6 +1352,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral { consumeOrFailWithFlags(OPENBRACKET, TreeBuilder::DontBuildStrings); + int oldNonLHSCount = m_nonLHSCount; + int elisions = 0; while (match(COMMA)) { next(TreeBuilder::DontBuildStrings); @@ -1379,6 +1389,8 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseArrayLiteral consumeOrFail(CLOSEBRACKET); + m_nonLHSCount = oldNonLHSCount; + return context.createArray(m_lexer->lastLineNumber(), elementList); } diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h index 7513d1f11..c0b13c53a 100644 --- a/Source/JavaScriptCore/parser/Parser.h +++ b/Source/JavaScriptCore/parser/Parser.h @@ -162,7 +162,7 @@ struct Scope { ALWAYS_INLINE ScopeFlags usesFlags() const { return m_scopeFlags & AllScopeUsesFlags; } ALWAYS_INLINE void setFlags(ScopeFlags scopeFlags) { m_scopeFlags |= scopeFlags; } - ALWAYS_INLINE bool needsFullActivation() const { return m_scopeFlags & (UsesEvalFlag | UsesWithFlag | UsesCatchFlag); } + ALWAYS_INLINE bool usesEval() const { return m_scopeFlags & UsesEvalFlag; } ALWAYS_INLINE bool strictMode() const { return m_scopeFlags & StrictModeFlag; } ALWAYS_INLINE bool shadowsArguments() const { return m_scopeFlags & ShadowsArgumentsFlag; } ALWAYS_INLINE bool isFunction() const { return m_scopeFlags & FunctionModeFlag; } @@ -223,7 +223,7 @@ struct Scope { bool declareParameter(const Identifier* ident) { bool isArguments = m_globalData->propertyNames->arguments == *ident; - bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).second && m_globalData->propertyNames->eval != *ident && !isArguments; + bool isValidStrictMode = m_declaredVariables.add(ident->ustring().impl()).isNewEntry && m_globalData->propertyNames->eval != *ident && !isArguments; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; if (isArguments) setFlags(ShadowsArgumentsFlag); @@ -269,7 +269,7 @@ struct Scope { void getCapturedVariables(IdentifierSet& capturedVariables) { - if (needsFullActivation()) { + if (usesEval()) { capturedVariables.swap(m_declaredVariables); return; } @@ -993,7 +993,7 @@ PassRefPtr<ParsedNode> Parser<LexerType>::parse(JSGlobalObject* lexicalGlobalObj else if (isEvalNode<ParsedNode>()) *exception = createSyntaxError(lexicalGlobalObject, errMsg); else - *exception = addErrorInfo(&lexicalGlobalObject->globalData(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source, Vector<StackFrame>()); + *exception = addErrorInfo(lexicalGlobalObject->globalExec(), createSyntaxError(lexicalGlobalObject, errMsg), errLine, *m_source); } if (debugger && !ParsedNode::scopeIsFunction) diff --git a/Source/JavaScriptCore/parser/SourceCode.h b/Source/JavaScriptCore/parser/SourceCode.h index 2a162b90f..a33ffea72 100644 --- a/Source/JavaScriptCore/parser/SourceCode.h +++ b/Source/JavaScriptCore/parser/SourceCode.h @@ -72,11 +72,6 @@ namespace JSC { int firstLine() const { return m_firstLine; } int startOffset() const { return m_startChar; } int endOffset() const { return m_endChar; } - const UChar* data() const - { - ASSERT(m_provider->data()); - return m_provider->data()->characters16() + m_startChar; - } int length() const { return m_endChar - m_startChar; } SourceCode subExpression(unsigned openBrace, unsigned closeBrace, int firstLine); diff --git a/Source/JavaScriptCore/parser/SourceProvider.h b/Source/JavaScriptCore/parser/SourceProvider.h index f66a921f5..20be63cac 100644 --- a/Source/JavaScriptCore/parser/SourceProvider.h +++ b/Source/JavaScriptCore/parser/SourceProvider.h @@ -86,7 +86,7 @@ namespace JSC { return adoptRef(new UStringSourceProvider(source, url, startPosition)); } - UString getRange(int start, int end) const + virtual UString getRange(int start, int end) const OVERRIDE { return m_source.substringSharingImpl(start, end - start); } diff --git a/Source/JavaScriptCore/runtime/Arguments.cpp b/Source/JavaScriptCore/runtime/Arguments.cpp index 7a53ec1a4..9a3d7257b 100644 --- a/Source/JavaScriptCore/runtime/Arguments.cpp +++ b/Source/JavaScriptCore/runtime/Arguments.cpp @@ -306,6 +306,10 @@ bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, const Ident bool isArrayIndex; unsigned i = propertyName.toArrayIndex(isArrayIndex); if (isArrayIndex && i < thisObject->d->numArguments) { + // If the property is not yet present on the object, and is not yet marked as deleted, then add it now. + PropertySlot slot; + if ((!thisObject->d->deletedArguments || !thisObject->d->deletedArguments[i]) && !JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot)) + object->putDirect(exec->globalData(), propertyName, thisObject->argument(i).get(), 0); if (!Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow)) return false; @@ -331,35 +335,16 @@ bool Arguments::defineOwnProperty(JSObject* object, ExecState* exec, const Ident thisObject->d->deletedArguments[i] = true; } } - return true; } if (propertyName == exec->propertyNames().length && !thisObject->d->overrodeLength) { + thisObject->putDirect(exec->globalData(), propertyName, jsNumber(thisObject->d->numArguments), DontEnum); thisObject->d->overrodeLength = true; - if (!descriptor.isAccessorDescriptor()) { - if (!descriptor.value()) - descriptor.setValue(jsNumber(thisObject->d->numArguments)); - if (!descriptor.configurablePresent()) - descriptor.setConfigurable(true); - } - if (!descriptor.configurablePresent()) - descriptor.setConfigurable(true); - } - - if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) { + } else if (propertyName == exec->propertyNames().callee && !thisObject->d->overrodeCallee) { + thisObject->putDirect(exec->globalData(), propertyName, thisObject->d->callee.get(), DontEnum); thisObject->d->overrodeCallee = true; - if (!descriptor.isAccessorDescriptor()) { - if (!descriptor.value()) - descriptor.setValue(thisObject->d->callee.get()); - if (!descriptor.configurablePresent()) - descriptor.setConfigurable(true); - } - if (!descriptor.configurablePresent()) - descriptor.setConfigurable(true); - } - - if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) + } else if (propertyName == exec->propertyNames().caller && thisObject->d->isStrictMode) thisObject->createStrictModeCallerIfNecessary(exec); return Base::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); diff --git a/Source/JavaScriptCore/runtime/Arguments.h b/Source/JavaScriptCore/runtime/Arguments.h index 8e7af1844..a1f36de56 100644 --- a/Source/JavaScriptCore/runtime/Arguments.h +++ b/Source/JavaScriptCore/runtime/Arguments.h @@ -158,7 +158,7 @@ namespace JSC { Base::finishCreation(callFrame->globalData()); ASSERT(inherits(&s_info)); - JSFunction* callee = asFunction(callFrame->callee()); + JSFunction* callee = jsCast<JSFunction*>(callFrame->callee()); d->numArguments = callFrame->argumentCount(); d->registers = reinterpret_cast<WriteBarrier<Unknown>*>(callFrame->registers()); d->callee.set(callFrame->globalData(), this, callee); diff --git a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp index 2f000fc74..6df58b773 100644 --- a/Source/JavaScriptCore/runtime/ArrayPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ArrayPrototype.cpp @@ -29,6 +29,7 @@ #include "Interpreter.h" #include "JIT.h" #include "JSStringBuilder.h" +#include "JSStringJoiner.h" #include "Lookup.h" #include "ObjectPrototype.h" #include "Operations.h" @@ -254,9 +255,27 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); - bool isRealArray = isJSArray(thisValue); - if (!isRealArray && !thisValue.inherits(&JSArray::s_info)) - return throwVMTypeError(exec); + // 1. Let array be the result of calling ToObject on the this value. + JSObject* thisObject = thisValue.toObject(exec); + if (exec->hadException()) + return JSValue::encode(jsUndefined()); + + // 2. Let func be the result of calling the [[Get]] internal method of array with argument "join". + JSValue function = JSValue(thisObject).get(exec, exec->propertyNames().join); + + // 3. If IsCallable(func) is false, then let func be the standard built-in method Object.prototype.toString (15.2.4.2). + if (!function.isCell()) + return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable()->className(thisObject), "]")); + CallData callData; + CallType callType = getCallData(function, callData); + if (callType == CallTypeNone) + return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable()->className(thisObject), "]")); + + // 4. Return the result of calling the [[Call]] internal method of func providing array as the this value and an empty arguments list. + if (!isJSArray(thisObject) || callType != CallTypeHost || callData.native.function != arrayProtoFuncJoin) + return JSValue::encode(call(exec, function, callType, callData, thisObject, exec->emptyList())); + + ASSERT(isJSArray(thisValue)); JSArray* thisObj = asArray(thisValue); unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec); @@ -273,7 +292,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) for (unsigned k = 0; k < length; k++) { JSValue element; - if (isRealArray && thisObj->canGetIndex(k)) + if (thisObj->canGetIndex(k)) element = thisObj->getIndex(k); else element = thisObj->get(exec, k); @@ -281,7 +300,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToString(ExecState* exec) if (element.isUndefinedOrNull()) continue; - UString str = element.toString(exec)->value(exec); + UString str = element.toUString(exec); strBuffer[k] = str.impl(); totalSize += str.length(); allStrings8Bit = allStrings8Bit && str.is8Bit(); @@ -343,11 +362,9 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) if (JSValue earlyReturnValue = checker.earlyReturnValue()) return JSValue::encode(earlyReturnValue); - JSStringBuilder strBuffer; + UString separator(","); + JSStringJoiner stringJoiner(separator, length); for (unsigned k = 0; k < length; k++) { - if (k >= 1) - strBuffer.append(','); - JSValue element = thisObj->get(exec, k); if (exec->hadException()) return JSValue::encode(jsUndefined()); @@ -360,16 +377,16 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncToLocaleString(ExecState* exec) CallData callData; CallType callType = getCallData(conversionFunction, callData); if (callType != CallTypeNone) - str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toString(exec)->value(exec); + str = call(exec, conversionFunction, callType, callData, element, exec->emptyList()).toUString(exec); else - str = element.toString(exec)->value(exec); + str = element.toUString(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); - strBuffer.append(str); + stringJoiner.append(str); } } - return JSValue::encode(strBuffer.build(exec)); + return JSValue::encode(stringJoiner.build(exec)); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) @@ -383,60 +400,39 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncJoin(ExecState* exec) if (JSValue earlyReturnValue = checker.earlyReturnValue()) return JSValue::encode(earlyReturnValue); - JSStringBuilder strBuffer; - UString separator; if (!exec->argument(0).isUndefined()) - separator = exec->argument(0).toString(exec)->value(exec); + separator = exec->argument(0).toUString(exec); + if (separator.isNull()) + separator = UString(","); + + JSStringJoiner stringJoiner(separator, length); unsigned k = 0; if (isJSArray(thisObj)) { JSArray* array = asArray(thisObj); - if (length) { - if (!array->canGetIndex(k)) - goto skipFirstLoop; + for (; k < length; k++) { + if (!array->canGetIndex(k)) + break; + JSValue element = array->getIndex(k); if (!element.isUndefinedOrNull()) - strBuffer.append(element.toString(exec)->value(exec)); - k++; - } - - if (separator.isNull()) { - for (; k < length; k++) { - if (!array->canGetIndex(k)) - break; - strBuffer.append(','); - JSValue element = array->getIndex(k); - if (!element.isUndefinedOrNull()) - strBuffer.append(element.toString(exec)->value(exec)); - } - } else { - for (; k < length; k++) { - if (!array->canGetIndex(k)) - break; - strBuffer.append(separator); - JSValue element = array->getIndex(k); - if (!element.isUndefinedOrNull()) - strBuffer.append(element.toString(exec)->value(exec)); - } - } - } - skipFirstLoop: - for (; k < length; k++) { - if (k >= 1) { - if (separator.isNull()) - strBuffer.append(','); + stringJoiner.append(element.toUStringInline(exec)); else - strBuffer.append(separator); + stringJoiner.append(UString()); } + } + for (; k < length; k++) { JSValue element = thisObj->get(exec, k); if (!element.isUndefinedOrNull()) - strBuffer.append(element.toString(exec)->value(exec)); + stringJoiner.append(element.toUStringInline(exec)); + else + stringJoiner.append(UString()); } - return JSValue::encode(strBuffer.build(exec)); + return JSValue::encode(stringJoiner.build(exec)); } EncodedJSValue JSC_HOST_CALL arrayProtoFuncConcat(ExecState* exec) @@ -524,7 +520,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(ExecState* exec) thisObj->methodTable()->putByIndex(thisObj, exec, length + n, exec->argument(n), true); else { PutPropertySlot slot; - Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toString(exec)->value(exec)); + Identifier propertyName(exec, JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toUString(exec)); thisObj->methodTable()->put(thisObj, exec, propertyName, exec->argument(n), slot); } if (exec->hadException()) @@ -665,7 +661,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSort(ExecState* exec) l.append(minObj); compareResult = call(exec, function, callType, callData, jsUndefined(), l).toNumber(exec); } else - compareResult = (jObj.toString(exec)->value(exec) < minObj.toString(exec)->value(exec)) ? -1 : 1; + compareResult = (jObj.toUStringInline(exec) < minObj.toUStringInline(exec)) ? -1 : 1; if (compareResult < 0) { themin = j; @@ -788,7 +784,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncFilter(ExecState* exec) unsigned filterIndex = 0; unsigned k = 0; if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = asFunction(function); + JSFunction* f = jsCast<JSFunction*>(function); JSArray* array = asArray(thisObj); CachedCall cachedCall(exec, f, 3); for (; k < length && !exec->hadException(); ++k) { @@ -846,7 +842,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncMap(ExecState* exec) JSArray* resultArray = constructEmptyArray(exec, length); unsigned k = 0; if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = asFunction(function); + JSFunction* f = jsCast<JSFunction*>(function); JSArray* array = asArray(thisObj); CachedCall cachedCall(exec, f, 3); for (; k < length && !exec->hadException(); ++k) { @@ -909,7 +905,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncEvery(ExecState* exec) unsigned k = 0; if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = asFunction(function); + JSFunction* f = jsCast<JSFunction*>(function); JSArray* array = asArray(thisObj); CachedCall cachedCall(exec, f, 3); for (; k < length && !exec->hadException(); ++k) { @@ -965,7 +961,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncForEach(ExecState* exec) unsigned k = 0; if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = asFunction(function); + JSFunction* f = jsCast<JSFunction*>(function); JSArray* array = asArray(thisObj); CachedCall cachedCall(exec, f, 3); for (; k < length && !exec->hadException(); ++k) { @@ -1017,7 +1013,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncSome(ExecState* exec) unsigned k = 0; if (callType == CallTypeJS && isJSArray(thisObj)) { - JSFunction* f = asFunction(function); + JSFunction* f = jsCast<JSFunction*>(function); JSArray* array = asArray(thisObj); CachedCall cachedCall(exec, f, 3); for (; k < length && !exec->hadException(); ++k) { @@ -1096,7 +1092,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduce(ExecState* exec) } if (callType == CallTypeJS && array) { - CachedCall cachedCall(exec, asFunction(function), 4); + CachedCall cachedCall(exec, jsCast<JSFunction*>(function), 4); for (; i < length && !exec->hadException(); ++i) { cachedCall.setThis(jsUndefined()); cachedCall.setArgument(0, rv); @@ -1173,7 +1169,7 @@ EncodedJSValue JSC_HOST_CALL arrayProtoFuncReduceRight(ExecState* exec) } if (callType == CallTypeJS && array) { - CachedCall cachedCall(exec, asFunction(function), 4); + CachedCall cachedCall(exec, jsCast<JSFunction*>(function), 4); for (; i < length && !exec->hadException(); ++i) { unsigned idx = length - i - 1; cachedCall.setThis(jsUndefined()); diff --git a/Source/JavaScriptCore/runtime/ClassInfo.h b/Source/JavaScriptCore/runtime/ClassInfo.h index 214258cc6..eb4a6f9cd 100644 --- a/Source/JavaScriptCore/runtime/ClassInfo.h +++ b/Source/JavaScriptCore/runtime/ClassInfo.h @@ -131,7 +131,6 @@ struct MemberCheck##member { \ &ClassName::defineOwnProperty, \ &ClassName::getOwnPropertyDescriptor, \ }, \ - sizeof(ClassName), \ ClassName::TypedArrayStorageType struct ClassInfo { @@ -180,8 +179,6 @@ struct MemberCheck##member { \ MethodTable methodTable; - size_t cellSize; - TypedArrayType typedArrayStorageType; }; diff --git a/Source/JavaScriptCore/runtime/CommonIdentifiers.h b/Source/JavaScriptCore/runtime/CommonIdentifiers.h index 0d9580197..e15335ef0 100644 --- a/Source/JavaScriptCore/runtime/CommonIdentifiers.h +++ b/Source/JavaScriptCore/runtime/CommonIdentifiers.h @@ -73,10 +73,11 @@ macro(valueOf) \ macro(writable) \ macro(displayName) \ - macro(undefined) + macro(join) #define JSC_COMMON_IDENTIFIERS_EACH_KEYWORD(macro) \ macro(null) \ + macro(undefined) \ macro(true) \ macro(false) \ macro(break) \ diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h index 345af2ebe..c41ced7ee 100644 --- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h +++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h @@ -44,7 +44,7 @@ namespace CommonSlowPaths { ALWAYS_INLINE ExecState* arityCheckFor(ExecState* exec, RegisterFile* registerFile, CodeSpecializationKind kind) { - JSFunction* callee = asFunction(exec->callee()); + JSFunction* callee = jsCast<JSFunction*>(exec->callee()); ASSERT(!callee->isHostFunction()); CodeBlock* newCodeBlock = &callee->jsExecutable()->generatedBytecodeFor(kind); int argumentCountIncludingThis = exec->argumentCountIncludingThis(); diff --git a/Source/JavaScriptCore/runtime/DateConstructor.cpp b/Source/JavaScriptCore/runtime/DateConstructor.cpp index 365172294..66f0baea5 100644 --- a/Source/JavaScriptCore/runtime/DateConstructor.cpp +++ b/Source/JavaScriptCore/runtime/DateConstructor.cpp @@ -166,10 +166,8 @@ ConstructType DateConstructor::getConstructData(JSCell*, ConstructData& construc // ECMA 15.9.2 static EncodedJSValue JSC_HOST_CALL callDate(ExecState* exec) { - time_t localTime = time(0); - tm localTM; - getLocalTime(&localTime, &localTM); - GregorianDateTime ts(exec, localTM); + GregorianDateTime ts; + msToGregorianDateTime(exec, currentTimeMS(), false, ts); DateConversionBuffer date; DateConversionBuffer time; formatDate(ts, date); diff --git a/Source/JavaScriptCore/runtime/Error.cpp b/Source/JavaScriptCore/runtime/Error.cpp index 5266c1ebe..bae07448b 100644 --- a/Source/JavaScriptCore/runtime/Error.cpp +++ b/Source/JavaScriptCore/runtime/Error.cpp @@ -79,6 +79,11 @@ JSObject* createTypeError(JSGlobalObject* globalObject, const UString& message) return ErrorInstance::create(globalObject->globalData(), globalObject->typeErrorConstructor()->errorStructure(), message); } +JSObject* createNotEnoughArgumentsError(JSGlobalObject* globalObject) +{ + return createTypeError(globalObject, "Not enough arguments"); +} + JSObject* createURIError(JSGlobalObject* globalObject, const UString& message) { ASSERT(!message.isEmpty()); @@ -115,42 +120,31 @@ JSObject* createTypeError(ExecState* exec, const UString& message) return createTypeError(exec->lexicalGlobalObject(), message); } +JSObject* createNotEnoughArgumentsError(ExecState* exec) +{ + return createNotEnoughArgumentsError(exec->lexicalGlobalObject()); +} + JSObject* createURIError(ExecState* exec, const UString& message) { return createURIError(exec->lexicalGlobalObject(), message); } -JSObject* addErrorInfo(JSGlobalData* globalData, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace) +JSObject* addErrorInfo(CallFrame* callFrame, JSObject* error, int line, const SourceCode& source) { + JSGlobalData* globalData = &callFrame->globalData(); const UString& sourceURL = source.provider()->url(); if (line != -1) error->putDirect(*globalData, Identifier(globalData, linePropertyName), jsNumber(line), ReadOnly | DontDelete); if (!sourceURL.isNull()) error->putDirect(*globalData, Identifier(globalData, sourceURLPropertyName), jsString(globalData, sourceURL), ReadOnly | DontDelete); - if (!stackTrace.isEmpty()) { - JSGlobalObject* globalObject = 0; - if (isTerminatedExecutionException(error) || isInterruptedExecutionException(error)) - globalObject = globalData->dynamicGlobalObject; - else - globalObject = error->globalObject(); - StringBuilder builder; - for (unsigned i = 0; i < stackTrace.size(); i++) { - builder.append(String(stackTrace[i].toString(globalObject->globalExec()).impl())); - if (i != stackTrace.size() - 1) - builder.append('\n'); - } - - error->putDirect(*globalData, globalData->propertyNames->stack, jsString(globalData, UString(builder.toString().impl())), ReadOnly | DontDelete); - } + + globalData->interpreter->addStackTraceIfNecessary(callFrame, error); return error; } -JSObject* addErrorInfo(ExecState* exec, JSObject* error, int line, const SourceCode& source, const Vector<StackFrame>& stackTrace) -{ - return addErrorInfo(&exec->globalData(), error, line, source, stackTrace); -} bool hasErrorInfo(ExecState* exec, JSObject* error) { @@ -160,12 +154,15 @@ bool hasErrorInfo(ExecState* exec, JSObject* error) JSValue throwError(ExecState* exec, JSValue error) { + if (error.isObject()) + return throwError(exec, asObject(error)); exec->globalData().exception = error; return error; } JSObject* throwError(ExecState* exec, JSObject* error) { + Interpreter::addStackTraceIfNecessary(exec, error); exec->globalData().exception = error; return error; } diff --git a/Source/JavaScriptCore/runtime/Error.h b/Source/JavaScriptCore/runtime/Error.h index 59b39495f..79617655e 100644 --- a/Source/JavaScriptCore/runtime/Error.h +++ b/Source/JavaScriptCore/runtime/Error.h @@ -45,6 +45,7 @@ namespace JSC { JSObject* createReferenceError(JSGlobalObject*, const UString&); JSObject* createSyntaxError(JSGlobalObject*, const UString&); JSObject* createTypeError(JSGlobalObject*, const UString&); + JSObject* createNotEnoughArgumentsError(JSGlobalObject*); JSObject* createURIError(JSGlobalObject*, const UString&); // ExecState wrappers. JS_EXPORT_PRIVATE JSObject* createError(ExecState*, const UString&); @@ -53,13 +54,13 @@ namespace JSC { JS_EXPORT_PRIVATE JSObject* createReferenceError(ExecState*, const UString&); JS_EXPORT_PRIVATE JSObject* createSyntaxError(ExecState*, const UString&); JS_EXPORT_PRIVATE JSObject* createTypeError(ExecState*, const UString&); + JS_EXPORT_PRIVATE JSObject* createNotEnoughArgumentsError(ExecState*); JSObject* createURIError(ExecState*, const UString&); // Methods to add bool hasErrorInfo(ExecState*, JSObject* error); - JSObject* addErrorInfo(JSGlobalData*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&); // ExecState wrappers. - JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&, const Vector<StackFrame>&); + JSObject* addErrorInfo(ExecState*, JSObject* error, int line, const SourceCode&); // Methods to throw Errors. JS_EXPORT_PRIVATE JSValue throwError(ExecState*, JSValue); diff --git a/Source/JavaScriptCore/runtime/Executable.cpp b/Source/JavaScriptCore/runtime/Executable.cpp index ea40447e4..934533c46 100644 --- a/Source/JavaScriptCore/runtime/Executable.cpp +++ b/Source/JavaScriptCore/runtime/Executable.cpp @@ -146,6 +146,8 @@ FunctionExecutable::FunctionExecutable(JSGlobalData& globalData, const Identifie , m_name(name) , m_inferredName(inferredName.isNull() ? globalData.propertyNames->emptyIdentifier : inferredName) , m_symbolTable(0) + , m_next(0) + , m_prev(0) { } @@ -157,6 +159,8 @@ FunctionExecutable::FunctionExecutable(ExecState* exec, const Identifier& name, , m_name(name) , m_inferredName(inferredName.isNull() ? exec->globalData().propertyNames->emptyIdentifier : inferredName) , m_symbolTable(0) + , m_next(0) + , m_prev(0) { } @@ -654,7 +658,9 @@ void FunctionExecutable::discardCode() void FunctionExecutable::finalize(JSCell* cell) { - jsCast<FunctionExecutable*>(cell)->clearCode(); + FunctionExecutable* executable = jsCast<FunctionExecutable*>(cell); + Heap::heap(executable)->removeFunctionExecutable(executable); + executable->clearCode(); } inline void FunctionExecutable::clearCode() diff --git a/Source/JavaScriptCore/runtime/Executable.h b/Source/JavaScriptCore/runtime/Executable.h index 08b39fcf0..3b979ba82 100644 --- a/Source/JavaScriptCore/runtime/Executable.h +++ b/Source/JavaScriptCore/runtime/Executable.h @@ -463,9 +463,10 @@ namespace JSC { OwnPtr<ProgramCodeBlock> m_programCodeBlock; }; - class FunctionExecutable : public ScriptExecutable { + class FunctionExecutable : public ScriptExecutable, public DoublyLinkedListNode<FunctionExecutable> { friend class JIT; friend class LLIntOffsetsExtractor; + friend class WTF::DoublyLinkedListNode<FunctionExecutable>; public: typedef ScriptExecutable Base; @@ -473,6 +474,7 @@ namespace JSC { { FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(*exec->heap())) FunctionExecutable(exec, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext); executable->finishCreation(exec->globalData(), name, firstLine, lastLine); + exec->globalData().heap.addFunctionExecutable(executable); exec->globalData().heap.addFinalizer(executable, &finalize); return executable; } @@ -481,6 +483,7 @@ namespace JSC { { FunctionExecutable* executable = new (NotNull, allocateCell<FunctionExecutable>(globalData.heap)) FunctionExecutable(globalData, name, inferredName, source, forceUsesArguments, parameters, isInStrictContext); executable->finishCreation(globalData, name, firstLine, lastLine); + globalData.heap.addFunctionExecutable(executable); globalData.heap.addFinalizer(executable, &finalize); return executable; } @@ -567,7 +570,7 @@ namespace JSC { { ASSERT(exec->callee()); ASSERT(exec->callee()->inherits(&JSFunction::s_info)); - ASSERT(asFunction(exec->callee())->jsExecutable() == this); + ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this); if (kind == CodeForCall) return compileForCall(exec, scopeChainNode); @@ -579,7 +582,7 @@ namespace JSC { { ASSERT(exec->callee()); ASSERT(exec->callee()->inherits(&JSFunction::s_info)); - ASSERT(asFunction(exec->callee())->jsExecutable() == this); + ASSERT(jsCast<JSFunction*>(exec->callee())->jsExecutable() == this); if (kind == CodeForCall) return compileOptimizedForCall(exec, scopeChainNode); @@ -688,6 +691,8 @@ namespace JSC { Identifier m_inferredName; WriteBarrier<JSString> m_nameValue; SharedSymbolTable* m_symbolTable; + FunctionExecutable* m_next; + FunctionExecutable* m_prev; }; inline FunctionExecutable* JSFunction::jsExecutable() const @@ -716,7 +721,7 @@ namespace JSC { inline bool isHostFunction(JSValue value, NativeFunction nativeFunction) { - JSFunction* function = static_cast<JSFunction*>(getJSFunction(value)); + JSFunction* function = jsCast<JSFunction*>(getJSFunction(value)); if (!function || !function->isHostFunction()) return false; return function->nativeFunction() == nativeFunction; diff --git a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp index 266ddc241..d341b847b 100644 --- a/Source/JavaScriptCore/runtime/FunctionPrototype.cpp +++ b/Source/JavaScriptCore/runtime/FunctionPrototype.cpp @@ -102,7 +102,7 @@ EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec) { JSValue thisValue = exec->hostThisValue(); if (thisValue.inherits(&JSFunction::s_info)) { - JSFunction* function = asFunction(thisValue); + JSFunction* function = jsCast<JSFunction*>(thisValue); if (function->isHostFunction()) return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(exec), "() {\n [native code]\n}")); FunctionExecutable* executable = function->jsExecutable(); diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp index 308d245a9..6ec538f72 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallback.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallback.cpp @@ -42,7 +42,11 @@ DefaultGCActivityCallback::~DefaultGCActivityCallback() { } -void DefaultGCActivityCallback::operator()() +void DefaultGCActivityCallback::didAllocate(size_t) +{ +} + +void DefaultGCActivityCallback::willCollect() { } @@ -50,5 +54,9 @@ void DefaultGCActivityCallback::synchronize() { } +void DefaultGCActivityCallback::cancel() +{ +} + } diff --git a/Source/JavaScriptCore/runtime/GCActivityCallback.h b/Source/JavaScriptCore/runtime/GCActivityCallback.h index f40ebee5b..1a18a8b45 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallback.h +++ b/Source/JavaScriptCore/runtime/GCActivityCallback.h @@ -42,9 +42,11 @@ class Heap; class GCActivityCallback { public: - virtual ~GCActivityCallback() {} - virtual void operator()() {} - virtual void synchronize() {} + virtual ~GCActivityCallback() { } + virtual void didAllocate(size_t) { } + virtual void willCollect() { } + virtual void synchronize() { } + virtual void cancel() { } protected: GCActivityCallback() {} @@ -57,10 +59,12 @@ public: static PassOwnPtr<DefaultGCActivityCallback> create(Heap*); DefaultGCActivityCallback(Heap*); - ~DefaultGCActivityCallback(); + virtual ~DefaultGCActivityCallback(); - void operator()(); - void synchronize(); + virtual void didAllocate(size_t); + virtual void willCollect(); + virtual void synchronize(); + virtual void cancel(); #if USE(CF) protected: diff --git a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp index 7f45f0746..8b690a480 100644 --- a/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp +++ b/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp @@ -45,21 +45,34 @@ namespace JSC { struct DefaultGCActivityCallbackPlatformData { - static void trigger(CFRunLoopTimerRef, void *info); + static void timerDidFire(CFRunLoopTimerRef, void *info); RetainPtr<CFRunLoopTimerRef> timer; RetainPtr<CFRunLoopRef> runLoop; CFRunLoopTimerContext context; + double delay; }; +const double gcTimeSlicePerMB = 0.01; // Percentage of CPU time we will spend to reclaim 1 MB +const double maxGCTimeSlice = 0.05; // The maximum amount of CPU time we want to use for opportunistic timer-triggered collections. +const double timerSlop = 2.0; // Fudge factor to avoid performance cost of resetting timer. +const double pagingTimeOut = 0.1; // Time in seconds to allow opportunistic timer to iterate over all blocks to see if the Heap is paged out. const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10; +const CFTimeInterval hour = 60 * 60; -void DefaultGCActivityCallbackPlatformData::trigger(CFRunLoopTimerRef timer, void *info) +void DefaultGCActivityCallbackPlatformData::timerDidFire(CFRunLoopTimerRef, void *info) { Heap* heap = static_cast<Heap*>(info); APIEntryShim shim(heap->globalData()); +#if !PLATFORM(IOS) + double startTime = WTF::monotonicallyIncreasingTime(); + if (heap->isPagedOut(startTime + pagingTimeOut)) { + heap->activityCallback()->cancel(); + heap->increaseLastGCLength(pagingTimeOut); + return; + } +#endif heap->collectAllGarbage(); - CFRunLoopTimerSetNextFireDate(timer, CFAbsoluteTimeGetCurrent() + decade); } DefaultGCActivityCallback::DefaultGCActivityCallback(Heap* heap) @@ -76,9 +89,6 @@ DefaultGCActivityCallback::~DefaultGCActivityCallback() { CFRunLoopRemoveTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes); CFRunLoopTimerInvalidate(d->timer.get()); - d->context.info = 0; - d->runLoop = 0; - d->timer = 0; } void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLoop) @@ -88,14 +98,41 @@ void DefaultGCActivityCallback::commonConstructor(Heap* heap, CFRunLoopRef runLo memset(&d->context, 0, sizeof(CFRunLoopTimerContext)); d->context.info = heap; d->runLoop = runLoop; - d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::trigger, &d->context)); + d->timer.adoptCF(CFRunLoopTimerCreate(0, decade, decade, 0, 0, DefaultGCActivityCallbackPlatformData::timerDidFire, &d->context)); + d->delay = decade; CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes); } -void DefaultGCActivityCallback::operator()() +static void scheduleTimer(DefaultGCActivityCallbackPlatformData* d, double newDelay) +{ + if (newDelay * timerSlop > d->delay) + return; + double delta = d->delay - newDelay; + d->delay = newDelay; + CFRunLoopTimerSetNextFireDate(d->timer.get(), CFRunLoopTimerGetNextFireDate(d->timer.get()) - delta); +} + +static void cancelTimer(DefaultGCActivityCallbackPlatformData* d) { - CFTimeInterval triggerInterval = static_cast<Heap*>(d->context.info)->lastGCLength() * 100.0; - CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + triggerInterval); + d->delay = decade; + CFRunLoopTimerSetNextFireDate(d->timer.get(), CFAbsoluteTimeGetCurrent() + decade); +} + +void DefaultGCActivityCallback::didAllocate(size_t bytes) +{ + // The first byte allocated in an allocation cycle will report 0 bytes to didAllocate. + // We pretend it's one byte so that we don't ignore this allocation entirely. + if (!bytes) + bytes = 1; + Heap* heap = static_cast<Heap*>(d->context.info); + double gcTimeSlice = std::min((static_cast<double>(bytes) / MB) * gcTimeSlicePerMB, maxGCTimeSlice); + double newDelay = heap->lastGCLength() / gcTimeSlice; + scheduleTimer(d.get(), newDelay); +} + +void DefaultGCActivityCallback::willCollect() +{ + cancelTimer(d.get()); } void DefaultGCActivityCallback::synchronize() @@ -107,4 +144,9 @@ void DefaultGCActivityCallback::synchronize() CFRunLoopAddTimer(d->runLoop.get(), d->timer.get(), kCFRunLoopCommonModes); } +void DefaultGCActivityCallback::cancel() +{ + cancelTimer(d.get()); +} + } diff --git a/Source/JavaScriptCore/runtime/Identifier.cpp b/Source/JavaScriptCore/runtime/Identifier.cpp index fbc5787ce..182bcc462 100644 --- a/Source/JavaScriptCore/runtime/Identifier.cpp +++ b/Source/JavaScriptCore/runtime/Identifier.cpp @@ -110,11 +110,11 @@ PassRefPtr<StringImpl> Identifier::add(JSGlobalData* globalData, const char* c) if (iter != literalIdentifierTable.end()) return iter->second; - pair<HashSet<StringImpl*>::iterator, bool> addResult = identifierTable.add<const LChar*, IdentifierCStringTranslator>(reinterpret_cast<const LChar*>(c)); + HashSet<StringImpl*>::AddResult addResult = identifierTable.add<const LChar*, IdentifierCStringTranslator>(reinterpret_cast<const LChar*>(c)); // If the string is newly-translated, then we need to adopt it. // The boolean in the pair tells us if that is so. - RefPtr<StringImpl> addedString = addResult.second ? adoptRef(*addResult.first) : *addResult.first; + RefPtr<StringImpl> addedString = addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator; literalIdentifierTable.add(c, addedString.get()); @@ -138,11 +138,11 @@ PassRefPtr<StringImpl> Identifier::add8(JSGlobalData* globalData, const UChar* s if (!length) return StringImpl::empty(); CharBuffer<UChar> buf = {s, length}; - pair<HashSet<StringImpl*>::iterator, bool> addResult = globalData->identifierTable->add<CharBuffer<UChar>, IdentifierLCharFromUCharTranslator >(buf); + HashSet<StringImpl*>::AddResult addResult = globalData->identifierTable->add<CharBuffer<UChar>, IdentifierLCharFromUCharTranslator >(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; + return addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator; } template <typename CharType> @@ -210,7 +210,7 @@ PassRefPtr<StringImpl> Identifier::addSlowCase(JSGlobalData* globalData, StringI return r; } - return *globalData->identifierTable->add(r).first; + return *globalData->identifierTable->add(r).iterator; } PassRefPtr<StringImpl> Identifier::addSlowCase(ExecState* exec, StringImpl* r) diff --git a/Source/JavaScriptCore/runtime/Identifier.h b/Source/JavaScriptCore/runtime/Identifier.h index b9e5a1854..14960876b 100644 --- a/Source/JavaScriptCore/runtime/Identifier.h +++ b/Source/JavaScriptCore/runtime/Identifier.h @@ -178,11 +178,11 @@ namespace JSC { if (!length) return StringImpl::empty(); CharBuffer<T> buf = {s, length}; - pair<HashSet<StringImpl*>::iterator, bool> addResult = globalData->identifierTable->add<CharBuffer<T>, IdentifierCharBufferTranslator<T> >(buf); + HashSet<StringImpl*>::AddResult addResult = globalData->identifierTable->add<CharBuffer<T>, IdentifierCharBufferTranslator<T> >(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; + return addResult.isNewEntry ? adoptRef(*addResult.iterator) : *addResult.iterator; } inline bool operator==(const Identifier& a, const Identifier& b) @@ -246,10 +246,10 @@ namespace JSC { typedef HashMap<RefPtr<StringImpl>, int, IdentifierRepHash, HashTraits<RefPtr<StringImpl> >, IdentifierMapIndexHashTraits> IdentifierMap; template<typename U, typename V> - std::pair<HashSet<StringImpl*>::iterator, bool> IdentifierTable::add(U value) + HashSet<StringImpl*>::AddResult IdentifierTable::add(U value) { - std::pair<HashSet<StringImpl*>::iterator, bool> result = m_table.add<U, V>(value); - (*result.first)->setIsIdentifier(true); + HashSet<StringImpl*>::AddResult result = m_table.add<U, V>(value); + (*result.iterator)->setIsIdentifier(true); return result; } diff --git a/Source/JavaScriptCore/runtime/InitializeThreading.cpp b/Source/JavaScriptCore/runtime/InitializeThreading.cpp index b6fd6ce1f..4c0e123a4 100644 --- a/Source/JavaScriptCore/runtime/InitializeThreading.cpp +++ b/Source/JavaScriptCore/runtime/InitializeThreading.cpp @@ -57,7 +57,7 @@ static void initializeThreadingOnce() #if ENABLE(WRITE_BARRIER_PROFILING) WriteBarrierCounters::initialize(); #endif -#if ENABLE(JIT) && ENABLE(ASSEMBLER) +#if ENABLE(ASSEMBLER) ExecutableAllocator::initializeAllocator(); #endif RegisterFile::initializeThreading(); diff --git a/Source/JavaScriptCore/runtime/Intrinsic.h b/Source/JavaScriptCore/runtime/Intrinsic.h index 5cc00685f..73244e7c7 100644 --- a/Source/JavaScriptCore/runtime/Intrinsic.h +++ b/Source/JavaScriptCore/runtime/Intrinsic.h @@ -45,6 +45,8 @@ enum Intrinsic { RoundIntrinsic, ExpIntrinsic, LogIntrinsic, + RegExpExecIntrinsic, + RegExpTestIntrinsic, }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSActivation.cpp b/Source/JavaScriptCore/runtime/JSActivation.cpp index 3e05738eb..a10361007 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.cpp +++ b/Source/JavaScriptCore/runtime/JSActivation.cpp @@ -45,6 +45,7 @@ JSActivation::JSActivation(CallFrame* callFrame, FunctionExecutable* functionExe : Base(callFrame->globalData(), callFrame->globalData().activationStructure.get(), functionExecutable->symbolTable(), callFrame->registers()) , m_numCapturedArgs(max(callFrame->argumentCount(), functionExecutable->parameterCount())) , m_numCapturedVars(functionExecutable->capturedVariableCount()) + , m_isTornOff(false) , m_requiresDynamicChecks(functionExecutable->usesEval() && !functionExecutable->isStrictMode()) , m_argumentsRegister(functionExecutable->generatedBytecode().argumentsRegister()) { @@ -78,11 +79,15 @@ void JSActivation::visitChildren(JSCell* cell, SlotVisitor& visitor) WriteBarrier<Unknown>* registerArray = thisObject->m_registerArray.get(); if (!registerArray) return; - + visitor.appendValues(registerArray, thisObject->m_numCapturedArgs); - // Skip 'this' and call frame. - visitor.appendValues(registerArray + CallFrame::offsetFor(thisObject->m_numCapturedArgs + 1), thisObject->m_numCapturedVars); + // Skip 'this' and call frame, except for callee and scope chain. + int offset = CallFrame::offsetFor(thisObject->m_numCapturedArgs + 1); + visitor.append(registerArray + offset + RegisterFile::ScopeChain); + visitor.append(registerArray + offset + RegisterFile::Callee); + + visitor.appendValues(registerArray + offset, thisObject->m_numCapturedVars); } inline bool JSActivation::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) @@ -90,7 +95,7 @@ inline bool JSActivation::symbolTableGet(const Identifier& propertyName, Propert SymbolTableEntry entry = symbolTable().inlineGet(propertyName.impl()); if (entry.isNull()) return false; - if (entry.getIndex() >= m_numCapturedVars) + if (m_isTornOff && entry.getIndex() >= m_numCapturedVars) return false; slot.setValue(registerAt(entry.getIndex()).get()); @@ -110,7 +115,7 @@ inline bool JSActivation::symbolTablePut(ExecState* exec, const Identifier& prop throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return true; } - if (entry.getIndex() >= m_numCapturedVars) + if (m_isTornOff && entry.getIndex() >= m_numCapturedVars) return false; registerAt(entry.getIndex()).set(globalData, this, value); diff --git a/Source/JavaScriptCore/runtime/JSActivation.h b/Source/JavaScriptCore/runtime/JSActivation.h index 80c8aa8d0..fd1b2fd7f 100644 --- a/Source/JavaScriptCore/runtime/JSActivation.h +++ b/Source/JavaScriptCore/runtime/JSActivation.h @@ -92,7 +92,8 @@ namespace JSC { NEVER_INLINE PropertySlot::GetValueFunc getArgumentsGetter(); int m_numCapturedArgs; - int m_numCapturedVars : 31; + int m_numCapturedVars : 30; + bool m_isTornOff : 1; bool m_requiresDynamicChecks : 1; int m_argumentsRegister; }; @@ -102,7 +103,7 @@ namespace JSC { inline JSActivation* asActivation(JSValue value) { ASSERT(asObject(value)->inherits(&JSActivation::s_info)); - return static_cast<JSActivation*>(asObject(value)); + return jsCast<JSActivation*>(asObject(value)); } ALWAYS_INLINE JSActivation* Register::activation() const @@ -127,19 +128,13 @@ namespace JSC { OwnArrayPtr<WriteBarrier<Unknown> > registerArray = adoptArrayPtr(new WriteBarrier<Unknown>[registerArraySize]); WriteBarrier<Unknown>* registers = registerArray.get() + registerOffset; - // Copy all arguments that can be captured by name or by the arguments object. - for (int i = 0; i < m_numCapturedArgs; ++i) { - int index = CallFrame::argumentOffset(i); - registers[index].set(globalData, this, m_registers[index].get()); - } - - // Skip 'this' and call frame. - - // Copy all captured vars. - for (int i = 0; i < m_numCapturedVars; ++i) + int from = CallFrame::argumentOffset(m_numCapturedArgs - 1); + int to = m_numCapturedVars; + for (int i = from; i < to; ++i) registers[i].set(globalData, this, m_registers[i].get()); setRegisters(registers, registerArray.release()); + m_isTornOff = true; } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSArray.cpp b/Source/JavaScriptCore/runtime/JSArray.cpp index 4244bc31c..aa1b8b7d9 100644 --- a/Source/JavaScriptCore/runtime/JSArray.cpp +++ b/Source/JavaScriptCore/runtime/JSArray.cpp @@ -125,15 +125,6 @@ inline void JSArray::checkConsistency(ConsistencyCheckType) #endif -JSArray::JSArray(JSGlobalData& globalData, Structure* structure) - : JSNonFinalObject(globalData, structure) - , m_indexBias(0) - , m_storage(0) - , m_sparseValueMap(0) - , m_subclassData(0) -{ -} - void JSArray::finishCreation(JSGlobalData& globalData, unsigned initialLength) { Base::finishCreation(globalData); @@ -176,11 +167,12 @@ JSArray* JSArray::tryFinishCreationUninitialized(JSGlobalData& globalData, unsig m_storage = static_cast<ArrayStorage*>(newStorage); m_storage->m_allocBase = m_storage; - m_storage->m_length = 0; + m_storage->m_length = initialLength; m_vectorLength = initialVectorLength; m_storage->m_numValuesInVector = initialLength; #if CHECK_ARRAY_CONSISTENCY + m_storage->m_initializationIndex = 0; m_storage->m_inCompactInitialization = true; #endif @@ -195,10 +187,12 @@ void JSArray::finalize(JSCell* cell) thisObject->deallocateSparseMap(); } -inline std::pair<SparseArrayValueMap::iterator, bool> SparseArrayValueMap::add(JSArray* array, unsigned i) +inline SparseArrayValueMap::AddResult SparseArrayValueMap::add(JSArray* array, unsigned i) { SparseArrayEntry entry; - std::pair<iterator, bool> result = m_map.add(i, entry); + entry.setWithoutWriteBarrier(jsUndefined()); + + AddResult result = m_map.add(i, entry); size_t capacity = m_map.capacity(); if (capacity != m_reportedCapacity) { Heap::heap(array)->reportExtraMemoryCost((capacity - m_reportedCapacity) * (sizeof(unsigned) + sizeof(WriteBarrier<Unknown>))); @@ -209,14 +203,14 @@ inline std::pair<SparseArrayValueMap::iterator, bool> SparseArrayValueMap::add(J inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i, JSValue value, bool shouldThrow) { - std::pair<SparseArrayValueMap::iterator, bool> result = add(array, i); - SparseArrayEntry& entry = result.first->second; + AddResult result = add(array, i); + SparseArrayEntry& entry = result.iterator->second; // To save a separate find & add, we first always add to the sparse map. // In the uncommon case that this is a new property, and the array is not // extensible, this is not the right thing to have done - so remove again. - if (result.second && !array->isExtensible()) { - remove(result.first); + if (result.isNewEntry && !array->isExtensible()) { + remove(result.iterator); if (shouldThrow) throwTypeError(exec, StrictModeReadonlyPropertyWriteError); return; @@ -252,14 +246,14 @@ inline void SparseArrayValueMap::put(ExecState* exec, JSArray* array, unsigned i inline bool SparseArrayValueMap::putDirect(ExecState* exec, JSArray* array, unsigned i, JSValue value, bool shouldThrow) { - std::pair<SparseArrayValueMap::iterator, bool> result = add(array, i); - SparseArrayEntry& entry = result.first->second; + AddResult result = add(array, i); + SparseArrayEntry& entry = result.iterator->second; // To save a separate find & add, we first always add to the sparse map. // In the uncommon case that this is a new property, and the array is not // extensible, this is not the right thing to have done - so remove again. - if (result.second && !array->isExtensible()) { - remove(result.first); + if (result.isNewEntry && !array->isExtensible()) { + remove(result.iterator); return reject(exec, shouldThrow, "Attempting to define property on object that is not extensible."); } @@ -355,7 +349,7 @@ void JSArray::enterDictionaryMode(JSGlobalData& globalData) // This will always be a new entry in the map, so no need to check we can write, // and attributes are default so no need to set them. if (value) - map->add(this, i).first->second.set(globalData, this, value); + map->add(this, i).iterator->second.set(globalData, this, value); } void* newRawStorage = 0; @@ -430,15 +424,15 @@ bool JSArray::defineOwnNumericProperty(ExecState* exec, unsigned index, Property ASSERT(map); // 1. Let current be the result of calling the [[GetOwnProperty]] internal method of O with property name P. - std::pair<SparseArrayValueMap::iterator, bool> result = map->add(this, index); - SparseArrayEntry* entryInMap = &result.first->second; + SparseArrayValueMap::AddResult result = map->add(this, index); + SparseArrayEntry* entryInMap = &result.iterator->second; // 2. Let extensible be the value of the [[Extensible]] internal property of O. // 3. If current is undefined and extensible is false, then Reject. // 4. If current is undefined and extensible is true, then - if (result.second) { + if (result.isNewEntry) { if (!isExtensible()) { - map->remove(result.first); + map->remove(result.iterator); return reject(exec, throwException, "Attempting to define property on object that is not extensible."); } @@ -543,7 +537,7 @@ void JSArray::setLengthWritable(ExecState* exec, bool writable) // Defined in ES5.1 15.4.5.1 bool JSArray::defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool throwException) { - JSArray* array = static_cast<JSArray*>(object); + JSArray* array = jsCast<JSArray*>(object); // 3. If P is "length", then if (propertyName == exec->propertyNames().length) { @@ -1388,7 +1382,7 @@ void JSArray::visitChildren(JSCell* cell, SlotVisitor& visitor) visitor.copyAndAppend(reinterpret_cast<void**>(&baseStorage), storageSize(thisObject->m_vectorLength + thisObject->m_indexBias), storage->m_vector->slot(), thisObject->m_vectorLength); if (baseStorage != thisObject->m_storage->m_allocBase) { - thisObject->m_storage = reinterpret_cast<ArrayStorage*>(static_cast<char*>(baseStorage) + sizeof(JSValue) * thisObject->m_indexBias); + thisObject->m_storage = reinterpret_cast_ptr<ArrayStorage*>(static_cast<char*>(baseStorage) + sizeof(JSValue) * thisObject->m_indexBias); thisObject->m_storage->m_allocBase = baseStorage; ASSERT(thisObject->m_storage->m_allocBase); } @@ -1473,17 +1467,19 @@ void JSArray::sort(ExecState* exec) Heap::heap(this)->pushTempSortVector(&values); + bool isSortingPrimitiveValues = true; for (size_t i = 0; i < lengthNotIncludingUndefined; i++) { JSValue value = m_storage->m_vector[i].get(); ASSERT(!value.isUndefined()); values[i].first = value; + isSortingPrimitiveValues = isSortingPrimitiveValues && value.isPrimitive(); } // FIXME: The following loop continues to call toString on subsequent values even after // a toString call raises an exception. for (size_t i = 0; i < lengthNotIncludingUndefined; i++) - values[i].second = values[i].first.toString(exec)->value(exec); + values[i].second = values[i].first.toUStringInline(exec); if (exec->hadException()) { Heap::heap(this)->popTempSortVector(&values); @@ -1494,7 +1490,10 @@ void JSArray::sort(ExecState* exec) // than O(N log N). #if HAVE(MERGESORT) - mergesort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort); + if (isSortingPrimitiveValues) + qsort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort); + else + mergesort(values.begin(), values.size(), sizeof(ValueStringPair), compareByStringPairForQSort); #else // FIXME: The qsort library function is likely to not be a stable sort. // ECMAScript-262 does not specify a stable sort, but in practice, browsers perform a stable sort. @@ -1622,7 +1621,7 @@ void JSArray::sort(ExecState* exec, JSValue compareFunction, CallType callType, tree.abstractor().m_nodes.grow(nodeCount); if (callType == CallTypeJS) - tree.abstractor().m_cachedCall = adoptPtr(new CachedCall(exec, asFunction(compareFunction), 2)); + tree.abstractor().m_cachedCall = adoptPtr(new CachedCall(exec, jsCast<JSFunction*>(compareFunction), 2)); if (!tree.abstractor().m_nodes.begin()) { throwOutOfMemoryError(exec); @@ -1802,16 +1801,6 @@ unsigned JSArray::compactForSorting(JSGlobalData& globalData) return numDefined; } -void* JSArray::subclassData() const -{ - return m_subclassData; -} - -void JSArray::setSubclassData(void* d) -{ - m_subclassData = d; -} - #if CHECK_ARRAY_CONSISTENCY void JSArray::checkConsistency(ConsistencyCheckType type) @@ -1826,7 +1815,7 @@ void JSArray::checkConsistency(ConsistencyCheckType type) unsigned numValuesInVector = 0; for (unsigned i = 0; i < m_vectorLength; ++i) { - if (JSValue value = storage->m_vector[i]) { + if (JSValue value = storage->m_vector[i].get()) { ASSERT(i < storage->m_length); if (type != DestructorConsistencyCheck) value.isUndefined(); // Likely to crash if the object was deallocated. @@ -1840,15 +1829,15 @@ void JSArray::checkConsistency(ConsistencyCheckType type) ASSERT(numValuesInVector <= storage->m_length); if (m_sparseValueMap) { - SparseArrayValueMap::iterator end = m_sparseValueMap->end(); - for (SparseArrayValueMap::iterator it = m_sparseValueMap->begin(); it != end; ++it) { + SparseArrayValueMap::const_iterator end = m_sparseValueMap->end(); + for (SparseArrayValueMap::const_iterator it = m_sparseValueMap->begin(); it != end; ++it) { unsigned index = it->first; ASSERT(index < storage->m_length); - ASSERT(index >= storage->m_vectorLength); + ASSERT(index >= m_vectorLength); ASSERT(index <= MAX_ARRAY_INDEX); ASSERT(it->second); if (type != DestructorConsistencyCheck) - it->second.isUndefined(); // Likely to crash if the object was deallocated. + it->second.getNonSparseMode().isUndefined(); // Likely to crash if the object was deallocated. } } } diff --git a/Source/JavaScriptCore/runtime/JSArray.h b/Source/JavaScriptCore/runtime/JSArray.h index ad98d6619..17c7f3ed7 100644 --- a/Source/JavaScriptCore/runtime/JSArray.h +++ b/Source/JavaScriptCore/runtime/JSArray.h @@ -55,6 +55,7 @@ namespace JSC { public: typedef Map::iterator iterator; typedef Map::const_iterator const_iterator; + typedef Map::AddResult AddResult; SparseArrayValueMap() : m_flags(Normal) @@ -87,7 +88,7 @@ namespace JSC { // These methods may mutate the contents of the map void put(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow); bool putDirect(ExecState*, JSArray*, unsigned, JSValue, bool shouldThrow); - std::pair<iterator, bool> add(JSArray*, unsigned); + AddResult add(JSArray*, unsigned); iterator find(unsigned i) { return m_map.find(i); } // This should ASSERT the remove is valid (check the result of the find). void remove(iterator it) { m_map.remove(it); } @@ -118,7 +119,9 @@ namespace JSC { unsigned m_numValuesInVector; void* m_allocBase; // Pointer to base address returned by malloc(). Keeping this pointer does eliminate false positives from the leak detector. #if CHECK_ARRAY_CONSISTENCY - uintptr_t m_inCompactInitialization; // Needs to be a uintptr_t for alignment purposes. + // Needs to be a uintptr_t for alignment purposes. + uintptr_t m_initializationIndex; + uintptr_t m_inCompactInitialization; #else uintptr_t m_padding; #endif @@ -136,7 +139,13 @@ namespace JSC { friend class JIT; protected: - JS_EXPORT_PRIVATE explicit JSArray(JSGlobalData&, Structure*); + explicit JSArray(JSGlobalData& globalData, Structure* structure) + : JSNonFinalObject(globalData, structure) + , m_indexBias(0) + , m_storage(0) + , m_sparseValueMap(0) + { + } JS_EXPORT_PRIVATE void finishCreation(JSGlobalData&, unsigned initialLength = 0); JS_EXPORT_PRIVATE JSArray* tryFinishCreationUninitialized(JSGlobalData&, unsigned initialLength); @@ -218,24 +227,25 @@ namespace JSC { ArrayStorage *storage = m_storage; #if CHECK_ARRAY_CONSISTENCY ASSERT(storage->m_inCompactInitialization); -#endif // Check that we are initializing the next index in sequence. - ASSERT_UNUSED(i, i == storage->m_length); + ASSERT(i == storage->m_initializationIndex); // tryCreateUninitialized set m_numValuesInVector to the initialLength, // check we do not try to initialize more than this number of properties. - ASSERT(storage->m_length < storage->m_numValuesInVector); - // It is improtant that we increment length here, so that all newly added - // values in the array still get marked during the initialization phase. - storage->m_vector[storage->m_length++].set(globalData, this, v); + ASSERT(storage->m_initializationIndex < storage->m_numValuesInVector); + storage->m_initializationIndex++; +#endif + ASSERT(i < storage->m_length); + ASSERT(i < storage->m_numValuesInVector); + storage->m_vector[i].set(globalData, this, v); } inline void completeInitialization(unsigned newLength) { // Check that we have initialized as meny properties as we think we have. ASSERT_UNUSED(newLength, newLength == m_storage->m_length); - // Check that the number of propreties initialized matches the initialLength. - ASSERT(m_storage->m_length == m_storage->m_numValuesInVector); #if CHECK_ARRAY_CONSISTENCY + // Check that the number of propreties initialized matches the initialLength. + ASSERT(m_storage->m_initializationIndex == m_storage->m_numValuesInVector); ASSERT(m_storage->m_inCompactInitialization); m_storage->m_inCompactInitialization = false; #endif @@ -313,10 +323,8 @@ namespace JSC { // FIXME: Maybe SparseArrayValueMap should be put into its own JSCell? SparseArrayValueMap* m_sparseValueMap; - void* m_subclassData; // A JSArray subclass can use this to fill the vector lazily. static ptrdiff_t sparseValueMapOffset() { return OBJECT_OFFSETOF(JSArray, m_sparseValueMap); } - static ptrdiff_t subclassDataOffset() { return OBJECT_OFFSETOF(JSArray, m_subclassData); } static ptrdiff_t indexBiasOffset() { return OBJECT_OFFSETOF(JSArray, m_indexBias); } }; @@ -338,7 +346,7 @@ namespace JSC { inline JSArray* asArray(JSCell* cell) { ASSERT(cell->inherits(&JSArray::s_info)); - return static_cast<JSArray*>(cell); + return jsCast<JSArray*>(cell); } inline JSArray* asArray(JSValue value) diff --git a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp index 8ebf8c638..5fee47c24 100644 --- a/Source/JavaScriptCore/runtime/JSBoundFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSBoundFunction.cpp @@ -38,7 +38,7 @@ const ClassInfo JSBoundFunction::s_info = { "Function", &Base::s_info, 0, 0, CRE EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState* exec) { - JSBoundFunction* boundFunction = static_cast<JSBoundFunction*>(exec->callee()); + JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee()); ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true! JSArray* boundArgs = asArray(boundFunction->boundArgs()); @@ -58,7 +58,7 @@ EncodedJSValue JSC_HOST_CALL boundFunctionCall(ExecState* exec) EncodedJSValue JSC_HOST_CALL boundFunctionConstruct(ExecState* exec) { - JSBoundFunction* boundFunction = static_cast<JSBoundFunction*>(exec->callee()); + JSBoundFunction* boundFunction = jsCast<JSBoundFunction*>(exec->callee()); ASSERT(isJSArray(boundFunction->boundArgs())); // Currently this is true! JSArray* boundArgs = asArray(boundFunction->boundArgs()); diff --git a/Source/JavaScriptCore/runtime/JSByteArray.cpp b/Source/JavaScriptCore/runtime/JSByteArray.cpp deleted file mode 100644 index 39ea4d0b9..000000000 --- a/Source/JavaScriptCore/runtime/JSByteArray.cpp +++ /dev/null @@ -1,120 +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 "JSByteArray.h" - -#include "JSGlobalObject.h" -#include "PropertyNameArray.h" - -using namespace WTF; - -namespace JSC { - -const ClassInfo JSByteArray::s_info = { "Uint8ClampedArray", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSByteArray) }; - -JSByteArray::JSByteArray(ExecState* exec, Structure* structure, ByteArray* storage) - : JSNonFinalObject(exec->globalData(), structure) - , m_storage(storage) -{ -} - -JSByteArray::~JSByteArray() -{ - ASSERT(jsCast<JSByteArray*>(this)); -} - -void JSByteArray::destroy(JSCell* cell) -{ - jsCast<JSByteArray*>(cell)->JSByteArray::~JSByteArray(); -} - -Structure* JSByteArray::createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue prototype, const JSC::ClassInfo* classInfo) -{ - return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), classInfo); -} - -bool JSByteArray::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) -{ - JSByteArray* thisObject = jsCast<JSByteArray*>(cell); - bool ok; - unsigned index = propertyName.toUInt32(ok); - if (ok && thisObject->canAccessIndex(index)) { - slot.setValue(thisObject->getIndex(exec, index)); - return true; - } - return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot); -} - -bool JSByteArray::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) -{ - JSByteArray* thisObject = jsCast<JSByteArray*>(object); - bool ok; - unsigned index = propertyName.toUInt32(ok); - if (ok && thisObject->canAccessIndex(index)) { - descriptor.setDescriptor(thisObject->getIndex(exec, index), DontDelete); - return true; - } - return JSObject::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); -} - -bool JSByteArray::getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot) -{ - JSByteArray* thisObject = jsCast<JSByteArray*>(cell); - if (thisObject->canAccessIndex(propertyName)) { - slot.setValue(thisObject->getIndex(exec, propertyName)); - return true; - } - return JSObject::getOwnPropertySlot(thisObject, exec, Identifier::from(exec, propertyName), slot); -} - -void JSByteArray::put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue value, PutPropertySlot& slot) -{ - JSByteArray* thisObject = jsCast<JSByteArray*>(cell); - bool ok; - unsigned index = propertyName.toUInt32(ok); - if (ok) { - thisObject->setIndex(exec, index, value); - return; - } - JSObject::put(thisObject, exec, propertyName, value, slot); -} - -void JSByteArray::putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue value, bool) -{ - jsCast<JSByteArray*>(cell)->setIndex(exec, propertyName, value); -} - -void JSByteArray::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode) -{ - JSByteArray* thisObject = jsCast<JSByteArray*>(object); - unsigned length = thisObject->m_storage->length(); - for (unsigned i = 0; i < length; ++i) - propertyNames.add(Identifier::from(exec, i)); - JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode); -} - -} - diff --git a/Source/JavaScriptCore/runtime/JSByteArray.h b/Source/JavaScriptCore/runtime/JSByteArray.h deleted file mode 100644 index 06181d901..000000000 --- a/Source/JavaScriptCore/runtime/JSByteArray.h +++ /dev/null @@ -1,133 +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. - */ - -#ifndef JSByteArray_h -#define JSByteArray_h - -#include "JSObject.h" - -#include <wtf/ByteArray.h> - -namespace JSC { - - class JSByteArray : public JSNonFinalObject { - friend class JSGlobalData; - public: - typedef JSNonFinalObject Base; - - bool canAccessIndex(unsigned i) { return i < m_storage->length(); } - JSValue getIndex(ExecState*, unsigned i) - { - ASSERT(canAccessIndex(i)); - return jsNumber(m_storage->data()[i]); - } - - void setIndex(unsigned i, int value) - { - ASSERT(canAccessIndex(i)); - if (value & ~0xFF) { - if (value < 0) - value = 0; - else - value = 255; - } - m_storage->data()[i] = static_cast<unsigned char>(value); - } - - void setIndex(unsigned i, double value) - { - ASSERT(canAccessIndex(i)); - if (!(value > 0)) // Clamp NaN to 0 - value = 0; - else if (value > 255) - value = 255; - m_storage->data()[i] = static_cast<unsigned char>(value + 0.5); - } - - void setIndex(ExecState* exec, unsigned i, JSValue value) - { - double byteValue = value.toNumber(exec); - if (exec->hadException()) - return; - if (canAccessIndex(i)) - setIndex(i, byteValue); - } - - private: - JS_EXPORT_PRIVATE JSByteArray(ExecState*, Structure*, ByteArray* storage); - - public: - static JSByteArray* create(ExecState* exec, Structure* structure, ByteArray* storage) - { - JSByteArray* array = new (NotNull, allocateCell<JSByteArray>(*exec->heap())) JSByteArray(exec, structure, storage); - array->finishCreation(exec); - return array; - } - - JS_EXPORT_PRIVATE static Structure* createStructure(JSGlobalData&, JSGlobalObject*, JSValue prototype, const JSC::ClassInfo* = &s_info); - - JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::PropertySlot&); - JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&); - JS_EXPORT_PRIVATE static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); - JS_EXPORT_PRIVATE static void put(JSC::JSCell*, JSC::ExecState*, const JSC::Identifier& propertyName, JSC::JSValue, JSC::PutPropertySlot&); - JS_EXPORT_PRIVATE static void putByIndex(JSC::JSCell*, JSC::ExecState*, unsigned propertyName, JSC::JSValue, bool shouldThrow); - - JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, EnumerationMode); - - static JS_EXPORTDATA const ClassInfo s_info; - - size_t length() const { return m_storage->length(); } - - WTF::ByteArray* storage() const { return m_storage.get(); } - - ~JSByteArray(); - JS_EXPORT_PRIVATE static void destroy(JSCell*); - - static size_t offsetOfStorage() { return OBJECT_OFFSETOF(JSByteArray, m_storage); } - - protected: - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags; - - void finishCreation(ExecState* exec) - { - Base::finishCreation(exec->globalData()); - putDirect(exec->globalData(), exec->globalData().propertyNames->length, jsNumber(m_storage->length()), ReadOnly | DontDelete); - } - - private: - RefPtr<WTF::ByteArray> m_storage; - }; - - JSByteArray* asByteArray(JSValue value); - inline JSByteArray* asByteArray(JSValue value) - { - return static_cast<JSByteArray*>(value.asCell()); - } - - inline bool isJSByteArray(JSValue v) { return v.isCell() && v.asCell()->classInfo() == &JSByteArray::s_info; } - -} // namespace JSC - -#endif // JSByteArray_h diff --git a/Source/JavaScriptCore/runtime/JSCell.cpp b/Source/JavaScriptCore/runtime/JSCell.cpp index f08d0260a..7f9ba88a2 100644 --- a/Source/JavaScriptCore/runtime/JSCell.cpp +++ b/Source/JavaScriptCore/runtime/JSCell.cpp @@ -159,7 +159,7 @@ JSObject* JSCell::toObject(ExecState* exec, JSGlobalObject* globalObject) const if (isString()) return static_cast<const JSString*>(this)->toObject(exec, globalObject); ASSERT(isObject()); - return static_cast<JSObject*>(const_cast<JSCell*>(this)); + return jsCast<JSObject*>(const_cast<JSCell*>(this)); } void slowValidateCell(JSCell* cell) diff --git a/Source/JavaScriptCore/runtime/JSCell.h b/Source/JavaScriptCore/runtime/JSCell.h index 2ef359b76..431e67145 100644 --- a/Source/JavaScriptCore/runtime/JSCell.h +++ b/Source/JavaScriptCore/runtime/JSCell.h @@ -178,7 +178,7 @@ namespace JSC { { #if ENABLE(GC_VALIDATION) ASSERT(globalData.isInitializingObject()); - globalData.setInitializingObject(false); + globalData.setInitializingObjectClass(0); #else UNUSED_PARAM(globalData); #endif @@ -328,9 +328,8 @@ namespace JSC { void* allocateCell(Heap& heap) { #if ENABLE(GC_VALIDATION) - ASSERT(sizeof(T) == T::s_info.cellSize); ASSERT(!heap.globalData()->isInitializingObject()); - heap.globalData()->setInitializingObject(true); + heap.globalData()->setInitializingObjectClass(&T::s_info); #endif JSCell* result = 0; if (NeedsDestructor<T>::value) @@ -351,16 +350,29 @@ namespace JSC { template<typename To, typename From> inline To jsCast(From* from) { - ASSERT(from->inherits(&WTF::RemovePointer<To>::Type::s_info)); + ASSERT(!from || from->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info)); return static_cast<To>(from); } + template<typename To> + inline To jsCast(JSValue from) + { + ASSERT(from.isCell() && from.asCell()->JSCell::inherits(&WTF::RemovePointer<To>::Type::s_info)); + return static_cast<To>(from.asCell()); + } + template<typename To, typename From> inline To jsDynamicCast(From* from) { return from->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from) : 0; } + template<typename To> + inline To jsDynamicCast(JSValue from) + { + return from.isCell() && from.asCell()->inherits(&WTF::RemovePointer<To>::Type::s_info) ? static_cast<To>(from.asCell()) : 0; + } + } // namespace JSC #endif // JSCell_h diff --git a/Source/JavaScriptCore/runtime/JSDateMath.cpp b/Source/JavaScriptCore/runtime/JSDateMath.cpp index 882f86fa0..dbe748835 100644 --- a/Source/JavaScriptCore/runtime/JSDateMath.cpp +++ b/Source/JavaScriptCore/runtime/JSDateMath.cpp @@ -72,12 +72,8 @@ #include "config.h" #include "JSDateMath.h" -#include "CurrentTime.h" #include "JSObject.h" -#include "MathExtras.h" #include "ScopeChain.h" -#include "StdLibExtras.h" -#include "StringExtras.h" #include <algorithm> #include <limits.h> @@ -86,17 +82,16 @@ #include <time.h> #include <wtf/ASCIICType.h> #include <wtf/Assertions.h> +#include <wtf/CurrentTime.h> +#include <wtf/MathExtras.h> +#include <wtf/StdLibExtras.h> +#include <wtf/StringExtras.h> #include <wtf/text/StringBuilder.h> #if HAVE(ERRNO_H) #include <errno.h> #endif -#if OS(WINCE) -extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); -extern "C" struct tm * localtime(const time_t *timer); -#endif - #if HAVE(SYS_TIME_H) #include <sys/time.h> #endif diff --git a/Source/JavaScriptCore/runtime/JSDateMath.h b/Source/JavaScriptCore/runtime/JSDateMath.h index ba6d647dd..f77cf1e75 100644 --- a/Source/JavaScriptCore/runtime/JSDateMath.h +++ b/Source/JavaScriptCore/runtime/JSDateMath.h @@ -74,33 +74,6 @@ public: { } - GregorianDateTime(ExecState* exec, const tm& inTm) - : second(inTm.tm_sec) - , minute(inTm.tm_min) - , hour(inTm.tm_hour) - , weekDay(inTm.tm_wday) - , monthDay(inTm.tm_mday) - , yearDay(inTm.tm_yday) - , month(inTm.tm_mon) - , year(inTm.tm_year) - , isDST(inTm.tm_isdst) - { - UNUSED_PARAM(exec); -#if HAVE(TM_GMTOFF) - utcOffset = static_cast<int>(inTm.tm_gmtoff); -#else - utcOffset = static_cast<int>(getUTCOffset(exec) / WTF::msPerSecond + (isDST ? WTF::secondsPerHour : 0)); -#endif - -#if HAVE(TM_ZONE) - int inZoneSize = strlen(inTm.tm_zone) + 1; - timeZone = adoptArrayPtr(new char[inZoneSize]); - strncpy(timeZone.get(), inTm.tm_zone, inZoneSize); -#else - timeZone = nullptr; -#endif - } - operator tm() const { tm ret; diff --git a/Source/JavaScriptCore/runtime/JSFunction.cpp b/Source/JavaScriptCore/runtime/JSFunction.cpp index fa798f41a..243946ba9 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.cpp +++ b/Source/JavaScriptCore/runtime/JSFunction.cpp @@ -59,22 +59,25 @@ bool JSFunction::isHostFunctionNonInline() const return isHostFunction(); } -JSFunction* JSFunction::create(ExecState* exec, JSGlobalObject* globalObject, int length, const Identifier& name, NativeFunction nativeFunction, NativeFunction nativeConstructor) +JSFunction* JSFunction::create(ExecState* exec, JSGlobalObject* globalObject, int length, const Identifier& name, NativeFunction nativeFunction, Intrinsic intrinsic, NativeFunction nativeConstructor) { - NativeExecutable* executable = exec->globalData().getHostFunction(nativeFunction, nativeConstructor); + NativeExecutable* executable; +#if !ENABLE(JIT) + UNUSED_PARAM(intrinsic); +#else + if (intrinsic != NoIntrinsic && exec->globalData().canUseJIT()) { + ASSERT(nativeConstructor == callHostFunctionAsConstructor); + executable = exec->globalData().getHostFunction(nativeFunction, intrinsic); + } else +#endif + executable = exec->globalData().getHostFunction(nativeFunction, nativeConstructor); + JSFunction* function = new (NotNull, allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, globalObject, globalObject->functionStructure()); // Can't do this during initialization because getHostFunction might do a GC allocation. function->finishCreation(exec, executable, length, name); return function; } -JSFunction* JSFunction::create(ExecState* exec, JSGlobalObject* globalObject, int length, const Identifier& name, NativeExecutable* nativeExecutable) -{ - JSFunction* function = new (NotNull, allocateCell<JSFunction>(*exec->heap())) JSFunction(exec, globalObject, globalObject->functionStructure()); - function->finishCreation(exec, nativeExecutable, length, name); - return function; -} - JSFunction::JSFunction(ExecState* exec, JSGlobalObject* globalObject, Structure* structure) : Base(exec->globalData(), structure) , m_executable() @@ -172,21 +175,21 @@ CallType JSFunction::getCallData(JSCell* cell, CallData& callData) JSValue JSFunction::argumentsGetter(ExecState* exec, JSValue slotBase, const Identifier&) { - JSFunction* thisObj = asFunction(slotBase); + JSFunction* thisObj = jsCast<JSFunction*>(slotBase); ASSERT(!thisObj->isHostFunction()); return exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObj); } JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identifier&) { - JSFunction* thisObj = asFunction(slotBase); + JSFunction* thisObj = jsCast<JSFunction*>(slotBase); ASSERT(!thisObj->isHostFunction()); JSValue caller = exec->interpreter()->retrieveCallerFromVMCode(exec, thisObj); // See ES5.1 15.3.5.4 - Function.caller may not be used to retrieve a strict caller. if (!caller.isObject() || !asObject(caller)->inherits(&JSFunction::s_info)) return caller; - JSFunction* function = asFunction(caller); + JSFunction* function = jsCast<JSFunction*>(caller); if (function->isHostFunction() || !function->jsExecutable()->isStrictMode()) return caller; return throwTypeError(exec, "Function.caller used to retrieve strict caller"); @@ -194,7 +197,7 @@ JSValue JSFunction::callerGetter(ExecState* exec, JSValue slotBase, const Identi JSValue JSFunction::lengthGetter(ExecState*, JSValue slotBase, const Identifier&) { - JSFunction* thisObj = asFunction(slotBase); + JSFunction* thisObj = jsCast<JSFunction*>(slotBase); ASSERT(!thisObj->isHostFunction()); return jsNumber(thisObj->jsExecutable()->parameterCount()); } @@ -369,46 +372,55 @@ bool JSFunction::defineOwnProperty(JSObject* object, ExecState* exec, const Iden // following the rules set out in ECMA-262 8.12.9. PropertySlot slot; thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot); - } else if (propertyName == exec->propertyNames().arguments || propertyName == exec->propertyNames().length || propertyName == exec->propertyNames().caller) { - if (!object->isExtensible()) { - if (throwException) - throwError(exec, createTypeError(exec, "Attempting to define property on object that is not extensible.")); - return false; - } - if (descriptor.configurablePresent() && descriptor.configurable()) { - if (throwException) - throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property.")); - return false; - } - if (descriptor.enumerablePresent() && descriptor.enumerable()) { - if (throwException) - throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property.")); - return false; - } - if (descriptor.isAccessorDescriptor()) { - if (throwException) - throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property.")); - return false; + return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); + } + + bool valueCheck; + if (propertyName == exec->propertyNames().arguments) { + if (thisObject->jsExecutable()->isStrictMode()) { + if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor)) + thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); + return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); } - if (descriptor.writablePresent() && descriptor.writable()) { - if (throwException) - throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property.")); - return false; + valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject)); + } else if (propertyName == exec->propertyNames().caller) { + if (thisObject->jsExecutable()->isStrictMode()) { + if (!Base::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor)) + thisObject->putDirectAccessor(exec->globalData(), propertyName, thisObject->globalObject()->throwTypeErrorGetterSetter(exec), DontDelete | DontEnum | Accessor); + return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); } - if (!descriptor.value()) - return true; - if (propertyName == exec->propertyNames().arguments && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveArgumentsFromVMCode(exec, thisObject))) - return true; - if (propertyName == exec->propertyNames().length && sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount()))) - return true; - if (propertyName == exec->propertyNames().caller && sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject))) - return true; + valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), exec->interpreter()->retrieveCallerFromVMCode(exec, thisObject)); + } else if (propertyName == exec->propertyNames().length) + valueCheck = !descriptor.value() || sameValue(exec, descriptor.value(), jsNumber(thisObject->jsExecutable()->parameterCount())); + else + return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); + + if (descriptor.configurablePresent() && descriptor.configurable()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to configurable attribute of unconfigurable property.")); + return false; + } + if (descriptor.enumerablePresent() && descriptor.enumerable()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change enumerable attribute of unconfigurable property.")); + return false; + } + if (descriptor.isAccessorDescriptor()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change access mechanism for an unconfigurable property.")); + return false; + } + if (descriptor.writablePresent() && descriptor.writable()) { + if (throwException) + throwError(exec, createTypeError(exec, "Attempting to change writable attribute of unconfigurable property.")); + return false; + } + if (!valueCheck) { if (throwException) throwError(exec, createTypeError(exec, "Attempting to change value of a readonly property.")); return false; } - - return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException); + return true; } // ECMA 13.2.2 [[Construct]] diff --git a/Source/JavaScriptCore/runtime/JSFunction.h b/Source/JavaScriptCore/runtime/JSFunction.h index 288181060..5553115bf 100644 --- a/Source/JavaScriptCore/runtime/JSFunction.h +++ b/Source/JavaScriptCore/runtime/JSFunction.h @@ -24,6 +24,7 @@ #ifndef JSFunction_h #define JSFunction_h +#include "InternalFunction.h" #include "JSObject.h" namespace JSC { @@ -54,8 +55,7 @@ namespace JSC { public: typedef JSNonFinalObject Base; - JS_EXPORT_PRIVATE static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, NativeFunction nativeConstructor = callHostFunctionAsConstructor); - static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeExecutable* nativeExecutable); + JS_EXPORT_PRIVATE static JSFunction* create(ExecState*, JSGlobalObject*, int length, const Identifier& name, NativeFunction nativeFunction, Intrinsic = NoIntrinsic, NativeFunction nativeConstructor = callHostFunctionAsConstructor); static JSFunction* create(ExecState* exec, FunctionExecutable* executable, ScopeChainNode* scopeChain) { @@ -154,12 +154,9 @@ namespace JSC { WriteBarrier<ScopeChainNode> m_scopeChain; }; - JSFunction* asFunction(JSValue); - - inline JSFunction* asFunction(JSValue value) + inline bool JSValue::isFunction() const { - ASSERT(asObject(value)->inherits(&JSFunction::s_info)); - return static_cast<JSFunction*>(asObject(value)); + return isCell() && (asCell()->inherits(&JSFunction::s_info) || asCell()->inherits(&InternalFunction::s_info)); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.cpp b/Source/JavaScriptCore/runtime/JSGlobalData.cpp index f138e75fb..b08c7dfa2 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalData.cpp @@ -40,7 +40,6 @@ #include "JSActivation.h" #include "JSAPIValueWrapper.h" #include "JSArray.h" -#include "JSByteArray.h" #include "JSClassRef.h" #include "JSFunction.h" #include "JSLock.h" @@ -62,33 +61,12 @@ #include "RegExp.h" #endif -#if PLATFORM(MAC) +#if USE(CF) #include <CoreFoundation/CoreFoundation.h> #endif using namespace WTF; -namespace { - -using namespace JSC; - -class Recompiler : public MarkedBlock::VoidFunctor { -public: - void operator()(JSCell*); -}; - -inline void Recompiler::operator()(JSCell* cell) -{ - if (!cell->inherits(&JSFunction::s_info)) - return; - JSFunction* function = asFunction(cell); - if (!function->executable() || function->executable()->isHostFunction()) - return; - function->jsExecutable()->discardCode(); -} - -} // namespace - namespace JSC { extern const HashTable arrayConstructorTable; @@ -110,8 +88,34 @@ extern const HashTable regExpPrototypeTable; extern const HashTable stringTable; extern const HashTable stringConstructorTable; +#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) +static bool enableAssembler(ExecutableAllocator& executableAllocator) +{ + if (!executableAllocator.isValid() || !Options::useJIT) + return false; + +#if USE(CF) + CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman); + CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication); + if (canUseJIT) { + return kCFBooleanTrue == canUseJIT; + CFRelease(canUseJIT); + } + CFRelease(canUseJITKey); +#endif + +#if USE(CF) || OS(UNIX) + char* canUseJITString = getenv("JavaScriptCoreUseJIT"); + return !canUseJITString || atoi(canUseJITString); +#else + return true; +#endif +} +#endif + JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType threadStackType, HeapSize heapSize) - : globalDataType(globalDataType) + : heap(this, heapSize) + , globalDataType(globalDataType) , clientData(0) , topCallFrame(CallFrame::noCaller()) , arrayConstructorTable(fastNew<HashTable>(JSC::arrayConstructorTable)) @@ -141,7 +145,6 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread , parserArena(adoptPtr(new ParserArena)) , keywords(adoptPtr(new Keywords(this))) , interpreter(0) - , heap(this, heapSize) , jsArrayClassInfo(&JSArray::s_info) , jsFinalObjectClassInfo(&JSFinalObject::s_info) #if ENABLE(DFG_JIT) @@ -160,8 +163,11 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread #if CPU(X86) && ENABLE(JIT) , m_timeoutCount(512) #endif +#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) + , m_canUseAssembler(enableAssembler(executableAllocator)) +#endif #if ENABLE(GC_VALIDATION) - , m_isInitializingObject(false) + , m_initializingObjectClass(0) #endif , m_inDefineOwnProperty(false) { @@ -193,33 +199,7 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread wtfThreadData().setCurrentIdentifierTable(existingEntryIdentifierTable); -#if ENABLE(JIT) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) -#if USE(CF) - CFStringRef canUseJITKey = CFStringCreateWithCString(0 , "JavaScriptCoreUseJIT", kCFStringEncodingMacRoman); - CFBooleanRef canUseJIT = (CFBooleanRef)CFPreferencesCopyAppValue(canUseJITKey, kCFPreferencesCurrentApplication); - if (canUseJIT) { - m_canUseJIT = kCFBooleanTrue == canUseJIT; - CFRelease(canUseJIT); - } else { - char* canUseJITString = getenv("JavaScriptCoreUseJIT"); - m_canUseJIT = !canUseJITString || atoi(canUseJITString); - } - CFRelease(canUseJITKey); -#elif OS(UNIX) - char* canUseJITString = getenv("JavaScriptCoreUseJIT"); - m_canUseJIT = !canUseJITString || atoi(canUseJITString); -#else - m_canUseJIT = true; -#endif -#endif #if ENABLE(JIT) -#if ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT) - if (m_canUseJIT) - m_canUseJIT = executableAllocator.isValid(); - - if (!Options::useJIT) - m_canUseJIT = false; -#endif jitStubs = adoptPtr(new JITThunks(this)); #endif @@ -232,38 +212,13 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread llintData.performAssertions(*this); } -void JSGlobalData::clearBuiltinStructures() -{ - structureStructure.clear(); - debuggerActivationStructure.clear(); - activationStructure.clear(); - interruptedExecutionErrorStructure.clear(); - terminatedExecutionErrorStructure.clear(); - staticScopeStructure.clear(); - strictEvalActivationStructure.clear(); - stringStructure.clear(); - notAnObjectStructure.clear(); - propertyNameIteratorStructure.clear(); - getterSetterStructure.clear(); - apiWrapperStructure.clear(); - scopeChainNodeStructure.clear(); - executableStructure.clear(); - nativeExecutableStructure.clear(); - evalExecutableStructure.clear(); - programExecutableStructure.clear(); - functionExecutableStructure.clear(); - regExpStructure.clear(); - structureChainStructure.clear(); -} - JSGlobalData::~JSGlobalData() { - // By the time this is destroyed, heap.destroy() must already have been called. + heap.lastChanceToFinalize(); delete interpreter; #ifndef NDEBUG - // Zeroing out to make the behavior more predictable when someone attempts to use a deleted instance. - interpreter = 0; + interpreter = reinterpret_cast<Interpreter*>(0xbbadbeef); #endif arrayPrototypeTable->deleteTable(); @@ -443,15 +398,6 @@ void JSGlobalData::dumpSampleData(ExecState* exec) #endif } -void JSGlobalData::recompileAllJSFunctions() -{ - // If JavaScript is running, it's not safe to recompile, since we'll end - // up throwing away code that is live on the stack. - ASSERT(!dynamicGlobalObject); - - heap.objectSpace().forEachCell<Recompiler>(); -} - struct StackPreservingRecompiler : public MarkedBlock::VoidFunctor { HashSet<FunctionExecutable*> currentlyExecutingFunctions; void operator()(JSCell* cell) @@ -478,7 +424,7 @@ void JSGlobalData::releaseExecutableMemory() if (cell->inherits(&ScriptExecutable::s_info)) executable = static_cast<ScriptExecutable*>(*ptr); else if (cell->inherits(&JSFunction::s_info)) { - JSFunction* function = asFunction(*ptr); + JSFunction* function = jsCast<JSFunction*>(*ptr); if (function->isHostFunction()) continue; executable = function->jsExecutable(); diff --git a/Source/JavaScriptCore/runtime/JSGlobalData.h b/Source/JavaScriptCore/runtime/JSGlobalData.h index acbcee816..177d80298 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalData.h +++ b/Source/JavaScriptCore/runtime/JSGlobalData.h @@ -152,6 +152,8 @@ namespace JSC { void makeUsableFromMultipleThreads() { heap.machineThreads().makeUsableFromMultipleThreads(); } + Heap heap; // The heap is our first data member to ensure that it's destructed after all the objects that reference it. + GlobalDataType globalDataType; ClientData* clientData; CallFrame* topCallFrame; @@ -234,7 +236,15 @@ namespace JSC { #elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT) bool canUseJIT() { return true; } // jit only #else - bool canUseJIT() { return m_canUseJIT; } + bool canUseJIT() { return m_canUseAssembler; } +#endif + +#if !ENABLE(YARR_JIT) + bool canUseRegExpJIT() { return false; } // interpreter only +#elif !ENABLE(CLASSIC_INTERPRETER) && !ENABLE(LLINT) + bool canUseRegExpJIT() { return true; } // jit only +#else + bool canUseRegExpJIT() { return m_canUseAssembler; } #endif OwnPtr<ParserArena> parserArena; @@ -252,7 +262,6 @@ namespace JSC { TimeoutChecker timeoutChecker; Terminator terminator; - Heap heap; JSValue exception; @@ -324,20 +333,18 @@ namespace JSC { JS_EXPORT_PRIVATE void startSampling(); JS_EXPORT_PRIVATE void stopSampling(); JS_EXPORT_PRIVATE void dumpSampleData(ExecState* exec); - void recompileAllJSFunctions(); RegExpCache* regExpCache() { return m_regExpCache; } #if ENABLE(REGEXP_TRACING) void addRegExpToTrace(PassRefPtr<RegExp> regExp); #endif JS_EXPORT_PRIVATE void dumpRegExpTrace(); - JS_EXPORT_PRIVATE void clearBuiltinStructures(); bool isCollectorBusy() { return heap.isBusy(); } JS_EXPORT_PRIVATE void releaseExecutableMemory(); #if ENABLE(GC_VALIDATION) bool isInitializingObject() const; - void setInitializingObject(bool); + void setInitializingObjectClass(const ClassInfo*); #endif #if CPU(X86) && ENABLE(JIT) @@ -369,11 +376,11 @@ namespace JSC { JSGlobalData(GlobalDataType, ThreadStackType, HeapSize); static JSGlobalData*& sharedInstanceInternal(); void createNativeThunk(); -#if ENABLE(JIT) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) - bool m_canUseJIT; +#if ENABLE(ASSEMBLER) && (ENABLE(CLASSIC_INTERPRETER) || ENABLE(LLINT)) + bool m_canUseAssembler; #endif #if ENABLE(GC_VALIDATION) - bool m_isInitializingObject; + const ClassInfo* m_initializingObjectClass; #endif bool m_inDefineOwnProperty; @@ -391,12 +398,12 @@ namespace JSC { #if ENABLE(GC_VALIDATION) inline bool JSGlobalData::isInitializingObject() const { - return m_isInitializingObject; + return !!m_initializingObjectClass; } - inline void JSGlobalData::setInitializingObject(bool initializingObject) + inline void JSGlobalData::setInitializingObjectClass(const ClassInfo* initializingObjectClass) { - m_isInitializingObject = initializingObject; + m_initializingObjectClass = initializingObjectClass; } #endif diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp index 8d3975848..0f74a8061 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp @@ -133,8 +133,7 @@ void JSGlobalObject::init(JSObject* thisValue) structure()->disableSpecificFunctionTracking(); - m_globalData = Heap::heap(this)->globalData(); - m_globalScopeChain.set(*m_globalData, this, ScopeChainNode::create(0, this, m_globalData.get(), this, thisValue)); + m_globalScopeChain.set(globalData(), this, ScopeChainNode::create(0, this, &globalData(), this, thisValue)); JSGlobalObject::globalExec()->init(0, 0, m_globalScopeChain.get(), CallFrame::noCaller(), 0, 0); @@ -460,7 +459,7 @@ DynamicGlobalObjectScope::DynamicGlobalObjectScope(JSGlobalData& globalData, JSG if (!m_dynamicGlobalObjectSlot) { #if ENABLE(ASSEMBLER) if (ExecutableAllocator::underMemoryPressure()) - globalData.recompileAllJSFunctions(); + globalData.heap.discardAllCompiledCode(); #endif m_dynamicGlobalObjectSlot = dynamicGlobalObject; diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h index cbc436e1a..d9fc81dc4 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObject.h +++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h @@ -86,8 +86,6 @@ namespace JSC { protected: - RefPtr<JSGlobalData> m_globalData; - size_t m_registerArraySize; Register m_globalCallFrame[RegisterFile::CallFrameHeaderSize]; @@ -302,7 +300,7 @@ namespace JSC { void resetPrototype(JSGlobalData&, JSValue prototype); - JSGlobalData& globalData() const { return *m_globalData.get(); } + JSGlobalData& globalData() const { return *Heap::heap(this)->globalData(); } static Structure* createStructure(JSGlobalData& globalData, JSValue prototype) { @@ -358,7 +356,7 @@ namespace JSC { inline JSGlobalObject* asGlobalObject(JSValue value) { ASSERT(asObject(value)->isGlobalObject()); - return static_cast<JSGlobalObject*>(asObject(value)); + return jsCast<JSGlobalObject*>(asObject(value)); } inline void JSGlobalObject::setRegisters(WriteBarrier<Unknown>* registers, PassOwnArrayPtr<WriteBarrier<Unknown> > registerArray, size_t count) diff --git a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp index 75789e602..e8017b904 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp @@ -1,7 +1,7 @@ /* * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) * Copyright (C) 2001 Peter Kelly (pmk@post.com) - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved. * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) * Copyright (C) 2007 Maks Orlovich * @@ -295,17 +295,20 @@ static double parseInt(const UString& s, const CharType* data, int radix) number += digit; ++p; } - if (number >= mantissaOverflowLowerBound) { - if (radix == 10) - number = WTF::strtod<WTF::AllowTrailingJunk>(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), 0); - else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32) - number = parseIntOverflow(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), p - firstDigitPosition, radix); - } // 12. If Z is empty, return NaN. if (!sawDigit) return std::numeric_limits<double>::quiet_NaN(); + // Alternate code path for certain large numbers. + if (number >= mantissaOverflowLowerBound) { + if (radix == 10) { + size_t parsedLength; + number = parseDouble(s.characters() + firstDigitPosition, p - firstDigitPosition, parsedLength); + } else if (radix == 2 || radix == 4 || radix == 8 || radix == 16 || radix == 32) + number = parseIntOverflow(s.substringSharingImpl(firstDigitPosition, p - firstDigitPosition).utf8().data(), p - firstDigitPosition, radix); + } + // 15. Return sign x number. return sign * number; } @@ -361,20 +364,10 @@ static double jsStrDecimalLiteral(const CharType*& data, const CharType* end) { ASSERT(data < end); - // Copy the sting into a null-terminated byte buffer, and call strtod. - Vector<char, 32> byteBuffer; - for (const CharType* characters = data; characters < end; ++characters) { - CharType character = *characters; - byteBuffer.append(isASCII(character) ? static_cast<char>(character) : 0); - } - byteBuffer.append(0); - char* endOfNumber; - double number = WTF::strtod<WTF::AllowTrailingJunk>(byteBuffer.data(), &endOfNumber); - - // Check if strtod found a number; if so return it. - ptrdiff_t consumed = endOfNumber - byteBuffer.data(); - if (consumed) { - data += consumed; + size_t parsedLength; + double number = parseDouble(data, end - data, parsedLength); + if (parsedLength) { + data += parsedLength; return number; } @@ -505,7 +498,7 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) { JSObject* thisObject = exec->hostThisValue().toThisObject(exec); JSObject* unwrappedObject = thisObject->unwrappedObject(); - if (!unwrappedObject->isGlobalObject() || static_cast<JSGlobalObject*>(unwrappedObject)->evalFunction() != exec->callee()) + if (!unwrappedObject->isGlobalObject() || jsCast<JSGlobalObject*>(unwrappedObject)->evalFunction() != exec->callee()) return throwVMError(exec, createEvalError(exec, "The \"this\" value passed to eval must be the global object from which eval originated")); JSValue x = exec->argument(0); @@ -525,11 +518,11 @@ EncodedJSValue JSC_HOST_CALL globalFuncEval(ExecState* exec) } EvalExecutable* eval = EvalExecutable::create(exec, makeSource(s), false); - JSObject* error = eval->compile(exec, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()); + JSObject* error = eval->compile(exec, jsCast<JSGlobalObject*>(unwrappedObject)->globalScopeChain()); if (error) return throwVMError(exec, error); - return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, static_cast<JSGlobalObject*>(unwrappedObject)->globalScopeChain())); + return JSValue::encode(exec->interpreter()->execute(eval, exec, thisObject, jsCast<JSGlobalObject*>(unwrappedObject)->globalScopeChain())); } EncodedJSValue JSC_HOST_CALL globalFuncParseInt(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/JSGlobalThis.cpp b/Source/JavaScriptCore/runtime/JSGlobalThis.cpp index 8b2a7a1ef..abd31ac14 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalThis.cpp +++ b/Source/JavaScriptCore/runtime/JSGlobalThis.cpp @@ -48,9 +48,12 @@ void JSGlobalThis::visitChildren(JSCell* cell, SlotVisitor& visitor) visitor.append(&thisObject->m_unwrappedObject); } -JSGlobalObject* JSGlobalThis::unwrappedObject() +void JSGlobalThis::setUnwrappedObject(JSGlobalData& globalData, JSGlobalObject* globalObject) { - return m_unwrappedObject.get(); + ASSERT_ARG(globalObject, globalObject); + m_unwrappedObject.set(globalData, this, globalObject); + setPrototype(globalData, globalObject->prototype()); + resetInheritorID(); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSGlobalThis.h b/Source/JavaScriptCore/runtime/JSGlobalThis.h index fa5c2eb34..0ca99414a 100644 --- a/Source/JavaScriptCore/runtime/JSGlobalThis.h +++ b/Source/JavaScriptCore/runtime/JSGlobalThis.h @@ -48,7 +48,7 @@ public: static JS_EXPORTDATA const JSC::ClassInfo s_info; - JSGlobalObject* unwrappedObject(); + JSGlobalObject* unwrappedObject() const { return m_unwrappedObject.get(); } protected: JSGlobalThis(JSGlobalData& globalData, Structure* structure) @@ -65,6 +65,9 @@ protected: JS_EXPORT_PRIVATE static void visitChildren(JSCell*, SlotVisitor&); + JS_EXPORT_PRIVATE void setUnwrappedObject(JSGlobalData&, JSGlobalObject*); + +private: WriteBarrier<JSGlobalObject> m_unwrappedObject; }; diff --git a/Source/JavaScriptCore/runtime/JSObject.cpp b/Source/JavaScriptCore/runtime/JSObject.cpp index 1bdb90ff6..500f3891a 100644 --- a/Source/JavaScriptCore/runtime/JSObject.cpp +++ b/Source/JavaScriptCore/runtime/JSObject.cpp @@ -203,7 +203,7 @@ bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prot { JSValue checkFor = this; if (this->isGlobalObject()) - checkFor = static_cast<JSGlobalObject*>(this)->globalExec()->thisValue(); + checkFor = jsCast<JSGlobalObject*>(this)->globalExec()->thisValue(); JSValue nextPrototype = prototype; while (nextPrototype && nextPrototype.isObject()) { @@ -217,7 +217,7 @@ bool JSObject::setPrototypeWithCycleCheck(JSGlobalData& globalData, JSValue prot bool JSObject::allowsAccessFrom(ExecState* exec) { - JSGlobalObject* globalObject = isGlobalThis() ? static_cast<JSGlobalThis*>(this)->unwrappedObject() : this->globalObject(); + JSGlobalObject* globalObject = isGlobalThis() ? jsCast<JSGlobalThis*>(this)->unwrappedObject() : this->globalObject(); return globalObject->globalObjectMethodTable()->allowsAccessFrom(globalObject, exec); } @@ -445,13 +445,13 @@ JSString* JSObject::toString(ExecState* exec) const JSObject* JSObject::toThisObject(JSCell* cell, ExecState*) { - return static_cast<JSObject*>(cell); + return jsCast<JSObject*>(cell); } JSObject* JSObject::unwrappedObject() { if (isGlobalThis()) - return static_cast<JSGlobalThis*>(this)->unwrappedObject(); + return jsCast<JSGlobalThis*>(this)->unwrappedObject(); return this; } @@ -541,12 +541,18 @@ NEVER_INLINE void JSObject::fillGetterPropertySlot(PropertySlot& slot, WriteBarr Structure* JSObject::createInheritorID(JSGlobalData& globalData) { - m_inheritorID.set(globalData, this, createEmptyObjectStructure(globalData, structure()->globalObject(), this)); + JSGlobalObject* globalObject; + if (isGlobalThis()) + globalObject = static_cast<JSGlobalThis*>(this)->unwrappedObject(); + else + globalObject = structure()->globalObject(); + ASSERT(globalObject); + m_inheritorID.set(globalData, this, createEmptyObjectStructure(globalData, globalObject, this)); ASSERT(m_inheritorID->isEmpty()); return m_inheritorID.get(); } -void JSObject::allocatePropertyStorage(JSGlobalData& globalData, size_t oldSize, size_t newSize) +PropertyStorage JSObject::growPropertyStorage(JSGlobalData& globalData, size_t oldSize, size_t newSize) { ASSERT(newSize > oldSize); @@ -574,7 +580,7 @@ void JSObject::allocatePropertyStorage(JSGlobalData& globalData, size_t oldSize, } ASSERT(newPropertyStorage); - m_propertyStorage.set(globalData, this, newPropertyStorage); + return newPropertyStorage; } bool JSObject::getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) diff --git a/Source/JavaScriptCore/runtime/JSObject.h b/Source/JavaScriptCore/runtime/JSObject.h index 3f3d281cf..d95860d62 100644 --- a/Source/JavaScriptCore/runtime/JSObject.h +++ b/Source/JavaScriptCore/runtime/JSObject.h @@ -212,8 +212,9 @@ namespace JSC { bool staticFunctionsReified() { return structure()->staticFunctionsReified(); } void reifyStaticFunctionsForDelete(ExecState* exec); - JS_EXPORT_PRIVATE void allocatePropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize); + JS_EXPORT_PRIVATE PropertyStorage growPropertyStorage(JSGlobalData&, size_t oldSize, size_t newSize); bool isUsingInlineStorage() const { return static_cast<const void*>(m_propertyStorage.get()) == static_cast<const void*>(this + 1); } + void setPropertyStorage(JSGlobalData&, PropertyStorage, Structure*); void* addressOfPropertyStorage() { @@ -263,6 +264,11 @@ namespace JSC { // To instantiate objects you likely want JSFinalObject, below. // To create derived types you likely want JSNonFinalObject, below. JSObject(JSGlobalData&, Structure*, PropertyStorage inlineStorage); + + void resetInheritorID() + { + m_inheritorID.clear(); + } private: friend class LLIntOffsetsExtractor; @@ -447,6 +453,14 @@ inline bool JSObject::isGlobalThis() const return structure()->typeInfo().type() == GlobalThisType; } +inline void JSObject::setPropertyStorage(JSGlobalData& globalData, PropertyStorage storage, Structure* structure) +{ + ASSERT(storage); + ASSERT(structure); + setStructure(globalData, structure); + m_propertyStorage.set(globalData, this, storage); +} + inline JSObject* constructEmptyObject(ExecState* exec, Structure* structure) { return JSFinalObject::create(exec, structure); @@ -474,7 +488,7 @@ inline Structure* createEmptyObjectStructure(JSGlobalData& globalData, JSGlobalO inline JSObject* asObject(JSCell* cell) { ASSERT(cell->isObject()); - return static_cast<JSObject*>(cell); + return jsCast<JSObject*>(cell); } inline JSObject* asObject(JSValue value) @@ -658,10 +672,11 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi if ((mode == PutModePut) && !isExtensible()) return false; - size_t currentCapacity = structure()->propertyStorageCapacity(); + PropertyStorage newStorage = propertyStorage(); + if (structure()->shouldGrowPropertyStorage()) + newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize()); offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, specificFunction); - if (currentCapacity != structure()->propertyStorageCapacity()) - allocatePropertyStorage(globalData, currentCapacity, structure()->propertyStorageCapacity()); + setPropertyStorage(globalData, newStorage, structure()); ASSERT(offset < structure()->propertyStorageCapacity()); putDirectOffset(globalData, offset, value); @@ -673,12 +688,13 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi size_t offset; size_t currentCapacity = structure()->propertyStorageCapacity(); - if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) { + if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) { + PropertyStorage newStorage = propertyStorage(); if (currentCapacity != structure->propertyStorageCapacity()) - allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity()); + newStorage = growPropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity()); ASSERT(offset < structure->propertyStorageCapacity()); - setStructure(globalData, structure); + setPropertyStorage(globalData, newStorage, structure); putDirectOffset(globalData, offset, value); // This is a new property; transitions with specific values are not currently cachable, // so leave the slot in an uncachable state. @@ -722,13 +738,14 @@ inline bool JSObject::putDirectInternal(JSGlobalData& globalData, const Identifi if ((mode == PutModePut) && !isExtensible()) return false; - Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset); + PropertyStorage newStorage = propertyStorage(); + if (structure()->shouldGrowPropertyStorage()) + newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize()); - if (currentCapacity != structure->propertyStorageCapacity()) - allocatePropertyStorage(globalData, currentCapacity, structure->propertyStorageCapacity()); + Structure* structure = Structure::addPropertyTransition(globalData, this->structure(), propertyName, attributes, specificFunction, offset); ASSERT(offset < structure->propertyStorageCapacity()); - setStructure(globalData, structure); + setPropertyStorage(globalData, newStorage, structure); putDirectOffset(globalData, offset, value); // This is a new property; transitions with specific values are not currently cachable, // so leave the slot in an uncachable state. @@ -762,18 +779,20 @@ inline void JSObject::putDirect(JSGlobalData& globalData, const Identifier& prop inline void JSObject::putDirectWithoutTransition(JSGlobalData& globalData, const Identifier& propertyName, JSValue value, unsigned attributes) { ASSERT(!value.isGetterSetter() && !(attributes & Accessor)); - size_t currentCapacity = structure()->propertyStorageCapacity(); + PropertyStorage newStorage = propertyStorage(); + if (structure()->shouldGrowPropertyStorage()) + newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), structure()->suggestedNewPropertyStorageSize()); size_t offset = structure()->addPropertyWithoutTransition(globalData, propertyName, attributes, getJSFunction(value)); - if (currentCapacity != structure()->propertyStorageCapacity()) - allocatePropertyStorage(globalData, currentCapacity, structure()->propertyStorageCapacity()); + setPropertyStorage(globalData, newStorage, structure()); putDirectOffset(globalData, offset, value); } inline void JSObject::transitionTo(JSGlobalData& globalData, Structure* newStructure) { + PropertyStorage newStorage = propertyStorage(); if (structure()->propertyStorageCapacity() != newStructure->propertyStorageCapacity()) - allocatePropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity()); - setStructure(globalData, newStructure); + newStorage = growPropertyStorage(globalData, structure()->propertyStorageCapacity(), newStructure->propertyStorageCapacity()); + setPropertyStorage(globalData, newStorage, newStructure); } inline JSValue JSObject::toPrimitive(ExecState* exec, PreferredPrimitiveType preferredType) const diff --git a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h index 7530d7532..5b65e59f2 100644 --- a/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h +++ b/Source/JavaScriptCore/runtime/JSPropertyNameIterator.h @@ -121,7 +121,7 @@ namespace JSC { ALWAYS_INLINE JSPropertyNameIterator* Register::propertyNameIterator() const { - return static_cast<JSPropertyNameIterator*>(jsValue().asCell()); + return jsCast<JSPropertyNameIterator*>(jsValue().asCell()); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp index e84ce3620..904cc4d3e 100644 --- a/Source/JavaScriptCore/runtime/JSString.cpp +++ b/Source/JavaScriptCore/runtime/JSString.cpp @@ -36,9 +36,9 @@ static const unsigned substringFromRopeCutoff = 4; const ClassInfo JSString::s_info = { "string", 0, 0, 0, CREATE_METHOD_TABLE(JSString) }; -void JSString::RopeBuilder::expand() +void JSRopeString::RopeBuilder::expand() { - ASSERT(m_index == JSString::s_maxInternalRopeLength); + ASSERT(m_index == JSRopeString::s_maxInternalRopeLength); JSString* jsString = m_jsString; m_jsString = jsStringBuilder(&m_globalData); m_index = 0; @@ -55,11 +55,18 @@ void JSString::visitChildren(JSCell* cell, SlotVisitor& visitor) { JSString* thisObject = jsCast<JSString*>(cell); Base::visitChildren(thisObject, visitor); - for (size_t i = 0; i < s_maxInternalRopeLength && thisObject->m_fibers[i]; ++i) - visitor.append(&thisObject->m_fibers[i]); + + if (thisObject->isRope()) + static_cast<JSRopeString*>(thisObject)->visitFibers(visitor); +} + +void JSRopeString::visitFibers(SlotVisitor& visitor) +{ + for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) + visitor.append(&m_fibers[i]); } -void JSString::resolveRope(ExecState* exec) const +void JSRopeString::resolveRope(ExecState* exec) const { ASSERT(isRope()); @@ -128,7 +135,7 @@ void JSString::resolveRope(ExecState* exec) const // Vector before performing any concatenation, but by working backwards we likely // only fill the queue with the number of substrings at any given level in a // rope-of-ropes.) -void JSString::resolveRopeSlowCase8(LChar* buffer) const +void JSRopeString::resolveRopeSlowCase8(LChar* buffer) const { LChar* position = buffer + m_length; // We will be working backwards over the rope. Vector<JSString*, 32> workQueue; // Putting strings into a Vector is only OK because there are no GC points in this method. @@ -144,8 +151,9 @@ void JSString::resolveRopeSlowCase8(LChar* buffer) const workQueue.removeLast(); if (currentFiber->isRope()) { - for (size_t i = 0; i < s_maxInternalRopeLength && currentFiber->m_fibers[i]; ++i) - workQueue.append(currentFiber->m_fibers[i].get()); + JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber); + for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->m_fibers[i]; ++i) + workQueue.append(currentFiberAsRope->m_fibers[i].get()); continue; } @@ -159,7 +167,7 @@ void JSString::resolveRopeSlowCase8(LChar* buffer) const ASSERT(!isRope()); } -void JSString::resolveRopeSlowCase(UChar* buffer) const +void JSRopeString::resolveRopeSlowCase(UChar* buffer) const { UChar* position = buffer + m_length; // We will be working backwards over the rope. Vector<JSString*, 32> workQueue; // These strings are kept alive by the parent rope, so using a Vector is OK. @@ -172,8 +180,9 @@ void JSString::resolveRopeSlowCase(UChar* buffer) const workQueue.removeLast(); if (currentFiber->isRope()) { - for (size_t i = 0; i < s_maxInternalRopeLength && currentFiber->m_fibers[i]; ++i) - workQueue.append(currentFiber->m_fibers[i].get()); + JSRopeString* currentFiberAsRope = static_cast<JSRopeString*>(currentFiber); + for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->m_fibers[i]; ++i) + workQueue.append(currentFiberAsRope->m_fibers[i].get()); continue; } @@ -187,7 +196,7 @@ void JSString::resolveRopeSlowCase(UChar* buffer) const ASSERT(!isRope()); } -void JSString::outOfMemory(ExecState* exec) const +void JSRopeString::outOfMemory(ExecState* exec) const { for (size_t i = 0; i < s_maxInternalRopeLength && m_fibers[i]; ++i) m_fibers[i].clear(); @@ -197,7 +206,7 @@ void JSString::outOfMemory(ExecState* exec) const throwOutOfMemoryError(exec); } -JSString* JSString::getIndexSlowCase(ExecState* exec, unsigned i) +JSString* JSRopeString::getIndexSlowCase(ExecState* exec, unsigned i) { ASSERT(isRope()); resolveRope(exec); diff --git a/Source/JavaScriptCore/runtime/JSString.h b/Source/JavaScriptCore/runtime/JSString.h index 32a32788a..10ec799e5 100644 --- a/Source/JavaScriptCore/runtime/JSString.h +++ b/Source/JavaScriptCore/runtime/JSString.h @@ -32,6 +32,7 @@ namespace JSC { class JSString; + class JSRopeString; class LLIntOffsetsExtractor; JSString* jsEmptyString(JSGlobalData*); @@ -58,55 +59,20 @@ namespace JSC { JSString* jsOwnedString(JSGlobalData*, const UString&); JSString* jsOwnedString(ExecState*, const UString&); - JSString* jsStringBuilder(JSGlobalData*); + JSRopeString* jsStringBuilder(JSGlobalData*); class JSString : public JSCell { public: friend class JIT; friend class JSGlobalData; friend class SpecializedThunkJIT; + friend class JSRopeString; friend struct ThunkHelpers; - friend JSString* jsStringBuilder(JSGlobalData*); typedef JSCell Base; static void destroy(JSCell*); - class RopeBuilder { - public: - RopeBuilder(JSGlobalData& globalData) - : m_globalData(globalData) - , m_jsString(jsStringBuilder(&globalData)) - , m_index(0) - { - } - - void append(JSString* jsString) - { - if (m_index == JSString::s_maxInternalRopeLength) - expand(); - m_jsString->m_fibers[m_index++].set(m_globalData, m_jsString, jsString); - m_jsString->m_length += jsString->m_length; - m_jsString->m_is8Bit = m_jsString->m_is8Bit && jsString->m_is8Bit; - } - - JSString* release() - { - JSString* tmp = m_jsString; - m_jsString = 0; - return tmp; - } - - unsigned length() { return m_jsString->m_length; } - - private: - void expand(); - - JSGlobalData& m_globalData; - JSString* m_jsString; - size_t m_index; - }; - private: JSString(JSGlobalData& globalData, PassRefPtr<StringImpl> value) : JSCell(globalData, globalData.stringStructure.get()) @@ -119,13 +85,6 @@ namespace JSC { { } - void finishCreation(JSGlobalData& globalData) - { - Base::finishCreation(globalData); - m_length = 0; - m_is8Bit = true; - } - void finishCreation(JSGlobalData& globalData, size_t length) { ASSERT(!m_value.isNull()); @@ -143,32 +102,14 @@ namespace JSC { Heap::heap(this)->reportExtraMemoryCost(cost); } - void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2) - { - Base::finishCreation(globalData); - m_length = s1->length() + s2->length(); - m_is8Bit = (s1->is8Bit() && s2->is8Bit()); - m_fibers[0].set(globalData, this, s1); - m_fibers[1].set(globalData, this, s2); - } - - void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) + protected: + void finishCreation(JSGlobalData& globalData) { Base::finishCreation(globalData); - m_length = s1->length() + s2->length() + s3->length(); - m_is8Bit = (s1->is8Bit() && s2->is8Bit() && s3->is8Bit()); - m_fibers[0].set(globalData, this, s1); - m_fibers[1].set(globalData, this, s2); - m_fibers[2].set(globalData, this, s3); - } - - static JSString* createNull(JSGlobalData& globalData) - { - JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData); - newString->finishCreation(globalData); - return newString; + m_length = 0; + m_is8Bit = true; } - + public: static JSString* create(JSGlobalData& globalData, PassRefPtr<StringImpl> value) { @@ -179,18 +120,6 @@ namespace JSC { newString->finishCreation(globalData, length, cost); return newString; } - static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2) - { - JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData); - newString->finishCreation(globalData, s1, s2); - return newString; - } - static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) - { - JSString* newString = new (NotNull, allocateCell<JSString>(globalData.heap)) JSString(globalData); - newString->finishCreation(globalData, s1, s2, s3); - return newString; - } static JSString* createHasOtherOwner(JSGlobalData& globalData, PassRefPtr<StringImpl> value) { ASSERT(value); @@ -200,18 +129,8 @@ namespace JSC { return newString; } - const UString& value(ExecState* exec) const - { - if (isRope()) - resolveRope(exec); - return m_value; - } - const UString& tryGetValue() const - { - if (isRope()) - resolveRope(0); - return m_value; - } + const UString& value(ExecState*) const; + const UString& tryGetValue() const; unsigned length() { return m_length; } JSValue toPrimitive(ExecState*, PreferredPrimitiveType) const; @@ -226,7 +145,6 @@ namespace JSC { bool canGetIndex(unsigned i) { return i < m_length; } JSString* getIndex(ExecState*, unsigned); - JSString* getIndexSlowCase(ExecState*, unsigned); static Structure* createStructure(JSGlobalData& globalData, JSGlobalObject* globalObject, JSValue proto) { @@ -240,44 +158,145 @@ namespace JSC { static void visitChildren(JSCell*, SlotVisitor&); + protected: + bool isRope() const { return m_value.isNull(); } + bool is8Bit() const { return m_is8Bit; } + + // A string is represented either by a UString or a rope of fibers. + bool m_is8Bit : 1; + unsigned m_length; + mutable UString m_value; + private: friend class LLIntOffsetsExtractor; - JS_EXPORT_PRIVATE void resolveRope(ExecState*) const; - void resolveRopeSlowCase8(LChar*) const; - void resolveRopeSlowCase(UChar*) const; - void outOfMemory(ExecState*) const; - static JSObject* toThisObject(JSCell*, ExecState*); // Actually getPropertySlot, not getOwnPropertySlot (see JSCell). static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); static bool getOwnPropertySlotByIndex(JSCell*, ExecState*, unsigned propertyName, PropertySlot&); - static const unsigned s_maxInternalRopeLength = 3; - - // A string is represented either by a UString or a rope of fibers. - bool m_is8Bit : 1; - unsigned m_length; - mutable UString m_value; - mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers; - - bool isRope() const { return m_value.isNull(); } - bool is8Bit() const { return m_is8Bit; } UString& string() { ASSERT(!isRope()); return m_value; } friend JSValue jsString(ExecState*, JSString*, JSString*); - friend JSValue jsString(ExecState*, Register*, unsigned count); - friend JSValue jsStringFromArguments(ExecState*, JSValue thisValue); friend JSString* jsSubstring(ExecState*, JSString*, unsigned offset, unsigned length); }; + class JSRopeString : public JSString { + friend class JSString; + + friend JSRopeString* jsStringBuilder(JSGlobalData*); + + class RopeBuilder { + public: + RopeBuilder(JSGlobalData& globalData) + : m_globalData(globalData) + , m_jsString(jsStringBuilder(&globalData)) + , m_index(0) + { + } + + void append(JSString* jsString) + { + if (m_index == JSRopeString::s_maxInternalRopeLength) + expand(); + m_jsString->m_fibers[m_index++].set(m_globalData, m_jsString, jsString); + m_jsString->m_length += jsString->m_length; + m_jsString->m_is8Bit = m_jsString->m_is8Bit && jsString->m_is8Bit; + } + + JSRopeString* release() + { + JSRopeString* tmp = m_jsString; + m_jsString = 0; + return tmp; + } + + unsigned length() { return m_jsString->m_length; } + + private: + void expand(); + + JSGlobalData& m_globalData; + JSRopeString* m_jsString; + size_t m_index; + }; + + private: + JSRopeString(JSGlobalData& globalData) + : JSString(globalData) + { + } + + void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2) + { + Base::finishCreation(globalData); + m_length = s1->length() + s2->length(); + m_is8Bit = (s1->is8Bit() && s2->is8Bit()); + m_fibers[0].set(globalData, this, s1); + m_fibers[1].set(globalData, this, s2); + } + + void finishCreation(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) + { + Base::finishCreation(globalData); + m_length = s1->length() + s2->length() + s3->length(); + m_is8Bit = (s1->is8Bit() && s2->is8Bit() && s3->is8Bit()); + m_fibers[0].set(globalData, this, s1); + m_fibers[1].set(globalData, this, s2); + m_fibers[2].set(globalData, this, s3); + } + + void finishCreation(JSGlobalData& globalData) + { + JSString::finishCreation(globalData); + } + + static JSRopeString* createNull(JSGlobalData& globalData) + { + JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData); + newString->finishCreation(globalData); + return newString; + } + + public: + static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2) + { + JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData); + newString->finishCreation(globalData, s1, s2); + return newString; + } + static JSString* create(JSGlobalData& globalData, JSString* s1, JSString* s2, JSString* s3) + { + JSRopeString* newString = new (NotNull, allocateCell<JSRopeString>(globalData.heap)) JSRopeString(globalData); + newString->finishCreation(globalData, s1, s2, s3); + return newString; + } + + void visitFibers(SlotVisitor&); + + private: + friend JSValue jsString(ExecState*, Register*, unsigned); + friend JSValue jsStringFromArguments(ExecState*, JSValue); + + JS_EXPORT_PRIVATE void resolveRope(ExecState*) const; + void resolveRopeSlowCase8(LChar*) const; + void resolveRopeSlowCase(UChar*) const; + void outOfMemory(ExecState*) const; + + JSString* getIndexSlowCase(ExecState*, unsigned); + + static const unsigned s_maxInternalRopeLength = 3; + + mutable FixedArray<WriteBarrier<JSString>, s_maxInternalRopeLength> m_fibers; + }; + JSString* asString(JSValue); inline JSString* asString(JSValue value) { ASSERT(value.asCell()->isString()); - return static_cast<JSString*>(value.asCell()); + return jsCast<JSString*>(value.asCell()); } inline JSString* jsEmptyString(JSGlobalData* globalData) @@ -285,14 +304,14 @@ namespace JSC { return globalData->smallStrings.emptyString(globalData); } - inline JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c) + ALWAYS_INLINE JSString* jsSingleCharacterString(JSGlobalData* globalData, UChar c) { if (c <= maxSingleCharacterString) return globalData->smallStrings.singleCharacterString(globalData, c); return JSString::create(*globalData, UString(&c, 1).impl()); } - inline JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) + ALWAYS_INLINE JSString* jsSingleCharacterSubstring(ExecState* exec, const UString& s, unsigned offset) { JSGlobalData* globalData = &exec->globalData(); ASSERT(offset < static_cast<unsigned>(s.length())); @@ -316,11 +335,25 @@ namespace JSC { return JSString::create(*globalData, s.impl()); } + inline const UString& JSString::value(ExecState* exec) const + { + if (isRope()) + static_cast<const JSRopeString*>(this)->resolveRope(exec); + return m_value; + } + + inline const UString& JSString::tryGetValue() const + { + if (isRope()) + static_cast<const JSRopeString*>(this)->resolveRope(0); + return m_value; + } + inline JSString* JSString::getIndex(ExecState* exec, unsigned i) { ASSERT(canGetIndex(i)); if (isRope()) - return getIndexSlowCase(exec, i); + return static_cast<JSRopeString*>(this)->getIndexSlowCase(exec, i); ASSERT(i < m_value.length()); return jsSingleCharacterSubstring(exec, m_value, i); } @@ -392,9 +425,9 @@ namespace JSC { return JSString::createHasOtherOwner(*globalData, s.impl()); } - inline JSString* jsStringBuilder(JSGlobalData* globalData) + inline JSRopeString* jsStringBuilder(JSGlobalData* globalData) { - return JSString::createNull(*globalData); + return JSRopeString::createNull(*globalData); } inline JSString* jsEmptyString(ExecState* exec) { return jsEmptyString(&exec->globalData()); } @@ -458,10 +491,43 @@ namespace JSC { inline JSString* JSValue::toString(ExecState* exec) const { if (isString()) - return static_cast<JSString*>(asCell()); + return jsCast<JSString*>(asCell()); return toStringSlowCase(exec); } + inline UString JSValue::toUString(ExecState* exec) const + { + if (isString()) + return static_cast<JSString*>(asCell())->value(exec); + return toUStringSlowCase(exec); + } + + ALWAYS_INLINE UString inlineJSValueNotStringtoUString(const JSValue& value, ExecState* exec) + { + JSGlobalData& globalData = exec->globalData(); + if (value.isInt32()) + return globalData.numericStrings.add(value.asInt32()); + if (value.isDouble()) + return globalData.numericStrings.add(value.asDouble()); + if (value.isTrue()) + return globalData.propertyNames->trueKeyword.ustring(); + if (value.isFalse()) + return globalData.propertyNames->falseKeyword.ustring(); + if (value.isNull()) + return globalData.propertyNames->nullKeyword.ustring(); + if (value.isUndefined()) + return globalData.propertyNames->undefinedKeyword.ustring(); + return value.toString(exec)->value(exec); + } + + ALWAYS_INLINE UString JSValue::toUStringInline(ExecState* exec) const + { + if (isString()) + return static_cast<JSString*>(asCell())->value(exec); + + return inlineJSValueNotStringtoUString(*this, exec); + } + } // namespace JSC #endif // JSString_h diff --git a/Source/JavaScriptCore/runtime/JSStringJoiner.cpp b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp new file mode 100644 index 000000000..ea260243b --- /dev/null +++ b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2012 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 "JSStringJoiner.h" + +#include "ExceptionHelpers.h" +#include "JSString.h" +#include "ScopeChain.h" +#include <wtf/text/StringImpl.h> + + +namespace JSC { + +// The destination is 16bits, at least one string is 16 bits. +static inline void appendStringToData(UChar*& data, const UString& string) +{ + if (string.isNull()) + return; + + unsigned length = string.length(); + const StringImpl* stringImpl = string.impl(); + + if (stringImpl->is8Bit()) { + for (unsigned i = 0; i < length; ++i) { + *data = stringImpl->characters8()[i]; + ++data; + } + } else { + for (unsigned i = 0; i < length; ++i) { + *data = stringImpl->characters16()[i]; + ++data; + } + } +} + +// If the destination is 8bits, we know every string has to be 8bit. +static inline void appendStringToData(LChar*& data, const UString& string) +{ + if (string.isNull()) + return; + ASSERT(string.is8Bit()); + + unsigned length = string.length(); + const StringImpl* stringImpl = string.impl(); + + for (unsigned i = 0; i < length; ++i) { + *data = stringImpl->characters8()[i]; + ++data; + } +} + +template<typename CharacterType> +static inline PassRefPtr<StringImpl> joinStrings(const Vector<UString>& strings, const UString& separator, unsigned outputLength) +{ + ASSERT(outputLength); + + CharacterType* data; + RefPtr<StringImpl> outputStringImpl = StringImpl::tryCreateUninitialized(outputLength, data); + if (!outputStringImpl) + return PassRefPtr<StringImpl>(); + + const UString firstString = strings.first(); + appendStringToData(data, firstString); + + for (size_t i = 1; i < strings.size(); ++i) { + appendStringToData(data, separator); + appendStringToData(data, strings[i]); + } + + ASSERT(data == (outputStringImpl->getCharacters<CharacterType>() + outputStringImpl->length())); + return outputStringImpl.release(); +} + +JSValue JSStringJoiner::build(ExecState* exec) +{ + if (!m_isValid) + return throwOutOfMemoryError(exec); + + if (!m_strings.size()) + return jsEmptyString(exec); + + size_t separatorLength = m_separator.length(); + // FIXME: add special cases of joinStrings() for (separatorLength == 0) and (separatorLength == 1). + ASSERT(m_strings.size() > 0); + size_t totalSeparactorsLength = separatorLength * (m_strings.size() - 1); + size_t outputStringSize = totalSeparactorsLength + m_cumulatedStringsLength; + + if (!outputStringSize) + return jsEmptyString(exec); + + RefPtr<StringImpl> outputStringImpl; + if (m_is8Bits) + outputStringImpl = joinStrings<LChar>(m_strings, m_separator, outputStringSize); + else + outputStringImpl = joinStrings<UChar>(m_strings, m_separator, outputStringSize); + + if (!outputStringImpl) + return throwOutOfMemoryError(exec); + + return JSString::create(exec->globalData(), outputStringImpl.release()); +} + +} diff --git a/Source/JavaScriptCore/wtf/url/api/URLString.h b/Source/JavaScriptCore/runtime/JSStringJoiner.h index 9ae30d7a9..49f846c1f 100644 --- a/Source/JavaScriptCore/wtf/url/api/URLString.h +++ b/Source/JavaScriptCore/runtime/JSStringJoiner.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Google, Inc. All Rights Reserved. + * Copyright (C) 2012 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,37 +23,56 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef URLString_h -#define URLString_h +#ifndef JSStringJoiner_h +#define JSStringJoiner_h -#if USE(WTFURL) +#include "JSValue.h" +#include "UString.h" +#include <wtf/Vector.h> -#include <wtf/text/WTFString.h> +namespace JSC { -namespace WTF { +class ExecState; -// URLString represents a string that's a canonicalized URL. -class URLString { + +class JSStringJoiner { public: - URLString() { } + JSStringJoiner(const UString& separator, size_t stringCount); - const String& string() const { return m_string;} + void append(const UString&); + JSValue build(ExecState*); private: - friend class ParsedURL; - - // URLString can only be constructed by a ParsedURL. - explicit URLString(const String& string) - : m_string(string) - { - } + UString m_separator; + Vector<UString> m_strings; - String m_string; + unsigned m_cumulatedStringsLength; + bool m_isValid; + bool m_is8Bits; }; +inline JSStringJoiner::JSStringJoiner(const UString& separator, size_t stringCount) + : m_separator(separator) + , m_cumulatedStringsLength(0) + , m_isValid(true) + , m_is8Bits(m_separator.is8Bit()) +{ + ASSERT(!m_separator.isNull()); + m_isValid = m_strings.tryReserveCapacity(stringCount); } -#endif // USE(WTFURL) +inline void JSStringJoiner::append(const UString& str) +{ + if (!m_isValid) + return; -#endif + m_strings.uncheckedAppend(str); + if (!str.isNull()) { + m_cumulatedStringsLength += str.length(); + m_is8Bits = m_is8Bits && str.is8Bit(); + } +} + +} +#endif diff --git a/Source/JavaScriptCore/runtime/JSValue.cpp b/Source/JavaScriptCore/runtime/JSValue.cpp index 36697c60c..088f214b9 100644 --- a/Source/JavaScriptCore/runtime/JSValue.cpp +++ b/Source/JavaScriptCore/runtime/JSValue.cpp @@ -260,19 +260,20 @@ bool JSValue::isValidCallee() JSString* JSValue::toStringSlowCase(ExecState* exec) const { + JSGlobalData& globalData = exec->globalData(); ASSERT(!isString()); if (isInt32()) - return jsString(&exec->globalData(), exec->globalData().numericStrings.add(asInt32())); + return jsString(&globalData, globalData.numericStrings.add(asInt32())); if (isDouble()) - return jsString(&exec->globalData(), exec->globalData().numericStrings.add(asDouble())); + return jsString(&globalData, globalData.numericStrings.add(asDouble())); if (isTrue()) - return jsNontrivialString(exec, exec->propertyNames().trueKeyword.ustring()); + return globalData.smallStrings.trueString(&globalData); if (isFalse()) - return jsNontrivialString(exec, exec->propertyNames().falseKeyword.ustring()); + return globalData.smallStrings.falseString(&globalData); if (isNull()) - return jsNontrivialString(exec, exec->propertyNames().nullKeyword.ustring()); + return globalData.smallStrings.nullString(&globalData); if (isUndefined()) - return jsNontrivialString(exec, exec->propertyNames().undefined.ustring()); + return globalData.smallStrings.undefinedString(&globalData); ASSERT(isCell()); JSValue value = asCell()->toPrimitive(exec, PreferString); @@ -282,4 +283,9 @@ JSString* JSValue::toStringSlowCase(ExecState* exec) const return value.toString(exec); } +UString JSValue::toUStringSlowCase(ExecState* exec) const +{ + return inlineJSValueNotStringtoUString(*this, exec); +} + } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/JSValue.h b/Source/JavaScriptCore/runtime/JSValue.h index a6f359360..7facb9353 100644 --- a/Source/JavaScriptCore/runtime/JSValue.h +++ b/Source/JavaScriptCore/runtime/JSValue.h @@ -173,6 +173,7 @@ namespace JSC { // Querying the type. bool isEmpty() const; + bool isFunction() const; bool isUndefined() const; bool isNull() const; bool isUndefinedOrNull() const; @@ -202,6 +203,8 @@ namespace JSC { // been set in the ExecState already. double toNumber(ExecState*) const; JSString* toString(ExecState*) const; + UString toUString(ExecState*) const; + UString toUStringInline(ExecState*) const; JSObject* toObject(ExecState*) const; JSObject* toObject(ExecState*, JSGlobalObject*) const; @@ -250,6 +253,7 @@ namespace JSC { inline const JSValue asValue() const { return *this; } JS_EXPORT_PRIVATE double toNumberSlowCase(ExecState*) const; JS_EXPORT_PRIVATE JSString* toStringSlowCase(ExecState*) const; + JS_EXPORT_PRIVATE UString toUStringSlowCase(ExecState*) const; JS_EXPORT_PRIVATE JSObject* toObjectSlowCase(ExecState*, JSGlobalObject*) const; JS_EXPORT_PRIVATE JSObject* toThisObjectSlowCase(ExecState*) const; diff --git a/Source/JavaScriptCore/runtime/LiteralParser.cpp b/Source/JavaScriptCore/runtime/LiteralParser.cpp index 3bde3ff08..e1f85cefe 100644 --- a/Source/JavaScriptCore/runtime/LiteralParser.cpp +++ b/Source/JavaScriptCore/runtime/LiteralParser.cpp @@ -529,16 +529,8 @@ TokenType LiteralParser<CharType>::Lexer::lexNumber(LiteralParserToken<CharType> token.type = TokNumber; token.end = m_ptr; - Vector<char, 64> buffer(token.end - token.start + 1); - int i; - for (i = 0; i < token.end - token.start; i++) { - ASSERT(static_cast<char>(token.start[i]) == token.start[i]); - buffer[i] = static_cast<char>(token.start[i]); - } - buffer[i] = 0; - char* end; - token.numberToken = WTF::strtod<WTF::AllowTrailingJunk>(buffer.data(), &end); - ASSERT(buffer.data() + (token.end - token.start) == end); + size_t parsedLength; + token.numberToken = parseDouble(token.start, token.end - token.start, parsedLength); return TokNumber; } diff --git a/Source/JavaScriptCore/runtime/Lookup.cpp b/Source/JavaScriptCore/runtime/Lookup.cpp index 55c048fa3..b935eb260 100644 --- a/Source/JavaScriptCore/runtime/Lookup.cpp +++ b/Source/JavaScriptCore/runtime/Lookup.cpp @@ -76,15 +76,7 @@ bool setUpStaticFunctionSlot(ExecState* exec, const HashEntry* entry, JSObject* if (thisObj->staticFunctionsReified()) return false; - JSFunction* function; - JSGlobalObject* globalObject = thisObj->globalObject(); -#if ENABLE(JIT) - if (exec->globalData().canUseJIT() && entry->intrinsic() != NoIntrinsic) - function = JSFunction::create(exec, globalObject, entry->functionLength(), propertyName, exec->globalData().getHostFunction(entry->function(), entry->intrinsic())); - else -#endif - function = JSFunction::create(exec, globalObject, entry->functionLength(), propertyName, entry->function()); - + JSFunction* function = JSFunction::create(exec, thisObj->globalObject(), entry->functionLength(), propertyName, entry->function(), entry->intrinsic()); thisObj->putDirect(exec->globalData(), propertyName, function, entry->attributes()); location = thisObj->getDirectLocation(exec->globalData(), propertyName); } diff --git a/Source/JavaScriptCore/wtf/CheckedBoolean.h b/Source/JavaScriptCore/runtime/MatchResult.h index c65c70ef8..d87c8516b 100644 --- a/Source/JavaScriptCore/wtf/CheckedBoolean.h +++ b/Source/JavaScriptCore/runtime/MatchResult.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 Apple Inc. All rights reserved. + * Copyright (C) 2012 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,39 +23,49 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CheckedBoolean_h -#define CheckedBoolean_h +#ifndef MatchResult_h +#define MatchResult_h -#include <wtf/Assertions.h> +typedef uint64_t EncodedMatchResult; -class CheckedBoolean { -public: - CheckedBoolean(bool value) - : m_value(value) -#if !ASSERT_DISABLED - , m_checked(false) -#endif +struct MatchResult { + ALWAYS_INLINE MatchResult(size_t start, size_t end) + : start(start) + , end(end) { } - - ~CheckedBoolean() + + explicit ALWAYS_INLINE MatchResult(EncodedMatchResult encoded) { - ASSERT(m_checked); + union u { + uint64_t encoded; + struct s { + size_t start; + size_t end; + } split; + } value; + value.encoded = encoded; + start = value.split.start; + end = value.split.end; } - - operator bool() + + ALWAYS_INLINE static MatchResult failed() { -#if !ASSERT_DISABLED - m_checked = true; -#endif - return m_value; + return MatchResult(WTF::notFound, 0); } - -private: - bool m_value; -#if !ASSERT_DISABLED - bool m_checked; -#endif + + ALWAYS_INLINE operator bool() + { + return start != WTF::notFound; + } + + ALWAYS_INLINE bool empty() + { + return start == end; + } + + size_t start; + size_t end; }; #endif diff --git a/Source/JavaScriptCore/runtime/NumberPrototype.cpp b/Source/JavaScriptCore/runtime/NumberPrototype.cpp index 8f8c3c00f..060a80107 100644 --- a/Source/JavaScriptCore/runtime/NumberPrototype.cpp +++ b/Source/JavaScriptCore/runtime/NumberPrototype.cpp @@ -148,7 +148,7 @@ static ALWAYS_INLINE bool getIntegerArgumentInRange(ExecState* exec, int low, in typedef char RadixBuffer[2180]; // Mapping from integers 0..35 to digit identifying this value, for radix 2..36. -static const char* const radixDigits = "0123456789abcdefghijklmnopqrstuvwxyz"; +static const char radixDigits[] = "0123456789abcdefghijklmnopqrstuvwxyz"; static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radix) { @@ -339,6 +339,31 @@ static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radi return startOfResultString; } +static UString toUStringWithRadix(int32_t number, unsigned radix) +{ + LChar buf[1 + 32]; // Worst case is radix == 2, which gives us 32 digits + sign. + LChar* end = buf + WTF_ARRAY_LENGTH(buf); + LChar* p = end; + + bool negative = false; + uint32_t positiveNumber = number; + if (number < 0) { + negative = true; + positiveNumber = -number; + } + + while (positiveNumber) { + uint32_t index = positiveNumber % radix; + ASSERT(index < sizeof(radixDigits)); + *--p = static_cast<LChar>(radixDigits[index]); + positiveNumber /= radix; + } + if (negative) + *--p = '-'; + + return UString(p, static_cast<unsigned>(end - p)); +} + // toExponential converts a number to a string, always formatting as an expoential. // This method takes an optional argument specifying a number of *decimal places* // to round the significand to (or, put another way, this method optionally rounds @@ -431,41 +456,63 @@ EncodedJSValue JSC_HOST_CALL numberProtoFuncToPrecision(ExecState* exec) return JSValue::encode(jsString(exec, UString(numberToFixedPrecisionString(x, significantFigures, buffer)))); } -EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec) +static inline int32_t extractRadixFromArgs(ExecState* exec) { - double x; - if (!toThisNumber(exec->hostThisValue(), x)) - return throwVMTypeError(exec); - JSValue radixValue = exec->argument(0); - int radix; + int32_t radix; if (radixValue.isInt32()) radix = radixValue.asInt32(); else if (radixValue.isUndefined()) radix = 10; else - radix = static_cast<int>(radixValue.toInteger(exec)); // nan -> 0 + radix = static_cast<int32_t>(radixValue.toInteger(exec)); // nan -> 0 - if (radix == 10) - return JSValue::encode(jsNumber(x).toString(exec)); + return radix; +} - // Fast path for number to character conversion. - if (radix == 36) { - unsigned c = static_cast<unsigned>(x); - if (c == x && c < 36) { - JSGlobalData* globalData = &exec->globalData(); - return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, radixDigits[c])); - } +static inline EncodedJSValue integerValueToString(ExecState* exec, int32_t radix, int32_t value) +{ + // A negative value casted to unsigned would be bigger than 36 (the max radix). + if (static_cast<unsigned>(value) < static_cast<unsigned>(radix)) { + ASSERT(value <= 36); + ASSERT(value >= 0); + JSGlobalData* globalData = &exec->globalData(); + return JSValue::encode(globalData->smallStrings.singleCharacterString(globalData, radixDigits[value])); } + if (radix == 10) { + JSGlobalData* globalData = &exec->globalData(); + return JSValue::encode(jsString(globalData, globalData->numericStrings.add(value))); + } + + return JSValue::encode(jsString(exec, toUStringWithRadix(value, radix))); + +} + +EncodedJSValue JSC_HOST_CALL numberProtoFuncToString(ExecState* exec) +{ + double doubleValue; + if (!toThisNumber(exec->hostThisValue(), doubleValue)) + return throwVMTypeError(exec); + + int32_t radix = extractRadixFromArgs(exec); if (radix < 2 || radix > 36) return throwVMError(exec, createRangeError(exec, "toString() radix argument must be between 2 and 36")); - if (!isfinite(x)) - return JSValue::encode(jsString(exec, UString::number(x))); + int32_t integerValue = static_cast<int32_t>(doubleValue); + if (integerValue == doubleValue) + return integerValueToString(exec, radix, integerValue); + + if (radix == 10) { + JSGlobalData* globalData = &exec->globalData(); + return JSValue::encode(jsString(globalData, globalData->numericStrings.add(doubleValue))); + } + + if (!isfinite(doubleValue)) + return JSValue::encode(jsString(exec, UString::number(doubleValue))); RadixBuffer s; - return JSValue::encode(jsString(exec, toStringWithRadix(s, x, radix))); + return JSValue::encode(jsString(exec, toStringWithRadix(s, doubleValue, radix))); } EncodedJSValue JSC_HOST_CALL numberProtoFuncToLocaleString(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/NumericStrings.h b/Source/JavaScriptCore/runtime/NumericStrings.h index d65f14265..7fa20c44d 100644 --- a/Source/JavaScriptCore/runtime/NumericStrings.h +++ b/Source/JavaScriptCore/runtime/NumericStrings.h @@ -34,7 +34,7 @@ namespace JSC { class NumericStrings { public: - UString add(double d) + ALWAYS_INLINE UString add(double d) { CacheEntry<double>& entry = lookup(d); if (d == entry.key && !entry.value.isNull()) @@ -44,7 +44,7 @@ namespace JSC { return entry.value; } - UString add(int i) + ALWAYS_INLINE UString add(int i) { if (static_cast<unsigned>(i) < cacheSize) return lookupSmallString(static_cast<unsigned>(i)); @@ -56,7 +56,7 @@ namespace JSC { return entry.value; } - UString add(unsigned i) + ALWAYS_INLINE UString add(unsigned i) { if (i < cacheSize) return lookupSmallString(static_cast<unsigned>(i)); @@ -79,7 +79,7 @@ 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) + ALWAYS_INLINE const UString& lookupSmallString(unsigned i) { ASSERT(i < cacheSize); if (smallIntCache[i].isNull()) diff --git a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp index 6ad312c7c..e980ac590 100644 --- a/Source/JavaScriptCore/runtime/ObjectPrototype.cpp +++ b/Source/JavaScriptCore/runtime/ObjectPrototype.cpp @@ -255,7 +255,17 @@ EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec) if (thisValue.isUndefinedOrNull()) return JSValue::encode(jsNontrivialString(exec, thisValue.isUndefined() ? "[object Undefined]" : "[object Null]")); JSObject* thisObject = thisValue.toObject(exec); - return JSValue::encode(jsMakeNontrivialString(exec, "[object ", thisObject->methodTable()->className(thisObject), "]")); + + JSString* result = thisObject->structure()->objectToStringValue(); + if (!result) { + RefPtr<StringImpl> newString = WTF::tryMakeString("[object ", thisObject->methodTable()->className(thisObject), "]"); + if (!newString) + return JSValue::encode(throwOutOfMemoryError(exec)); + + result = jsNontrivialString(exec, newString.release()); + thisObject->structure()->setObjectToStringValue(exec->globalData(), thisObject, result); + } + return JSValue::encode(result); } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/Operations.cpp b/Source/JavaScriptCore/runtime/Operations.cpp index 459feb466..4cb9de505 100644 --- a/Source/JavaScriptCore/runtime/Operations.cpp +++ b/Source/JavaScriptCore/runtime/Operations.cpp @@ -58,25 +58,26 @@ NEVER_INLINE JSValue jsAddSlowCase(CallFrame* callFrame, JSValue v1, JSValue v2) JSValue jsTypeStringForValue(CallFrame* callFrame, JSValue v) { + JSGlobalData& globalData = callFrame->globalData(); if (v.isUndefined()) - return jsNontrivialString(callFrame, "undefined"); + return globalData.smallStrings.undefinedString(&globalData); if (v.isBoolean()) - return jsNontrivialString(callFrame, "boolean"); + return globalData.smallStrings.booleanString(&globalData); if (v.isNumber()) - return jsNontrivialString(callFrame, "number"); + return globalData.smallStrings.numberString(&globalData); if (v.isString()) - return jsNontrivialString(callFrame, "string"); + return globalData.smallStrings.stringString(&globalData); if (v.isObject()) { // Return "undefined" for objects that should be treated // as null when doing comparisons. if (asObject(v)->structure()->typeInfo().masqueradesAsUndefined()) - return jsNontrivialString(callFrame, "undefined"); + return globalData.smallStrings.undefinedString(&globalData); CallData callData; JSObject* object = asObject(v); if (object->methodTable()->getCallData(object, callData) != CallTypeNone) - return jsNontrivialString(callFrame, "function"); + return globalData.smallStrings.functionString(&globalData); } - return jsNontrivialString(callFrame, "object"); + return globalData.smallStrings.objectString(&globalData); } bool jsIsObjectType(JSValue v) diff --git a/Source/JavaScriptCore/runtime/Operations.h b/Source/JavaScriptCore/runtime/Operations.h index 945283899..b2081f3dd 100644 --- a/Source/JavaScriptCore/runtime/Operations.h +++ b/Source/JavaScriptCore/runtime/Operations.h @@ -47,7 +47,7 @@ namespace JSC { if ((length1 + length2) < length1) return throwOutOfMemoryError(exec); - return JSString::create(globalData, s1, s2); + return JSRopeString::create(globalData, s1, s2); } ALWAYS_INLINE JSValue jsString(ExecState* exec, const UString& u1, const UString& u2, const UString& u3) @@ -69,13 +69,13 @@ namespace JSC { if ((length1 + length2 + length3) < length3) return throwOutOfMemoryError(exec); - return JSString::create(exec->globalData(), jsString(globalData, u1), jsString(globalData, u2), jsString(globalData, u3)); + return JSRopeString::create(exec->globalData(), jsString(globalData, u1), jsString(globalData, u2), jsString(globalData, u3)); } ALWAYS_INLINE JSValue jsString(ExecState* exec, Register* strings, unsigned count) { JSGlobalData* globalData = &exec->globalData(); - JSString::RopeBuilder ropeBuilder(*globalData); + JSRopeString::RopeBuilder ropeBuilder(*globalData); unsigned oldLength = 0; @@ -93,7 +93,7 @@ namespace JSC { ALWAYS_INLINE JSValue jsStringFromArguments(ExecState* exec, JSValue thisValue) { JSGlobalData* globalData = &exec->globalData(); - JSString::RopeBuilder ropeBuilder(*globalData); + JSRopeString::RopeBuilder ropeBuilder(*globalData); ropeBuilder.append(thisValue.toString(exec)); unsigned oldLength = 0; diff --git a/Source/JavaScriptCore/runtime/Options.cpp b/Source/JavaScriptCore/runtime/Options.cpp index c4bf39db4..8f5a05067 100644 --- a/Source/JavaScriptCore/runtime/Options.cpp +++ b/Source/JavaScriptCore/runtime/Options.cpp @@ -75,6 +75,7 @@ double osrExitProminenceForFrequentExitSite; unsigned largeFailCountThresholdBase; unsigned largeFailCountThresholdBaseForLoop; +unsigned forcedOSRExitCountForReoptimization; unsigned reoptimizationRetryCounterMax; unsigned reoptimizationRetryCounterStep; @@ -174,8 +175,9 @@ void initializeOptions() SET(osrExitProminenceForFrequentExitSite, 0.3); - SET(largeFailCountThresholdBase, 20); - SET(largeFailCountThresholdBaseForLoop, 1); + SET(largeFailCountThresholdBase, 20); + SET(largeFailCountThresholdBaseForLoop, 1); + SET(forcedOSRExitCountForReoptimization, 250); SET(reoptimizationRetryCounterStep, 1); diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h index fae6a7376..d1ad2ca87 100644 --- a/Source/JavaScriptCore/runtime/Options.h +++ b/Source/JavaScriptCore/runtime/Options.h @@ -61,6 +61,7 @@ extern double osrExitProminenceForFrequentExitSite; extern unsigned largeFailCountThresholdBase; extern unsigned largeFailCountThresholdBaseForLoop; +extern unsigned forcedOSRExitCountForReoptimization; extern unsigned reoptimizationRetryCounterMax; extern unsigned reoptimizationRetryCounterStep; diff --git a/Source/JavaScriptCore/runtime/PropertyNameArray.cpp b/Source/JavaScriptCore/runtime/PropertyNameArray.cpp index 8efb4065e..9bae94097 100644 --- a/Source/JavaScriptCore/runtime/PropertyNameArray.cpp +++ b/Source/JavaScriptCore/runtime/PropertyNameArray.cpp @@ -45,7 +45,7 @@ void PropertyNameArray::add(StringImpl* identifier) for (size_t i = 0; i < size; ++i) m_set.add(m_data->propertyNameVector()[i].impl()); } - if (!m_set.add(identifier).second) + if (!m_set.add(identifier).isNewEntry) return; } diff --git a/Source/JavaScriptCore/runtime/RegExp.cpp b/Source/JavaScriptCore/runtime/RegExp.cpp index 1a3362b2d..b0f67607e 100644 --- a/Source/JavaScriptCore/runtime/RegExp.cpp +++ b/Source/JavaScriptCore/runtime/RegExp.cpp @@ -131,11 +131,11 @@ void RegExpFunctionalTestCollector::outputOneTest(RegExp* regExp, UString s, int outputEscapedUString(s); fprintf(m_file, "\", %d, %d, (", startOffset, result); for (unsigned i = 0; i <= regExp->numSubpatterns(); i++) { - int subPatternBegin = ovector[i * 2]; - int subPatternEnd = ovector[i * 2 + 1]; - if (subPatternBegin == -1) - subPatternEnd = -1; - fprintf(m_file, "%d, %d", subPatternBegin, subPatternEnd); + int subpatternBegin = ovector[i * 2]; + int subpatternEnd = ovector[i * 2 + 1]; + if (subpatternBegin == -1) + subpatternEnd = -1; + fprintf(m_file, "%d, %d", subpatternBegin, subpatternEnd); if (i < regExp->numSubpatterns()) fputs(", ", m_file); } @@ -217,13 +217,6 @@ void RegExpFunctionalTestCollector::outputEscapedUString(const UString& s, bool } #endif -struct RegExpRepresentation { -#if ENABLE(YARR_JIT) - Yarr::YarrCodeBlock m_regExpJITCode; -#endif - OwnPtr<Yarr::BytecodePattern> m_regExpBytecode; -}; - RegExp::RegExp(JSGlobalData& globalData, const UString& patternString, RegExpFlags flags) : JSCell(globalData, globalData.regExpStructure.get()) , m_state(NotCompiled) @@ -279,23 +272,22 @@ void RegExp::compile(JSGlobalData* globalData, Yarr::YarrCharSize charSize) } ASSERT(m_numSubpatterns == pattern.m_numSubpatterns); - if (!m_representation) { + if (!hasCode()) { ASSERT(m_state == NotCompiled); - m_representation = adoptPtr(new RegExpRepresentation); globalData->regExpCache()->addToStrongCache(this); m_state = ByteCode; } #if ENABLE(YARR_JIT) - if (!pattern.m_containsBackreferences && globalData->canUseJIT()) { - Yarr::jitCompile(pattern, charSize, globalData, m_representation->m_regExpJITCode); + if (!pattern.m_containsBackreferences && globalData->canUseRegExpJIT()) { + Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode); #if ENABLE(YARR_JIT_DEBUG) - if (!m_representation->m_regExpJITCode.isFallBack()) + if (!m_regExpJITCode.isFallBack()) m_state = JITCode; else m_state = ByteCode; #else - if (!m_representation->m_regExpJITCode.isFallBack()) { + if (!m_regExpJITCode.isFallBack()) { m_state = JITCode; return; } @@ -305,22 +297,18 @@ void RegExp::compile(JSGlobalData* globalData, Yarr::YarrCharSize charSize) UNUSED_PARAM(charSize); #endif - m_representation->m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator); + m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator); } void RegExp::compileIfNecessary(JSGlobalData& globalData, Yarr::YarrCharSize charSize) { - // If the state is NotCompiled or ParseError, then there is no representation. - // If there is a representation, and the state must be either JITCode or ByteCode. - ASSERT(!!m_representation == (m_state == JITCode || m_state == ByteCode)); - - if (m_representation) { + if (hasCode()) { #if ENABLE(YARR_JIT) if (m_state != JITCode) return; - if ((charSize == Yarr::Char8) && (m_representation->m_regExpJITCode.has8BitCode())) + if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCode())) return; - if ((charSize == Yarr::Char16) && (m_representation->m_regExpJITCode.has16BitCode())) + if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCode())) return; #else return; @@ -330,7 +318,7 @@ void RegExp::compileIfNecessary(JSGlobalData& globalData, Yarr::YarrCharSize cha compile(&globalData, charSize); } -int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset, Vector<int, 32>* ovector) +int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset, Vector<int, 32>& ovector) { #if ENABLE(REGEXP_TRACING) m_rtMatchCallCount++; @@ -340,30 +328,22 @@ int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffs compileIfNecessary(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16); 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); + ovector.resize(offsetVectorSize); + int* offsetVector = ovector.data(); int result; #if ENABLE(YARR_JIT) if (m_state == JITCode) { if (s.is8Bit()) - result = Yarr::execute(m_representation->m_regExpJITCode, s.characters8(), startOffset, s.length(), offsetVector); + result = m_regExpJITCode.execute(s.characters8(), startOffset, s.length(), offsetVector).start; else - result = Yarr::execute(m_representation->m_regExpJITCode, s.characters16(), startOffset, s.length(), offsetVector); + result = m_regExpJITCode.execute(s.characters16(), startOffset, s.length(), offsetVector).start; #if ENABLE(YARR_JIT_DEBUG) matchCompareWithInterpreter(s, startOffset, offsetVector, result); #endif } else #endif - result = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), reinterpret_cast<unsigned*>(offsetVector)); + result = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector)); // FIXME: The YARR engine should handle unsigned or size_t length matches. // The YARR Interpreter is "unsigned" clean, while the YARR JIT hasn't been addressed. @@ -404,12 +384,113 @@ int RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffs return result; } +void RegExp::compileMatchOnly(JSGlobalData* globalData, Yarr::YarrCharSize charSize) +{ + Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), &m_constructionError); + if (m_constructionError) { + ASSERT_NOT_REACHED(); + m_state = ParseError; + return; + } + ASSERT(m_numSubpatterns == pattern.m_numSubpatterns); + + if (!hasCode()) { + ASSERT(m_state == NotCompiled); + globalData->regExpCache()->addToStrongCache(this); + m_state = ByteCode; + } + +#if ENABLE(YARR_JIT) + if (!pattern.m_containsBackreferences && globalData->canUseRegExpJIT()) { + Yarr::jitCompile(pattern, charSize, globalData, m_regExpJITCode, Yarr::MatchOnly); +#if ENABLE(YARR_JIT_DEBUG) + if (!m_regExpJITCode.isFallBack()) + m_state = JITCode; + else + m_state = ByteCode; +#else + if (!m_regExpJITCode.isFallBack()) { + m_state = JITCode; + return; + } +#endif + } +#else + UNUSED_PARAM(charSize); +#endif + + m_regExpBytecode = Yarr::byteCompile(pattern, &globalData->m_regExpAllocator); +} + +void RegExp::compileIfNecessaryMatchOnly(JSGlobalData& globalData, Yarr::YarrCharSize charSize) +{ + if (hasCode()) { +#if ENABLE(YARR_JIT) + if (m_state != JITCode) + return; + if ((charSize == Yarr::Char8) && (m_regExpJITCode.has8BitCodeMatchOnly())) + return; + if ((charSize == Yarr::Char16) && (m_regExpJITCode.has16BitCodeMatchOnly())) + return; +#else + return; +#endif + } + + compileMatchOnly(&globalData, charSize); +} + +MatchResult RegExp::match(JSGlobalData& globalData, const UString& s, unsigned startOffset) +{ +#if ENABLE(REGEXP_TRACING) + m_rtMatchCallCount++; +#endif + + ASSERT(m_state != ParseError); + compileIfNecessaryMatchOnly(globalData, s.is8Bit() ? Yarr::Char8 : Yarr::Char16); + +#if ENABLE(YARR_JIT) + if (m_state == JITCode) { + MatchResult result = s.is8Bit() ? + m_regExpJITCode.execute(s.characters8(), startOffset, s.length()) : + m_regExpJITCode.execute(s.characters16(), startOffset, s.length()); +#if ENABLE(REGEXP_TRACING) + if (!result) + m_rtMatchFoundCount++; +#endif + return result; + } +#endif + + int offsetVectorSize = (m_numSubpatterns + 1) * 2; + int* offsetVector; + Vector<int, 32> nonReturnedOvector; + nonReturnedOvector.resize(offsetVectorSize); + offsetVector = nonReturnedOvector.data(); + int r = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, reinterpret_cast<unsigned*>(offsetVector)); +#if REGEXP_FUNC_TEST_DATA_GEN + RegExpFunctionalTestCollector::get()->outputOneTest(this, s, startOffset, offsetVector, result); +#endif + + if (r >= 0) { +#if ENABLE(REGEXP_TRACING) + m_rtMatchFoundCount++; +#endif + return MatchResult(r, reinterpret_cast<unsigned*>(offsetVector)[1]); + } + + return MatchResult::failed(); +} + void RegExp::invalidateCode() { - if (!m_representation) + if (!hasCode()) return; m_state = NotCompiled; - m_representation.clear(); +#if ENABLE(YARR_JIT) + m_regExpJITCode.clear(); +#endif + m_regExpBytecode.clear(); } #if ENABLE(YARR_JIT_DEBUG) @@ -428,7 +509,7 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int* for (unsigned j = 0, i = 0; i < m_numSubpatterns + 1; j += 2, i++) interpreterOffsetVector[j] = -1; - interpreterResult = Yarr::interpret(m_representation->m_regExpBytecode.get(), s, startOffset, s.length(), interpreterOffsetVector); + interpreterResult = Yarr::interpret(m_regExpBytecode.get(), s, startOffset, interpreterOffsetVector); if (jitResult != interpreterResult) differences++; @@ -477,7 +558,7 @@ void RegExp::matchCompareWithInterpreter(const UString& s, int startOffset, int* snprintf(formattedPattern, 41, (pattLen <= 38) ? "/%.38s/" : "/%.36s...", rawPattern); #if ENABLE(YARR_JIT) - Yarr::YarrCodeBlock& codeBlock = m_representation->m_regExpJITCode; + Yarr::YarrCodeBlock& codeBlock = m_regExpJITCode; const size_t jitAddrSize = 20; char jitAddr[jitAddrSize]; diff --git a/Source/JavaScriptCore/runtime/RegExp.h b/Source/JavaScriptCore/runtime/RegExp.h index d0201cbfb..ad1020376 100644 --- a/Source/JavaScriptCore/runtime/RegExp.h +++ b/Source/JavaScriptCore/runtime/RegExp.h @@ -22,14 +22,19 @@ #ifndef RegExp_h #define RegExp_h -#include "UString.h" #include "ExecutableAllocator.h" -#include "Structure.h" +#include "MatchResult.h" #include "RegExpKey.h" +#include "Structure.h" +#include "UString.h" #include "yarr/Yarr.h" #include <wtf/Forward.h> #include <wtf/RefCounted.h> +#if ENABLE(YARR_JIT) +#include "yarr/YarrJIT.h" +#endif + namespace JSC { struct RegExpRepresentation; @@ -53,12 +58,13 @@ namespace JSC { bool isValid() const { return !m_constructionError && m_flags != InvalidFlags; } const char* errorMessage() const { return m_constructionError; } - JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector<int, 32>* ovector = 0); + JS_EXPORT_PRIVATE int match(JSGlobalData&, const UString&, unsigned startOffset, Vector<int, 32>& ovector); + MatchResult match(JSGlobalData&, const UString&, unsigned startOffset); unsigned numSubpatterns() const { return m_numSubpatterns; } bool hasCode() { - return m_representation; + return m_state != NotCompiled; } void invalidateCode(); @@ -95,6 +101,9 @@ namespace JSC { void compile(JSGlobalData*, Yarr::YarrCharSize); void compileIfNecessary(JSGlobalData&, Yarr::YarrCharSize); + void compileMatchOnly(JSGlobalData*, Yarr::YarrCharSize); + void compileIfNecessaryMatchOnly(JSGlobalData&, Yarr::YarrCharSize); + #if ENABLE(YARR_JIT_DEBUG) void matchCompareWithInterpreter(const UString&, int startOffset, int* offsetVector, int jitResult); #endif @@ -108,7 +117,10 @@ namespace JSC { unsigned m_rtMatchFoundCount; #endif - OwnPtr<RegExpRepresentation> m_representation; +#if ENABLE(YARR_JIT) + Yarr::YarrCodeBlock m_regExpJITCode; +#endif + OwnPtr<Yarr::BytecodePattern> m_regExpBytecode; }; } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/RegExpCache.cpp b/Source/JavaScriptCore/runtime/RegExpCache.cpp index d5edbbc7f..36ea326e6 100644 --- a/Source/JavaScriptCore/runtime/RegExpCache.cpp +++ b/Source/JavaScriptCore/runtime/RegExpCache.cpp @@ -46,7 +46,7 @@ RegExp* RegExpCache::lookupOrCreate(const UString& patternString, RegExpFlags fl // We need to do a second lookup to add the RegExp as // allocating it may have caused a gc cycle, which in // turn may have removed items from the cache. - m_weakCache.add(key, PassWeak<RegExp>(*m_globalData, regExp, this)); + m_weakCache.add(key, PassWeak<RegExp>(regExp, this)); return regExp; } diff --git a/Source/JavaScriptCore/wtf/ByteArray.cpp b/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp index 80c603f30..07881451a 100644 --- a/Source/JavaScriptCore/wtf/ByteArray.cpp +++ b/Source/JavaScriptCore/runtime/RegExpCachedResult.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * Copyright (C) 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -20,21 +20,43 @@ * 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. + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" -#include "ByteArray.h" +#include "RegExpCachedResult.h" -#include "StdLibExtras.h" +#include "RegExpMatchesArray.h" -namespace WTF { +namespace JSC { -PassRefPtr<ByteArray> ByteArray::create(size_t size) +void RegExpCachedResult::visitChildren(SlotVisitor& visitor) { - unsigned char* buffer = new unsigned char[size + OBJECT_OFFSETOF(ByteArray, m_data)]; - ASSERT((reinterpret_cast<size_t>(buffer) & 3) == 0); - return adoptRef(new (NotNull, buffer) ByteArray(size)); + if (m_result) { + visitor.append(&m_lastInput); + visitor.append(&m_lastRegExp); + } else { + visitor.append(&m_reifiedInput); + visitor.append(&m_reifiedResult); + } } +RegExpMatchesArray* RegExpCachedResult::lastResult(ExecState* exec, JSObject* owner) +{ + if (m_result) { + m_reifiedInput.set(exec->globalData(), owner, m_lastInput.get()); + m_reifiedResult.set(exec->globalData(), owner, RegExpMatchesArray::create(exec, m_lastInput.get(), m_lastRegExp.get(), m_result)); + m_result = MatchResult::failed(); + } + return m_reifiedResult.get(); } + +void RegExpCachedResult::setInput(ExecState* exec, JSObject* owner, JSString* input) +{ + // Make sure we're reified, otherwise m_reifiedInput will be ignored. + lastResult(exec, owner); + ASSERT(!m_result); + m_reifiedInput.set(exec->globalData(), owner, input); +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/RegExpCachedResult.h b/Source/JavaScriptCore/runtime/RegExpCachedResult.h new file mode 100644 index 000000000..a72244025 --- /dev/null +++ b/Source/JavaScriptCore/runtime/RegExpCachedResult.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2012 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 RegExpCachedResult_h +#define RegExpCachedResult_h + +#include "RegExpObject.h" + +namespace JSC { + + class JSString; + class RegExpMatchesArray; + + // RegExpCachedResult is used to track the cached results of the last + // match, stores on the RegExp constructor (e.g. $&, $_, $1, $2 ...). + // These values will be lazily generated on demand, so the cached result + // may be in a lazy or reified state. A lazy state is indicated by a + // value of m_result indicating a successful match, and a reified state + // is indicated by setting m_result to MatchResult::failed(). + // Following a successful match, m_result, m_lastInput and m_lastRegExp + // can be used to reify the results from the match, following reification + // m_reifiedResult and m_reifiedInput hold the cached results. + class RegExpCachedResult { + public: + RegExpCachedResult(JSGlobalData& globalData, JSObject* owner, RegExp* emptyRegExp) + : m_result(0, 0) + { + m_lastInput.set(globalData, owner, jsEmptyString(&globalData)); + m_lastRegExp.set(globalData, owner, emptyRegExp); + m_reifiedResult.clear(); + m_reifiedInput.clear(); + } + + ALWAYS_INLINE void record(JSGlobalData& globalData, JSObject* owner, RegExp* regExp, JSString* input, MatchResult result) + { + m_lastRegExp.set(globalData, owner, regExp); + m_lastInput.set(globalData, owner, input); + m_result = result; + } + + RegExpMatchesArray* lastResult(ExecState*, JSObject* owner); + void setInput(ExecState*, JSObject* owner, JSString*); + + JSString* input() + { + // If m_result showas a match then we're in a lazy state, so m_lastInput + // is the most recent value of the input property. If not then we have + // reified, in which case m_reifiedInput will contain the correct value. + return m_result ? m_lastInput.get() : m_reifiedInput.get(); + } + + void visitChildren(SlotVisitor&); + + private: + MatchResult m_result; + WriteBarrier<JSString> m_lastInput; + WriteBarrier<RegExp> m_lastRegExp; + WriteBarrier<RegExpMatchesArray> m_reifiedResult; + WriteBarrier<JSString> m_reifiedInput; + }; + +} // namespace JSC + +#endif // RegExpCachedResult_h diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp index 90082f07e..fd03db569 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.cpp +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.cpp @@ -22,21 +22,9 @@ #include "config.h" #include "RegExpConstructor.h" -#include "ArrayPrototype.h" #include "Error.h" -#include "ExceptionHelpers.h" -#include "JSArray.h" -#include "JSFunction.h" -#include "JSString.h" -#include "Lookup.h" -#include "ObjectPrototype.h" #include "RegExpMatchesArray.h" -#include "RegExpObject.h" #include "RegExpPrototype.h" -#include "RegExp.h" -#include "RegExpCache.h" -#include "UStringConcatenate.h" -#include <wtf/PassOwnPtr.h> namespace JSC { @@ -69,8 +57,6 @@ ASSERT_CLASS_FITS_IN_CELL(RegExpConstructor); const ClassInfo RegExpConstructor::s_info = { "Function", &InternalFunction::s_info, 0, ExecState::regExpConstructorTable, CREATE_METHOD_TABLE(RegExpConstructor) }; -const ClassInfo RegExpMatchesArray::s_info = {"Array", &JSArray::s_info, 0, 0, CREATE_METHOD_TABLE(RegExpMatchesArray)}; - /* Source for RegExpConstructor.lut.h @begin regExpConstructorTable input regExpConstructorInput None @@ -97,18 +83,10 @@ const ClassInfo RegExpMatchesArray::s_info = {"Array", &JSArray::s_info, 0, 0, C @end */ -RegExpResult& RegExpResult::operator=(const RegExpConstructorPrivate& rhs) -{ - this->input = rhs.input; - this->ovector = rhs.lastOvector(); - this->lastNumSubPatterns = rhs.lastNumSubPatterns; - - return *this; -} - - -RegExpConstructor::RegExpConstructor(JSGlobalObject* globalObject, Structure* structure) +RegExpConstructor::RegExpConstructor(JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype) : InternalFunction(globalObject, structure) + , m_cachedResult(globalObject->globalData(), this, regExpPrototype->regExp()) + , m_multiline(false) { } @@ -129,81 +107,51 @@ void RegExpConstructor::destroy(JSCell* cell) jsCast<RegExpConstructor*>(cell)->RegExpConstructor::~RegExpConstructor(); } -RegExpMatchesArray::RegExpMatchesArray(ExecState* exec) - : JSArray(exec->globalData(), exec->lexicalGlobalObject()->regExpMatchesArrayStructure()) - , m_didFillArrayInstance(false) -{ -} - -void RegExpMatchesArray::finishCreation(JSGlobalData& globalData, const RegExpConstructorPrivate& data) +void RegExpConstructor::visitChildren(JSCell* cell, SlotVisitor& visitor) { - Base::finishCreation(globalData, data.lastNumSubPatterns + 1); - m_regExpResult = data; -} - -void RegExpMatchesArray::destroy(JSCell* cell) -{ - jsCast<RegExpMatchesArray*>(cell)->RegExpMatchesArray::~RegExpMatchesArray(); -} - -void RegExpMatchesArray::fillArrayInstance(ExecState* exec) -{ - unsigned lastNumSubpatterns = m_regExpResult.lastNumSubPatterns; - - for (unsigned i = 0; i <= lastNumSubpatterns; ++i) { - int start = m_regExpResult.ovector[2 * i]; - if (start >= 0) - putDirectIndex(exec, i, jsSubstring(exec, m_regExpResult.input, start, m_regExpResult.ovector[2 * i + 1] - start), false); - else - putDirectIndex(exec, i, jsUndefined(), false); - } + RegExpConstructor* thisObject = jsCast<RegExpConstructor*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); + COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); + ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); - PutPropertySlot slot; - JSArray::put(this, exec, exec->propertyNames().index, jsNumber(m_regExpResult.ovector[0]), slot); - JSArray::put(this, exec, exec->propertyNames().input, jsString(exec, m_regExpResult.input), slot); - - m_didFillArrayInstance = true; + Base::visitChildren(thisObject, visitor); + thisObject->m_cachedResult.visitChildren(visitor); } -JSObject* RegExpConstructor::arrayOfMatches(ExecState* exec) const +JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) { - return RegExpMatchesArray::create(exec, d); -} + RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this); -JSValue RegExpConstructor::getBackref(ExecState* exec, unsigned i) const -{ - if (!d.lastOvector().isEmpty() && i <= d.lastNumSubPatterns) { - int start = d.lastOvector()[2 * i]; - if (start >= 0) - return jsSubstring(exec, d.lastInput, start, d.lastOvector()[2 * i + 1] - start); + if (i < array->length()) { + JSValue result = JSValue(array).get(exec, i); + ASSERT(result.isString() || result.isUndefined()); + if (!result.isUndefined()) + return result; } return jsEmptyString(exec); } -JSValue RegExpConstructor::getLastParen(ExecState* exec) const +JSValue RegExpConstructor::getLastParen(ExecState* exec) { - unsigned i = d.lastNumSubPatterns; - if (i > 0) { - ASSERT(!d.lastOvector().isEmpty()); - int start = d.lastOvector()[2 * i]; - if (start >= 0) - return jsSubstring(exec, d.lastInput, start, d.lastOvector()[2 * i + 1] - start); + RegExpMatchesArray* array = m_cachedResult.lastResult(exec, this); + unsigned length = array->length(); + if (length > 1) { + JSValue result = JSValue(array).get(exec, length - 1); + ASSERT(result.isString() || result.isUndefined()); + if (!result.isUndefined()) + return result; } return jsEmptyString(exec); } -JSValue RegExpConstructor::getLeftContext(ExecState* exec) const +JSValue RegExpConstructor::getLeftContext(ExecState* exec) { - if (!d.lastOvector().isEmpty()) - return jsSubstring(exec, d.lastInput, 0, d.lastOvector()[0]); - return jsEmptyString(exec); + return m_cachedResult.lastResult(exec, this)->leftContext(exec); } -JSValue RegExpConstructor::getRightContext(ExecState* exec) const +JSValue RegExpConstructor::getRightContext(ExecState* exec) { - if (!d.lastOvector().isEmpty()) - return jsSubstring(exec, d.lastInput, d.lastOvector()[1], d.lastInput.length() - d.lastOvector()[1]); - return jsEmptyString(exec); + return m_cachedResult.lastResult(exec, this)->rightContext(exec); } bool RegExpConstructor::getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) @@ -261,9 +209,9 @@ JSValue regExpConstructorDollar9(ExecState* exec, JSValue slotBase, const Identi return asRegExpConstructor(slotBase)->getBackref(exec, 9); } -JSValue regExpConstructorInput(ExecState* exec, JSValue slotBase, const Identifier&) +JSValue regExpConstructorInput(ExecState*, JSValue slotBase, const Identifier&) { - return jsString(exec, asRegExpConstructor(slotBase)->input()); + return asRegExpConstructor(slotBase)->input(); } JSValue regExpConstructorMultiline(ExecState*, JSValue slotBase, const Identifier&) @@ -298,7 +246,7 @@ void RegExpConstructor::put(JSCell* cell, ExecState* exec, const Identifier& pro void setRegExpConstructorInput(ExecState* exec, JSObject* baseObject, JSValue value) { - asRegExpConstructor(baseObject)->setInput(value.toString(exec)->value(exec)); + asRegExpConstructor(baseObject)->setInput(exec, value.toString(exec)); } void setRegExpConstructorMultiline(ExecState* exec, JSObject* baseObject, JSValue value) @@ -367,26 +315,4 @@ CallType RegExpConstructor::getCallData(JSCell*, CallData& callData) return CallTypeHost; } -void RegExpConstructor::setInput(const UString& input) -{ - d.input = input; -} - -const UString& RegExpConstructor::input() const -{ - // Can detect a distinct initial state that is invisible to JavaScript, by checking for null - // state (since jsString turns null strings to empty strings). - return d.input; -} - -void RegExpConstructor::setMultiline(bool multiline) -{ - d.multiline = multiline; -} - -bool RegExpConstructor::multiline() const -{ - return d.multiline; -} - } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/RegExpConstructor.h b/Source/JavaScriptCore/runtime/RegExpConstructor.h index 08a96b544..0093f9484 100644 --- a/Source/JavaScriptCore/runtime/RegExpConstructor.h +++ b/Source/JavaScriptCore/runtime/RegExpConstructor.h @@ -23,60 +23,22 @@ #include "InternalFunction.h" #include "RegExp.h" +#include "RegExpCachedResult.h" +#include "RegExpObject.h" #include <wtf/OwnPtr.h> + namespace JSC { - class RegExp; class RegExpPrototype; - struct RegExpConstructorPrivate; - - struct RegExpConstructorPrivate { - WTF_MAKE_FAST_ALLOCATED; - public: - // Global search cache / settings - RegExpConstructorPrivate() - : lastNumSubPatterns(0) - , multiline(false) - , lastOvectorIndex(0) - { - } - - const Vector<int, 32>& lastOvector() const { return ovector[lastOvectorIndex]; } - Vector<int, 32>& lastOvector() { return ovector[lastOvectorIndex]; } - Vector<int, 32>& tempOvector() { return ovector[lastOvectorIndex ? 0 : 1]; } - void changeLastOvector() { lastOvectorIndex = lastOvectorIndex ? 0 : 1; } - - UString input; - UString lastInput; - Vector<int, 32> ovector[2]; - unsigned lastNumSubPatterns : 30; - bool multiline : 1; - unsigned lastOvectorIndex : 1; - }; - struct RegExpResult { - WTF_MAKE_FAST_ALLOCATED; - public: - RegExpResult() - : lastNumSubPatterns(0) - { - } - - RegExpResult& operator=(const RegExpConstructorPrivate&); - - UString input; - unsigned lastNumSubPatterns; - Vector<int, 32> ovector; - }; - class RegExpConstructor : public InternalFunction { public: typedef InternalFunction Base; static RegExpConstructor* create(ExecState* exec, JSGlobalObject* globalObject, Structure* structure, RegExpPrototype* regExpPrototype) { - RegExpConstructor* constructor = new (NotNull, allocateCell<RegExpConstructor>(*exec->heap())) RegExpConstructor(globalObject, structure); + RegExpConstructor* constructor = new (NotNull, allocateCell<RegExpConstructor>(*exec->heap())) RegExpConstructor(globalObject, structure, regExpPrototype); constructor->finishCreation(exec, regExpPrototype); return constructor; } @@ -93,31 +55,35 @@ namespace JSC { static const ClassInfo s_info; - void performMatch(JSGlobalData&, RegExp*, const UString&, int startOffset, int& position, int& length, int** ovector = 0); - JSObject* arrayOfMatches(ExecState*) const; + MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset, int** ovector); + MatchResult performMatch(JSGlobalData&, RegExp*, JSString*, const UString&, int startOffset); + + void setMultiline(bool multiline) { m_multiline = multiline; } + bool multiline() const { return m_multiline; } - void setInput(const UString&); - const UString& input() const; + JSValue getBackref(ExecState*, unsigned); + JSValue getLastParen(ExecState*); + JSValue getLeftContext(ExecState*); + JSValue getRightContext(ExecState*); - void setMultiline(bool); - bool multiline() const; + void setInput(ExecState* exec, JSString* string) { m_cachedResult.setInput(exec, this, string); } + JSString* input() { return m_cachedResult.input(); } - JSValue getBackref(ExecState*, unsigned) const; - JSValue getLastParen(ExecState*) const; - JSValue getLeftContext(ExecState*) const; - JSValue getRightContext(ExecState*) const; + static void visitChildren(JSCell*, SlotVisitor&); protected: void finishCreation(ExecState*, RegExpPrototype*); - static const unsigned StructureFlags = OverridesGetOwnPropertySlot | ImplementsHasInstance | InternalFunction::StructureFlags; + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | Base::StructureFlags; private: - RegExpConstructor(JSGlobalObject*, Structure*); + RegExpConstructor(JSGlobalObject*, Structure*, RegExpPrototype*); static void destroy(JSCell*); static ConstructType getConstructData(JSCell*, ConstructData&); static CallType getCallData(JSCell*, CallData&); - RegExpConstructorPrivate d; + RegExpCachedResult m_cachedResult; + bool m_multiline; + Vector<int, 32> m_ovector; }; RegExpConstructor* asRegExpConstructor(JSValue); @@ -135,23 +101,31 @@ namespace JSC { expression matching through the performMatch function. We use cached results to calculate, e.g., RegExp.lastMatch and RegExp.leftParen. */ - ALWAYS_INLINE void RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* r, const UString& s, int startOffset, int& position, int& length, int** ovector) + ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset, int** ovector) { - position = r->match(globalData, s, startOffset, &d.tempOvector()); + int position = regExp->match(globalData, input, startOffset, m_ovector); if (ovector) - *ovector = d.tempOvector().data(); + *ovector = m_ovector.data(); - if (position != -1) { - ASSERT(!d.tempOvector().isEmpty()); + if (position == -1) + return MatchResult::failed(); - length = d.tempOvector()[1] - d.tempOvector()[0]; + ASSERT(!m_ovector.isEmpty()); + ASSERT(m_ovector[0] == position); + ASSERT(m_ovector[1] >= position); + size_t end = m_ovector[1]; - d.input = s; - d.lastInput = s; - d.changeLastOvector(); - d.lastNumSubPatterns = r->numSubpatterns(); - } + m_cachedResult.record(globalData, this, regExp, string, MatchResult(position, end)); + + return MatchResult(position, end); + } + ALWAYS_INLINE MatchResult RegExpConstructor::performMatch(JSGlobalData& globalData, RegExp* regExp, JSString* string, const UString& input, int startOffset) + { + MatchResult result = regExp->match(globalData, input, startOffset); + if (result) + m_cachedResult.record(globalData, this, regExp, string, result); + return result; } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp new file mode 100644 index 000000000..80f1068f2 --- /dev/null +++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.cpp @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2012 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 "RegExpMatchesArray.h" + +namespace JSC { + +ASSERT_CLASS_FITS_IN_CELL(RegExpMatchesArray); + +const ClassInfo RegExpMatchesArray::s_info = {"Array", &JSArray::s_info, 0, 0, CREATE_METHOD_TABLE(RegExpMatchesArray)}; + +void RegExpMatchesArray::finishCreation(JSGlobalData& globalData) +{ + Base::finishCreation(globalData, m_regExp->numSubpatterns() + 1); +} + +void RegExpMatchesArray::visitChildren(JSCell* cell, SlotVisitor& visitor) +{ + RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); + ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); + COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag); + ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); + + Base::visitChildren(thisObject, visitor); + visitor.append(&thisObject->m_input); + visitor.append(&thisObject->m_regExp); +} + +void RegExpMatchesArray::reifyAllProperties(ExecState* exec) +{ + ASSERT(m_state != ReifiedAll); + ASSERT(m_result); + + reifyMatchPropertyIfNecessary(exec); + + if (unsigned numSubpatterns = m_regExp->numSubpatterns()) { + Vector<int, 32> subpatternResults; + int position = m_regExp->match(exec->globalData(), m_input->value(exec), m_result.start, subpatternResults); + ASSERT_UNUSED(position, position >= 0 && static_cast<size_t>(position) == m_result.start); + ASSERT(m_result.start == static_cast<size_t>(subpatternResults[0])); + ASSERT(m_result.end == static_cast<size_t>(subpatternResults[1])); + + for (unsigned i = 1; i <= numSubpatterns; ++i) { + int start = subpatternResults[2 * i]; + if (start >= 0) + putDirectIndex(exec, i, jsSubstring(exec, m_input.get(), start, subpatternResults[2 * i + 1] - start), false); + else + putDirectIndex(exec, i, jsUndefined(), false); + } + } + + PutPropertySlot slot; + JSArray::put(this, exec, exec->propertyNames().index, jsNumber(m_result.start), slot); + JSArray::put(this, exec, exec->propertyNames().input, m_input.get(), slot); + + m_state = ReifiedAll; +} + +void RegExpMatchesArray::reifyMatchProperty(ExecState* exec) +{ + ASSERT(m_state == ReifiedNone); + ASSERT(m_result); + putDirectIndex(exec, 0, jsSubstring(exec, m_input.get(), m_result.start, m_result.end - m_result.start), false); + m_state = ReifiedMatch; +} + +JSString* RegExpMatchesArray::leftContext(ExecState* exec) +{ + if (!m_result.start) + return jsEmptyString(exec); + return jsSubstring(exec, m_input.get(), 0, m_result.start); +} + +JSString* RegExpMatchesArray::rightContext(ExecState* exec) +{ + unsigned length = m_input->length(); + if (m_result.end == length) + return jsEmptyString(exec); + return jsSubstring(exec, m_input.get(), m_result.end, length - m_result.end); +} + +} // namespace JSC diff --git a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h index a3c4497fc..595457bca 100644 --- a/Source/JavaScriptCore/runtime/RegExpMatchesArray.h +++ b/Source/JavaScriptCore/runtime/RegExpMatchesArray.h @@ -21,23 +21,38 @@ #define RegExpMatchesArray_h #include "JSArray.h" +#include "JSGlobalObject.h" +#include "RegExpObject.h" namespace JSC { class RegExpMatchesArray : public JSArray { private: - RegExpMatchesArray(ExecState*); + RegExpMatchesArray(JSGlobalData& globalData, JSGlobalObject* globalObject, JSString* input, RegExp* regExp, MatchResult result) + : JSArray(globalData, globalObject->regExpMatchesArrayStructure()) + , m_result(result) + , m_state(ReifiedNone) + { + m_input.set(globalData, this, input); + m_regExp.set(globalData, this, regExp); + } + + enum ReifiedState { ReifiedNone, ReifiedMatch, ReifiedAll }; public: typedef JSArray Base; - static RegExpMatchesArray* create(ExecState* exec, const RegExpConstructorPrivate& ctorPrivate) + static RegExpMatchesArray* create(ExecState* exec, JSString* input, RegExp* regExp, MatchResult result) { - RegExpMatchesArray* regExp = new (NotNull, allocateCell<RegExpMatchesArray>(*exec->heap())) RegExpMatchesArray(exec); - regExp->finishCreation(exec->globalData(), ctorPrivate); - return regExp; + ASSERT(result); + JSGlobalData& globalData = exec->globalData(); + RegExpMatchesArray* array = new (NotNull, allocateCell<RegExpMatchesArray>(globalData.heap)) RegExpMatchesArray(globalData, exec->lexicalGlobalObject(), input, regExp, result); + array->finishCreation(globalData); + return array; } - static void destroy(JSCell*); + + JSString* leftContext(ExecState*); + JSString* rightContext(ExecState*); static const ClassInfo s_info; @@ -46,78 +61,99 @@ namespace JSC { return Structure::create(globalData, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), &s_info); } + static void visitChildren(JSCell*, SlotVisitor&); + protected: - void finishCreation(JSGlobalData&, const RegExpConstructorPrivate& data); + void finishCreation(JSGlobalData&); + + static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | OverridesGetPropertyNames | Base::StructureFlags; private: + ALWAYS_INLINE void reifyAllPropertiesIfNecessary(ExecState* exec) + { + if (m_state != ReifiedAll) + reifyAllProperties(exec); + } + + ALWAYS_INLINE void reifyMatchPropertyIfNecessary(ExecState* exec) + { + if (m_state == ReifiedNone) + reifyMatchProperty(exec); + } + static bool getOwnPropertySlot(JSCell* cell, ExecState* exec, const Identifier& propertyName, PropertySlot& slot) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (!thisObject->m_didFillArrayInstance) - thisObject->fillArrayInstance(exec); + thisObject->reifyAllPropertiesIfNecessary(exec); return JSArray::getOwnPropertySlot(thisObject, exec, propertyName, slot); } static bool getOwnPropertySlotByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, PropertySlot& slot) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (!thisObject->m_didFillArrayInstance) - thisObject->fillArrayInstance(exec); + if (propertyName) + thisObject->reifyAllPropertiesIfNecessary(exec); + else + thisObject->reifyMatchPropertyIfNecessary(exec); return JSArray::getOwnPropertySlotByIndex(thisObject, exec, propertyName, slot); } static bool getOwnPropertyDescriptor(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); - if (!thisObject->m_didFillArrayInstance) - thisObject->fillArrayInstance(exec); + thisObject->reifyAllPropertiesIfNecessary(exec); return JSArray::getOwnPropertyDescriptor(thisObject, exec, propertyName, descriptor); } static void put(JSCell* cell, ExecState* exec, const Identifier& propertyName, JSValue v, PutPropertySlot& slot) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (!thisObject->m_didFillArrayInstance) - thisObject->fillArrayInstance(exec); + thisObject->reifyAllPropertiesIfNecessary(exec); JSArray::put(thisObject, exec, propertyName, v, slot); } static void putByIndex(JSCell* cell, ExecState* exec, unsigned propertyName, JSValue v, bool shouldThrow) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (!thisObject->m_didFillArrayInstance) - thisObject->fillArrayInstance(exec); + thisObject->reifyAllPropertiesIfNecessary(exec); JSArray::putByIndex(thisObject, exec, propertyName, v, shouldThrow); } static bool deleteProperty(JSCell* cell, ExecState* exec, const Identifier& propertyName) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (!thisObject->m_didFillArrayInstance) - thisObject->fillArrayInstance(exec); + thisObject->reifyAllPropertiesIfNecessary(exec); return JSArray::deleteProperty(thisObject, exec, propertyName); } static bool deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(cell); - if (!thisObject->m_didFillArrayInstance) - thisObject->fillArrayInstance(exec); + thisObject->reifyAllPropertiesIfNecessary(exec); return JSArray::deletePropertyByIndex(thisObject, exec, propertyName); } static void getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& arr, EnumerationMode mode = ExcludeDontEnumProperties) { RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); - if (!thisObject->m_didFillArrayInstance) - thisObject->fillArrayInstance(exec); + thisObject->reifyAllPropertiesIfNecessary(exec); JSArray::getOwnPropertyNames(thisObject, exec, arr, mode); } - void fillArrayInstance(ExecState*); + static bool defineOwnProperty(JSObject* object, ExecState* exec, const Identifier& propertyName, PropertyDescriptor& descriptor, bool shouldThrow) + { + RegExpMatchesArray* thisObject = jsCast<RegExpMatchesArray*>(object); + thisObject->reifyAllPropertiesIfNecessary(exec); + return JSArray::defineOwnProperty(object, exec, propertyName, descriptor, shouldThrow); + } + + void reifyAllProperties(ExecState*); + void reifyMatchProperty(ExecState*); - RegExpResult m_regExpResult; - bool m_didFillArrayInstance; + WriteBarrier<JSString> m_input; + WriteBarrier<RegExp> m_regExp; + MatchResult m_result; + ReifiedState m_state; }; } diff --git a/Source/JavaScriptCore/runtime/RegExpObject.cpp b/Source/JavaScriptCore/runtime/RegExpObject.cpp index a81799c46..da4ea0446 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.cpp +++ b/Source/JavaScriptCore/runtime/RegExpObject.cpp @@ -29,6 +29,7 @@ #include "Lexer.h" #include "Lookup.h" #include "RegExpConstructor.h" +#include "RegExpMatchesArray.h" #include "RegExpPrototype.h" #include "UStringBuilder.h" #include "UStringConcatenate.h" @@ -276,30 +277,22 @@ void RegExpObject::put(JSCell* cell, ExecState* exec, const Identifier& property lookupPut<RegExpObject, JSObject>(exec, propertyName, value, ExecState::regExpTable(exec), jsCast<RegExpObject*>(cell), slot); } -JSValue RegExpObject::test(ExecState* exec) +JSValue RegExpObject::exec(ExecState* exec, JSString* string) { - return jsBoolean(match(exec)); -} - -JSValue RegExpObject::exec(ExecState* exec) -{ - if (match(exec)) - return exec->lexicalGlobalObject()->regExpConstructor()->arrayOfMatches(exec); + if (MatchResult result = match(exec, string)) + return RegExpMatchesArray::create(exec, string, regExp(), result); return jsNull(); } // Shared implementation used by test and exec. -bool RegExpObject::match(ExecState* exec) +MatchResult RegExpObject::match(ExecState* exec, JSString* string) { + RegExp* regExp = this->regExp(); RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); - UString input = exec->argument(0).toString(exec)->value(exec); - JSGlobalData* globalData = &exec->globalData(); - if (!regExp()->global()) { - int position; - int length; - regExpConstructor->performMatch(*globalData, m_regExp.get(), input, 0, position, length); - return position >= 0; - } + UString input = string->value(exec); + JSGlobalData& globalData = exec->globalData(); + if (!regExp->global()) + return regExpConstructor->performMatch(globalData, regExp, string, input, 0); JSValue jsLastIndex = getLastIndex(); unsigned lastIndex; @@ -307,27 +300,20 @@ bool RegExpObject::match(ExecState* exec) lastIndex = jsLastIndex.asUInt32(); if (lastIndex > input.length()) { setLastIndex(exec, 0); - return false; + return MatchResult::failed(); } } else { double doubleLastIndex = jsLastIndex.toInteger(exec); if (doubleLastIndex < 0 || doubleLastIndex > input.length()) { setLastIndex(exec, 0); - return false; + return MatchResult::failed(); } lastIndex = static_cast<unsigned>(doubleLastIndex); } - int position; - int length = 0; - regExpConstructor->performMatch(*globalData, m_regExp.get(), input, lastIndex, position, length); - if (position < 0) { - setLastIndex(exec, 0); - return false; - } - - setLastIndex(exec, position + length); - return true; + MatchResult result = regExpConstructor->performMatch(globalData, regExp, string, input, lastIndex); + setLastIndex(exec, result.end); + return result; } } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/RegExpObject.h b/Source/JavaScriptCore/runtime/RegExpObject.h index 456cfa683..a7dd54705 100644 --- a/Source/JavaScriptCore/runtime/RegExpObject.h +++ b/Source/JavaScriptCore/runtime/RegExpObject.h @@ -67,8 +67,8 @@ namespace JSC { return m_lastIndex.get(); } - JSValue test(ExecState*); - JSValue exec(ExecState*); + bool test(ExecState* exec, JSString* string) { return match(exec, string); } + JSValue exec(ExecState*, JSString*); static bool getOwnPropertySlot(JSCell*, ExecState*, const Identifier& propertyName, PropertySlot&); static bool getOwnPropertyDescriptor(JSObject*, ExecState*, const Identifier&, PropertyDescriptor&); @@ -95,7 +95,7 @@ namespace JSC { JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, const Identifier& propertyName, PropertyDescriptor&, bool shouldThrow); private: - bool match(ExecState*); + MatchResult match(ExecState*, JSString*); WriteBarrier<RegExp> m_regExp; WriteBarrier<Unknown> m_lastIndex; diff --git a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp index 8e4b5a9d5..fba4de2b4 100644 --- a/Source/JavaScriptCore/runtime/RegExpPrototype.cpp +++ b/Source/JavaScriptCore/runtime/RegExpPrototype.cpp @@ -84,7 +84,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncTest(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&RegExpObject::s_info)) return throwVMTypeError(exec); - return JSValue::encode(asRegExpObject(thisValue)->test(exec)); + return JSValue::encode(jsBoolean(asRegExpObject(thisValue)->test(exec, exec->argument(0).toString(exec)))); } EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec) @@ -92,7 +92,7 @@ EncodedJSValue JSC_HOST_CALL regExpProtoFuncExec(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (!thisValue.inherits(&RegExpObject::s_info)) return throwVMTypeError(exec); - return JSValue::encode(asRegExpObject(thisValue)->exec(exec)); + return JSValue::encode(asRegExpObject(thisValue)->exec(exec, exec->argument(0).toString(exec))); } EncodedJSValue JSC_HOST_CALL regExpProtoFuncCompile(ExecState* exec) diff --git a/Source/JavaScriptCore/runtime/SmallStrings.cpp b/Source/JavaScriptCore/runtime/SmallStrings.cpp index caf201c3d..f50f73d27 100644 --- a/Source/JavaScriptCore/runtime/SmallStrings.cpp +++ b/Source/JavaScriptCore/runtime/SmallStrings.cpp @@ -68,9 +68,15 @@ SmallStringsStorage::SmallStringsStorage() } SmallStrings::SmallStrings() + : m_emptyString(0) +#define JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE(name) , m_##name(0) + JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE) +#undef JSC_COMMON_STRINGS_ATTRIBUTE_INITIALIZE { COMPILE_ASSERT(singleCharacterStringCount == sizeof(m_singleCharacterStrings) / sizeof(m_singleCharacterStrings[0]), IsNumCharactersConstInSyncWithClassUsage); - clear(); + + for (unsigned i = 0; i < singleCharacterStringCount; ++i) + m_singleCharacterStrings[i] = 0; } SmallStrings::~SmallStrings() @@ -82,25 +88,9 @@ void SmallStrings::finalizeSmallStrings() finalize(m_emptyString); for (unsigned i = 0; i < singleCharacterStringCount; ++i) finalize(m_singleCharacterStrings[i]); -} - -void SmallStrings::clear() -{ - m_emptyString = 0; - for (unsigned i = 0; i < singleCharacterStringCount; ++i) - m_singleCharacterStrings[i] = 0; -} - -unsigned SmallStrings::count() const -{ - unsigned count = 0; - if (m_emptyString) - ++count; - for (unsigned i = 0; i < singleCharacterStringCount; ++i) { - if (m_singleCharacterStrings[i]) - ++count; - } - return count; +#define JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE(name) finalize(m_##name); + JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE) +#undef JSC_COMMON_STRINGS_ATTRIBUTE_FINALIZE } void SmallStrings::createEmptyString(JSGlobalData* globalData) @@ -124,4 +114,9 @@ StringImpl* SmallStrings::singleCharacterStringRep(unsigned char character) return m_storage->rep(character); } +void SmallStrings::initialize(JSGlobalData* globalData, JSString*& string, const char* value) const +{ + string = JSString::create(*globalData, StringImpl::create(value)); +} + } // namespace JSC diff --git a/Source/JavaScriptCore/runtime/SmallStrings.h b/Source/JavaScriptCore/runtime/SmallStrings.h index cd8e63095..e609c5092 100644 --- a/Source/JavaScriptCore/runtime/SmallStrings.h +++ b/Source/JavaScriptCore/runtime/SmallStrings.h @@ -30,6 +30,17 @@ #include <wtf/FixedArray.h> #include <wtf/OwnPtr.h> +#define JSC_COMMON_STRINGS_EACH_NAME(macro) \ + macro(boolean) \ + macro(false) \ + macro(function) \ + macro(number) \ + macro(null) \ + macro(object) \ + macro(undefined) \ + macro(string) \ + macro(true) + namespace JSC { class HeapRootVisitor; @@ -63,19 +74,31 @@ namespace JSC { JS_EXPORT_PRIVATE StringImpl* singleCharacterStringRep(unsigned char character); void finalizeSmallStrings(); - void clear(); - - unsigned count() const; JSString** singleCharacterStrings() { return &m_singleCharacterStrings[0]; } +#define JSC_COMMON_STRINGS_ACCESSOR_DEFINITION(name) \ + JSString* name##String(JSGlobalData* globalData) const \ + { \ + if (!m_##name) \ + initialize(globalData, m_##name, #name); \ + return m_##name; \ + } + JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ACCESSOR_DEFINITION) +#undef JSC_COMMON_STRINGS_ACCESSOR_DEFINITION + private: static const unsigned singleCharacterStringCount = maxSingleCharacterString + 1; JS_EXPORT_PRIVATE void createEmptyString(JSGlobalData*); JS_EXPORT_PRIVATE void createSingleCharacterString(JSGlobalData*, unsigned char); + void initialize(JSGlobalData* globalData, JSString*& string, const char* value) const; + JSString* m_emptyString; +#define JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION(name) mutable JSString* m_##name; + JSC_COMMON_STRINGS_EACH_NAME(JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION) +#undef JSC_COMMON_STRINGS_ATTRIBUTE_DECLARATION JSString* m_singleCharacterStrings[singleCharacterStringCount]; OwnPtr<SmallStringsStorage> m_storage; }; diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp index 708c1fb77..81129f2a2 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.cpp +++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp @@ -35,6 +35,7 @@ #include "PropertyNameArray.h" #include "RegExpCache.h" #include "RegExpConstructor.h" +#include "RegExpMatchesArray.h" #include "RegExpObject.h" #include <wtf/ASCIICType.h> #include <wtf/MathExtras.h> @@ -239,7 +240,7 @@ static NEVER_INLINE UString substituteBackreferencesSlow(const UString& replacem static inline UString substituteBackreferences(const UString& replacement, const UString& source, const int* ovector, RegExp* reg) { - size_t i = replacement.find('$', 0); + size_t i = replacement.find('$'); if (UNLIKELY(i != notFound)) { if (replacement.is8Bit() && source.is8Bit()) return substituteBackreferencesSlow<LChar>(replacement, source, ovector, reg, i); @@ -404,7 +405,7 @@ static ALWAYS_INLINE JSValue jsSpliceSubstringsWithSeparators(ExecState* exec, J static NEVER_INLINE EncodedJSValue removeUsingRegExpSearch(ExecState* exec, JSString* string, const UString& source, RegExp* regExp) { - int lastIndex = 0; + size_t lastIndex = 0; unsigned startPosition = 0; Vector<StringRange, 16> sourceRanges; @@ -413,21 +414,18 @@ static NEVER_INLINE EncodedJSValue removeUsingRegExpSearch(ExecState* exec, JSSt unsigned sourceLen = source.length(); while (true) { - int matchIndex; - int matchLen = 0; - int* ovector; - regExpConstructor->performMatch(*globalData, regExp, source, startPosition, matchIndex, matchLen, &ovector); - if (matchIndex < 0) + MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition); + if (!result) break; - if (lastIndex < matchIndex) - sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + if (lastIndex < result.start) + sourceRanges.append(StringRange(lastIndex, result.start - lastIndex)); - lastIndex = matchIndex + matchLen; + lastIndex = result.end; startPosition = lastIndex; // special case of empty match - if (!matchLen) { + if (result.empty()) { startPosition++; if (startPosition > sourceLen) break; @@ -443,8 +441,9 @@ static NEVER_INLINE EncodedJSValue removeUsingRegExpSearch(ExecState* exec, JSSt return JSValue::encode(jsSpliceSubstrings(exec, string, source, sourceRanges.data(), sourceRanges.size())); } -static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSString* string, JSValue searchValue, JSValue replaceValue) +static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSString* string, JSValue searchValue) { + JSValue replaceValue = exec->argument(1); UString replacementString; CallData callData; CallType callType = getCallData(replaceValue, callData); @@ -471,7 +470,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); - int lastIndex = 0; + size_t lastIndex = 0; unsigned startPosition = 0; Vector<StringRange, 16> sourceRanges; @@ -481,23 +480,20 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS if (global && callType == CallTypeJS) { // regExp->numSubpatterns() + 1 for pattern args, + 2 for match start and string int argCount = regExp->numSubpatterns() + 1 + 2; - JSFunction* func = asFunction(replaceValue); + JSFunction* func = jsCast<JSFunction*>(replaceValue); CachedCall cachedCall(exec, func, argCount); if (exec->hadException()) return JSValue::encode(jsNull()); JSGlobalData* globalData = &exec->globalData(); if (source.is8Bit()) { while (true) { - int matchIndex; - int matchLen = 0; int* ovector; - regExpConstructor->performMatch(*globalData, regExp, source, startPosition, matchIndex, matchLen, &ovector); - if (matchIndex < 0) + MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition, &ovector); + if (!result) break; - sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + sourceRanges.append(StringRange(lastIndex, result.start - lastIndex)); - int completeMatchStart = ovector[0]; unsigned i = 0; for (; i < regExp->numSubpatterns() + 1; ++i) { int matchStart = ovector[i * 2]; @@ -509,20 +505,20 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS cachedCall.setArgument(i, jsSubstring8(globalData, source, matchStart, matchLen)); } - cachedCall.setArgument(i++, jsNumber(completeMatchStart)); + cachedCall.setArgument(i++, jsNumber(result.start)); cachedCall.setArgument(i++, string); cachedCall.setThis(jsUndefined()); - JSValue result = cachedCall.call(); - replacements.append(result.toString(cachedCall.newCallFrame(exec))->value(exec)); + JSValue jsResult = cachedCall.call(); + replacements.append(jsResult.toString(cachedCall.newCallFrame(exec))->value(exec)); if (exec->hadException()) break; - lastIndex = matchIndex + matchLen; + lastIndex = result.end; startPosition = lastIndex; // special case of empty match - if (!matchLen) { + if (result.empty()) { startPosition++; if (startPosition > sourceLen) break; @@ -530,16 +526,13 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS } } else { while (true) { - int matchIndex; - int matchLen = 0; int* ovector; - regExpConstructor->performMatch(*globalData, regExp, source, startPosition, matchIndex, matchLen, &ovector); - if (matchIndex < 0) + MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition, &ovector); + if (!result) break; - sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + sourceRanges.append(StringRange(lastIndex, result.start - lastIndex)); - int completeMatchStart = ovector[0]; unsigned i = 0; for (; i < regExp->numSubpatterns() + 1; ++i) { int matchStart = ovector[i * 2]; @@ -551,20 +544,20 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS cachedCall.setArgument(i, jsSubstring(globalData, source, matchStart, matchLen)); } - cachedCall.setArgument(i++, jsNumber(completeMatchStart)); + cachedCall.setArgument(i++, jsNumber(result.start)); cachedCall.setArgument(i++, string); cachedCall.setThis(jsUndefined()); - JSValue result = cachedCall.call(); - replacements.append(result.toString(cachedCall.newCallFrame(exec))->value(exec)); + JSValue jsResult = cachedCall.call(); + replacements.append(jsResult.toString(cachedCall.newCallFrame(exec))->value(exec)); if (exec->hadException()) break; - lastIndex = matchIndex + matchLen; + lastIndex = result.end; startPosition = lastIndex; // special case of empty match - if (!matchLen) { + if (result.empty()) { startPosition++; if (startPosition > sourceLen) break; @@ -574,17 +567,14 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS } else { JSGlobalData* globalData = &exec->globalData(); do { - int matchIndex; - int matchLen = 0; int* ovector; - regExpConstructor->performMatch(*globalData, regExp, source, startPosition, matchIndex, matchLen, &ovector); - if (matchIndex < 0) + MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, source, startPosition, &ovector); + if (!result) break; if (callType != CallTypeNone) { - sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + sourceRanges.append(StringRange(lastIndex, result.start - lastIndex)); - int completeMatchStart = ovector[0]; MarkedArgumentBuffer args; for (unsigned i = 0; i < regExp->numSubpatterns() + 1; ++i) { @@ -597,7 +587,7 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS args.append(jsSubstring(exec, source, matchStart, matchLen)); } - args.append(jsNumber(completeMatchStart)); + args.append(jsNumber(result.start)); args.append(string); replacements.append(call(exec, replaceValue, callType, callData, jsUndefined(), args).toString(exec)->value(exec)); @@ -605,8 +595,8 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS break; } else { int replLen = replacementString.length(); - if (lastIndex < matchIndex || replLen) { - sourceRanges.append(StringRange(lastIndex, matchIndex - lastIndex)); + if (lastIndex < result.start || replLen) { + sourceRanges.append(StringRange(lastIndex, result.start - lastIndex)); if (replLen) replacements.append(substituteBackreferences(replacementString, source, ovector, regExp)); @@ -615,11 +605,11 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS } } - lastIndex = matchIndex + matchLen; + lastIndex = result.end; startPosition = lastIndex; // special case of empty match - if (!matchLen) { + if (result.empty()) { startPosition++; if (startPosition > sourceLen) break; @@ -636,22 +626,24 @@ static NEVER_INLINE EncodedJSValue replaceUsingRegExpSearch(ExecState* exec, JSS return JSValue::encode(jsSpliceSubstringsWithSeparators(exec, string, source, sourceRanges.data(), sourceRanges.size(), replacements.data(), replacements.size())); } -static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSString* jsString, JSValue searchValue, JSValue replaceValue) +static inline EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSString* jsString, JSValue searchValue) { const UString& string = jsString->value(exec); - UString searchString = searchValue.toString(exec)->value(exec); + UString searchString = searchValue.toUString(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); size_t matchStart = string.find(searchString); + if (matchStart == notFound) return JSValue::encode(jsString); + JSValue replaceValue = exec->argument(1); CallData callData; CallType callType = getCallData(replaceValue, callData); if (callType != CallTypeNone) { MarkedArgumentBuffer args; - args.append(jsSubstring(exec, string, matchStart, searchString.length())); + args.append(jsSubstring(exec, string, matchStart, searchString.impl()->length())); args.append(jsNumber(matchStart)); args.append(jsString); replaceValue = call(exec, replaceValue, callType, callData, jsUndefined(), args); @@ -659,13 +651,20 @@ static NEVER_INLINE EncodedJSValue replaceUsingStringSearch(ExecState* exec, JSS return JSValue::encode(jsUndefined()); } - UString replaceString = replaceValue.toString(exec)->value(exec); + UString replaceString = replaceValue.toUString(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); - size_t matchEnd = matchStart + searchString.length(); + StringImpl* stringImpl = string.impl(); + UString leftPart(StringImpl::create(stringImpl, 0, matchStart)); + + size_t matchEnd = matchStart + searchString.impl()->length(); int ovector[2] = { matchStart, matchEnd}; - return JSValue::encode(JSC::jsString(exec, string.substringSharingImpl(0, matchStart), substituteBackreferences(replaceString, string, ovector, 0), string.substringSharingImpl(matchEnd))); + UString middlePart = substituteBackreferences(replaceString, string, ovector, 0); + + size_t leftLength = stringImpl->length() - matchEnd; + UString rightPart(StringImpl::create(stringImpl, matchEnd, leftLength)); + return JSValue::encode(JSC::jsString(exec, leftPart, middlePart, rightPart)); } EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) @@ -675,11 +674,10 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncReplace(ExecState* exec) return throwVMTypeError(exec); JSString* string = thisValue.toString(exec); JSValue searchValue = exec->argument(0); - JSValue replaceValue = exec->argument(1); if (searchValue.inherits(&RegExpObject::s_info)) - return replaceUsingRegExpSearch(exec, string, searchValue, replaceValue); - return replaceUsingStringSearch(exec, string, searchValue, replaceValue); + return replaceUsingRegExpSearch(exec, string, searchValue); + return replaceUsingStringSearch(exec, string, searchValue); } EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState* exec) @@ -756,26 +754,30 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState* exec) if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); UString s = thisValue.toString(exec)->value(exec); - int len = s.length(); JSValue a0 = exec->argument(0); JSValue a1 = exec->argument(1); UString u2 = a0.toString(exec)->value(exec); - int pos; + + size_t result; if (a1.isUndefined()) - pos = 0; - else if (a1.isUInt32()) - pos = min<uint32_t>(a1.asUInt32(), len); + result = s.find(u2); else { - double dpos = a1.toInteger(exec); - if (dpos < 0) - dpos = 0; - else if (dpos > len) - dpos = len; - pos = static_cast<int>(dpos); + unsigned pos; + int len = s.length(); + if (a1.isUInt32()) + pos = min<uint32_t>(a1.asUInt32(), len); + else { + double dpos = a1.toInteger(exec); + if (dpos < 0) + dpos = 0; + else if (dpos > len) + dpos = len; + pos = static_cast<unsigned>(dpos); + } + result = s.find(u2, pos); } - size_t result = s.find(u2, pos); if (result == notFound) return JSValue::encode(jsNumber(-1)); return JSValue::encode(jsNumber(result)); @@ -810,17 +812,18 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec)->value(exec); + JSString* string = thisValue.toString(exec); + UString s = string->value(exec); JSGlobalData* globalData = &exec->globalData(); JSValue a0 = exec->argument(0); - RegExp* reg; + RegExp* regExp; bool global = false; if (a0.inherits(&RegExpObject::s_info)) { RegExpObject* regExpObject = asRegExpObject(a0); - reg = regExpObject->regExp(); - if ((global = reg->global())) { + regExp = regExpObject->regExp(); + if ((global = regExp->global())) { // ES5.1 15.5.4.10 step 8.a. regExpObject->setLastIndex(exec, 0); if (exec->hadException()) @@ -833,27 +836,25 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncMatch(ExecState* exec) * replaced with the result of the expression new RegExp(regexp). * Per ECMA 15.10.4.1, if a0 is undefined substitute the empty string. */ - reg = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags); - if (!reg->isValid()) - return throwVMError(exec, createSyntaxError(exec, reg->errorMessage())); + regExp = RegExp::create(exec->globalData(), a0.isUndefined() ? UString("") : a0.toString(exec)->value(exec), NoFlags); + if (!regExp->isValid()) + return throwVMError(exec, createSyntaxError(exec, regExp->errorMessage())); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); - int pos; - int matchLength = 0; - regExpConstructor->performMatch(*globalData, reg, s, 0, pos, matchLength); - if (!global) { - // case without 'g' flag is handled like RegExp.prototype.exec - if (pos < 0) - return JSValue::encode(jsNull()); - return JSValue::encode(regExpConstructor->arrayOfMatches(exec)); - } + MatchResult result = regExpConstructor->performMatch(*globalData, regExp, string, s, 0); + // case without 'g' flag is handled like RegExp.prototype.exec + if (!global) + return JSValue::encode(result ? RegExpMatchesArray::create(exec, string, regExp, result) : jsNull()); // return array of matches MarkedArgumentBuffer list; - while (pos >= 0) { - list.append(jsSubstring(exec, s, pos, matchLength)); - pos += matchLength == 0 ? 1 : matchLength; - regExpConstructor->performMatch(*globalData, reg, s, pos, pos, matchLength); + while (result) { + size_t end = result.end; + size_t length = end - result.start; + list.append(jsSubstring(exec, s, result.start, length)); + if (!length) + ++end; + result = regExpConstructor->performMatch(*globalData, regExp, string, s, end); } if (list.isEmpty()) { // if there are no matches at all, it's important to return @@ -870,7 +871,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) JSValue thisValue = exec->hostThisValue(); if (thisValue.isUndefinedOrNull()) // CheckObjectCoercible return throwVMTypeError(exec); - UString s = thisValue.toString(exec)->value(exec); + JSString* string = thisValue.toString(exec); + UString s = string->value(exec); JSGlobalData* globalData = &exec->globalData(); JSValue a0 = exec->argument(0); @@ -890,10 +892,8 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSearch(ExecState* exec) return throwVMError(exec, createSyntaxError(exec, reg->errorMessage())); } RegExpConstructor* regExpConstructor = exec->lexicalGlobalObject()->regExpConstructor(); - int pos; - int matchLength = 0; - regExpConstructor->performMatch(*globalData, reg, s, 0, pos, matchLength); - return JSValue::encode(jsNumber(pos)); + MatchResult result = regExpConstructor->performMatch(*globalData, reg, string, s, 0); + return JSValue::encode(result ? jsNumber(result.start) : jsNumber(-1)); } EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec) @@ -923,6 +923,35 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSlice(ExecState* exec) return JSValue::encode(jsEmptyString(exec)); } +// Return true in case of early return (resultLength got to limitLength). +template<typename CharacterType> +static ALWAYS_INLINE bool splitStringByOneCharacterImpl(ExecState* exec, JSArray* result, const UString& input, StringImpl* string, UChar separatorCharacter, size_t& position, unsigned& resultLength, unsigned limitLength) +{ + // 12. Let q = p. + size_t matchPosition; + const CharacterType* characters = string->getCharacters<CharacterType>(); + // 13. Repeat, while q != s + // a. Call SplitMatch(S, q, R) and let z be its MatchResult result. + // b. If z is failure, then let q = q+1. + // c. Else, z is not failure + while ((matchPosition = WTF::find(characters, string->length(), separatorCharacter, position)) != notFound) { + // 1. Let T be a String value equal to the substring of S consisting of the characters at positions p (inclusive) + // through q (exclusive). + // 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA), + // Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. + result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false); + // 3. Increment lengthA by 1. + // 4. If lengthA == lim, return A. + if (++resultLength == limitLength) + return true; + + // 5. Let p = e. + // 8. Let q = p. + position = matchPosition + 1; + } + return false; +} + // ES 5.1 - 15.5.4.14 String.prototype.split (separator, limit) EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) { @@ -976,7 +1005,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) // c. Call the [[DefineOwnProperty]] internal method of A with arguments "0", // Property Descriptor {[[Value]]: S, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. // d. Return A. - if (reg->match(*globalData, input, 0) < 0) + if (!reg->match(*globalData, input, 0)) result->putDirectIndex(exec, 0, jsStringWithReuse(exec, thisValue, input), false); return JSValue::encode(result); } @@ -987,7 +1016,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) while (matchPosition < input.length()) { // a. Call SplitMatch(S, q, R) and let z be its MatchResult result. Vector<int, 32> ovector; - int mpos = reg->match(*globalData, input, matchPosition, &ovector); + int mpos = reg->match(*globalData, input, matchPosition, ovector); // b. If z is failure, then let q = q + 1. if (mpos < 0) break; @@ -1076,26 +1105,50 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSplit(ExecState* exec) return JSValue::encode(result); } - // 12. Let q = p. - size_t matchPosition; - // 13. Repeat, while q != s - // a. Call SplitMatch(S, q, R) and let z be its MatchResult result. - // b. If z is failure, then let q = q+1. - // c. Else, z is not failure - while ((matchPosition = input.find(separator, position)) != notFound) { - // 1. Let T be a String value equal to the substring of S consisting of the characters at positions p (inclusive) - // through q (exclusive). - // 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA), - // Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. - result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false); - // 3. Increment lengthA by 1. - // 4. If lengthA == lim, return A. - if (++resultLength == limit) - return JSValue::encode(result); + // 3 cases: + // -separator length == 1, 8 bits + // -separator length == 1, 16 bits + // -separator length > 1 + StringImpl* stringImpl = input.impl(); + StringImpl* separatorImpl = separator.impl(); + size_t separatorLength = separatorImpl->length(); + + if (separatorLength == 1) { + UChar separatorCharacter; + if (separatorImpl->is8Bit()) + separatorCharacter = separatorImpl->characters8()[0]; + else + separatorCharacter = separatorImpl->characters16()[0]; + + if (stringImpl->is8Bit()) { + if (splitStringByOneCharacterImpl<LChar>(exec, result, input, stringImpl, separatorCharacter, position, resultLength, limit)) + return JSValue::encode(result); + } else { + if (splitStringByOneCharacterImpl<UChar>(exec, result, input, stringImpl, separatorCharacter, position, resultLength, limit)) + return JSValue::encode(result); + } + } else { + // 12. Let q = p. + size_t matchPosition; + // 13. Repeat, while q != s + // a. Call SplitMatch(S, q, R) and let z be its MatchResult result. + // b. If z is failure, then let q = q+1. + // c. Else, z is not failure + while ((matchPosition = stringImpl->find(separatorImpl, position)) != notFound) { + // 1. Let T be a String value equal to the substring of S consisting of the characters at positions p (inclusive) + // through q (exclusive). + // 2. Call the [[DefineOwnProperty]] internal method of A with arguments ToString(lengthA), + // Property Descriptor {[[Value]]: T, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true}, and false. + result->putDirectIndex(exec, resultLength, jsSubstring(exec, input, position, matchPosition - position), false); + // 3. Increment lengthA by 1. + // 4. If lengthA == lim, return A. + if (++resultLength == limit) + return JSValue::encode(result); - // 5. Let p = e. - // 8. Let q = p. - position = matchPosition + separator.length(); + // 5. Let p = e. + // 8. Let q = p. + position = matchPosition + separator.length(); + } } } @@ -1116,7 +1169,7 @@ EncodedJSValue JSC_HOST_CALL stringProtoFuncSubstr(ExecState* exec) JSString* jsString = 0; UString uString; if (thisValue.isString()) { - jsString = static_cast<JSString*>(thisValue.asCell()); + jsString = jsCast<JSString*>(thisValue.asCell()); len = jsString->length(); } else if (thisValue.isUndefinedOrNull()) { // CheckObjectCoercible diff --git a/Source/JavaScriptCore/runtime/StringRecursionChecker.h b/Source/JavaScriptCore/runtime/StringRecursionChecker.h index e3408b08b..127d028e0 100644 --- a/Source/JavaScriptCore/runtime/StringRecursionChecker.h +++ b/Source/JavaScriptCore/runtime/StringRecursionChecker.h @@ -48,7 +48,7 @@ inline JSValue StringRecursionChecker::performCheck() int size = m_exec->globalData().stringRecursionCheckVisitedObjects.size(); if (size >= MaxSmallThreadReentryDepth && size >= m_exec->globalData().maxReentryDepth) return throwStackOverflowError(); - bool alreadyVisited = !m_exec->globalData().stringRecursionCheckVisitedObjects.add(m_thisObject).second; + bool alreadyVisited = !m_exec->globalData().stringRecursionCheckVisitedObjects.add(m_thisObject).isNewEntry; if (alreadyVisited) return emptyString(); // Return empty string to avoid infinite recursion. return JSValue(); // Indicate success. diff --git a/Source/JavaScriptCore/runtime/Structure.cpp b/Source/JavaScriptCore/runtime/Structure.cpp index 6ee419da6..074c8b354 100644 --- a/Source/JavaScriptCore/runtime/Structure.cpp +++ b/Source/JavaScriptCore/runtime/Structure.cpp @@ -102,12 +102,12 @@ inline void StructureTransitionTable::add(JSGlobalData& globalData, Structure* s // Newer versions of the STL have an std::make_pair function that takes rvalue references. // When either of the parameters are bitfields, the C++ compiler will try to bind them as lvalues, which is invalid. To work around this, use unary "+" to make the parameter an rvalue. // See https://bugs.webkit.org/show_bug.cgi?id=59261 for more details - std::pair<TransitionMap::iterator, bool> result = map()->add(globalData, make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure); - if (!result.second) { + TransitionMap::AddResult result = map()->add(globalData, make_pair(structure->m_nameInPrevious, +structure->m_attributesInPrevious), structure); + if (!result.isNewEntry) { // There already is an entry! - we should only hit this when despecifying. - ASSERT(result.first.get().second->m_specificValueInPrevious); + ASSERT(result.iterator.get().second->m_specificValueInPrevious); ASSERT(!structure->m_specificValueInPrevious); - map()->set(result.first, structure); + map()->set(globalData, result.iterator.get().first, structure); } } @@ -267,6 +267,13 @@ void Structure::growPropertyStorageCapacity() m_propertyStorageCapacity *= 2; } +size_t Structure::suggestedNewPropertyStorageSize() +{ + if (isUsingInlineStorage()) + return JSObject::baseExternalStorageCapacity; + return m_propertyStorageCapacity * 2; +} + void Structure::despecifyDictionaryFunction(JSGlobalData& globalData, const Identifier& propertyName) { StringImpl* rep = propertyName.impl(); @@ -787,6 +794,8 @@ void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor) visitor.append(&ptr->specificValue); } } + if (thisObject->m_objectToStringValue) + visitor.append(&thisObject->m_objectToStringValue); } #if DO_PROPERTYMAP_CONSTENCY_CHECK diff --git a/Source/JavaScriptCore/runtime/Structure.h b/Source/JavaScriptCore/runtime/Structure.h index 46cf732e1..00bc76177 100644 --- a/Source/JavaScriptCore/runtime/Structure.h +++ b/Source/JavaScriptCore/runtime/Structure.h @@ -50,6 +50,7 @@ namespace JSC { class PropertyNameArrayData; class StructureChain; class SlotVisitor; + class JSString; class Structure : public JSCell { public: @@ -101,6 +102,8 @@ namespace JSC { bool isFrozen(JSGlobalData&); bool isExtensible() const { return !m_preventExtensions; } bool didTransition() const { return m_didTransition; } + bool shouldGrowPropertyStorage() { return propertyStorageCapacity() == propertyStorageSize(); } + JS_EXPORT_PRIVATE size_t suggestedNewPropertyStorageSize(); Structure* flattenDictionaryStructure(JSGlobalData&, JSObject*); @@ -169,6 +172,13 @@ namespace JSC { JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h. void getPropertyNamesFromStructure(JSGlobalData&, PropertyNameArray&, EnumerationMode); + JSString* objectToStringValue() { return m_objectToStringValue.get(); } + + void setObjectToStringValue(JSGlobalData& globalData, const JSCell* owner, JSString* value) + { + m_objectToStringValue.set(globalData, owner, value); + } + bool staticFunctionsReified() { return m_staticFunctionReified; @@ -289,6 +299,8 @@ namespace JSC { uint32_t m_propertyStorageCapacity; + WriteBarrier<JSString> m_objectToStringValue; + // m_offset does not account for anonymous slots int m_offset; @@ -406,7 +418,7 @@ namespace JSC { { #if ENABLE(GC_VALIDATION) ASSERT(globalData.isInitializingObject()); - globalData.setInitializingObject(false); + globalData.setInitializingObjectClass(0); if (structure) #endif m_structure.setEarlyValue(globalData, this, structure); diff --git a/Source/JavaScriptCore/runtime/StructureTransitionTable.h b/Source/JavaScriptCore/runtime/StructureTransitionTable.h index 517992470..2067a8995 100644 --- a/Source/JavaScriptCore/runtime/StructureTransitionTable.h +++ b/Source/JavaScriptCore/runtime/StructureTransitionTable.h @@ -34,6 +34,7 @@ namespace JSC { +class JSCell; class Structure; class StructureTransitionTable { @@ -83,10 +84,10 @@ public: return; } - HandleSlot slot = this->slot(); - if (!slot) + WeakImpl* impl = this->weakImpl(); + if (!impl) return; - HandleHeap::heapFor(slot)->deallocate(slot); + WeakSet::deallocate(impl); } inline void add(JSGlobalData&, Structure*); @@ -105,18 +106,18 @@ private: return reinterpret_cast<TransitionMap*>(m_data); } - HandleSlot slot() const + WeakImpl* weakImpl() const { ASSERT(isUsingSingleSlot()); - return reinterpret_cast<HandleSlot>(m_data & ~UsingSingleSlotFlag); + return reinterpret_cast<WeakImpl*>(m_data & ~UsingSingleSlotFlag); } void setMap(TransitionMap* map) { ASSERT(isUsingSingleSlot()); - if (HandleSlot slot = this->slot()) - HandleHeap::heapFor(slot)->deallocate(slot); + if (WeakImpl* impl = this->weakImpl()) + WeakSet::deallocate(impl); // This implicitly clears the flag that indicates we're using a single transition m_data = reinterpret_cast<intptr_t>(map); @@ -127,24 +128,20 @@ private: Structure* singleTransition() const { ASSERT(isUsingSingleSlot()); - if (HandleSlot slot = this->slot()) { - if (*slot) - return reinterpret_cast<Structure*>(slot->asCell()); + if (WeakImpl* impl = this->weakImpl()) { + if (impl->state() == WeakImpl::Live) + return reinterpret_cast<Structure*>(impl->jsValue().asCell()); } return 0; } - void setSingleTransition(JSGlobalData& globalData, Structure* structure) + void setSingleTransition(JSGlobalData&, Structure* structure) { ASSERT(isUsingSingleSlot()); - HandleSlot slot = this->slot(); - if (!slot) { - slot = globalData.heap.handleHeap()->allocate(); - HandleHeap::heapFor(slot)->makeWeak(slot, 0, 0); - m_data = reinterpret_cast<intptr_t>(slot) | UsingSingleSlotFlag; - } - HandleHeap::heapFor(slot)->writeBarrier(slot, reinterpret_cast<JSCell*>(structure)); - *slot = reinterpret_cast<JSCell*>(structure); + if (WeakImpl* impl = this->weakImpl()) + WeakSet::deallocate(impl); + WeakImpl* impl = WeakSet::allocate(reinterpret_cast<JSCell*>(structure)); + m_data = reinterpret_cast<intptr_t>(impl) | UsingSingleSlotFlag; } intptr_t m_data; diff --git a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp index 3065c99ed..8f3d1a578 100644 --- a/Source/JavaScriptCore/runtime/TimeoutChecker.cpp +++ b/Source/JavaScriptCore/runtime/TimeoutChecker.cpp @@ -38,7 +38,7 @@ #elif OS(WINDOWS) #include <windows.h> #else -#include "CurrentTime.h" +#include <wtf/CurrentTime.h> #endif using namespace std; diff --git a/Source/JavaScriptCore/runtime/UString.h b/Source/JavaScriptCore/runtime/UString.h index 668eb0489..7677161a3 100644 --- a/Source/JavaScriptCore/runtime/UString.h +++ b/Source/JavaScriptCore/runtime/UString.h @@ -121,8 +121,12 @@ public: // Find a single character or string, also with match function & latin1 forms. size_t find(UChar c, unsigned start = 0) const { return m_impl ? m_impl->find(c, start) : notFound; } - size_t find(const UString& str, unsigned start = 0) const + + size_t find(const UString& str) const + { return m_impl ? m_impl->find(str.impl()) : notFound; } + size_t find(const UString& str, unsigned start) const { return m_impl ? m_impl->find(str.impl(), start) : notFound; } + size_t find(const LChar* str, unsigned start = 0) const { return m_impl ? m_impl->find(str, start) : notFound; } diff --git a/Source/JavaScriptCore/runtime/WeakGCMap.h b/Source/JavaScriptCore/runtime/WeakGCMap.h index 1bb3cd5bb..ec010fb4b 100644 --- a/Source/JavaScriptCore/runtime/WeakGCMap.h +++ b/Source/JavaScriptCore/runtime/WeakGCMap.h @@ -51,7 +51,7 @@ class WeakGCMap : private WeakHandleOwner { WTF_MAKE_FAST_ALLOCATED; WTF_MAKE_NONCOPYABLE(WeakGCMap); - typedef HashMap<KeyType, HandleSlot, HashArg, KeyTraitsArg> MapType; + typedef HashMap<KeyType, WeakImpl*, HashArg, KeyTraitsArg> MapType; typedef typename HandleTypes<MappedType>::ExternalType ExternalType; typedef typename MapType::iterator map_iterator; @@ -64,8 +64,7 @@ public: { } - std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(m_iterator->second)); } - std::pair<KeyType, HandleSlot> getSlot() const { return *m_iterator; } + std::pair<KeyType, ExternalType> get() const { return std::make_pair(m_iterator->first, HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&m_iterator->second->jsValue()))); } iterator& operator++() { ++m_iterator; return *this; } @@ -79,6 +78,8 @@ public: map_iterator m_iterator; }; + typedef WTF::HashTableAddResult<iterator> AddResult; + WeakGCMap() { } @@ -88,7 +89,7 @@ public: { map_iterator end = m_map.end(); for (map_iterator ptr = m_map.begin(); ptr != end; ++ptr) - HandleHeap::heapFor(ptr->second)->deallocate(ptr->second); + WeakSet::deallocate(ptr->second); m_map.clear(); } @@ -105,63 +106,42 @@ public: void remove(iterator iter) { ASSERT(iter.m_iterator != m_map.end()); - HandleSlot slot = iter.m_iterator->second; - ASSERT(slot); - HandleHeap::heapFor(slot)->deallocate(slot); + WeakImpl* impl = iter.m_iterator->second; + ASSERT(impl); + WeakSet::deallocate(impl); m_map.remove(iter.m_iterator); } ExternalType get(const KeyType& key) const { - return HandleTypes<MappedType>::getFromSlot(m_map.get(key)); + return HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&m_map.get(key)->jsValue())); } - HandleSlot getSlot(const KeyType& key) const + AddResult add(JSGlobalData&, const KeyType& key, ExternalType value) { - return m_map.get(key); - } + typename MapType::AddResult result = m_map.add(key, 0); + if (result.isNewEntry) + result.iterator->second = WeakSet::allocate(value, this, FinalizerCallback::finalizerContextFor(key)); - pair<iterator, bool> add(JSGlobalData& globalData, const KeyType& key, ExternalType value) - { - pair<typename MapType::iterator, bool> iter = m_map.add(key, 0); - if (iter.second) { - HandleSlot slot = globalData.heap.handleHeap()->allocate(); - iter.first->second = slot; - HandleHeap::heapFor(slot)->makeWeak(slot, this, FinalizerCallback::finalizerContextFor(key)); - HandleHeap::heapFor(slot)->writeBarrier(slot, value); - *slot = value; - } - return iter; - } - - void set(iterator iter, ExternalType value) - { - HandleSlot slot = iter.m_iterator->second; - ASSERT(slot); - HandleHeap::heapFor(slot)->writeBarrier(slot, value); - *slot = value; + // WeakGCMap exposes a different iterator, so we need to wrap it and create our own AddResult. + return AddResult(iterator(result.iterator), result.isNewEntry); } - void set(JSGlobalData& globalData, const KeyType& key, ExternalType value) + void set(JSGlobalData&, const KeyType& key, ExternalType value) { - pair<typename MapType::iterator, bool> iter = m_map.add(key, 0); - HandleSlot slot = iter.first->second; - if (iter.second) { - slot = globalData.heap.handleHeap()->allocate(); - HandleHeap::heapFor(slot)->makeWeak(slot, this, key); - iter.first->second = slot; - } - HandleHeap::heapFor(slot)->writeBarrier(slot, value); - *slot = value; + typename MapType::AddResult result = m_map.add(key, 0); + if (!result.isNewEntry) + WeakSet::deallocate(result.iterator->second); + result.iterator->second = WeakSet::allocate(value, this, FinalizerCallback::finalizerContextFor(key)); } ExternalType take(const KeyType& key) { - HandleSlot slot = m_map.take(key); - if (!slot) + WeakImpl* impl = m_map.take(key); + if (!impl) return HashTraits<ExternalType>::emptyValue(); - ExternalType result = HandleTypes<MappedType>::getFromSlot(slot); - HandleHeap::heapFor(slot)->deallocate(slot); + ExternalType result = HandleTypes<MappedType>::getFromSlot(const_cast<JSValue*>(&impl->jsValue())); + WeakSet::deallocate(impl); return result; } @@ -178,9 +158,9 @@ public: private: virtual void finalize(Handle<Unknown> handle, void* context) { - HandleSlot slot = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot()))); - ASSERT(slot); - HandleHeap::heapFor(slot)->deallocate(slot); + WeakImpl* impl = m_map.take(FinalizerCallback::keyForFinalizer(context, HandleTypes<MappedType>::getFromSlot(handle.slot()))); + ASSERT(impl); + WeakSet::deallocate(impl); } MapType m_map; diff --git a/Source/JavaScriptCore/shell/CMakeLists.txt b/Source/JavaScriptCore/shell/CMakeLists.txt index b9d64dbae..85ad89a88 100644 --- a/Source/JavaScriptCore/shell/CMakeLists.txt +++ b/Source/JavaScriptCore/shell/CMakeLists.txt @@ -3,6 +3,7 @@ SET(JSC_SOURCES ) SET(JSC_LIBRARIES + ${WTF_LIBRARY_NAME} ${JavaScriptCore_LIBRARY_NAME} ) @@ -12,6 +13,7 @@ WEBKIT_WRAP_SOURCELIST(${JSC_SOURCES}) INCLUDE_DIRECTORIES(./ ${JavaScriptCore_INCLUDE_DIRECTORIES}) ADD_EXECUTABLE(${JSC_EXECUTABLE_NAME} ${JSC_SOURCES}) TARGET_LINK_LIBRARIES(${JSC_EXECUTABLE_NAME} ${JSC_LIBRARIES}) +SET_TARGET_PROPERTIES(${JSC_EXECUTABLE_NAME} PROPERTIES FOLDER "JavaScriptCore") IF (JSC_LINK_FLAGS) ADD_TARGET_PROPERTIES(${JSC_EXECUTABLE_NAME} LINK_FLAGS "${JSC_LINK_FLAGS}") diff --git a/Source/JavaScriptCore/testRegExp.cpp b/Source/JavaScriptCore/testRegExp.cpp index bbea4c8a2..6899ac284 100644 --- a/Source/JavaScriptCore/testRegExp.cpp +++ b/Source/JavaScriptCore/testRegExp.cpp @@ -21,7 +21,7 @@ #include "config.h" #include "RegExp.h" -#include "CurrentTime.h" +#include <wtf/CurrentTime.h> #include "InitializeThreading.h" #include "JSGlobalObject.h" #include "UStringBuilder.h" @@ -54,8 +54,6 @@ const int MaxLineLength = 100 * 1024; using namespace JSC; using namespace WTF; -static void cleanupGlobalData(JSGlobalData*); - struct CommandLine { CommandLine() : interactive(false) @@ -159,7 +157,7 @@ GlobalObject::GlobalObject(JSGlobalData& globalData, Structure* structure, const #define EXCEPT(x) #endif -int realMain(int argc, char** argv, JSGlobalData*); +int realMain(int argc, char** argv); int main(int argc, char** argv) { @@ -193,29 +191,18 @@ 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(ThreadStackTypeLarge, LargeHeap).leakRef(); TRY - res = realMain(argc, argv, globalData); + res = realMain(argc, argv); EXCEPT(res = 3) - - cleanupGlobalData(globalData); return res; } -static void cleanupGlobalData(JSGlobalData* globalData) -{ - JSLock lock(SilenceAssertionsOnly); - globalData->clearBuiltinStructures(); - globalData->heap.destroy(); - globalData->deref(); -} - static bool testOneRegExp(JSGlobalData& globalData, RegExp* regexp, RegExpTest* regExpTest, bool verbose, unsigned int lineNumber) { bool result = true; Vector<int, 32> outVector; outVector.resize(regExpTest->expectVector.size()); - int matchResult = regexp->match(globalData, regExpTest->subject, regExpTest->offset, &outVector); + int matchResult = regexp->match(globalData, regExpTest->subject, regExpTest->offset, outVector); if (matchResult != regExpTest->result) { result = false; @@ -480,23 +467,22 @@ static bool runFromFiles(GlobalObject* globalObject, const Vector<UString>& file #define RUNNING_FROM_XCODE 0 -static NO_RETURN void printUsageStatement(JSGlobalData* globalData, bool help = false) +static NO_RETURN void printUsageStatement(bool help = false) { fprintf(stderr, "Usage: regexp_test [options] file\n"); fprintf(stderr, " -h|--help Prints this help message\n"); fprintf(stderr, " -v|--verbose Verbose output\n"); - cleanupGlobalData(globalData); exit(help ? EXIT_SUCCESS : EXIT_FAILURE); } -static void parseArguments(int argc, char** argv, CommandLine& options, JSGlobalData* globalData) +static void parseArguments(int argc, char** argv, CommandLine& options) { int i = 1; for (; i < argc; ++i) { const char* arg = argv[i]; if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) - printUsageStatement(globalData, true); + printUsageStatement(true); if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose")) options.verbose = true; else @@ -507,12 +493,14 @@ static void parseArguments(int argc, char** argv, CommandLine& options, JSGlobal options.arguments.append(argv[i]); } -int realMain(int argc, char** argv, JSGlobalData* globalData) +int realMain(int argc, char** argv) { JSLock lock(SilenceAssertionsOnly); + RefPtr<JSGlobalData> globalData = JSGlobalData::create(ThreadStackTypeLarge, LargeHeap); + CommandLine options; - parseArguments(argc, argv, options, globalData); + parseArguments(argc, argv, options); GlobalObject* globalObject = GlobalObject::create(*globalData, GlobalObject::createStructure(*globalData, jsNull()), options.arguments); bool success = runFromFiles(globalObject, options.files, options.verbose); diff --git a/Source/JavaScriptCore/tests/mozilla/expected.html b/Source/JavaScriptCore/tests/mozilla/expected.html index 7dd958b98..2283f77b5 100644 --- a/Source/JavaScriptCore/tests/mozilla/expected.html +++ b/Source/JavaScriptCore/tests/mozilla/expected.html @@ -6,90 +6,83 @@ <h2>Test results, squirrelfish</h2><br> <p class='results_summary'> Test List: All tests<br> -Skip List: ecma/Date/15.9.2.1.js, ecma/Date/15.9.2.2-1.js, ecma/Date/15.9.2.2-2.js, ecma/Date/15.9.2.2-3.js, ecma/Date/15.9.2.2-4.js, ecma/Date/15.9.2.2-5.js, ecma/Date/15.9.2.2-6.js, ecma_3/Date/15.9.5.7.js<br> -1127 test(s) selected, 1119 test(s) completed, 51 failures reported (4.55% failed)<br> -Engine command line: "/Volumes/BigData/git/WebKit/WebKitBuild/Debug/jsc" <br> -OS type: Darwin 10.6.0 Darwin Kernel Version 10.6.0: Wed Nov 10 18:13:17 PST 2010; root:xnu-1504.9.26~3/RELEASE_I386 i386<br> -Testcase execution time: 1 minutes, 3 seconds.<br> -Tests completed on Wed Jan 19 13:26:57 2011.<br><br> +Skip List: ecma/Date/15.9.2.1.js, ecma/Date/15.9.2.2-1.js, ecma/Date/15.9.2.2-2.js, ecma/Date/15.9.2.2-3.js, ecma/Date/15.9.2.2-4.js, ecma/Date/15.9.2.2-5.js, ecma/Date/15.9.2.2-6.js, ecma_3/Date/15.9.5.7.js, ecma/Date/15.9.5.14.js, ecma/Date/15.9.5.31-1.js, ecma/Date/15.9.5.34-1.js<br> +1124 test(s) selected, 1116 test(s) completed, 46 failures reported (4.12% failed)<br> +Engine command line: "/Volumes/Big/ggaren/webkit/WebKitBuild/Debug/jsc" <br> +OS type: Darwin garen.apple.com 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64<br> +Testcase execution time: 1 minutes, 8 seconds.<br> +Tests completed on Tue Apr 3 22:31:56 2012.<br><br> [ <a href='#fail_detail'>Failure Details</a> | <a href='#retest_list'>Retest List</a> | <a href='menu.html'>Test Selection Page</a> ]<br> <hr> <a name='fail_detail'></a> <h2>Failure Details</h2><br> -<dl><a name='failure1'></a><dd><b>Testcase <a target='other_window' href='./ecma/TypeConversion/9.3.1-3.js'>ecma/TypeConversion/9.3.1-3.js</a> failed</b> <br> +<dl><a name='failure1'></a><dd><b>Testcase <a target='other_window' href='./ecma_2/Exceptions/function-001.js'>ecma_2/Exceptions/function-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br> [ <a href='#failure2'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt><br> Failure messages were:<br> -- "-0x123456789abcde8" = NaN FAILED! expected: 81985529216486880<br> -- "-0x123456789abcde8" = NaN FAILED! expected: 81985529216486880<br> -</tt><br> -<a name='failure2'></a><dd><b>Testcase <a target='other_window' href='./ecma_2/Exceptions/function-001.js'>ecma_2/Exceptions/function-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br> - [ <a href='#failure1'>Previous Failure</a> | <a href='#failure3'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> -<tt><br> -Failure messages were:<br> eval("function f(){}function g(){}") (threw no exception thrown = fail FAILED! expected: pass<br> </tt><br> -<a name='failure3'></a><dd><b>Testcase <a target='other_window' href='./ecma_2/RegExp/regress-001.js'>ecma_2/RegExp/regress-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=http://bugzilla.mozilla.org/show_bug.cgi?id=2157' target='other_window'>Bug Number http://bugzilla.mozilla.org/show_bug.cgi?id=2157</a><br> - [ <a href='#failure2'>Previous Failure</a> | <a href='#failure4'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure2'></a><dd><b>Testcase <a target='other_window' href='./ecma_2/RegExp/regress-001.js'>ecma_2/RegExp/regress-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=http://bugzilla.mozilla.org/show_bug.cgi?id=2157' target='other_window'>Bug Number http://bugzilla.mozilla.org/show_bug.cgi?id=2157</a><br> + [ <a href='#failure1'>Previous Failure</a> | <a href='#failure3'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> RegExp/hex-001.js JS regexp anchoring on empty match bug<br> BUGNUMBER: http://bugzilla.mozilla.org/show_bug.cgi?id=2157<br> </tt><br> -<a name='failure4'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/FunExpr/fe-001.js'>ecma_3/FunExpr/fe-001.js</a> failed</b> <br> - [ <a href='#failure3'>Previous Failure</a> | <a href='#failure5'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure3'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/FunExpr/fe-001.js'>ecma_3/FunExpr/fe-001.js</a> failed</b> <br> + [ <a href='#failure2'>Previous Failure</a> | <a href='#failure4'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>STATUS: Function Expression Statements basic test.<br> Failure messages were:<br> FAILED!: [reported from test()] Both functions were defined.<br> FAILED!: [reported from test()] Expected value '1', Actual value '0'<br> FAILED!: [reported from test()] <br> </tt><br> -<a name='failure5'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Statements/regress-194364.js'>ecma_3/Statements/regress-194364.js</a> failed</b> <br> - [ <a href='#failure4'>Previous Failure</a> | <a href='#failure6'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure4'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Statements/regress-194364.js'>ecma_3/Statements/regress-194364.js</a> failed</b> <br> + [ <a href='#failure3'>Previous Failure</a> | <a href='#failure5'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure6'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Unicode/uc-001.js'>ecma_3/Unicode/uc-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=23610' target='other_window'>Bug Number 23610</a><br> - [ <a href='#failure5'>Previous Failure</a> | <a href='#failure7'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure5'></a><dd><b>Testcase <a target='other_window' href='./ecma_3/Unicode/uc-001.js'>ecma_3/Unicode/uc-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=23610' target='other_window'>Bug Number 23610</a><br> + [ <a href='#failure4'>Previous Failure</a> | <a href='#failure6'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>STATUS: Unicode format-control character (Category Cf) test.<br> Failure messages were:<br> FAILED!: [reported from test()] Unicode format-control character test (Category Cf.)<br> FAILED!: [reported from test()] Expected value 'no error', Actual value 'no‎ error'<br> FAILED!: [reported from test()] <br> </tt><br> -<a name='failure7'></a><dd><b>Testcase <a target='other_window' href='./js1_2/Objects/toString-001.js'>js1_2/Objects/toString-001.js</a> failed</b> <br> - [ <a href='#failure6'>Previous Failure</a> | <a href='#failure8'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure6'></a><dd><b>Testcase <a target='other_window' href='./js1_2/Objects/toString-001.js'>js1_2/Objects/toString-001.js</a> failed</b> <br> + [ <a href='#failure5'>Previous Failure</a> | <a href='#failure7'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> JS1_2 Object.toString()<br> </tt><br> -<a name='failure8'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/Function_object.js'>js1_2/function/Function_object.js</a> failed</b> <br> - [ <a href='#failure7'>Previous Failure</a> | <a href='#failure9'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure7'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/Function_object.js'>js1_2/function/Function_object.js</a> failed</b> <br> + [ <a href='#failure6'>Previous Failure</a> | <a href='#failure8'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt><br> Failure messages were:<br> f.arity = undefined FAILED! expected: 3<br> } FAILED! expected: <br> </tt><br> -<a name='failure9'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/function-001-n.js'>js1_2/function/function-001-n.js</a> failed</b> <br> - [ <a href='#failure8'>Previous Failure</a> | <a href='#failure10'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure8'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/function-001-n.js'>js1_2/function/function-001-n.js</a> failed</b> <br> + [ <a href='#failure7'>Previous Failure</a> | <a href='#failure9'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 3, got 0<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> function-001.js functions not separated by semicolons are errors in version 120 and higher<br> eval("function f(){}function g(){}") = undefined FAILED! expected: error<br> </tt><br> -<a name='failure10'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/regexparg-1.js'>js1_2/function/regexparg-1.js</a> failed</b> <br> - [ <a href='#failure9'>Previous Failure</a> | <a href='#failure11'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure9'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/regexparg-1.js'>js1_2/function/regexparg-1.js</a> failed</b> <br> + [ <a href='#failure8'>Previous Failure</a> | <a href='#failure10'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> JS_1.2 The variable statment<br> </tt><br> -<a name='failure11'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-1.js'>js1_2/function/tostring-1.js</a> failed</b> <br> - [ <a href='#failure10'>Previous Failure</a> | <a href='#failure12'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure10'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-1.js'>js1_2/function/tostring-1.js</a> failed</b> <br> + [ <a href='#failure9'>Previous Failure</a> | <a href='#failure11'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt><br> Failure messages were:<br> } FAILED! expected: <br> @@ -98,8 +91,8 @@ Failure messages were:<br> } FAILED! expected: <br> } FAILED! expected: <br> </tt><br> -<a name='failure12'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-2.js'>js1_2/function/tostring-2.js</a> failed</b> <br> - [ <a href='#failure11'>Previous Failure</a> | <a href='#failure13'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure11'></a><dd><b>Testcase <a target='other_window' href='./js1_2/function/tostring-2.js'>js1_2/function/tostring-2.js</a> failed</b> <br> + [ <a href='#failure10'>Previous Failure</a> | <a href='#failure12'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt><br> Failure messages were:<br> } FAILED! expected: <br> @@ -112,76 +105,44 @@ Failure messages were:<br> } FAILED! expected: <br> } FAILED! expected: <br> </tt><br> -<a name='failure13'></a><dd><b>Testcase <a target='other_window' href='./js1_2/operator/equality.js'>js1_2/operator/equality.js</a> failed</b> <br> - [ <a href='#failure12'>Previous Failure</a> | <a href='#failure14'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure12'></a><dd><b>Testcase <a target='other_window' href='./js1_2/operator/equality.js'>js1_2/operator/equality.js</a> failed</b> <br> + [ <a href='#failure11'>Previous Failure</a> | <a href='#failure13'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt><br> Failure messages were:<br> (new String('x') == 'x') = true FAILED! expected: false<br> ('x' == new String('x')) = true FAILED! expected: false<br> </tt><br> -<a name='failure14'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_lastIndex.js'>js1_2/regexp/RegExp_lastIndex.js</a> failed</b> <br> - [ <a href='#failure13'>Previous Failure</a> | <a href='#failure15'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure13'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_lastIndex.js'>js1_2/regexp/RegExp_lastIndex.js</a> failed</b> <br> + [ <a href='#failure12'>Previous Failure</a> | <a href='#failure14'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt><br> Failure messages were:<br> re=/x./g; re.lastIndex=4; re.exec('xyabcdxa') = xa FAILED! expected: ["xa"]<br> re.exec('xyabcdef') = xy FAILED! expected: ["xy"]<br> </tt><br> -<a name='failure15'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline.js'>js1_2/regexp/RegExp_multiline.js</a> failed</b> <br> - [ <a href='#failure14'>Previous Failure</a> | <a href='#failure16'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> -<tt><br> -Failure messages were:<br> -(multiline == true) '123\n456'.match(/^4../) = null FAILED! expected: 456<br> -(multiline == true) 'a11\na22\na23\na24'.match(/^a../g) = a11 FAILED! expected: a11,a22,a23,a24<br> -(multiline == true) '123\n456'.match(/.3$/) = null FAILED! expected: 23<br> -(multiline == true) 'a11\na22\na23\na24'.match(/a..$/g) = a24 FAILED! expected: a11,a22,a23,a24<br> -(multiline == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g')) = a24 FAILED! expected: a11,a22,a23,a24<br> -</tt><br> -<a name='failure16'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/RegExp_multiline_as_array.js'>js1_2/regexp/RegExp_multiline_as_array.js</a> failed</b> <br> - [ <a href='#failure15'>Previous Failure</a> | <a href='#failure17'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> -<tt><br> -Failure messages were:<br> -(['$*'] == true) '123\n456'.match(/^4../) = null FAILED! expected: 456<br> -(['$*'] == true) 'a11\na22\na23\na24'.match(/^a../g) = a11 FAILED! expected: a11,a22,a23,a24<br> -(['$*'] == true) '123\n456'.match(/.3$/) = null FAILED! expected: 23<br> -(['$*'] == true) 'a11\na22\na23\na24'.match(/a..$/g) = a24 FAILED! expected: a11,a22,a23,a24<br> -(['$*'] == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g')) = a24 FAILED! expected: a11,a22,a23,a24<br> -</tt><br> -<a name='failure17'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/beginLine.js'>js1_2/regexp/beginLine.js</a> failed</b> <br> - [ <a href='#failure16'>Previous Failure</a> | <a href='#failure18'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> -<tt><br> -Failure messages were:<br> -123xyz'.match(new RegExp('^\d+')) = null FAILED! expected: 123<br> -</tt><br> -<a name='failure18'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/endLine.js'>js1_2/regexp/endLine.js</a> failed</b> <br> - [ <a href='#failure17'>Previous Failure</a> | <a href='#failure19'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> -<tt><br> -Failure messages were:<br> -xyz'.match(new RegExp('\d+$')) = null FAILED! expected: 890<br> -</tt><br> -<a name='failure19'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/regress-6359.js'>js1_2/regexp/regress-6359.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=http://bugzilla.mozilla.org/show_bug.cgi?id=6359' target='other_window'>Bug Number http://bugzilla.mozilla.org/show_bug.cgi?id=6359</a><br> - [ <a href='#failure18'>Previous Failure</a> | <a href='#failure20'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure14'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/regress-6359.js'>js1_2/regexp/regress-6359.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=http://bugzilla.mozilla.org/show_bug.cgi?id=6359' target='other_window'>Bug Number http://bugzilla.mozilla.org/show_bug.cgi?id=6359</a><br> + [ <a href='#failure13'>Previous Failure</a> | <a href='#failure15'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> BUGNUMBER: http://bugzilla.mozilla.org/show_bug.cgi?id=6359<br> </tt><br> -<a name='failure20'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/regress-9141.js'>js1_2/regexp/regress-9141.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=http://bugzilla.mozilla.org/show_bug.cgi?id=9141' target='other_window'>Bug Number http://bugzilla.mozilla.org/show_bug.cgi?id=9141</a><br> - [ <a href='#failure19'>Previous Failure</a> | <a href='#failure21'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure15'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/regress-9141.js'>js1_2/regexp/regress-9141.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=http://bugzilla.mozilla.org/show_bug.cgi?id=9141' target='other_window'>Bug Number http://bugzilla.mozilla.org/show_bug.cgi?id=9141</a><br> + [ <a href='#failure14'>Previous Failure</a> | <a href='#failure16'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> BUGNUMBER: http://bugzilla.mozilla.org/show_bug.cgi?id=9141<br> </tt><br> -<a name='failure21'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/simple_form.js'>js1_2/regexp/simple_form.js</a> failed</b> <br> - [ <a href='#failure20'>Previous Failure</a> | <a href='#failure22'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure16'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/simple_form.js'>js1_2/regexp/simple_form.js</a> failed</b> <br> + [ <a href='#failure15'>Previous Failure</a> | <a href='#failure17'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Executing script: simple_form.js<br> As described in Netscape doc "Whats new in JavaScript 1.2" RegExp: simple form<br> </tt><br> -<a name='failure22'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/string_split.js'>js1_2/regexp/string_split.js</a> failed</b> <br> - [ <a href='#failure21'>Previous Failure</a> | <a href='#failure23'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure17'></a><dd><b>Testcase <a target='other_window' href='./js1_2/regexp/string_split.js'>js1_2/regexp/string_split.js</a> failed</b> <br> + [ <a href='#failure16'>Previous Failure</a> | <a href='#failure18'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt><br> Failure messages were:<br> 'abc'.split(/[a-z]/) = ,,, FAILED! expected: ,,<br> @@ -189,22 +150,22 @@ Failure messages were:<br> 'abc'.split(new RegExp('[a-z]')) = ,,, FAILED! expected: ,,<br> 'abc'.split(new RegExp('[a-z]')) = ,,, FAILED! expected: ,,<br> </tt><br> -<a name='failure23'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/boolean-001.js'>js1_2/version120/boolean-001.js</a> failed</b> <br> - [ <a href='#failure22'>Previous Failure</a> | <a href='#failure24'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure18'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/boolean-001.js'>js1_2/version120/boolean-001.js</a> failed</b> <br> + [ <a href='#failure17'>Previous Failure</a> | <a href='#failure19'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt><br> Failure messages were:<br> new Boolean(false) = true FAILED! expected: false<br> </tt><br> -<a name='failure24'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/regress-99663.js'>js1_2/version120/regress-99663.js</a> failed</b> <br> - [ <a href='#failure23'>Previous Failure</a> | <a href='#failure25'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure19'></a><dd><b>Testcase <a target='other_window' href='./js1_2/version120/regress-99663.js'>js1_2/version120/regress-99663.js</a> failed</b> <br> + [ <a href='#failure18'>Previous Failure</a> | <a href='#failure20'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>STATUS: Regression test for Bugzilla bug 99663<br> Failure messages were:<br> Section 1 of test - got Error: Can't find variable: it FAILED! expected: a "read-only" error<br> Section 2 of test - got Error: Can't find variable: it FAILED! expected: a "read-only" error<br> Section 3 of test - got Error: Can't find variable: it FAILED! expected: a "read-only" error<br> </tt><br> -<a name='failure25'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/function-001-n.js'>js1_3/Script/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br> - [ <a href='#failure24'>Previous Failure</a> | <a href='#failure26'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure20'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/function-001-n.js'>js1_3/Script/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br> + [ <a href='#failure19'>Previous Failure</a> | <a href='#failure21'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 3, got 0<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> @@ -212,15 +173,15 @@ BUGNUMBER: 10278<br> function-001.js functions not separated by semicolons are errors in version 120 and higher<br> eval("function f(){}function g(){}") = undefined FAILED! expected: error<br> </tt><br> -<a name='failure26'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/script-001.js'>js1_3/Script/script-001.js</a> failed</b> <br> - [ <a href='#failure25'>Previous Failure</a> | <a href='#failure27'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure21'></a><dd><b>Testcase <a target='other_window' href='./js1_3/Script/script-001.js'>js1_3/Script/script-001.js</a> failed</b> <br> + [ <a href='#failure20'>Previous Failure</a> | <a href='#failure22'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> script-001 NativeScript<br> </tt><br> -<a name='failure27'></a><dd><b>Testcase <a target='other_window' href='./js1_3/regress/function-001-n.js'>js1_3/regress/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br> - [ <a href='#failure26'>Previous Failure</a> | <a href='#failure28'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure22'></a><dd><b>Testcase <a target='other_window' href='./js1_3/regress/function-001-n.js'>js1_3/regress/function-001-n.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=10278' target='other_window'>Bug Number 10278</a><br> + [ <a href='#failure21'>Previous Failure</a> | <a href='#failure23'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 3, got 0<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> @@ -228,90 +189,90 @@ BUGNUMBER: 10278<br> function-001.js functions not separated by semicolons are errors in version 120 and higher<br> eval("function f(){}function g(){}") = undefined FAILED! expected: error<br> </tt><br> -<a name='failure28'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-001.js'>js1_5/Exceptions/catchguard-001.js</a> failed</b> <br> - [ <a href='#failure27'>Previous Failure</a> | <a href='#failure29'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure23'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-001.js'>js1_5/Exceptions/catchguard-001.js</a> failed</b> <br> + [ <a href='#failure22'>Previous Failure</a> | <a href='#failure24'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure29'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-002.js'>js1_5/Exceptions/catchguard-002.js</a> failed</b> <br> - [ <a href='#failure28'>Previous Failure</a> | <a href='#failure30'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure24'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-002.js'>js1_5/Exceptions/catchguard-002.js</a> failed</b> <br> + [ <a href='#failure23'>Previous Failure</a> | <a href='#failure25'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure30'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-003.js'>js1_5/Exceptions/catchguard-003.js</a> failed</b> <br> - [ <a href='#failure29'>Previous Failure</a> | <a href='#failure31'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure25'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/catchguard-003.js'>js1_5/Exceptions/catchguard-003.js</a> failed</b> <br> + [ <a href='#failure24'>Previous Failure</a> | <a href='#failure26'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure31'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/errstack-001.js'>js1_5/Exceptions/errstack-001.js</a> failed</b> <br> - [ <a href='#failure30'>Previous Failure</a> | <a href='#failure32'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure26'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/errstack-001.js'>js1_5/Exceptions/errstack-001.js</a> failed</b> <br> + [ <a href='#failure25'>Previous Failure</a> | <a href='#failure27'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure32'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/regress-50447.js'>js1_5/Exceptions/regress-50447.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=50447' target='other_window'>Bug Number 50447</a><br> - [ <a href='#failure31'>Previous Failure</a> | <a href='#failure33'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure27'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Exceptions/regress-50447.js'>js1_5/Exceptions/regress-50447.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=50447' target='other_window'>Bug Number 50447</a><br> + [ <a href='#failure26'>Previous Failure</a> | <a href='#failure28'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> BUGNUMBER: 50447<br> STATUS: Test (non-ECMA) Error object properties fileName, lineNumber<br> </tt><br> -<a name='failure33'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-001.js'>js1_5/GetSet/getset-001.js</a> failed</b> <br> - [ <a href='#failure32'>Previous Failure</a> | <a href='#failure34'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure28'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-001.js'>js1_5/GetSet/getset-001.js</a> failed</b> <br> + [ <a href='#failure27'>Previous Failure</a> | <a href='#failure29'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure34'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-002.js'>js1_5/GetSet/getset-002.js</a> failed</b> <br> - [ <a href='#failure33'>Previous Failure</a> | <a href='#failure35'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure29'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-002.js'>js1_5/GetSet/getset-002.js</a> failed</b> <br> + [ <a href='#failure28'>Previous Failure</a> | <a href='#failure30'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure35'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-003.js'>js1_5/GetSet/getset-003.js</a> failed</b> <br> - [ <a href='#failure34'>Previous Failure</a> | <a href='#failure36'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure30'></a><dd><b>Testcase <a target='other_window' href='./js1_5/GetSet/getset-003.js'>js1_5/GetSet/getset-003.js</a> failed</b> <br> + [ <a href='#failure29'>Previous Failure</a> | <a href='#failure31'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure36'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-001.js'>js1_5/Object/regress-90596-001.js</a> failed</b> <br> - [ <a href='#failure35'>Previous Failure</a> | <a href='#failure37'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure31'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-001.js'>js1_5/Object/regress-90596-001.js</a> failed</b> <br> + [ <a href='#failure30'>Previous Failure</a> | <a href='#failure32'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure37'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-002.js'>js1_5/Object/regress-90596-002.js</a> failed</b> <br> - [ <a href='#failure36'>Previous Failure</a> | <a href='#failure38'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure32'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-90596-002.js'>js1_5/Object/regress-90596-002.js</a> failed</b> <br> + [ <a href='#failure31'>Previous Failure</a> | <a href='#failure33'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure38'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-001.js'>js1_5/Object/regress-96284-001.js</a> failed</b> <br> - [ <a href='#failure37'>Previous Failure</a> | <a href='#failure39'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure33'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-001.js'>js1_5/Object/regress-96284-001.js</a> failed</b> <br> + [ <a href='#failure32'>Previous Failure</a> | <a href='#failure34'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure39'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-002.js'>js1_5/Object/regress-96284-002.js</a> failed</b> <br> - [ <a href='#failure38'>Previous Failure</a> | <a href='#failure40'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure34'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Object/regress-96284-002.js'>js1_5/Object/regress-96284-002.js</a> failed</b> <br> + [ <a href='#failure33'>Previous Failure</a> | <a href='#failure35'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure40'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-44009.js'>js1_5/Regress/regress-44009.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=44009' target='other_window'>Bug Number 44009</a><br> - [ <a href='#failure39'>Previous Failure</a> | <a href='#failure41'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure35'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-44009.js'>js1_5/Regress/regress-44009.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=44009' target='other_window'>Bug Number 44009</a><br> + [ <a href='#failure34'>Previous Failure</a> | <a href='#failure36'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> BUGNUMBER: 44009<br> STATUS: Testing that we don't crash on obj.toSource()<br> </tt><br> -<a name='failure41'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-103602.js'>js1_5/Regress/regress-103602.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=103602' target='other_window'>Bug Number 103602</a><br> - [ <a href='#failure40'>Previous Failure</a> | <a href='#failure42'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure36'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-103602.js'>js1_5/Regress/regress-103602.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=103602' target='other_window'>Bug Number 103602</a><br> + [ <a href='#failure35'>Previous Failure</a> | <a href='#failure37'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>STATUS: Reassignment to a const is NOT an error per ECMA<br> Failure messages were:<br> FAILED!: [reported from test()] Section 1 of test -<br> @@ -321,26 +282,26 @@ FAILED!: [reported from test()] Section 3 of test -<br> FAILED!: [reported from test()] Expected value '1', Actual value '2'<br> FAILED!: [reported from test()] <br> </tt><br> -<a name='failure42'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-104077.js'>js1_5/Regress/regress-104077.js</a> failed</b> <br> - [ <a href='#failure41'>Previous Failure</a> | <a href='#failure43'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure37'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-104077.js'>js1_5/Regress/regress-104077.js</a> failed</b> <br> + [ <a href='#failure36'>Previous Failure</a> | <a href='#failure38'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure43'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-127557.js'>js1_5/Regress/regress-127557.js</a> failed</b> <br> - [ <a href='#failure42'>Previous Failure</a> | <a href='#failure44'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure38'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-127557.js'>js1_5/Regress/regress-127557.js</a> failed</b> <br> + [ <a href='#failure37'>Previous Failure</a> | <a href='#failure39'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure44'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-172699.js'>js1_5/Regress/regress-172699.js</a> failed</b> <br> - [ <a href='#failure43'>Previous Failure</a> | <a href='#failure45'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure39'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-172699.js'>js1_5/Regress/regress-172699.js</a> failed</b> <br> + [ <a href='#failure38'>Previous Failure</a> | <a href='#failure40'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure45'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-179524.js'>js1_5/Regress/regress-179524.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=179524' target='other_window'>Bug Number 179524</a><br> - [ <a href='#failure44'>Previous Failure</a> | <a href='#failure46'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure40'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Regress/regress-179524.js'>js1_5/Regress/regress-179524.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=179524' target='other_window'>Bug Number 179524</a><br> + [ <a href='#failure39'>Previous Failure</a> | <a href='#failure41'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>STATUS: Don't crash on extraneous arguments to str.match(), etc.<br> Failure messages were:<br> FAILED!: [reported from test()] Section 14 of test -<br> @@ -390,14 +351,14 @@ FAILED!: [reported from test()] Section 36 of test -<br> FAILED!: [reported from test()] Expected value 'SHOULD HAVE FALLEN INTO CATCH-BLOCK!', Actual value 'ABC Zbc'<br> FAILED!: [reported from test()] <br> </tt><br> -<a name='failure46'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/regress-220584.js'>js1_5/Scope/regress-220584.js</a> failed</b> <br> - [ <a href='#failure45'>Previous Failure</a> | <a href='#failure47'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure41'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/regress-220584.js'>js1_5/Scope/regress-220584.js</a> failed</b> <br> + [ <a href='#failure40'>Previous Failure</a> | <a href='#failure42'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure47'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/scope-001.js'>js1_5/Scope/scope-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=53268' target='other_window'>Bug Number 53268</a><br> - [ <a href='#failure46'>Previous Failure</a> | <a href='#failure48'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure42'></a><dd><b>Testcase <a target='other_window' href='./js1_5/Scope/scope-001.js'>js1_5/Scope/scope-001.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=53268' target='other_window'>Bug Number 53268</a><br> + [ <a href='#failure41'>Previous Failure</a> | <a href='#failure43'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>STATUS: Testing scope after changing obj.__proto__<br> Failure messages were:<br> FAILED!: [reported from test()] Step 1: setting obj.__proto__ = global object<br> @@ -408,8 +369,8 @@ FAILED!: [reported from test()] Type mismatch, expected type undefined, actual t FAILED!: [reported from test()] Expected value 'undefined', Actual value '1'<br> FAILED!: [reported from test()] <br> </tt><br> -<a name='failure48'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-301574.js'>js1_6/Regress/regress-301574.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=301574' target='other_window'>Bug Number 301574</a><br> - [ <a href='#failure47'>Previous Failure</a> | <a href='#failure49'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure43'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-301574.js'>js1_6/Regress/regress-301574.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=301574' target='other_window'>Bug Number 301574</a><br> + [ <a href='#failure42'>Previous Failure</a> | <a href='#failure44'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>STATUS: E4X should be enabled even when e4x=1 not specified<br> Failure messages were:<br> FAILED!: E4X should be enabled even when e4x=1 not specified: XML()<br> @@ -419,20 +380,20 @@ FAILED!: E4X should be enabled even when e4x=1 not specified: XMLList()<br> FAILED!: Expected value 'No error', Actual value 'error: ReferenceError: Can't find variable: XML'<br> FAILED!: <br> </tt><br> -<a name='failure49'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-309242.js'>js1_6/Regress/regress-309242.js</a> failed</b> <br> - [ <a href='#failure48'>Previous Failure</a> | <a href='#failure50'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure44'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-309242.js'>js1_6/Regress/regress-309242.js</a> failed</b> <br> + [ <a href='#failure43'>Previous Failure</a> | <a href='#failure45'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure50'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-314887.js'>js1_6/Regress/regress-314887.js</a> failed</b> <br> - [ <a href='#failure49'>Previous Failure</a> | <a href='#failure51'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure45'></a><dd><b>Testcase <a target='other_window' href='./js1_6/Regress/regress-314887.js'>js1_6/Regress/regress-314887.js</a> failed</b> <br> + [ <a href='#failure44'>Previous Failure</a> | <a href='#failure46'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> Testcase produced no output!</tt><br> -<a name='failure51'></a><dd><b>Testcase <a target='other_window' href='./js1_6/String/regress-306591.js'>js1_6/String/regress-306591.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=306591' target='other_window'>Bug Number 306591</a><br> - [ <a href='#failure50'>Previous Failure</a> | <a href='#failure52'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> +<a name='failure46'></a><dd><b>Testcase <a target='other_window' href='./js1_6/String/regress-306591.js'>js1_6/String/regress-306591.js</a> failed</b> <a href='http://bugzilla.mozilla.org/show_bug.cgi?id=306591' target='other_window'>Bug Number 306591</a><br> + [ <a href='#failure45'>Previous Failure</a> | <a href='#failure47'>Next Failure</a> | <a href='#tippy_top'>Top of Page</a> ]<br> <tt>Expected exit code 0, got 3<br> Testcase terminated with signal 0<br> Complete testcase output was:<br> @@ -446,10 +407,9 @@ STATUS: See https://bugzilla.mozilla.org/show_bug.cgi?id=304828<br> <pre> <a name='retest_list'></a> <h2>Retest List</h2><br> -# Retest List, squirrelfish, generated Wed Jan 19 13:26:57 2011. +# Retest List, squirrelfish, generated Tue Apr 3 22:31:56 2012. # Original test base was: All tests. -# 1119 of 1127 test(s) were completed, 51 failures reported. -ecma/TypeConversion/9.3.1-3.js +# 1116 of 1124 test(s) were completed, 46 failures reported. ecma_2/Exceptions/function-001.js ecma_2/RegExp/regress-001.js ecma_3/FunExpr/fe-001.js @@ -463,10 +423,6 @@ js1_2/function/tostring-1.js js1_2/function/tostring-2.js js1_2/operator/equality.js js1_2/regexp/RegExp_lastIndex.js -js1_2/regexp/RegExp_multiline.js -js1_2/regexp/RegExp_multiline_as_array.js -js1_2/regexp/beginLine.js -js1_2/regexp/endLine.js js1_2/regexp/regress-6359.js js1_2/regexp/regress-9141.js js1_2/regexp/simple_form.js diff --git a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_multiline.js b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_multiline.js index be2226147..de22876c1 100644 --- a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_multiline.js +++ b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_multiline.js @@ -79,32 +79,32 @@ // **Now we do the tests with RegExp.multiline set to true // RegExp.multiline = true; RegExp.multiline RegExp.multiline = true; - testcases[count++] = new TestCase ( SECTION, "RegExp.multiline = true; RegExp.multiline", + testcases[count++] = new TestCase ( SECTION, "RegExp.multiline = true; RegExp.multiline", true, RegExp.multiline); // (multiline == true) '123\n456'.match(/^4../) - testcases[count++] = new TestCase ( SECTION, "(multiline == true) '123\\n456'.match(/^4../)", - String(['456']), String('123\n456'.match(/^4../))); + testcases[count++] = new TestCase ( SECTION, "(multiline == true) '123\\n456'.match(/^4../m)", + String(['456']), String('123\n456'.match(/^4../m))); // (multiline == true) 'a11\na22\na23\na24'.match(/^a../g) - testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(/^a../g)", - String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/^a../g))); + testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(/^a../gm)", + String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/^a../gm))); // (multiline == true) 'a11\na22'.match(/^.+^./) //testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\na22'.match(/^.+^./)", // String(['a11\na']), String('a11\na22'.match(/^.+^./))); // (multiline == true) '123\n456'.match(/.3$/) - testcases[count++] = new TestCase ( SECTION, "(multiline == true) '123\\n456'.match(/.3$/)", - String(['23']), String('123\n456'.match(/.3$/))); + testcases[count++] = new TestCase ( SECTION, "(multiline == true) '123\\n456'.match(/.3$/m)", + String(['23']), String('123\n456'.match(/.3$/m))); // (multiline == true) 'a11\na22\na23\na24'.match(/a..$/g) - testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(/a..$/g)", - String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/a..$/g))); + testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(/a..$/gm)", + String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/a..$/gm))); // (multiline == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g')) - testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(new RegExp('a..$','g'))", - String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(new RegExp('a..$','g')))); + testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'a11\\na22\\na23\\na24'.match(new RegExp('a..$','gm'))", + String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(new RegExp('a..$','gm')))); // (multiline == true) 'abc\ndef'.match(/c$....$/) //testcases[count++] = new TestCase ( SECTION, "(multiline == true) 'abc\ndef'.match(/c$.+$/)", diff --git a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_multiline_as_array.js b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_multiline_as_array.js index 690653f93..01734f5e7 100644 --- a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_multiline_as_array.js +++ b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/RegExp_multiline_as_array.js @@ -83,28 +83,28 @@ true, RegExp['$*']); // (['$*'] == true) '123\n456'.match(/^4../) - testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) '123\\n456'.match(/^4../)", - String(['456']), String('123\n456'.match(/^4../))); + testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) '123\\n456'.match(/^4../m)", + String(['456']), String('123\n456'.match(/^4../m))); // (['$*'] == true) 'a11\na22\na23\na24'.match(/^a../g) - testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(/^a../g)", - String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/^a../g))); + testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(/^a../gm)", + String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/^a../gm))); // (['$*'] == true) 'a11\na22'.match(/^.+^./) //testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\na22'.match(/^.+^./)", // String(['a11\na']), String('a11\na22'.match(/^.+^./))); // (['$*'] == true) '123\n456'.match(/.3$/) - testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) '123\\n456'.match(/.3$/)", - String(['23']), String('123\n456'.match(/.3$/))); + testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) '123\\n456'.match(/.3$/m)", + String(['23']), String('123\n456'.match(/.3$/m))); // (['$*'] == true) 'a11\na22\na23\na24'.match(/a..$/g) - testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(/a..$/g)", - String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/a..$/g))); + testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(/a..$/gm)", + String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(/a..$/gm))); // (['$*'] == true) 'a11\na22\na23\na24'.match(new RegExp('a..$','g')) - testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(new RegExp('a..$','g'))", - String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(new RegExp('a..$','g')))); + testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'a11\\na22\\na23\\na24'.match(new RegExp('a..$','gm'))", + String(['a11','a22','a23','a24']), String('a11\na22\na23\na24'.match(new RegExp('a..$','gm')))); // (['$*'] == true) 'abc\ndef'.match(/c$....$/) //testcases[count++] = new TestCase ( SECTION, "(['$*'] == true) 'abc\ndef'.match(/c$.+$/)", diff --git a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/beginLine.js b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/beginLine.js index c5ccbdc29..686092a69 100644 --- a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/beginLine.js +++ b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/beginLine.js @@ -60,8 +60,8 @@ RegExp.multiline = true; // 'abc\n123xyz'.match(new RegExp('^\d+')) <multiline==true> - testcases[count++] = new TestCase ( SECTION, "'abc\n123xyz'.match(new RegExp('^\\d+'))", - String(['123']), String('abc\n123xyz'.match(new RegExp('^\\d+')))); + testcases[count++] = new TestCase ( SECTION, "'abc\n123xyz'.match(new RegExp('^\\d+','m'))", + String(['123']), String('abc\n123xyz'.match(new RegExp('^\\d+','m')))); function test() { diff --git a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/endLine.js b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/endLine.js index 655d6ec69..e6d588cf9 100644 --- a/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/endLine.js +++ b/Source/JavaScriptCore/tests/mozilla/js1_2/regexp/endLine.js @@ -60,8 +60,8 @@ RegExp.multiline = true; // 'abc\n123xyz890\nxyz'.match(new RegExp('\d+$')) <multiline==true> - testcases[count++] = new TestCase ( SECTION, "'abc\n123xyz890\nxyz'.match(new RegExp('\\d+$'))", - String(['890']), String('abc\n123xyz890\nxyz'.match(new RegExp('\\d+$')))); + testcases[count++] = new TestCase ( SECTION, "'abc\n123xyz890\nxyz'.match(new RegExp('\\d+$','m'))", + String(['890']), String('abc\n123xyz890\nxyz'.match(new RegExp('\\d+$','m')))); function test() { diff --git a/Source/JavaScriptCore/tools/CodeProfiling.cpp b/Source/JavaScriptCore/tools/CodeProfiling.cpp index f11603854..740595e3e 100644 --- a/Source/JavaScriptCore/tools/CodeProfiling.cpp +++ b/Source/JavaScriptCore/tools/CodeProfiling.cpp @@ -27,7 +27,7 @@ #include "CodeProfiling.h" #include "CodeProfile.h" -#include "MetaAllocator.h" +#include <wtf/MetaAllocator.h> #if HAVE(SIGNAL_H) #include <signal.h> diff --git a/Source/JavaScriptCore/tools/ProfileTreeNode.h b/Source/JavaScriptCore/tools/ProfileTreeNode.h index 60d59928a..9de39ad8a 100644 --- a/Source/JavaScriptCore/tools/ProfileTreeNode.h +++ b/Source/JavaScriptCore/tools/ProfileTreeNode.h @@ -50,8 +50,8 @@ public: m_children = new Map(); ProfileTreeNode newEntry; - pair<Map::iterator, bool> result = m_children->add(String(name), newEntry); - ProfileTreeNode* childInMap = &result.first->second; + Map::AddResult result = m_children->add(String(name), newEntry); + ProfileTreeNode* childInMap = &result.iterator->second; ++childInMap->m_count; return childInMap; } diff --git a/Source/JavaScriptCore/wscript b/Source/JavaScriptCore/wscript index 2093601df..4afb4d26a 100644 --- a/Source/JavaScriptCore/wscript +++ b/Source/JavaScriptCore/wscript @@ -34,29 +34,39 @@ def build(bld): import Options jscore_excludes = ['jsc.cpp', 'ExecutableAllocatorPosix.cpp', 'LLIntOffsetsExtractor.cpp'] - jscore_excludes.extend(get_excludes(jscore_dir, ['*CF.cpp', '*Symbian.cpp'])) - jscore_excludes.extend(get_excludes(jscore_dir, ['*None.cpp'])) + jscore_exclude_patterns = get_port_excludes(Options.options.port) + jscore_exclude_patterns.append('*None.cpp') sources = [] if Options.options.port == "wx": if building_on_win32: jscore_excludes += ['OSAllocatorPosix.cpp', 'ThreadingPthreads.cpp'] + sources.extend(['../WTF/wtf/ThreadingWin.cpp', '../WTF/wtf/ThreadSpecificWin.cpp', '../WTF/wtf/OSAllocatorWin.cpp']) else: jscore_excludes.append('JSStringRefBSTR.cpp') - jscore_excludes.extend(get_excludes(jscore_dir, ['*Win.cpp'])) + if sys.platform.startswith('darwin'): + jscore_excludes.append('GCActivityCallback.cpp') # this is an empty impl. + + bld.env.LIBDIR = output_dir full_dirs = get_dirs_for_features(jscore_dir, features=[Options.options.port.lower()], dirs=jscore_dirs) + abs_dirs = [] + for adir in full_dirs: + abs_dirs.append(os.path.join(jscore_dir, adir)) + + jscore_excludes.extend(get_excludes_in_dirs(abs_dirs, jscore_exclude_patterns)) - includes = common_includes + full_dirs + includes = common_includes + full_dirs + [output_dir] if sys.platform.startswith('darwin'): includes.append(os.path.join(jscore_dir, 'icu')) # 1. A simple program jscore = bld.new_task_gen( - features = 'cc cxx cstaticlib', - includes = '. .. assembler DerivedSources ForwardingHeaders ' + ' '.join(includes), + features = 'cc cxx cshlib', + includes = '. .. assembler ../WTF ' + ' '.join(includes), source = sources, + defines = ['BUILDING_JavaScriptCore'], target = 'jscore', uselib = 'WX ICU ' + get_config(), uselib_local = '', @@ -66,7 +76,7 @@ def build(bld): obj = bld.new_task_gen( features = 'cxx cprogram', - includes = '. .. assembler DerivedSources ForwardingHeaders ' + ' '.join(includes), + includes = '. .. assembler ../WTF ' + ' '.join(includes), source = 'jsc.cpp', target = 'jsc', uselib = 'WX ICU ' + get_config(), @@ -80,4 +90,4 @@ def build(bld): myenv.CXXFLAGS.remove('/EHsc') obj.env = myenv - bld.install_files(os.path.join(output_dir, 'JavaScriptCore'), 'API/*.h') + bld.add_group() diff --git a/Source/JavaScriptCore/wtf/ASCIICType.h b/Source/JavaScriptCore/wtf/ASCIICType.h deleted file mode 100644 index 18e108e1b..000000000 --- a/Source/JavaScriptCore/wtf/ASCIICType.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2009, 2011 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 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 WTF_ASCIICType_h -#define WTF_ASCIICType_h - -#include <wtf/Assertions.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 -// are in code processing something that's not locale-specific. These equivalents -// for some of the <ctype.h> functions are named more explicitly, not dependent -// on the C library locale, and we should also optimize them as needed. - -// All functions return false or leave the character unchanged if passed a character -// that is outside the range 0-7F. So they can be used on Unicode strings or -// characters if the intent is to do processing only if the character is ASCII. - -namespace WTF { - -template<typename CharType> inline bool isASCII(CharType c) -{ - return !(c & ~0x7F); -} - -template<typename CharType> inline bool isASCIIAlpha(CharType c) -{ - return (c | 0x20) >= 'a' && (c | 0x20) <= 'z'; -} - -template<typename CharType> inline bool isASCIIDigit(CharType c) -{ - return c >= '0' && c <= '9'; -} - -template<typename CharType> inline bool isASCIIAlphanumeric(CharType c) -{ - return isASCIIDigit(c) || isASCIIAlpha(c); -} - -template<typename CharType> inline bool isASCIIHexDigit(CharType c) -{ - return isASCIIDigit(c) || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f'); -} - -template<typename CharType> inline bool isASCIILower(CharType c) -{ - return c >= 'a' && c <= 'z'; -} - -template<typename CharType> inline bool isASCIIOctalDigit(CharType c) -{ - return (c >= '0') & (c <= '7'); -} - -template<typename CharType> inline bool isASCIIPrintable(CharType c) -{ - return c >= ' ' && c <= '~'; -} - -/* - Statistics from a run of Apple's page load test for callers of isASCIISpace: - - character count - --------- ----- - non-spaces 689383 - 20 space 294720 - 0A \n 89059 - 09 \t 28320 - 0D \r 0 - 0C \f 0 - 0B \v 0 - */ -template<typename CharType> inline bool isASCIISpace(CharType c) -{ - return c <= ' ' && (c == ' ' || (c <= 0xD && c >= 0x9)); -} - -template<typename CharType> inline bool isASCIIUpper(CharType c) -{ - return c >= 'A' && c <= 'Z'; -} - -template<typename CharType> inline CharType toASCIILower(CharType c) -{ - return c | ((c >= 'A' && c <= 'Z') << 5); -} - -template<typename CharType> inline CharType toASCIILowerUnchecked(CharType character) -{ - // This function can be used for comparing any input character - // to a lowercase English character. The isASCIIAlphaCaselessEqual - // below should be used for regular comparison of ASCII alpha - // characters, but switch statements in CSS tokenizer require - // direct use of this function. - return character | 0x20; -} - -template<typename CharType> inline CharType toASCIIUpper(CharType c) -{ - return c & ~((c >= 'a' && c <= 'z') << 5); -} - -template<typename CharType> inline int toASCIIHexValue(CharType c) -{ - ASSERT(isASCIIHexDigit(c)); - return c < 'A' ? c - '0' : (c - 'A' + 10) & 0xF; -} - -template<typename CharType> inline int toASCIIHexValue(CharType upperValue, CharType lowerValue) -{ - ASSERT(isASCIIHexDigit(upperValue) && isASCIIHexDigit(lowerValue)); - return ((toASCIIHexValue(upperValue) << 4) & 0xF0) | toASCIIHexValue(lowerValue); -} - -inline char lowerNibbleToASCIIHexDigit(char c) -{ - char nibble = c & 0xF; - return nibble < 10 ? '0' + nibble : 'A' + nibble - 10; -} - -inline char upperNibbleToASCIIHexDigit(char c) -{ - char nibble = (c >> 4) & 0xF; - return nibble < 10 ? '0' + nibble : 'A' + nibble - 10; -} - -template<typename CharType> inline bool isASCIIAlphaCaselessEqual(CharType cssCharacter, char character) -{ - // This function compares a (preferrably) constant ASCII - // lowercase letter to any input character. - ASSERT(character >= 'a' && character <= 'z'); - return LIKELY(toASCIILowerUnchecked(cssCharacter) == character); -} - -} - -using WTF::isASCII; -using WTF::isASCIIAlpha; -using WTF::isASCIIAlphanumeric; -using WTF::isASCIIDigit; -using WTF::isASCIIHexDigit; -using WTF::isASCIILower; -using WTF::isASCIIOctalDigit; -using WTF::isASCIIPrintable; -using WTF::isASCIISpace; -using WTF::isASCIIUpper; -using WTF::toASCIIHexValue; -using WTF::toASCIILower; -using WTF::toASCIILowerUnchecked; -using WTF::toASCIIUpper; -using WTF::lowerNibbleToASCIIHexDigit; -using WTF::upperNibbleToASCIIHexDigit; -using WTF::isASCIIAlphaCaselessEqual; - -#endif diff --git a/Source/JavaScriptCore/wtf/AVLTree.h b/Source/JavaScriptCore/wtf/AVLTree.h deleted file mode 100644 index f2f82e170..000000000 --- a/Source/JavaScriptCore/wtf/AVLTree.h +++ /dev/null @@ -1,960 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Based on Abstract AVL Tree Template v1.5 by Walt Karas - * <http://geocities.com/wkaras/gen_cpp/avl_tree.html>. - * - * 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 AVL_TREE_H_ -#define AVL_TREE_H_ - -#include <wtf/Assertions.h> -#include <wtf/FixedArray.h> - -namespace WTF { - -// Here is the reference class for BSet. -// -// class BSet -// { -// public: -// -// class ANY_bitref -// { -// public: -// operator bool (); -// void operator = (bool b); -// }; -// -// // Does not have to initialize bits. -// BSet(); -// -// // Must return a valid value for index when 0 <= index < maxDepth -// ANY_bitref operator [] (unsigned index); -// -// // Set all bits to 1. -// void set(); -// -// // Set all bits to 0. -// void reset(); -// }; - -template<unsigned maxDepth> -class AVLTreeDefaultBSet { -public: - bool& operator[](unsigned i) { ASSERT(i < maxDepth); return m_data[i]; } - void set() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = true; } - void reset() { for (unsigned i = 0; i < maxDepth; ++i) m_data[i] = false; } - -private: - FixedArray<bool, maxDepth> m_data; -}; - -// How to determine maxDepth: -// d Minimum number of nodes -// 2 2 -// 3 4 -// 4 7 -// 5 12 -// 6 20 -// 7 33 -// 8 54 -// 9 88 -// 10 143 -// 11 232 -// 12 376 -// 13 609 -// 14 986 -// 15 1,596 -// 16 2,583 -// 17 4,180 -// 18 6,764 -// 19 10,945 -// 20 17,710 -// 21 28,656 -// 22 46,367 -// 23 75,024 -// 24 121,392 -// 25 196,417 -// 26 317,810 -// 27 514,228 -// 28 832,039 -// 29 1,346,268 -// 30 2,178,308 -// 31 3,524,577 -// 32 5,702,886 -// 33 9,227,464 -// 34 14,930,351 -// 35 24,157,816 -// 36 39,088,168 -// 37 63,245,985 -// 38 102,334,154 -// 39 165,580,140 -// 40 267,914,295 -// 41 433,494,436 -// 42 701,408,732 -// 43 1,134,903,169 -// 44 1,836,311,902 -// 45 2,971,215,072 -// -// E.g., if, in a particular instantiation, the maximum number of nodes in a tree instance is 1,000,000, the maximum depth should be 28. -// You pick 28 because MN(28) is 832,039, which is less than or equal to 1,000,000, and MN(29) is 1,346,268, which is strictly greater than 1,000,000. - -template <class Abstractor, unsigned maxDepth = 32, class BSet = AVLTreeDefaultBSet<maxDepth> > -class AVLTree { -public: - - typedef typename Abstractor::key key; - typedef typename Abstractor::handle handle; - typedef typename Abstractor::size size; - - enum SearchType { - EQUAL = 1, - LESS = 2, - GREATER = 4, - LESS_EQUAL = EQUAL | LESS, - GREATER_EQUAL = EQUAL | GREATER - }; - - - Abstractor& abstractor() { return abs; } - - inline handle insert(handle h); - - inline handle search(key k, SearchType st = EQUAL); - inline handle search_least(); - inline handle search_greatest(); - - inline handle remove(key k); - - inline handle subst(handle new_node); - - void purge() { abs.root = null(); } - - bool is_empty() { return abs.root == null(); } - - AVLTree() { abs.root = null(); } - - class Iterator { - public: - - // Initialize depth to invalid value, to indicate iterator is - // invalid. (Depth is zero-base.) - Iterator() { depth = ~0U; } - - void start_iter(AVLTree &tree, key k, SearchType st = EQUAL) - { - // Mask of high bit in an int. - const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1); - - // Save the tree that we're going to iterate through in a - // member variable. - tree_ = &tree; - - int cmp, target_cmp; - handle h = tree_->abs.root; - unsigned d = 0; - - depth = ~0U; - - if (h == null()) - // Tree is empty. - return; - - if (st & LESS) - // Key can be greater than key of starting node. - target_cmp = 1; - else if (st & GREATER) - // Key can be less than key of starting node. - target_cmp = -1; - else - // Key must be same as key of starting node. - target_cmp = 0; - - for (;;) { - cmp = cmp_k_n(k, h); - if (cmp == 0) { - if (st & EQUAL) { - // Equal node was sought and found as starting node. - depth = d; - break; - } - cmp = -target_cmp; - } else if (target_cmp != 0) { - if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) { - // cmp and target_cmp are both negative or both positive. - depth = d; - } - } - h = cmp < 0 ? get_lt(h) : get_gt(h); - if (h == null()) - break; - branch[d] = cmp > 0; - path_h[d++] = h; - } - } - - void start_iter_least(AVLTree &tree) - { - tree_ = &tree; - - handle h = tree_->abs.root; - - depth = ~0U; - - branch.reset(); - - while (h != null()) { - if (depth != ~0U) - path_h[depth] = h; - depth++; - h = get_lt(h); - } - } - - void start_iter_greatest(AVLTree &tree) - { - tree_ = &tree; - - handle h = tree_->abs.root; - - depth = ~0U; - - branch.set(); - - while (h != null()) { - if (depth != ~0U) - path_h[depth] = h; - depth++; - h = get_gt(h); - } - } - - handle operator*() - { - if (depth == ~0U) - return null(); - - return depth == 0 ? tree_->abs.root : path_h[depth - 1]; - } - - void operator++() - { - if (depth != ~0U) { - handle h = get_gt(**this); - if (h == null()) { - do { - if (depth == 0) { - depth = ~0U; - break; - } - depth--; - } while (branch[depth]); - } else { - branch[depth] = true; - path_h[depth++] = h; - for (;;) { - h = get_lt(h); - if (h == null()) - break; - branch[depth] = false; - path_h[depth++] = h; - } - } - } - } - - void operator--() - { - if (depth != ~0U) { - handle h = get_lt(**this); - if (h == null()) - do { - if (depth == 0) { - depth = ~0U; - break; - } - depth--; - } while (!branch[depth]); - else { - branch[depth] = false; - path_h[depth++] = h; - for (;;) { - h = get_gt(h); - if (h == null()) - break; - branch[depth] = true; - path_h[depth++] = h; - } - } - } - } - - void operator++(int) { ++(*this); } - void operator--(int) { --(*this); } - - protected: - - // Tree being iterated over. - AVLTree *tree_; - - // Records a path into the tree. If branch[n] is true, indicates - // take greater branch from the nth node in the path, otherwise - // take the less branch. branch[0] gives branch from root, and - // so on. - BSet branch; - - // Zero-based depth of path into tree. - unsigned depth; - - // Handles of nodes in path from root to current node (returned by *). - handle path_h[maxDepth - 1]; - - int cmp_k_n(key k, handle h) { return tree_->abs.compare_key_node(k, h); } - int cmp_n_n(handle h1, handle h2) { return tree_->abs.compare_node_node(h1, h2); } - handle get_lt(handle h) { return tree_->abs.get_less(h); } - handle get_gt(handle h) { return tree_->abs.get_greater(h); } - handle null() { return tree_->abs.null(); } - }; - - template<typename fwd_iter> - bool build(fwd_iter p, size num_nodes) - { - if (num_nodes == 0) { - abs.root = null(); - return true; - } - - // Gives path to subtree being built. If branch[N] is false, branch - // less from the node at depth N, if true branch greater. - BSet branch; - - // If rem[N] is true, then for the current subtree at depth N, it's - // greater subtree has one more node than it's less subtree. - BSet rem; - - // Depth of root node of current subtree. - unsigned depth = 0; - - // Number of nodes in current subtree. - size num_sub = num_nodes; - - // The algorithm relies on a stack of nodes whose less subtree has - // been built, but whose right subtree has not yet been built. The - // stack is implemented as linked list. The nodes are linked - // together by having the "greater" handle of a node set to the - // next node in the list. "less_parent" is the handle of the first - // node in the list. - handle less_parent = null(); - - // h is root of current subtree, child is one of its children. - handle h, child; - - for (;;) { - while (num_sub > 2) { - // Subtract one for root of subtree. - num_sub--; - rem[depth] = !!(num_sub & 1); - branch[depth++] = false; - num_sub >>= 1; - } - - if (num_sub == 2) { - // Build a subtree with two nodes, slanting to greater. - // I arbitrarily chose to always have the extra node in the - // greater subtree when there is an odd number of nodes to - // split between the two subtrees. - - h = *p; - p++; - child = *p; - p++; - set_lt(child, null()); - set_gt(child, null()); - set_bf(child, 0); - set_gt(h, child); - set_lt(h, null()); - set_bf(h, 1); - } else { // num_sub == 1 - // Build a subtree with one node. - - h = *p; - p++; - set_lt(h, null()); - set_gt(h, null()); - set_bf(h, 0); - } - - while (depth) { - depth--; - if (!branch[depth]) - // We've completed a less subtree. - break; - - // We've completed a greater subtree, so attach it to - // its parent (that is less than it). We pop the parent - // off the stack of less parents. - child = h; - h = less_parent; - less_parent = get_gt(h); - set_gt(h, child); - // num_sub = 2 * (num_sub - rem[depth]) + rem[depth] + 1 - num_sub <<= 1; - num_sub += 1 - rem[depth]; - if (num_sub & (num_sub - 1)) - // num_sub is not a power of 2 - set_bf(h, 0); - else - // num_sub is a power of 2 - set_bf(h, 1); - } - - if (num_sub == num_nodes) - // We've completed the full tree. - break; - - // The subtree we've completed is the less subtree of the - // next node in the sequence. - - child = h; - h = *p; - p++; - set_lt(h, child); - - // Put h into stack of less parents. - set_gt(h, less_parent); - less_parent = h; - - // Proceed to creating greater than subtree of h. - branch[depth] = true; - num_sub += rem[depth++]; - - } // end for (;;) - - abs.root = h; - - return true; - } - -protected: - - friend class Iterator; - - // Create a class whose sole purpose is to take advantage of - // the "empty member" optimization. - struct abs_plus_root : public Abstractor { - // The handle of the root element in the AVL tree. - handle root; - }; - - abs_plus_root abs; - - - handle get_lt(handle h) { return abs.get_less(h); } - void set_lt(handle h, handle lh) { abs.set_less(h, lh); } - - handle get_gt(handle h) { return abs.get_greater(h); } - void set_gt(handle h, handle gh) { abs.set_greater(h, gh); } - - int get_bf(handle h) { return abs.get_balance_factor(h); } - void set_bf(handle h, int bf) { abs.set_balance_factor(h, bf); } - - int cmp_k_n(key k, handle h) { return abs.compare_key_node(k, h); } - int cmp_n_n(handle h1, handle h2) { return abs.compare_node_node(h1, h2); } - - handle null() { return abs.null(); } - -private: - - // Balances subtree, returns handle of root node of subtree - // after balancing. - handle balance(handle bal_h) - { - handle deep_h; - - // Either the "greater than" or the "less than" subtree of - // this node has to be 2 levels deeper (or else it wouldn't - // need balancing). - - if (get_bf(bal_h) > 0) { - // "Greater than" subtree is deeper. - - deep_h = get_gt(bal_h); - - if (get_bf(deep_h) < 0) { - handle old_h = bal_h; - bal_h = get_lt(deep_h); - - set_gt(old_h, get_lt(bal_h)); - set_lt(deep_h, get_gt(bal_h)); - set_lt(bal_h, old_h); - set_gt(bal_h, deep_h); - - int bf = get_bf(bal_h); - if (bf != 0) { - if (bf > 0) { - set_bf(old_h, -1); - set_bf(deep_h, 0); - } else { - set_bf(deep_h, 1); - set_bf(old_h, 0); - } - set_bf(bal_h, 0); - } else { - set_bf(old_h, 0); - set_bf(deep_h, 0); - } - } else { - set_gt(bal_h, get_lt(deep_h)); - set_lt(deep_h, bal_h); - if (get_bf(deep_h) == 0) { - set_bf(deep_h, -1); - set_bf(bal_h, 1); - } else { - set_bf(deep_h, 0); - set_bf(bal_h, 0); - } - bal_h = deep_h; - } - } else { - // "Less than" subtree is deeper. - - deep_h = get_lt(bal_h); - - if (get_bf(deep_h) > 0) { - handle old_h = bal_h; - bal_h = get_gt(deep_h); - set_lt(old_h, get_gt(bal_h)); - set_gt(deep_h, get_lt(bal_h)); - set_gt(bal_h, old_h); - set_lt(bal_h, deep_h); - - int bf = get_bf(bal_h); - if (bf != 0) { - if (bf < 0) { - set_bf(old_h, 1); - set_bf(deep_h, 0); - } else { - set_bf(deep_h, -1); - set_bf(old_h, 0); - } - set_bf(bal_h, 0); - } else { - set_bf(old_h, 0); - set_bf(deep_h, 0); - } - } else { - set_lt(bal_h, get_gt(deep_h)); - set_gt(deep_h, bal_h); - if (get_bf(deep_h) == 0) { - set_bf(deep_h, 1); - set_bf(bal_h, -1); - } else { - set_bf(deep_h, 0); - set_bf(bal_h, 0); - } - bal_h = deep_h; - } - } - - return bal_h; - } - -}; - -template <class Abstractor, unsigned maxDepth, class BSet> -inline typename AVLTree<Abstractor, maxDepth, BSet>::handle -AVLTree<Abstractor, maxDepth, BSet>::insert(handle h) -{ - set_lt(h, null()); - set_gt(h, null()); - set_bf(h, 0); - - if (abs.root == null()) - abs.root = h; - else { - // Last unbalanced node encountered in search for insertion point. - handle unbal = null(); - // Parent of last unbalanced node. - handle parent_unbal = null(); - // Balance factor of last unbalanced node. - int unbal_bf; - - // Zero-based depth in tree. - unsigned depth = 0, unbal_depth = 0; - - // Records a path into the tree. If branch[n] is true, indicates - // take greater branch from the nth node in the path, otherwise - // take the less branch. branch[0] gives branch from root, and - // so on. - BSet branch; - - handle hh = abs.root; - handle parent = null(); - int cmp; - - do { - if (get_bf(hh) != 0) { - unbal = hh; - parent_unbal = parent; - unbal_depth = depth; - } - cmp = cmp_n_n(h, hh); - if (cmp == 0) - // Duplicate key. - return hh; - parent = hh; - hh = cmp < 0 ? get_lt(hh) : get_gt(hh); - branch[depth++] = cmp > 0; - } while (hh != null()); - - // Add node to insert as leaf of tree. - if (cmp < 0) - set_lt(parent, h); - else - set_gt(parent, h); - - depth = unbal_depth; - - if (unbal == null()) - hh = abs.root; - else { - cmp = branch[depth++] ? 1 : -1; - unbal_bf = get_bf(unbal); - if (cmp < 0) - unbal_bf--; - else // cmp > 0 - unbal_bf++; - hh = cmp < 0 ? get_lt(unbal) : get_gt(unbal); - if ((unbal_bf != -2) && (unbal_bf != 2)) { - // No rebalancing of tree is necessary. - set_bf(unbal, unbal_bf); - unbal = null(); - } - } - - if (hh != null()) - while (h != hh) { - cmp = branch[depth++] ? 1 : -1; - if (cmp < 0) { - set_bf(hh, -1); - hh = get_lt(hh); - } else { // cmp > 0 - set_bf(hh, 1); - hh = get_gt(hh); - } - } - - if (unbal != null()) { - unbal = balance(unbal); - if (parent_unbal == null()) - abs.root = unbal; - else { - depth = unbal_depth - 1; - cmp = branch[depth] ? 1 : -1; - if (cmp < 0) - set_lt(parent_unbal, unbal); - else // cmp > 0 - set_gt(parent_unbal, unbal); - } - } - } - - return h; -} - -template <class Abstractor, unsigned maxDepth, class BSet> -inline typename AVLTree<Abstractor, maxDepth, BSet>::handle -AVLTree<Abstractor, maxDepth, BSet>::search(key k, typename AVLTree<Abstractor, maxDepth, BSet>::SearchType st) -{ - const int MASK_HIGH_BIT = (int) ~ ((~ (unsigned) 0) >> 1); - - int cmp, target_cmp; - handle match_h = null(); - handle h = abs.root; - - if (st & LESS) - target_cmp = 1; - else if (st & GREATER) - target_cmp = -1; - else - target_cmp = 0; - - while (h != null()) { - cmp = cmp_k_n(k, h); - if (cmp == 0) { - if (st & EQUAL) { - match_h = h; - break; - } - cmp = -target_cmp; - } else if (target_cmp != 0) - if (!((cmp ^ target_cmp) & MASK_HIGH_BIT)) - // cmp and target_cmp are both positive or both negative. - match_h = h; - h = cmp < 0 ? get_lt(h) : get_gt(h); - } - - return match_h; -} - -template <class Abstractor, unsigned maxDepth, class BSet> -inline typename AVLTree<Abstractor, maxDepth, BSet>::handle -AVLTree<Abstractor, maxDepth, BSet>::search_least() -{ - handle h = abs.root, parent = null(); - - while (h != null()) { - parent = h; - h = get_lt(h); - } - - return parent; -} - -template <class Abstractor, unsigned maxDepth, class BSet> -inline typename AVLTree<Abstractor, maxDepth, BSet>::handle -AVLTree<Abstractor, maxDepth, BSet>::search_greatest() -{ - handle h = abs.root, parent = null(); - - while (h != null()) { - parent = h; - h = get_gt(h); - } - - return parent; -} - -template <class Abstractor, unsigned maxDepth, class BSet> -inline typename AVLTree<Abstractor, maxDepth, BSet>::handle -AVLTree<Abstractor, maxDepth, BSet>::remove(key k) -{ - // Zero-based depth in tree. - unsigned depth = 0, rm_depth; - - // Records a path into the tree. If branch[n] is true, indicates - // take greater branch from the nth node in the path, otherwise - // take the less branch. branch[0] gives branch from root, and - // so on. - BSet branch; - - handle h = abs.root; - handle parent = null(), child; - int cmp, cmp_shortened_sub_with_path = 0; - - for (;;) { - if (h == null()) - // No node in tree with given key. - return null(); - cmp = cmp_k_n(k, h); - if (cmp == 0) - // Found node to remove. - break; - parent = h; - h = cmp < 0 ? get_lt(h) : get_gt(h); - branch[depth++] = cmp > 0; - cmp_shortened_sub_with_path = cmp; - } - handle rm = h; - handle parent_rm = parent; - rm_depth = depth; - - // If the node to remove is not a leaf node, we need to get a - // leaf node, or a node with a single leaf as its child, to put - // in the place of the node to remove. We will get the greatest - // node in the less subtree (of the node to remove), or the least - // node in the greater subtree. We take the leaf node from the - // deeper subtree, if there is one. - - if (get_bf(h) < 0) { - child = get_lt(h); - branch[depth] = false; - cmp = -1; - } else { - child = get_gt(h); - branch[depth] = true; - cmp = 1; - } - depth++; - - if (child != null()) { - cmp = -cmp; - do { - parent = h; - h = child; - if (cmp < 0) { - child = get_lt(h); - branch[depth] = false; - } else { - child = get_gt(h); - branch[depth] = true; - } - depth++; - } while (child != null()); - - if (parent == rm) - // Only went through do loop once. Deleted node will be replaced - // in the tree structure by one of its immediate children. - cmp_shortened_sub_with_path = -cmp; - else - cmp_shortened_sub_with_path = cmp; - - // Get the handle of the opposite child, which may not be null. - child = cmp > 0 ? get_lt(h) : get_gt(h); - } - - if (parent == null()) - // There were only 1 or 2 nodes in this tree. - abs.root = child; - else if (cmp_shortened_sub_with_path < 0) - set_lt(parent, child); - else - set_gt(parent, child); - - // "path" is the parent of the subtree being eliminated or reduced - // from a depth of 2 to 1. If "path" is the node to be removed, we - // set path to the node we're about to poke into the position of the - // node to be removed. - handle path = parent == rm ? h : parent; - - if (h != rm) { - // Poke in the replacement for the node to be removed. - set_lt(h, get_lt(rm)); - set_gt(h, get_gt(rm)); - set_bf(h, get_bf(rm)); - if (parent_rm == null()) - abs.root = h; - else { - depth = rm_depth - 1; - if (branch[depth]) - set_gt(parent_rm, h); - else - set_lt(parent_rm, h); - } - } - - if (path != null()) { - // Create a temporary linked list from the parent of the path node - // to the root node. - h = abs.root; - parent = null(); - depth = 0; - while (h != path) { - if (branch[depth++]) { - child = get_gt(h); - set_gt(h, parent); - } else { - child = get_lt(h); - set_lt(h, parent); - } - parent = h; - h = child; - } - - // Climb from the path node to the root node using the linked - // list, restoring the tree structure and rebalancing as necessary. - bool reduced_depth = true; - int bf; - cmp = cmp_shortened_sub_with_path; - for (;;) { - if (reduced_depth) { - bf = get_bf(h); - if (cmp < 0) - bf++; - else // cmp > 0 - bf--; - if ((bf == -2) || (bf == 2)) { - h = balance(h); - bf = get_bf(h); - } else - set_bf(h, bf); - reduced_depth = (bf == 0); - } - if (parent == null()) - break; - child = h; - h = parent; - cmp = branch[--depth] ? 1 : -1; - if (cmp < 0) { - parent = get_lt(h); - set_lt(h, child); - } else { - parent = get_gt(h); - set_gt(h, child); - } - } - abs.root = h; - } - - return rm; -} - -template <class Abstractor, unsigned maxDepth, class BSet> -inline typename AVLTree<Abstractor, maxDepth, BSet>::handle -AVLTree<Abstractor, maxDepth, BSet>::subst(handle new_node) -{ - handle h = abs.root; - handle parent = null(); - int cmp, last_cmp; - - /* Search for node already in tree with same key. */ - for (;;) { - if (h == null()) - /* No node in tree with same key as new node. */ - return null(); - cmp = cmp_n_n(new_node, h); - if (cmp == 0) - /* Found the node to substitute new one for. */ - break; - last_cmp = cmp; - parent = h; - h = cmp < 0 ? get_lt(h) : get_gt(h); - } - - /* Copy tree housekeeping fields from node in tree to new node. */ - set_lt(new_node, get_lt(h)); - set_gt(new_node, get_gt(h)); - set_bf(new_node, get_bf(h)); - - if (parent == null()) - /* New node is also new root. */ - abs.root = new_node; - else { - /* Make parent point to new node. */ - if (last_cmp < 0) - set_lt(parent, new_node); - else - set_gt(parent, new_node); - } - - return h; -} - -} - -#endif diff --git a/Source/JavaScriptCore/wtf/Alignment.h b/Source/JavaScriptCore/wtf/Alignment.h deleted file mode 100644 index ac780b96e..000000000 --- a/Source/JavaScriptCore/wtf/Alignment.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 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 WTF_Alignment_h -#define WTF_Alignment_h - -#include <wtf/Platform.h> -#include <algorithm> - -namespace WTF { - -#if COMPILER(GCC) || COMPILER(MINGW) || COMPILER(RVCT) || COMPILER(GCCE) || (COMPILER(SUNCC) && __SUNPRO_CC > 0x590) - #define WTF_ALIGN_OF(type) __alignof__(type) - #define WTF_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((__aligned__(n))) -#elif COMPILER(MSVC) - #define WTF_ALIGN_OF(type) __alignof(type) - #define WTF_ALIGNED(variable_type, variable, n) __declspec(align(n)) variable_type variable -#else - #error WTF_ALIGN macros need alignment control. -#endif - -#if COMPILER(GCC) && !COMPILER(INTEL) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303) - typedef char __attribute__((__may_alias__)) AlignedBufferChar; -#else - typedef char AlignedBufferChar; -#endif - - template<size_t size, size_t alignment> struct AlignedBuffer; - template<size_t size> struct AlignedBuffer<size, 1> { AlignedBufferChar buffer[size]; }; - template<size_t size> struct AlignedBuffer<size, 2> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 2); }; - template<size_t size> struct AlignedBuffer<size, 4> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 4); }; - template<size_t size> struct AlignedBuffer<size, 8> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 8); }; - template<size_t size> struct AlignedBuffer<size, 16> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 16); }; - template<size_t size> struct AlignedBuffer<size, 32> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 32); }; - template<size_t size> struct AlignedBuffer<size, 64> { WTF_ALIGNED(AlignedBufferChar, buffer[size], 64); }; - - template <size_t size, size_t alignment> - void swap(AlignedBuffer<size, alignment>& a, AlignedBuffer<size, alignment>& b) - { - for (size_t i = 0; i < size; ++i) - std::swap(a.buffer[i], b.buffer[i]); - } - -} - -#endif // WTF_Alignment_h diff --git a/Source/JavaScriptCore/wtf/AlwaysInline.h b/Source/JavaScriptCore/wtf/AlwaysInline.h deleted file mode 100644 index 68b7ae1a8..000000000 --- a/Source/JavaScriptCore/wtf/AlwaysInline.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2005, 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. - * - */ - -/* This file is no longer necessary, since all the functionality has been moved to Compiler.h. */ - -#include <wtf/Platform.h> diff --git a/Source/JavaScriptCore/wtf/ArrayBuffer.cpp b/Source/JavaScriptCore/wtf/ArrayBuffer.cpp deleted file mode 100644 index 45cfa1deb..000000000 --- a/Source/JavaScriptCore/wtf/ArrayBuffer.cpp +++ /dev/null @@ -1,78 +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 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 "ArrayBuffer.h" - -#include "ArrayBufferView.h" - -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> - -namespace WTF { - -bool ArrayBuffer::transfer(ArrayBufferContents& result, Vector<RefPtr<ArrayBufferView> >& neuteredViews) -{ - RefPtr<ArrayBuffer> keepAlive(this); - - if (!m_contents.m_data) { - result.m_data = 0; - return false; - } - - m_contents.transfer(result); - - while (m_firstView) { - ArrayBufferView* current = m_firstView; - removeView(current); - current->neuter(); - neuteredViews.append(current); - } - return true; -} - -void ArrayBuffer::addView(ArrayBufferView* view) -{ - view->m_buffer = this; - view->m_prevView = 0; - view->m_nextView = m_firstView; - if (m_firstView) - m_firstView->m_prevView = view; - m_firstView = view; -} - -void ArrayBuffer::removeView(ArrayBufferView* view) -{ - ASSERT(this == view->m_buffer); - if (view->m_nextView) - view->m_nextView->m_prevView = view->m_prevView; - if (view->m_prevView) - view->m_prevView->m_nextView = view->m_nextView; - if (m_firstView == view) - m_firstView = view->m_nextView; - view->m_prevView = view->m_nextView = 0; -} - -} diff --git a/Source/JavaScriptCore/wtf/ArrayBuffer.h b/Source/JavaScriptCore/wtf/ArrayBuffer.h deleted file mode 100644 index 3257df3d0..000000000 --- a/Source/JavaScriptCore/wtf/ArrayBuffer.h +++ /dev/null @@ -1,220 +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 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 ArrayBuffer_h -#define ArrayBuffer_h - -#include <wtf/HashSet.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/Vector.h> - -namespace WTF { - -class ArrayBuffer; -class ArrayBufferView; - -class ArrayBufferContents { - WTF_MAKE_NONCOPYABLE(ArrayBufferContents); -public: - ArrayBufferContents() - : m_data(0) - , m_sizeInBytes(0) - { } - - inline ~ArrayBufferContents(); - - void* data() { return m_data; } - unsigned sizeInBytes() { return m_sizeInBytes; } - -private: - ArrayBufferContents(void* data, unsigned sizeInBytes) - : m_data(data) - , m_sizeInBytes(sizeInBytes) - { } - - friend class ArrayBuffer; - - static inline void tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents&); - void transfer(ArrayBufferContents& other) - { - ASSERT(!other.m_data); - other.m_data = m_data; - other.m_sizeInBytes = m_sizeInBytes; - m_data = 0; - m_sizeInBytes = 0; - } - - void* m_data; - unsigned m_sizeInBytes; -}; - -class ArrayBuffer : public RefCounted<ArrayBuffer> { -public: - static inline PassRefPtr<ArrayBuffer> create(unsigned numElements, unsigned elementByteSize); - static inline PassRefPtr<ArrayBuffer> create(ArrayBuffer*); - static inline PassRefPtr<ArrayBuffer> create(const void* source, unsigned byteLength); - static inline PassRefPtr<ArrayBuffer> create(ArrayBufferContents&); - - inline void* data(); - inline const void* data() const; - inline unsigned byteLength() const; - - inline PassRefPtr<ArrayBuffer> slice(int begin, int end) const; - inline PassRefPtr<ArrayBuffer> slice(int begin) const; - - void addView(ArrayBufferView*); - void removeView(ArrayBufferView*); - - WTF_EXPORT_PRIVATE bool transfer(ArrayBufferContents&, Vector<RefPtr<ArrayBufferView> >& neuteredViews); - bool isNeutered() { return !m_contents.m_data; } - - ~ArrayBuffer() { } - -private: - inline ArrayBuffer(ArrayBufferContents&); - inline PassRefPtr<ArrayBuffer> sliceImpl(unsigned begin, unsigned end) const; - inline unsigned clampIndex(int index) const; - static inline int clampValue(int x, int left, int right); - - ArrayBufferContents m_contents; - ArrayBufferView* m_firstView; -}; - -int ArrayBuffer::clampValue(int x, int left, int right) -{ - ASSERT(left <= right); - if (x < left) - x = left; - if (right < x) - x = right; - return x; -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::create(unsigned numElements, unsigned elementByteSize) -{ - ArrayBufferContents contents; - ArrayBufferContents::tryAllocate(numElements, elementByteSize, contents); - if (!contents.m_data) - return 0; - return adoptRef(new ArrayBuffer(contents)); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBuffer* other) -{ - return ArrayBuffer::create(other->data(), other->byteLength()); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::create(const void* source, unsigned byteLength) -{ - ArrayBufferContents contents; - ArrayBufferContents::tryAllocate(byteLength, 1, contents); - if (!contents.m_data) - return 0; - RefPtr<ArrayBuffer> buffer = adoptRef(new ArrayBuffer(contents)); - memcpy(buffer->data(), source, byteLength); - return buffer.release(); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::create(ArrayBufferContents& contents) -{ - return adoptRef(new ArrayBuffer(contents)); -} - -ArrayBuffer::ArrayBuffer(ArrayBufferContents& contents) - : m_firstView(0) -{ - contents.transfer(m_contents); -} - -void* ArrayBuffer::data() -{ - return m_contents.m_data; -} - -const void* ArrayBuffer::data() const -{ - return m_contents.m_data; -} - -unsigned ArrayBuffer::byteLength() const -{ - return m_contents.m_sizeInBytes; -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin, int end) const -{ - return sliceImpl(clampIndex(begin), clampIndex(end)); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::slice(int begin) const -{ - return sliceImpl(clampIndex(begin), byteLength()); -} - -PassRefPtr<ArrayBuffer> ArrayBuffer::sliceImpl(unsigned begin, unsigned end) const -{ - unsigned size = begin <= end ? end - begin : 0; - return ArrayBuffer::create(static_cast<const char*>(data()) + begin, size); -} - -unsigned ArrayBuffer::clampIndex(int index) const -{ - unsigned currentLength = byteLength(); - if (index < 0) - index = currentLength + index; - return clampValue(index, 0, currentLength); -} - -void ArrayBufferContents::tryAllocate(unsigned numElements, unsigned elementByteSize, ArrayBufferContents& result) -{ - // Do not allow 32-bit overflow of the total size. - // FIXME: Why not? The tryFastCalloc function already checks its arguments, - // and will fail if there is any overflow, so why should we include a - // redudant unnecessarily restrictive check here? - if (numElements) { - unsigned totalSize = numElements * elementByteSize; - if (totalSize / numElements != elementByteSize) { - result.m_data = 0; - return; - } - } - if (WTF::tryFastCalloc(numElements, elementByteSize).getValue(result.m_data)) { - result.m_sizeInBytes = numElements * elementByteSize; - return; - } - result.m_data = 0; -} - -ArrayBufferContents::~ArrayBufferContents() -{ - WTF::fastFree(m_data); -} - -} // namespace WTF - -using WTF::ArrayBuffer; - -#endif // ArrayBuffer_h diff --git a/Source/JavaScriptCore/wtf/ArrayBufferView.cpp b/Source/JavaScriptCore/wtf/ArrayBufferView.cpp deleted file mode 100644 index 67dbdcf8c..000000000 --- a/Source/JavaScriptCore/wtf/ArrayBufferView.cpp +++ /dev/null @@ -1,55 +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 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 "ArrayBufferView.h" - -#include "ArrayBuffer.h" - -namespace WTF { - -ArrayBufferView::ArrayBufferView(PassRefPtr<ArrayBuffer> buffer, - unsigned byteOffset) - : m_byteOffset(byteOffset) - , m_buffer(buffer) -{ - m_baseAddress = m_buffer ? (static_cast<char*>(m_buffer->data()) + m_byteOffset) : 0; - if (m_buffer) - m_buffer->addView(this); -} - -ArrayBufferView::~ArrayBufferView() -{ - if (m_buffer) - m_buffer->removeView(this); -} - -void ArrayBufferView::neuter() -{ - m_buffer = 0; - m_byteOffset = 0; -} - -} diff --git a/Source/JavaScriptCore/wtf/ArrayBufferView.h b/Source/JavaScriptCore/wtf/ArrayBufferView.h deleted file mode 100644 index f314dd56c..000000000 --- a/Source/JavaScriptCore/wtf/ArrayBufferView.h +++ /dev/null @@ -1,201 +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 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 ArrayBufferView_h -#define ArrayBufferView_h - -#include <wtf/ArrayBuffer.h> - -#include <algorithm> -#include <limits.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> - -namespace WTF { - -class WTF_EXPORT_PRIVATE_RTTI ArrayBufferView : public RefCounted<ArrayBufferView> { - public: - virtual bool isByteArray() const { return false; } - virtual bool isUnsignedByteArray() const { return false; } - virtual bool isUnsignedByteClampedArray() const { return false; } - virtual bool isShortArray() const { return false; } - virtual bool isUnsignedShortArray() const { return false; } - virtual bool isIntArray() const { return false; } - virtual bool isUnsignedIntArray() const { return false; } - virtual bool isFloatArray() const { return false; } - virtual bool isDoubleArray() const { return false; } - virtual bool isDataView() const { return false; } - - PassRefPtr<ArrayBuffer> buffer() const - { - return m_buffer; - } - - void* baseAddress() const - { - return m_baseAddress; - } - - unsigned byteOffset() const - { - return m_byteOffset; - } - - virtual unsigned byteLength() const = 0; - - WTF_EXPORT_PRIVATE virtual ~ArrayBufferView(); - - protected: - WTF_EXPORT_PRIVATE ArrayBufferView(PassRefPtr<ArrayBuffer>, unsigned byteOffset); - - inline bool setImpl(ArrayBufferView*, unsigned byteOffset); - - inline bool setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset); - - inline bool zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength); - - static inline void calculateOffsetAndLength(int start, int end, unsigned arraySize, - unsigned* offset, unsigned* length); - - // Helper to verify that a given sub-range of an ArrayBuffer is - // within range. - template <typename T> - static bool verifySubRange(PassRefPtr<ArrayBuffer> buffer, - unsigned byteOffset, - unsigned numElements) - { - if (!buffer) - return false; - if (sizeof(T) > 1 && byteOffset % sizeof(T)) - return false; - if (byteOffset > buffer->byteLength()) - return false; - unsigned remainingElements = (buffer->byteLength() - byteOffset) / sizeof(T); - if (numElements > remainingElements) - return false; - return true; - } - - // Input offset is in number of elements from this array's view; - // output offset is in number of bytes from the underlying buffer's view. - template <typename T> - static void clampOffsetAndNumElements(PassRefPtr<ArrayBuffer> buffer, - unsigned arrayByteOffset, - unsigned *offset, - unsigned *numElements) - { - unsigned maxOffset = (UINT_MAX - arrayByteOffset) / sizeof(T); - if (*offset > maxOffset) { - *offset = buffer->byteLength(); - *numElements = 0; - return; - } - *offset = arrayByteOffset + *offset * sizeof(T); - *offset = std::min(buffer->byteLength(), *offset); - unsigned remainingElements = (buffer->byteLength() - *offset) / sizeof(T); - *numElements = std::min(remainingElements, *numElements); - } - - WTF_EXPORT_PRIVATE virtual void neuter(); - - // This is the address of the ArrayBuffer's storage, plus the byte offset. - void* m_baseAddress; - - unsigned m_byteOffset; - - private: - friend class ArrayBuffer; - RefPtr<ArrayBuffer> m_buffer; - ArrayBufferView* m_prevView; - ArrayBufferView* m_nextView; -}; - -bool ArrayBufferView::setImpl(ArrayBufferView* array, unsigned byteOffset) -{ - if (byteOffset > byteLength() - || byteOffset + array->byteLength() > byteLength() - || byteOffset + array->byteLength() < byteOffset) { - // Out of range offset or overflow - return false; - } - - char* base = static_cast<char*>(baseAddress()); - memmove(base + byteOffset, array->baseAddress(), array->byteLength()); - return true; -} - -bool ArrayBufferView::setRangeImpl(const char* data, size_t dataByteLength, unsigned byteOffset) -{ - if (byteOffset > byteLength() - || byteOffset + dataByteLength > byteLength() - || byteOffset + dataByteLength < byteOffset) { - // Out of range offset or overflow - return false; - } - - char* base = static_cast<char*>(baseAddress()); - memmove(base + byteOffset, data, dataByteLength); - return true; -} - -bool ArrayBufferView::zeroRangeImpl(unsigned byteOffset, size_t rangeByteLength) -{ - if (byteOffset > byteLength() - || byteOffset + rangeByteLength > byteLength() - || byteOffset + rangeByteLength < byteOffset) { - // Out of range offset or overflow - return false; - } - - char* base = static_cast<char*>(baseAddress()); - memset(base + byteOffset, 0, rangeByteLength); - return true; -} - -void ArrayBufferView::calculateOffsetAndLength(int start, int end, unsigned arraySize, - unsigned* offset, unsigned* length) -{ - if (start < 0) - start += arraySize; - if (start < 0) - start = 0; - if (end < 0) - end += arraySize; - if (end < 0) - end = 0; - if (static_cast<unsigned>(end) > arraySize) - end = arraySize; - if (end < start) - end = start; - *offset = static_cast<unsigned>(start); - *length = static_cast<unsigned>(end - start); -} - -} // namespace WTF - -using WTF::ArrayBufferView; - -#endif // ArrayBufferView_h diff --git a/Source/JavaScriptCore/wtf/Assertions.cpp b/Source/JavaScriptCore/wtf/Assertions.cpp deleted file mode 100644 index 9e744d387..000000000 --- a/Source/JavaScriptCore/wtf/Assertions.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright (C) 2003, 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2007-2009 Torch Mobile, 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. - * - * 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. - */ - -// The vprintf_stderr_common function triggers this error in the Mac build. -// Feel free to remove this pragma if this file builds on Mac. -// According to http://gcc.gnu.org/onlinedocs/gcc-4.2.1/gcc/Diagnostic-Pragmas.html#Diagnostic-Pragmas -// we need to place this directive before any data or functions are defined. -#pragma GCC diagnostic ignored "-Wmissing-format-attribute" - -#include "config.h" -#include "Assertions.h" - -#include "OwnArrayPtr.h" - -#include <stdio.h> -#include <stdarg.h> -#include <string.h> - -#if PLATFORM(MAC) -#include <CoreFoundation/CFString.h> -#include <asl.h> -#endif - -#if COMPILER(MSVC) && !OS(WINCE) -#include <crtdbg.h> -#endif - -#if OS(WINDOWS) -#include <windows.h> -#endif - -#if OS(DARWIN) || OS(LINUX) -#include <cxxabi.h> -#include <dlfcn.h> -#include <execinfo.h> -#endif - -#if PLATFORM(BLACKBERRY) -#include <BlackBerryPlatformLog.h> -#endif - -extern "C" { - -WTF_ATTRIBUTE_PRINTF(1, 0) -static void vprintf_stderr_common(const char* format, va_list args) -{ -#if PLATFORM(MAC) - if (strstr(format, "%@")) { - CFStringRef cfFormat = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8); - -#if COMPILER(CLANG) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat-nonliteral" -#endif - CFStringRef str = CFStringCreateWithFormatAndArguments(NULL, NULL, cfFormat, args); -#if COMPILER(CLANG) -#pragma clang diagnostic pop -#endif - int length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str), kCFStringEncodingUTF8); - char* buffer = (char*)malloc(length + 1); - - CFStringGetCString(str, buffer, length, kCFStringEncodingUTF8); - -#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) - asl_log(0, 0, ASL_LEVEL_NOTICE, "%s", buffer); -#endif - fputs(buffer, stderr); - - free(buffer); - CFRelease(str); - CFRelease(cfFormat); - return; - } - -#if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) - va_list copyOfArgs; - va_copy(copyOfArgs, args); - asl_vlog(0, 0, ASL_LEVEL_NOTICE, format, copyOfArgs); - va_end(copyOfArgs); -#endif - - // Fall through to write to stderr in the same manner as other platforms. - -#elif PLATFORM(BLACKBERRY) - BlackBerry::Platform::logStreamV(format, args); -#elif HAVE(ISDEBUGGERPRESENT) - if (IsDebuggerPresent()) { - size_t size = 1024; - - do { - char* buffer = (char*)malloc(size); - - if (buffer == NULL) - break; - - if (_vsnprintf(buffer, size, format, args) != -1) { -#if OS(WINCE) - // WinCE only supports wide chars - wchar_t* wideBuffer = (wchar_t*)malloc(size * sizeof(wchar_t)); - if (wideBuffer == NULL) - break; - for (unsigned int i = 0; i < size; ++i) { - if (!(wideBuffer[i] = buffer[i])) - break; - } - OutputDebugStringW(wideBuffer); - free(wideBuffer); -#else - OutputDebugStringA(buffer); -#endif - free(buffer); - break; - } - - free(buffer); - size *= 2; - } while (size > 1024); - } -#endif -#if !PLATFORM(BLACKBERRY) - vfprintf(stderr, format, args); -#endif -} - -#if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0)) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" -#endif - -static void vprintf_stderr_with_prefix(const char* prefix, const char* format, va_list args) -{ - size_t prefixLength = strlen(prefix); - size_t formatLength = strlen(format); - OwnArrayPtr<char> formatWithPrefix = adoptArrayPtr(new char[prefixLength + formatLength + 1]); - memcpy(formatWithPrefix.get(), prefix, prefixLength); - memcpy(formatWithPrefix.get() + prefixLength, format, formatLength); - formatWithPrefix[prefixLength + formatLength] = 0; - - vprintf_stderr_common(formatWithPrefix.get(), args); -} - -static void vprintf_stderr_with_trailing_newline(const char* format, va_list args) -{ - size_t formatLength = strlen(format); - if (formatLength && format[formatLength - 1] == '\n') { - vprintf_stderr_common(format, args); - return; - } - - OwnArrayPtr<char> formatWithNewline = adoptArrayPtr(new char[formatLength + 2]); - memcpy(formatWithNewline.get(), format, formatLength); - formatWithNewline[formatLength] = '\n'; - formatWithNewline[formatLength + 1] = 0; - - vprintf_stderr_common(formatWithNewline.get(), args); -} - -#if COMPILER(CLANG) || (COMPILER(GCC) && GCC_VERSION_AT_LEAST(4, 6, 0)) -#pragma GCC diagnostic pop -#endif - -WTF_ATTRIBUTE_PRINTF(1, 2) -static void printf_stderr_common(const char* format, ...) -{ - va_list args; - va_start(args, format); - vprintf_stderr_common(format, args); - va_end(args); -} - -static void printCallSite(const char* file, int line, const char* function) -{ -#if OS(WINDOWS) && !OS(WINCE) && defined(_DEBUG) - _CrtDbgReport(_CRT_WARN, file, line, NULL, "%s\n", function); -#else - // By using this format, which matches the format used by MSVC for compiler errors, developers - // using Visual Studio can double-click the file/line number in the Output Window to have the - // editor navigate to that line of code. It seems fine for other developers, too. - printf_stderr_common("%s(%d) : %s\n", file, line, function); -#endif -} - -#if PLATFORM(BLACKBERRY) -struct WTFLogLocker { - WTFLogLocker(BlackBerry::Platform::MessageLogLevel logLevel) - { - BlackBerry::Platform::lockLogging(logLevel); - } - - ~WTFLogLocker() - { - BlackBerry::Platform::unlockLogging(); - } -}; -#endif - -void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion) -{ -#if PLATFORM(BLACKBERRY) - WTFLogLocker locker(BlackBerry::Platform::LogLevelCritical); -#endif - - if (assertion) - printf_stderr_common("ASSERTION FAILED: %s\n", assertion); - else - printf_stderr_common("SHOULD NEVER BE REACHED\n"); - printCallSite(file, line, function); -} - -void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) -{ -#if PLATFORM(BLACKBERRY) - WTFLogLocker locker(BlackBerry::Platform::LogLevelCritical); -#endif - - va_list args; - va_start(args, format); - vprintf_stderr_with_prefix("ASSERTION FAILED: ", format, args); - va_end(args); - printf_stderr_common("\n%s\n", assertion); - printCallSite(file, line, function); -} - -void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion) -{ -#if PLATFORM(BLACKBERRY) - WTFLogLocker locker(BlackBerry::Platform::LogLevelCritical); -#endif - - printf_stderr_common("ARGUMENT BAD: %s, %s\n", argName, assertion); - printCallSite(file, line, function); -} - -void WTFGetBacktrace(void** stack, int* size) -{ -#if OS(DARWIN) || OS(LINUX) - *size = backtrace(stack, *size); -#elif OS(WINDOWS) && !OS(WINCE) - // The CaptureStackBackTrace function is available in XP, but it is not defined - // in the Windows Server 2003 R2 Platform SDK. So, we'll grab the function - // through GetProcAddress. - typedef WORD (NTAPI* RtlCaptureStackBackTraceFunc)(DWORD, DWORD, PVOID*, PDWORD); - HMODULE kernel32 = ::GetModuleHandleW(L"Kernel32.dll"); - if (!kernel32) { - *size = 0; - return; - } - RtlCaptureStackBackTraceFunc captureStackBackTraceFunc = reinterpret_cast<RtlCaptureStackBackTraceFunc>( - ::GetProcAddress(kernel32, "RtlCaptureStackBackTrace")); - if (captureStackBackTraceFunc) - *size = captureStackBackTraceFunc(0, *size, stack, 0); - else - *size = 0; -#else - *size = 0; -#endif -} - -#if OS(DARWIN) || OS(LINUX) -# if PLATFORM(QT) || PLATFORM(GTK) -# if defined(__GLIBC__) && !defined(__UCLIBC__) -# define WTF_USE_BACKTRACE_SYMBOLS 1 -# endif -# else -# define WTF_USE_DLADDR 1 -# endif -#endif - -void WTFReportBacktrace() -{ - static const int framesToShow = 31; - static const int framesToSkip = 2; - void* samples[framesToShow + framesToSkip]; - int frames = framesToShow + framesToSkip; - - WTFGetBacktrace(samples, &frames); - -#if USE(BACKTRACE_SYMBOLS) - char** symbols = backtrace_symbols(samples, frames); - if (!symbols) - return; -#endif - - for (int i = framesToSkip; i < frames; ++i) { - const char* mangledName = 0; - char* cxaDemangled = 0; -#if USE(BACKTRACE_SYMBOLS) - mangledName = symbols[i]; -#elif USE(DLADDR) - Dl_info info; - if (dladdr(samples[i], &info) && info.dli_sname) - mangledName = info.dli_sname; - if (mangledName) - cxaDemangled = abi::__cxa_demangle(mangledName, 0, 0, 0); -#endif - const int frameNumber = i - framesToSkip + 1; - if (mangledName || cxaDemangled) - printf_stderr_common("%-3d %p %s\n", frameNumber, samples[i], cxaDemangled ? cxaDemangled : mangledName); - else - printf_stderr_common("%-3d %p\n", frameNumber, samples[i]); - free(cxaDemangled); - } - -#if USE(BACKTRACE_SYMBOLS) - free(symbols); -#endif -} - -#undef WTF_USE_BACKTRACE_SYMBOLS -#undef WTF_USE_DLADDR - -static WTFCrashHookFunction globalHook = 0; - -void WTFSetCrashHook(WTFCrashHookFunction function) -{ - globalHook = function; -} - -void WTFInvokeCrashHook() -{ - if (globalHook) - globalHook(); -} - -void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) -{ -#if PLATFORM(BLACKBERRY) - WTFLogLocker locker(BlackBerry::Platform::LogLevelCritical); -#endif - - va_list args; - va_start(args, format); - vprintf_stderr_with_prefix("FATAL ERROR: ", format, args); - va_end(args); - printf_stderr_common("\n"); - printCallSite(file, line, function); -} - -void WTFReportError(const char* file, int line, const char* function, const char* format, ...) -{ -#if PLATFORM(BLACKBERRY) - WTFLogLocker locker(BlackBerry::Platform::LogLevelWarn); -#endif - - va_list args; - va_start(args, format); - vprintf_stderr_with_prefix("ERROR: ", format, args); - va_end(args); - printf_stderr_common("\n"); - printCallSite(file, line, function); -} - -void WTFLog(WTFLogChannel* channel, const char* format, ...) -{ - if (channel->state != WTFLogChannelOn) - return; - -#if PLATFORM(BLACKBERRY) - WTFLogLocker locker(BlackBerry::Platform::LogLevelInfo); -#endif - - va_list args; - va_start(args, format); - vprintf_stderr_with_trailing_newline(format, args); - va_end(args); -} - -void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel* channel, const char* format, ...) -{ - if (channel->state != WTFLogChannelOn) - return; - -#if PLATFORM(BLACKBERRY) - WTFLogLocker locker(BlackBerry::Platform::LogLevelInfo); -#endif - - va_list args; - va_start(args, format); - vprintf_stderr_with_trailing_newline(format, args); - va_end(args); - - printCallSite(file, line, function); -} - -} // extern "C" diff --git a/Source/JavaScriptCore/wtf/Assertions.h b/Source/JavaScriptCore/wtf/Assertions.h deleted file mode 100644 index 14b9091fd..000000000 --- a/Source/JavaScriptCore/wtf/Assertions.h +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2003, 2006, 2007 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 WTF_Assertions_h -#define WTF_Assertions_h - -/* - no namespaces because this file has to be includable from C and Objective-C - - Note, this file uses many GCC extensions, but it should be compatible with - C, Objective C, C++, and Objective C++. - - For non-debug builds, everything is disabled by default. - Defining any of the symbols explicitly prevents this from having any effect. - - MSVC7 note: variadic macro support was added in MSVC8, so for now we disable - those macros in MSVC7. For more info, see the MSDN document on variadic - macros here: - - http://msdn2.microsoft.com/en-us/library/ms177415(VS.80).aspx -*/ - -#include <wtf/Platform.h> - -#include <stddef.h> - -#if !COMPILER(MSVC) -#include <inttypes.h> -#endif - -#ifdef NDEBUG -/* Disable ASSERT* macros in release mode. */ -#define ASSERTIONS_DISABLED_DEFAULT 1 -#else -#define ASSERTIONS_DISABLED_DEFAULT 0 -#endif - -#if COMPILER(MSVC7_OR_LOWER) -#define HAVE_VARIADIC_MACRO 0 -#else -#define HAVE_VARIADIC_MACRO 1 -#endif - -#ifndef BACKTRACE_DISABLED -#define BACKTRACE_DISABLED ASSERTIONS_DISABLED_DEFAULT -#endif - -#ifndef ASSERT_DISABLED -#define ASSERT_DISABLED ASSERTIONS_DISABLED_DEFAULT -#endif - -#ifndef ASSERT_MSG_DISABLED -#if HAVE(VARIADIC_MACRO) -#define ASSERT_MSG_DISABLED ASSERTIONS_DISABLED_DEFAULT -#else -#define ASSERT_MSG_DISABLED 1 -#endif -#endif - -#ifndef ASSERT_ARG_DISABLED -#define ASSERT_ARG_DISABLED ASSERTIONS_DISABLED_DEFAULT -#endif - -#ifndef FATAL_DISABLED -#if HAVE(VARIADIC_MACRO) -#define FATAL_DISABLED ASSERTIONS_DISABLED_DEFAULT -#else -#define FATAL_DISABLED 1 -#endif -#endif - -#ifndef ERROR_DISABLED -#if HAVE(VARIADIC_MACRO) -#define ERROR_DISABLED ASSERTIONS_DISABLED_DEFAULT -#else -#define ERROR_DISABLED 1 -#endif -#endif - -#ifndef LOG_DISABLED -#if HAVE(VARIADIC_MACRO) -#define LOG_DISABLED ASSERTIONS_DISABLED_DEFAULT -#else -#define LOG_DISABLED 1 -#endif -#endif - -#if COMPILER(GCC) -#define WTF_PRETTY_FUNCTION __PRETTY_FUNCTION__ -#else -#define WTF_PRETTY_FUNCTION __FUNCTION__ -#endif - -/* WTF logging functions can process %@ in the format string to log a NSObject* but the printf format attribute - emits a warning when %@ is used in the format string. Until <rdar://problem/5195437> is resolved we can't include - the attribute when being used from Objective-C code in case it decides to use %@. */ -#if COMPILER(GCC) && !defined(__OBJC__) -#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) __attribute__((__format__(printf, formatStringArgument, extraArguments))) -#else -#define WTF_ATTRIBUTE_PRINTF(formatStringArgument, extraArguments) -#endif - -/* These helper functions are always declared, but not necessarily always defined if the corresponding function is disabled. */ - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { WTFLogChannelOff, WTFLogChannelOn } WTFLogChannelState; - -typedef struct { - unsigned mask; - const char *defaultName; - WTFLogChannelState state; -} WTFLogChannel; - -WTF_EXPORT_PRIVATE void WTFReportAssertionFailure(const char* file, int line, const char* function, const char* assertion); -WTF_EXPORT_PRIVATE void WTFReportAssertionFailureWithMessage(const char* file, int line, const char* function, const char* assertion, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); -WTF_EXPORT_PRIVATE void WTFReportArgumentAssertionFailure(const char* file, int line, const char* function, const char* argName, const char* assertion); -WTF_EXPORT_PRIVATE void WTFReportFatalError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); -WTF_EXPORT_PRIVATE void WTFReportError(const char* file, int line, const char* function, const char* format, ...) WTF_ATTRIBUTE_PRINTF(4, 5); -WTF_EXPORT_PRIVATE void WTFLog(WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(2, 3); -WTF_EXPORT_PRIVATE void WTFLogVerbose(const char* file, int line, const char* function, WTFLogChannel*, const char* format, ...) WTF_ATTRIBUTE_PRINTF(5, 6); - -WTF_EXPORT_PRIVATE void WTFGetBacktrace(void** stack, int* size); -WTF_EXPORT_PRIVATE void WTFReportBacktrace(); - -typedef void (*WTFCrashHookFunction)(); -WTF_EXPORT_PRIVATE void WTFSetCrashHook(WTFCrashHookFunction); -WTF_EXPORT_PRIVATE void WTFInvokeCrashHook(); - -#ifdef __cplusplus -} -#endif - -/* 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 COMPILER(CLANG) -#define CRASH() do { \ - WTFReportBacktrace(); \ - WTFInvokeCrashHook(); \ - *(int *)(uintptr_t)0xbbadbeef = 0; \ - __builtin_trap(); \ -} while (false) -#else -#define CRASH() do { \ - WTFReportBacktrace(); \ - WTFInvokeCrashHook(); \ - *(int *)(uintptr_t)0xbbadbeef = 0; \ - ((void(*)())0)(); /* More reliable, but doesn't say BBADBEEF */ \ -} while (false) -#endif -#endif - -#if COMPILER(CLANG) -#define NO_RETURN_DUE_TO_CRASH NO_RETURN -#else -#define NO_RETURN_DUE_TO_CRASH -#endif - - -/* BACKTRACE - - Print a backtrace to the same location as ASSERT messages. -*/ - -#if BACKTRACE_DISABLED - -#define BACKTRACE() ((void)0) - -#else - -#define BACKTRACE() do { \ - WTFReportBacktrace(); \ -} while(false) - -#endif - -/* 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. */ -#include <windows.h> -#undef min -#undef max -#undef ERROR -#endif - -#if OS(WINDOWS) -/* FIXME: Change to use something other than ASSERT to avoid this conflict with the underlying platform */ -#undef ASSERT -#endif - -#if ASSERT_DISABLED - -#define ASSERT(assertion) ((void)0) -#define ASSERT_AT(assertion, file, line, function) ((void)0) -#define ASSERT_NOT_REACHED() ((void)0) -#define NO_RETURN_DUE_TO_ASSERT - -#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT) -template<typename T> -inline void assertUnused(T& x) { (void)x; } -#define ASSERT_UNUSED(variable, assertion) (assertUnused(variable)) -#else -#define ASSERT_UNUSED(variable, assertion) ((void)variable) -#endif - -#else - -#define ASSERT(assertion) do \ - if (!(assertion)) { \ - WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion); \ - CRASH(); \ - } \ -while (0) - -#define ASSERT_AT(assertion, file, line, function) do \ - if (!(assertion)) { \ - WTFReportAssertionFailure(file, line, function, #assertion); \ - CRASH(); \ - } \ -while (0) - -#define ASSERT_NOT_REACHED() do { \ - WTFReportAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, 0); \ - CRASH(); \ -} while (0) - -#define ASSERT_UNUSED(variable, assertion) ASSERT(assertion) - -#define NO_RETURN_DUE_TO_ASSERT NO_RETURN_DUE_TO_CRASH - -#endif - -/* ASSERT_WITH_MESSAGE */ - -#if COMPILER(MSVC7_OR_LOWER) -#define ASSERT_WITH_MESSAGE(assertion) ((void)0) -#elif ASSERT_MSG_DISABLED -#define ASSERT_WITH_MESSAGE(assertion, ...) ((void)0) -#else -#define ASSERT_WITH_MESSAGE(assertion, ...) do \ - if (!(assertion)) { \ - WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \ - CRASH(); \ - } \ -while (0) -#endif - -/* ASSERT_WITH_MESSAGE_UNUSED */ - -#if COMPILER(MSVC7_OR_LOWER) -#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion) ((void)0) -#elif ASSERT_MSG_DISABLED -#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT) -template<typename T> -inline void assertWithMessageUnused(T& x) { (void)x; } -#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) (assertWithMessageUnused(variable)) -#else -#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) ((void)variable) -#endif -#else -#define ASSERT_WITH_MESSAGE_UNUSED(variable, assertion, ...) do \ - if (!(assertion)) { \ - WTFReportAssertionFailureWithMessage(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #assertion, __VA_ARGS__); \ - CRASH(); \ - } \ -while (0) -#endif - - -/* ASSERT_ARG */ - -#if ASSERT_ARG_DISABLED - -#define ASSERT_ARG(argName, assertion) ((void)0) - -#else - -#define ASSERT_ARG(argName, assertion) do \ - if (!(assertion)) { \ - WTFReportArgumentAssertionFailure(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, #argName, #assertion); \ - CRASH(); \ - } \ -while (0) - -#endif - -/* COMPILE_ASSERT */ -#ifndef COMPILE_ASSERT -#if COMPILER_SUPPORTS(C_STATIC_ASSERT) -#define COMPILE_ASSERT(exp, name) _Static_assert((exp), #name) -#else -#define COMPILE_ASSERT(exp, name) typedef int dummy##name [(exp) ? 1 : -1] -#endif -#endif - -/* FATAL */ - -#if COMPILER(MSVC7_OR_LOWER) -#define FATAL() ((void)0) -#elif FATAL_DISABLED -#define FATAL(...) ((void)0) -#else -#define FATAL(...) do { \ - WTFReportFatalError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__); \ - CRASH(); \ -} while (0) -#endif - -/* LOG_ERROR */ - -#if COMPILER(MSVC7_OR_LOWER) -#define LOG_ERROR() ((void)0) -#elif ERROR_DISABLED -#define LOG_ERROR(...) ((void)0) -#else -#define LOG_ERROR(...) WTFReportError(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, __VA_ARGS__) -#endif - -/* LOG */ - -#if COMPILER(MSVC7_OR_LOWER) -#define LOG() ((void)0) -#elif LOG_DISABLED -#define LOG(channel, ...) ((void)0) -#else -#define LOG(channel, ...) WTFLog(&JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) -#define JOIN_LOG_CHANNEL_WITH_PREFIX(prefix, channel) JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) -#define JOIN_LOG_CHANNEL_WITH_PREFIX_LEVEL_2(prefix, channel) prefix ## channel -#endif - -/* LOG_VERBOSE */ - -#if COMPILER(MSVC7_OR_LOWER) -#define LOG_VERBOSE(channel) ((void)0) -#elif LOG_DISABLED -#define LOG_VERBOSE(channel, ...) ((void)0) -#else -#define LOG_VERBOSE(channel, ...) WTFLogVerbose(__FILE__, __LINE__, WTF_PRETTY_FUNCTION, &JOIN_LOG_CHANNEL_WITH_PREFIX(LOG_CHANNEL_PREFIX, channel), __VA_ARGS__) -#endif - -#endif /* WTF_Assertions_h */ diff --git a/Source/JavaScriptCore/wtf/Atomics.h b/Source/JavaScriptCore/wtf/Atomics.h deleted file mode 100644 index d30926897..000000000 --- a/Source/JavaScriptCore/wtf/Atomics.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * 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. - * - * - * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based - * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license - * is virtually identical to the Apple license above but is included here for completeness. - * - * Boost Software License - Version 1.0 - August 17th, 2003 - * - * Permission is hereby granted, free of charge, to any person or organization - * obtaining a copy of the software and accompanying documentation covered by - * this license (the "Software") to use, reproduce, display, distribute, - * execute, and transmit the Software, and to prepare derivative works of the - * Software, and to permit third-parties to whom the Software is furnished to - * do so, all subject to the following: - * - * The copyright notices in the Software and this entire statement, including - * the above license grant, this restriction and the following disclaimer, - * must be included in all copies of the Software, in whole or in part, and - * all derivative works of the Software, unless such copies or derivative - * works are solely in the form of machine-executable object code generated by - * a source language processor. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef Atomics_h -#define Atomics_h - -#include <wtf/Platform.h> -#include <wtf/StdLibExtras.h> -#include <wtf/UnusedParam.h> - -#if OS(WINDOWS) -#include <windows.h> -#elif OS(DARWIN) -#include <libkern/OSAtomic.h> -#elif OS(QNX) -#include <atomic.h> -#elif OS(ANDROID) -#include <sys/atomics.h> -#elif COMPILER(GCC) -#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) -#include <ext/atomicity.h> -#else -#include <bits/atomicity.h> -#endif -#endif - -namespace WTF { - -#if OS(WINDOWS) -#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 - -#if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE) -inline int atomicIncrement(int* addend) { return InterlockedIncrement(reinterpret_cast<long*>(addend)); } -inline int atomicDecrement(int* addend) { return InterlockedDecrement(reinterpret_cast<long*>(addend)); } -#else -inline int atomicIncrement(int volatile* addend) { return InterlockedIncrement(reinterpret_cast<long volatile*>(addend)); } -inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(reinterpret_cast<long volatile*>(addend)); } -#endif - -#elif OS(DARWIN) -#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 - -inline int atomicIncrement(int volatile* addend) { return OSAtomicIncrement32Barrier(const_cast<int*>(addend)); } -inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); } - -#elif OS(QNX) -#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 - -// Note, atomic_{add, sub}_value() return the previous value of addend's content. -inline int atomicIncrement(int volatile* addend) { return static_cast<int>(atomic_add_value(reinterpret_cast<unsigned volatile*>(addend), 1)) + 1; } -inline int atomicDecrement(int volatile* addend) { return static_cast<int>(atomic_sub_value(reinterpret_cast<unsigned volatile*>(addend), 1)) - 1; } - -#elif OS(ANDROID) - -inline int atomicIncrement(int volatile* addend) { return __atomic_inc(addend); } -inline int atomicDecrement(int volatile* addend) { return __atomic_dec(addend); } - -#elif COMPILER(GCC) && !CPU(SPARC64) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc -#define WTF_USE_LOCKFREE_THREADSAFEREFCOUNTED 1 - -inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; } -inline int atomicDecrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, -1) - 1; } - -#endif - -#if COMPILER(GCC) && !COMPILER(CLANG) // Work around a gcc bug -inline bool weakCompareAndSwap(volatile unsigned* location, unsigned expected, unsigned newValue) -#else -inline bool weakCompareAndSwap(unsigned* location, unsigned expected, unsigned newValue) -#endif -{ -#if ENABLE(COMPARE_AND_SWAP) - bool result; -#if CPU(X86) || CPU(X86_64) - asm volatile( - "lock; cmpxchgl %3, %2\n\t" - "sete %1" - : "+a"(expected), "=q"(result), "+m"(*location) - : "r"(newValue) - : "memory" - ); -#elif CPU(ARM_THUMB2) - unsigned tmp; - asm volatile( - "movw %1, #1\n\t" - "ldrex %2, %0\n\t" - "cmp %3, %2\n\t" - "bne.n 0f\n\t" - "strex %1, %4, %0\n\t" - "0:" - : "+m"(*location), "=&r"(result), "=&r"(tmp) - : "r"(expected), "r"(newValue) - : "memory"); - result = !result; -#else -#error "Bad architecture for compare and swap." -#endif - return result; -#else - UNUSED_PARAM(location); - UNUSED_PARAM(expected); - UNUSED_PARAM(newValue); - CRASH(); - return 0; -#endif -} - -inline bool weakCompareAndSwap(void*volatile* location, void* expected, void* newValue) -{ -#if ENABLE(COMPARE_AND_SWAP) -#if CPU(X86_64) - bool result; - asm volatile( - "lock; cmpxchgq %3, %2\n\t" - "sete %1" - : "+a"(expected), "=q"(result), "+m"(*location) - : "r"(newValue) - : "memory" - ); - return result; -#else - return weakCompareAndSwap(bitwise_cast<unsigned*>(location), bitwise_cast<unsigned>(expected), bitwise_cast<unsigned>(newValue)); -#endif -#else // ENABLE(COMPARE_AND_SWAP) - UNUSED_PARAM(location); - UNUSED_PARAM(expected); - UNUSED_PARAM(newValue); - CRASH(); - return 0; -#endif // ENABLE(COMPARE_AND_SWAP) -} - -inline bool weakCompareAndSwapUIntPtr(volatile uintptr_t* location, uintptr_t expected, uintptr_t newValue) -{ - return weakCompareAndSwap(reinterpret_cast<void*volatile*>(location), reinterpret_cast<void*>(expected), reinterpret_cast<void*>(newValue)); -} - -} // namespace WTF - -#if USE(LOCKFREE_THREADSAFEREFCOUNTED) -using WTF::atomicDecrement; -using WTF::atomicIncrement; -#endif - -#endif // Atomics_h diff --git a/Source/JavaScriptCore/wtf/BitVector.cpp b/Source/JavaScriptCore/wtf/BitVector.cpp deleted file mode 100644 index 863a5703a..000000000 --- a/Source/JavaScriptCore/wtf/BitVector.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2011 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 "BitVector.h" - -#include <algorithm> -#include <string.h> -#include <wtf/Assertions.h> -#include <wtf/FastMalloc.h> -#include <wtf/StdLibExtras.h> - -namespace WTF { - -void BitVector::setSlow(const BitVector& other) -{ - uintptr_t newBitsOrPointer; - if (other.isInline()) - newBitsOrPointer = other.m_bitsOrPointer; - else { - OutOfLineBits* newOutOfLineBits = OutOfLineBits::create(other.size()); - memcpy(newOutOfLineBits->bits(), other.bits(), byteCount(other.size())); - newBitsOrPointer = bitwise_cast<uintptr_t>(newOutOfLineBits) >> 1; - } - if (!isInline()) - OutOfLineBits::destroy(outOfLineBits()); - m_bitsOrPointer = newBitsOrPointer; -} - -void BitVector::resize(size_t numBits) -{ - if (numBits <= maxInlineBits()) { - if (isInline()) - return; - - OutOfLineBits* myOutOfLineBits = outOfLineBits(); - m_bitsOrPointer = makeInlineBits(*myOutOfLineBits->bits()); - OutOfLineBits::destroy(myOutOfLineBits); - return; - } - - resizeOutOfLine(numBits); -} - -void BitVector::clearAll() -{ - if (isInline()) - m_bitsOrPointer = makeInlineBits(0); - else - memset(outOfLineBits()->bits(), 0, byteCount(size())); -} - -BitVector::OutOfLineBits* BitVector::OutOfLineBits::create(size_t numBits) -{ - numBits = (numBits + bitsInPointer() - 1) & ~(bitsInPointer() - 1); - size_t size = sizeof(OutOfLineBits) + sizeof(uintptr_t) * (numBits / bitsInPointer()); - OutOfLineBits* result = new (NotNull, fastMalloc(size)) OutOfLineBits(numBits); - return result; -} - -void BitVector::OutOfLineBits::destroy(OutOfLineBits* outOfLineBits) -{ - fastFree(outOfLineBits); -} - -void BitVector::resizeOutOfLine(size_t numBits) -{ - ASSERT(numBits > maxInlineBits()); - OutOfLineBits* newOutOfLineBits = OutOfLineBits::create(numBits); - if (isInline()) { - // Make sure that all of the bits are zero in case we do a no-op resize. - *newOutOfLineBits->bits() = m_bitsOrPointer & ~(static_cast<uintptr_t>(1) << maxInlineBits()); - } else { - if (numBits > size()) { - size_t oldNumWords = outOfLineBits()->numWords(); - size_t newNumWords = newOutOfLineBits->numWords(); - memcpy(newOutOfLineBits->bits(), outOfLineBits()->bits(), oldNumWords * sizeof(void*)); - memset(newOutOfLineBits->bits() + oldNumWords, 0, (newNumWords - oldNumWords) * sizeof(void*)); - } else - memcpy(newOutOfLineBits->bits(), outOfLineBits()->bits(), newOutOfLineBits->numWords() * sizeof(void*)); - OutOfLineBits::destroy(outOfLineBits()); - } - m_bitsOrPointer = bitwise_cast<uintptr_t>(newOutOfLineBits) >> 1; -} - -void BitVector::dump(FILE* out) -{ - for (size_t i = 0; i < size(); ++i) { - if (get(i)) - fprintf(out, "1"); - else - fprintf(out, "-"); - } -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/BitVector.h b/Source/JavaScriptCore/wtf/BitVector.h deleted file mode 100644 index 335656c40..000000000 --- a/Source/JavaScriptCore/wtf/BitVector.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (C) 2011 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 BitVector_h -#define BitVector_h - -#include <stdio.h> -#include <wtf/Assertions.h> -#include <wtf/StdLibExtras.h> - -namespace WTF { - -// This is a space-efficient, resizeable bitvector class. In the common case it -// occupies one word, but if necessary, it will inflate this one word to point -// to a single chunk of out-of-line allocated storage to store an arbitrary number -// of bits. -// -// - The bitvector remembers the bound of how many bits can be stored, but this -// may be slightly greater (by as much as some platform-specific constant) -// than the last argument passed to ensureSize(). -// -// - The bitvector can resize itself automatically (set, clear, get) or can be used -// in a manual mode, which is faster (quickSet, quickClear, quickGet, ensureSize). -// -// - Accesses ASSERT that you are within bounds. -// -// - Bits are automatically initialized to zero. -// -// On the other hand, this BitVector class may not be the fastest around, since -// it does conditionals on every get/set/clear. But it is great if you need to -// juggle a lot of variable-length BitVectors and you're worried about wasting -// space. - -class BitVector { -public: - BitVector() - : m_bitsOrPointer(makeInlineBits(0)) - { - } - - explicit BitVector(size_t numBits) - : m_bitsOrPointer(makeInlineBits(0)) - { - ensureSize(numBits); - } - - BitVector(const BitVector& other) - : m_bitsOrPointer(makeInlineBits(0)) - { - (*this) = other; - } - - - ~BitVector() - { - if (isInline()) - return; - OutOfLineBits::destroy(outOfLineBits()); - } - - BitVector& operator=(const BitVector& other) - { - if (isInline() && other.isInline()) - m_bitsOrPointer = other.m_bitsOrPointer; - else - setSlow(other); - return *this; - } - - size_t size() const - { - if (isInline()) - return maxInlineBits(); - return outOfLineBits()->numBits(); - } - - void ensureSize(size_t numBits) - { - if (numBits <= size()) - return; - resizeOutOfLine(numBits); - } - - // Like ensureSize(), but supports reducing the size of the bitvector. - void resize(size_t numBits); - - void clearAll(); - - bool quickGet(size_t bit) const - { - ASSERT(bit < size()); - return !!(bits()[bit / bitsInPointer()] & (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1)))); - } - - void quickSet(size_t bit) - { - ASSERT(bit < size()); - bits()[bit / bitsInPointer()] |= (static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1))); - } - - void quickClear(size_t bit) - { - ASSERT(bit < size()); - bits()[bit / bitsInPointer()] &= ~(static_cast<uintptr_t>(1) << (bit & (bitsInPointer() - 1))); - } - - void quickSet(size_t bit, bool value) - { - if (value) - quickSet(bit); - else - quickClear(bit); - } - - bool get(size_t bit) const - { - if (bit >= size()) - return false; - return quickGet(bit); - } - - void set(size_t bit) - { - ensureSize(bit + 1); - quickSet(bit); - } - - void clear(size_t bit) - { - if (bit >= size()) - return; - quickClear(bit); - } - - void set(size_t bit, bool value) - { - if (value) - set(bit); - else - clear(bit); - } - - void dump(FILE* out); - -private: - static unsigned bitsInPointer() - { - return sizeof(void*) << 3; - } - - static unsigned maxInlineBits() - { - return bitsInPointer() - 1; - } - - static size_t byteCount(size_t bitCount) - { - return (bitCount + 7) >> 3; - } - - static uintptr_t makeInlineBits(uintptr_t bits) - { - ASSERT(!(bits & (static_cast<uintptr_t>(1) << maxInlineBits()))); - return bits | (static_cast<uintptr_t>(1) << maxInlineBits()); - } - - class OutOfLineBits { - public: - size_t numBits() const { return m_numBits; } - size_t numWords() const { return (m_numBits + bitsInPointer() - 1) / bitsInPointer(); } - uintptr_t* bits() { return bitwise_cast<uintptr_t*>(this + 1); } - const uintptr_t* bits() const { return bitwise_cast<const uintptr_t*>(this + 1); } - - static OutOfLineBits* create(size_t numBits); - - static void destroy(OutOfLineBits*); - - private: - OutOfLineBits(size_t numBits) - : m_numBits(numBits) - { - } - - size_t m_numBits; - }; - - bool isInline() const { return m_bitsOrPointer >> maxInlineBits(); } - - const OutOfLineBits* outOfLineBits() const { return bitwise_cast<const OutOfLineBits*>(m_bitsOrPointer << 1); } - OutOfLineBits* outOfLineBits() { return bitwise_cast<OutOfLineBits*>(m_bitsOrPointer << 1); } - - void resizeOutOfLine(size_t numBits); - void setSlow(const BitVector& other); - - uintptr_t* bits() - { - if (isInline()) - return &m_bitsOrPointer; - return outOfLineBits()->bits(); - } - - const uintptr_t* bits() const - { - if (isInline()) - return &m_bitsOrPointer; - return outOfLineBits()->bits(); - } - - uintptr_t m_bitsOrPointer; -}; - -} // namespace WTF - -using WTF::BitVector; - -#endif // BitVector_h diff --git a/Source/JavaScriptCore/wtf/Bitmap.h b/Source/JavaScriptCore/wtf/Bitmap.h deleted file mode 100644 index 76a2ca4b3..000000000 --- a/Source/JavaScriptCore/wtf/Bitmap.h +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU 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 - * - */ -#ifndef Bitmap_h -#define Bitmap_h - -#include <wtf/Atomics.h> -#include <wtf/FixedArray.h> -#include <wtf/StdLibExtras.h> -#include <stdint.h> -#include <string.h> - -namespace WTF { - -enum BitmapAtomicMode { - // This makes concurrentTestAndSet behave just like testAndSet. - BitmapNotAtomic, - - // This makes concurrentTestAndSet use compareAndSwap, so that it's - // atomic even when used concurrently. - BitmapAtomic -}; - -template<size_t size, BitmapAtomicMode atomicMode = BitmapNotAtomic> -class Bitmap { -private: - typedef uint32_t WordType; - -public: - Bitmap(); - - bool get(size_t) const; - void set(size_t); - bool testAndSet(size_t); - bool testAndClear(size_t); - bool concurrentTestAndSet(size_t); - bool concurrentTestAndClear(size_t); - size_t nextPossiblyUnset(size_t) const; - void clear(size_t); - void clearAll(); - int64_t findRunOfZeros(size_t) const; - size_t count(size_t = 0) const; - size_t isEmpty() const; - size_t isFull() const; - -private: - static const WordType wordSize = sizeof(WordType) * 8; - static const WordType words = (size + wordSize - 1) / wordSize; - - // the literal '1' is of type signed int. We want to use an unsigned - // version of the correct size when doing the calculations because if - // WordType is larger than int, '1 << 31' will first be sign extended - // and then casted to unsigned, meaning that set(31) when WordType is - // a 64 bit unsigned int would give 0xffff8000 - static const WordType one = 1; - - FixedArray<WordType, words> bits; -}; - -template<size_t size, BitmapAtomicMode atomicMode> -inline Bitmap<size, atomicMode>::Bitmap() -{ - clearAll(); -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline bool Bitmap<size, atomicMode>::get(size_t n) const -{ - return !!(bits[n / wordSize] & (one << (n % wordSize))); -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline void Bitmap<size, atomicMode>::set(size_t n) -{ - bits[n / wordSize] |= (one << (n % wordSize)); -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline bool Bitmap<size, atomicMode>::testAndSet(size_t n) -{ - WordType mask = one << (n % wordSize); - size_t index = n / wordSize; - bool result = bits[index] & mask; - bits[index] |= mask; - return result; -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline bool Bitmap<size, atomicMode>::testAndClear(size_t n) -{ - WordType mask = one << (n % wordSize); - size_t index = n / wordSize; - bool result = bits[index] & mask; - bits[index] &= ~mask; - return result; -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline bool Bitmap<size, atomicMode>::concurrentTestAndSet(size_t n) -{ - if (atomicMode == BitmapNotAtomic) - return testAndSet(n); - - ASSERT(atomicMode == BitmapAtomic); - - WordType mask = one << (n % wordSize); - size_t index = n / wordSize; - WordType* wordPtr = bits.data() + index; - WordType oldValue; - do { - oldValue = *wordPtr; - if (oldValue & mask) - return true; - } while (!weakCompareAndSwap(wordPtr, oldValue, oldValue | mask)); - return false; -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline bool Bitmap<size, atomicMode>::concurrentTestAndClear(size_t n) -{ - if (atomicMode == BitmapNotAtomic) - return testAndClear(n); - - ASSERT(atomicMode == BitmapAtomic); - - WordType mask = one << (n % wordSize); - size_t index = n / wordSize; - WordType* wordPtr = bits.data() + index; - WordType oldValue; - do { - oldValue = *wordPtr; - if (!(oldValue & mask)) - return false; - } while (!weakCompareAndSwap(wordPtr, oldValue, oldValue & ~mask)); - return true; -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline void Bitmap<size, atomicMode>::clear(size_t n) -{ - bits[n / wordSize] &= ~(one << (n % wordSize)); -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline void Bitmap<size, atomicMode>::clearAll() -{ - memset(bits.data(), 0, sizeof(bits)); -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline size_t Bitmap<size, atomicMode>::nextPossiblyUnset(size_t start) const -{ - if (!~bits[start / wordSize]) - return ((start / wordSize) + 1) * wordSize; - return start + 1; -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline int64_t Bitmap<size, atomicMode>::findRunOfZeros(size_t runLength) const -{ - if (!runLength) - runLength = 1; - - for (size_t i = 0; i <= (size - runLength) ; i++) { - bool found = true; - for (size_t j = i; j <= (i + runLength - 1) ; j++) { - if (get(j)) { - found = false; - break; - } - } - if (found) - return i; - } - return -1; -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline size_t Bitmap<size, atomicMode>::count(size_t start) const -{ - size_t result = 0; - for ( ; (start % wordSize); ++start) { - if (get(start)) - ++result; - } - for (size_t i = start / wordSize; i < words; ++i) - result += WTF::bitCount(bits[i]); - return result; -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline size_t Bitmap<size, atomicMode>::isEmpty() const -{ - for (size_t i = 0; i < words; ++i) - if (bits[i]) - return false; - return true; -} - -template<size_t size, BitmapAtomicMode atomicMode> -inline size_t Bitmap<size, atomicMode>::isFull() const -{ - for (size_t i = 0; i < words; ++i) - if (~bits[i]) - return false; - return true; -} - -} -#endif diff --git a/Source/JavaScriptCore/wtf/BlockStack.h b/Source/JavaScriptCore/wtf/BlockStack.h deleted file mode 100644 index 61e108db3..000000000 --- a/Source/JavaScriptCore/wtf/BlockStack.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2011 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 BlockStack_h -#define BlockStack_h - -#include <wtf/Assertions.h> -#include <wtf/FastMalloc.h> -#include <wtf/Vector.h> - -namespace WTF { - -template <typename T> class BlockStack { -public: - static const size_t blockSize = 4096; - static const size_t blockLength = blockSize / sizeof(T); - - BlockStack(); - ~BlockStack(); - - T* grow(); - void shrink(T*); - - const Vector<T*>& blocks(); - -private: - Vector<T*> m_blocks; - T* m_spareBlock; // Used to avoid thrash at block boundaries. -}; - -template <typename T> BlockStack<T>::BlockStack() - : m_spareBlock(0) -{ -} - -template <typename T> BlockStack<T>::~BlockStack() -{ - if (m_spareBlock) - fastFree(m_spareBlock); - for (size_t i = 0; i < m_blocks.size(); ++i) - fastFree(m_blocks[i]); -} - -template <typename T> inline const Vector<T*>& BlockStack<T>::blocks() -{ - return m_blocks; -} - -template <typename T> T* BlockStack<T>::grow() -{ - T* block = m_spareBlock ? m_spareBlock : static_cast<T*>(fastMalloc(blockSize)); - m_spareBlock = 0; - - m_blocks.append(block); - return block; -} - -template <typename T> void BlockStack<T>::shrink(T* newEnd) -{ - ASSERT(newEnd != m_blocks.last() + blockLength); - m_spareBlock = m_blocks.last(); - m_blocks.removeLast(); - - while (m_blocks.last() + blockLength != newEnd) { - fastFree(m_blocks.last()); - m_blocks.removeLast(); - } -} - -} - -using WTF::BlockStack; - -#endif diff --git a/Source/JavaScriptCore/wtf/BloomFilter.h b/Source/JavaScriptCore/wtf/BloomFilter.h deleted file mode 100644 index f81d83e21..000000000 --- a/Source/JavaScriptCore/wtf/BloomFilter.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2011 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 BloomFilter_h -#define BloomFilter_h - -#include <wtf/AlwaysInline.h> -#include <wtf/text/AtomicString.h> - -namespace WTF { - -// Counting bloom filter with k=2 and 8 bit counters. Uses 2^keyBits bytes of memory. -// False positive rate is approximately (1-e^(-2n/m))^2, where n is the number of unique -// keys and m is the table size (==2^keyBits). -template <unsigned keyBits> -class BloomFilter { -public: - COMPILE_ASSERT(keyBits <= 16, bloom_filter_key_size); - - static const size_t tableSize = 1 << keyBits; - static const unsigned keyMask = (1 << keyBits) - 1; - static uint8_t maximumCount() { return std::numeric_limits<uint8_t>::max(); } - - BloomFilter() { clear(); } - - void add(unsigned hash); - void remove(unsigned hash); - - // The filter may give false positives (claim it may contain a key it doesn't) - // but never false negatives (claim it doesn't contain a key it does). - bool mayContain(unsigned hash) const { return firstSlot(hash) && secondSlot(hash); } - - // The filter must be cleared before reuse even if all keys are removed. - // Otherwise overflowed keys will stick around. - void clear(); - - void add(const AtomicString& string) { add(string.impl()->existingHash()); } - void add(const String& string) { add(string.impl()->hash()); } - void remove(const AtomicString& string) { remove(string.impl()->existingHash()); } - void remove(const String& string) { remove(string.impl()->hash()); } - - bool mayContain(const AtomicString& string) const { return mayContain(string.impl()->existingHash()); } - bool mayContain(const String& string) const { return mayContain(string.impl()->hash()); } - -#if !ASSERT_DISABLED - // Slow. - bool likelyEmpty() const; - bool isClear() const; -#endif - -private: - uint8_t& firstSlot(unsigned hash) { return m_table[hash & keyMask]; } - uint8_t& secondSlot(unsigned hash) { return m_table[(hash >> 16) & keyMask]; } - const uint8_t& firstSlot(unsigned hash) const { return m_table[hash & keyMask]; } - const uint8_t& secondSlot(unsigned hash) const { return m_table[(hash >> 16) & keyMask]; } - - uint8_t m_table[tableSize]; -}; - -template <unsigned keyBits> -inline void BloomFilter<keyBits>::add(unsigned hash) -{ - uint8_t& first = firstSlot(hash); - uint8_t& second = secondSlot(hash); - if (LIKELY(first < maximumCount())) - ++first; - if (LIKELY(second < maximumCount())) - ++second; -} - -template <unsigned keyBits> -inline void BloomFilter<keyBits>::remove(unsigned hash) -{ - uint8_t& first = firstSlot(hash); - uint8_t& second = secondSlot(hash); - ASSERT(first); - ASSERT(second); - // In case of an overflow, the slot sticks in the table until clear(). - if (LIKELY(first < maximumCount())) - --first; - if (LIKELY(second < maximumCount())) - --second; -} - -template <unsigned keyBits> -inline void BloomFilter<keyBits>::clear() -{ - memset(m_table, 0, tableSize); -} - -#if !ASSERT_DISABLED -template <unsigned keyBits> -bool BloomFilter<keyBits>::likelyEmpty() const -{ - for (size_t n = 0; n < tableSize; ++n) { - if (m_table[n] && m_table[n] != maximumCount()) - return false; - } - return true; -} - -template <unsigned keyBits> -bool BloomFilter<keyBits>::isClear() const -{ - for (size_t n = 0; n < tableSize; ++n) { - if (m_table[n]) - return false; - } - return true; -} -#endif - -} - -using WTF::BloomFilter; - -#endif diff --git a/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h b/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h deleted file mode 100644 index 1f7caab63..000000000 --- a/Source/JavaScriptCore/wtf/BoundsCheckedPointer.h +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (C) 2011 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 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 WTF_BoundsCheckedPointer_h -#define WTF_BoundsCheckedPointer_h - -#include <wtf/Assertions.h> -#include <wtf/UnusedParam.h> - -namespace WTF { - -// Useful for when you'd like to do pointer arithmetic on a buffer, but -// you'd also like to get some ASSERT()'s that prevent you from overflowing. -// This should be performance-neutral in release builds, while providing -// you with strong assertions in debug builds. Note that all of the -// asserting happens when you actually access the pointer. You are allowed -// to overflow or underflow with arithmetic so long as no accesses are -// performed. - -template<typename T> -class BoundsCheckedPointer { -public: - BoundsCheckedPointer() - : m_pointer(0) -#if !ASSERT_DISABLED - , m_begin(0) - , m_end(0) -#endif - { - } - - BoundsCheckedPointer(T* pointer, size_t numElements) - : m_pointer(pointer) -#if !ASSERT_DISABLED - , m_begin(pointer) - , m_end(pointer + numElements) -#endif - { - UNUSED_PARAM(numElements); - } - - BoundsCheckedPointer(T* pointer, T* end) - : m_pointer(pointer) -#if !ASSERT_DISABLED - , m_begin(pointer) - , m_end(end) -#endif - { - UNUSED_PARAM(end); - } - - BoundsCheckedPointer(T* pointer, T* begin, size_t numElements) - : m_pointer(pointer) -#if !ASSERT_DISABLED - , m_begin(begin) - , m_end(begin + numElements) -#endif - { - UNUSED_PARAM(begin); - UNUSED_PARAM(numElements); - } - - BoundsCheckedPointer(T* pointer, T* begin, T* end) - : m_pointer(pointer) -#if !ASSERT_DISABLED - , m_begin(begin) - , m_end(end) -#endif - { - UNUSED_PARAM(begin); - UNUSED_PARAM(end); - } - - BoundsCheckedPointer& operator=(T* value) - { - m_pointer = value; - return *this; - } - - BoundsCheckedPointer& operator+=(ptrdiff_t amount) - { - m_pointer += amount; - return *this; - } - - BoundsCheckedPointer& operator-=(ptrdiff_t amount) - { - m_pointer -= amount; - return *this; - } - - BoundsCheckedPointer operator+(ptrdiff_t amount) const - { - BoundsCheckedPointer result = *this; - result.m_pointer += amount; - return result; - } - - BoundsCheckedPointer operator-(ptrdiff_t amount) const - { - BoundsCheckedPointer result = *this; - result.m_pointer -= amount; - return result; - } - - BoundsCheckedPointer operator++() // prefix - { - m_pointer++; - return *this; - } - - BoundsCheckedPointer operator--() // prefix - { - m_pointer--; - return *this; - } - - BoundsCheckedPointer operator++(int) // postfix - { - BoundsCheckedPointer result = *this; - m_pointer++; - return result; - } - - BoundsCheckedPointer operator--(int) // postfix - { - BoundsCheckedPointer result = *this; - m_pointer--; - return result; - } - - bool operator<(T* other) const - { - return m_pointer < other; - } - - bool operator<=(T* other) const - { - return m_pointer <= other; - } - - bool operator>(T* other) const - { - return m_pointer > other; - } - - bool operator>=(T* other) const - { - return m_pointer >= other; - } - - bool operator==(T* other) const - { - return m_pointer == other; - } - - bool operator!=(T* other) const - { - return m_pointer != other; - } - - bool operator<(BoundsCheckedPointer other) const - { - return m_pointer < other.m_pointer; - } - - bool operator<=(BoundsCheckedPointer other) const - { - return m_pointer <= other.m_pointer; - } - - bool operator>(BoundsCheckedPointer other) const - { - return m_pointer > other.m_pointer; - } - - bool operator>=(BoundsCheckedPointer other) const - { - return m_pointer >= other.m_pointer; - } - - bool operator==(BoundsCheckedPointer other) const - { - return m_pointer == other.m_pointer; - } - - bool operator!=(BoundsCheckedPointer other) const - { - return m_pointer != other.m_pointer; - } - - BoundsCheckedPointer operator!() - { - return !m_pointer; - } - - T* get() - { - return m_pointer; - } - - T& operator*() - { - validate(); - return *m_pointer; - } - - const T& operator*() const - { - validate(); - return *m_pointer; - } - - T& operator[](ptrdiff_t index) - { - validate(m_pointer + index); - return m_pointer[index]; - } - - const T& operator[](ptrdiff_t index) const - { - validate(m_pointer + index); - return m_pointer[index]; - } - - // The only thing this has in common with strcat() is that it - // keeps appending from the given pointer until reaching 0. - BoundsCheckedPointer& strcat(const T* source) - { - while (*source) - *(*this)++ = *source++; - return *this; - } - -private: - void validate(T* pointer) const - { - ASSERT_UNUSED(pointer, pointer >= m_begin); - - // This guard is designed to protect against the misaligned case. - // A simple pointer < m_end would miss the case if, for example, - // T = int16_t and pointer is 1 byte less than m_end. - ASSERT_UNUSED(pointer, pointer + 1 <= m_end); - } - - void validate() const - { - validate(m_pointer); - } - - T* m_pointer; -#if !ASSERT_DISABLED - T* m_begin; - T* m_end; -#endif -}; - -} // namespace WTF - -using WTF::BoundsCheckedPointer; - -#endif // WTF_BoundsCheckedPointer_h diff --git a/Source/JavaScriptCore/wtf/BumpPointerAllocator.h b/Source/JavaScriptCore/wtf/BumpPointerAllocator.h deleted file mode 100644 index 12911a4b0..000000000 --- a/Source/JavaScriptCore/wtf/BumpPointerAllocator.h +++ /dev/null @@ -1,250 +0,0 @@ -/* - * 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 BumpPointerAllocator_h -#define BumpPointerAllocator_h - -#include <wtf/PageAllocation.h> - -namespace WTF { - -#define MINIMUM_BUMP_POOL_SIZE 0x1000 - -class BumpPointerPool { -public: - // ensureCapacity will check whether the current pool has capacity to - // allocate 'size' bytes of memory If it does not, it will attempt to - // allocate a new pool (which will be added to this one in a chain). - // - // If allocation fails (out of memory) this method will return null. - // If the return value is non-null, then callers should update any - // references they have to this current (possibly full) BumpPointerPool - // to instead point to the newly returned BumpPointerPool. - BumpPointerPool* ensureCapacity(size_t size) - { - void* allocationEnd = static_cast<char*>(m_current) + size; - ASSERT(allocationEnd > m_current); // check for overflow - if (allocationEnd <= static_cast<void*>(this)) - return this; - return ensureCapacityCrossPool(this, size); - } - - // alloc should only be called after calling ensureCapacity; as such - // alloc will never fail. - void* alloc(size_t size) - { - void* current = m_current; - void* allocationEnd = static_cast<char*>(current) + size; - ASSERT(allocationEnd > current); // check for overflow - ASSERT(allocationEnd <= static_cast<void*>(this)); - m_current = allocationEnd; - return current; - } - - // The dealloc method releases memory allocated using alloc. Memory - // must be released in a LIFO fashion, e.g. if the client calls alloc - // four times, returning pointer A, B, C, D, then the only valid order - // in which these may be deallocaed is D, C, B, A. - // - // The client may optionally skip some deallocations. In the example - // above, it would be valid to only explicitly dealloc C, A (D being - // dealloced along with C, B along with A). - // - // If pointer was not allocated from this pool (or pools) then dealloc - // will CRASH(). Callers should update any references they have to - // this current BumpPointerPool to instead point to the returned - // BumpPointerPool. - BumpPointerPool* dealloc(void* position) - { - if ((position >= m_start) && (position <= static_cast<void*>(this))) { - ASSERT(position <= m_current); - m_current = position; - return this; - } - return deallocCrossPool(this, position); - } - -private: - // Placement operator new, returns the last 'size' bytes of allocation for use as this. - void* operator new(size_t size, const PageAllocation& allocation) - { - ASSERT(size < allocation.size()); - return reinterpret_cast<char*>(reinterpret_cast<intptr_t>(allocation.base()) + allocation.size()) - size; - } - - BumpPointerPool(const PageAllocation& allocation) - : m_current(allocation.base()) - , m_start(allocation.base()) - , m_next(0) - , m_previous(0) - , m_allocation(allocation) - { - } - - static BumpPointerPool* create(size_t minimumCapacity = 0) - { - // Add size of BumpPointerPool object, check for overflow. - minimumCapacity += sizeof(BumpPointerPool); - if (minimumCapacity < sizeof(BumpPointerPool)) - return 0; - - size_t poolSize = MINIMUM_BUMP_POOL_SIZE; - while (poolSize < minimumCapacity) { - poolSize <<= 1; - // The following if check relies on MINIMUM_BUMP_POOL_SIZE being a power of 2! - ASSERT(!(MINIMUM_BUMP_POOL_SIZE & (MINIMUM_BUMP_POOL_SIZE - 1))); - if (!poolSize) - return 0; - } - - PageAllocation allocation = PageAllocation::allocate(poolSize); - if (!!allocation) - return new (allocation) BumpPointerPool(allocation); - return 0; - } - - void shrink() - { - ASSERT(!m_previous); - m_current = m_start; - while (m_next) { - BumpPointerPool* nextNext = m_next->m_next; - m_next->destroy(); - m_next = nextNext; - } - } - - void destroy() - { - m_allocation.deallocate(); - } - - static BumpPointerPool* ensureCapacityCrossPool(BumpPointerPool* previousPool, size_t size) - { - // The pool passed should not have capacity, so we'll start with the next one. - ASSERT(previousPool); - ASSERT((static_cast<char*>(previousPool->m_current) + size) > previousPool->m_current); // check for overflow - ASSERT((static_cast<char*>(previousPool->m_current) + size) > static_cast<void*>(previousPool)); - BumpPointerPool* pool = previousPool->m_next; - - while (true) { - if (!pool) { - // We've run to the end; allocate a new pool. - pool = BumpPointerPool::create(size); - previousPool->m_next = pool; - pool->m_previous = previousPool; - return pool; - } - - // - void* current = pool->m_current; - void* allocationEnd = static_cast<char*>(current) + size; - ASSERT(allocationEnd > current); // check for overflow - if (allocationEnd <= static_cast<void*>(pool)) - return pool; - } - } - - static BumpPointerPool* deallocCrossPool(BumpPointerPool* pool, void* position) - { - // Should only be called if position is not in the current pool. - ASSERT((position < pool->m_start) || (position > static_cast<void*>(pool))); - - while (true) { - // Unwind the current pool to the start, move back in the chain to the previous pool. - pool->m_current = pool->m_start; - pool = pool->m_previous; - - // position was nowhere in the chain! - if (!pool) - CRASH(); - - if ((position >= pool->m_start) && (position <= static_cast<void*>(pool))) { - ASSERT(position <= pool->m_current); - pool->m_current = position; - return pool; - } - } - } - - void* m_current; - void* m_start; - BumpPointerPool* m_next; - BumpPointerPool* m_previous; - PageAllocation m_allocation; - - friend class BumpPointerAllocator; -}; - -// A BumpPointerAllocator manages a set of BumpPointerPool objects, which -// can be used for LIFO (stack like) allocation. -// -// To begin allocating using this class call startAllocator(). The result -// of this method will be null if the initial pool allocation fails, or a -// pointer to a BumpPointerPool object that can be used to perform -// allocations. Whilst running no memory will be released until -// stopAllocator() is called. At this point all allocations made through -// this allocator will be reaped, and underlying memory may be freed. -// -// (In practice we will still hold on to the initial pool to allow allocation -// to be quickly restared, but aditional pools will be freed). -// -// This allocator is non-renetrant, it is encumbant on the clients to ensure -// startAllocator() is not called again until stopAllocator() has been called. -class BumpPointerAllocator { -public: - BumpPointerAllocator() - : m_head(0) - { - } - - ~BumpPointerAllocator() - { - if (m_head) - m_head->destroy(); - } - - BumpPointerPool* startAllocator() - { - if (!m_head) - m_head = BumpPointerPool::create(); - return m_head; - } - - void stopAllocator() - { - if (m_head) - m_head->shrink(); - } - -private: - BumpPointerPool* m_head; -}; - -} - -using WTF::BumpPointerAllocator; - -#endif // BumpPointerAllocator_h diff --git a/Source/JavaScriptCore/wtf/ByteArray.h b/Source/JavaScriptCore/wtf/ByteArray.h deleted file mode 100644 index f68d032fd..000000000 --- a/Source/JavaScriptCore/wtf/ByteArray.h +++ /dev/null @@ -1,110 +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. - */ - -#ifndef ByteArray_h -#define ByteArray_h - -#include <limits.h> -#include <wtf/PassRefPtr.h> -#include <wtf/Platform.h> -#include <wtf/RefCounted.h> -#include <wtf/StdLibExtras.h> - -namespace WTF { - class ByteArray : public RefCountedBase { - public: - unsigned length() const { return m_size; } - - void set(unsigned index, double value) - { - if (index >= m_size) - return; - if (!(value > 0)) // Clamp NaN to 0 - value = 0; - else if (value > 255) - value = 255; - m_data[index] = static_cast<unsigned char>(value + 0.5); - } - - void set(unsigned index, unsigned char value) - { - if (index >= m_size) - return; - m_data[index] = value; - } - - bool get(unsigned index, unsigned char& result) const - { - if (index >= m_size) - return false; - result = m_data[index]; - return true; - } - - unsigned char get(unsigned index) const - { - ASSERT(index < m_size); - return m_data[index]; - } - - unsigned char* data() { return m_data; } - - void clear() { memset(m_data, 0, m_size); } - - void deref() - { - if (derefBase()) { - // We allocated with new unsigned char[] in create(), - // and then used placement new to construct the object. - this->~ByteArray(); - delete[] reinterpret_cast<unsigned char*>(this); - } - } - - WTF_EXPORT_PRIVATE static PassRefPtr<ByteArray> create(size_t size); - - static size_t offsetOfSize() { return OBJECT_OFFSETOF(ByteArray, m_size); } - static size_t offsetOfData() { return OBJECT_OFFSETOF(ByteArray, m_data); } - - private: - ByteArray(size_t size) - : m_size(size) - { - } - size_t m_size; -// MSVC can't handle correctly unsized array. -// warning C4200: nonstandard extension used : zero-sized array in struct/union -// Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array -#if (COMPILER(MSVC) || COMPILER(SUNCC)) && !COMPILER(INTEL) - unsigned char m_data[INT_MAX]; -#else - unsigned char m_data[]; -#endif - }; -} // namespace WTF - -using WTF::ByteArray; - -#endif diff --git a/Source/JavaScriptCore/wtf/CMakeLists.txt b/Source/JavaScriptCore/wtf/CMakeLists.txt deleted file mode 100644 index 72420128a..000000000 --- a/Source/JavaScriptCore/wtf/CMakeLists.txt +++ /dev/null @@ -1,214 +0,0 @@ -SET(WTF_HEADERS - ASCIICType.h - AVLTree.h - Alignment.h - AlwaysInline.h - Assertions.h - Atomics.h - BitVector.h - Bitmap.h - BoundsCheckedPointer.h - BumpPointerAllocator.h - ByteArray.h - Compiler.h - Complex.h - CryptographicallyRandomNumber.h - CurrentTime.h - DateMath.h - DataLog.h - DecimalNumber.h - Decoder.h - Deque.h - DisallowCType.h - DoublyLinkedList.h - DynamicAnnotations.h - Encoder.h - FastAllocBase.h - FastMalloc.h - FixedArray.h - Forward.h - GetPtr.h - HashCountedSet.h - HashFunctions.h - HashIterators.h - HashMap.h - HashSet.h - HashTable.h - HashTraits.h - HexNumber.h - ListHashSet.h - ListRefPtr.h - Locker.h - MD5.h - MainThread.h - MallocZoneSupport.h - MathExtras.h - MessageQueue.h - MetaAllocator.h - MetaAllocatorHandle.h - NonCopyingSort.h - ThreadRestrictionVerifier.h - Noncopyable.h - NotFound.h - NullPtr.h - NumberOfCores.h - OSAllocator.h - OSRandomSource.h - OwnArrayPtr.h - OwnPtr.h - OwnPtrCommon.h - PageAllocation.h - PageAllocationAligned.h - PageBlock.h - PageReservation.h - PassOwnArrayPtr.h - PassOwnPtr.h - PassRefPtr.h - PassTraits.h - ParallelJobs.h - ParallelJobsGeneric.h - ParallelJobsLibdispatch.h - ParallelJobsOpenMP.h - Platform.h - PossiblyNull.h - RandomNumber.h - RandomNumberSeed.h - RedBlackTree.h - RefCounted.h - RefCountedLeakCounter.h - RefPtr.h - RefPtrHashMap.h - RetainPtr.h - SegmentedVector.h - SHA1.h - StackBounds.h - StaticConstructors.h - StdLibExtras.h - StringExtras.h - StringHasher.h - TCPackedCache.h - TCPageMap.h - TCSpinLock.h - TCSystemAlloc.h - ThreadIdentifierDataPthreads.h - ThreadSafeRefCounted.h - ThreadSpecific.h - Threading.h - ThreadingPrimitives.h - TypeTraits.h - UnusedParam.h - VMTags.h - ValueCheck.h - Vector.h - VectorTraits.h - WTFThreadData.h - dtoa.h - - dtoa/bignum-dtoa.h - dtoa/bignum.h - dtoa/cached-powers.h - dtoa/diy-fp.h - dtoa/double-conversion.h - dtoa/double.h - dtoa/fast-dtoa.h - dtoa/fixed-dtoa.h - dtoa/strtod.h - dtoa/utils.h - - text/AtomicString.h - text/AtomicStringImpl.h - text/CString.h - text/StringBuffer.h - text/StringHash.h - text/StringImpl.h - text/WTFString.h - - threads/BinarySemaphore.h - - unicode/CharacterNames.h - unicode/Collator.h - unicode/UTF8.h - unicode/Unicode.h -) - -SET(WTF_SOURCES - ArrayBuffer.cpp - ArrayBufferView.cpp - Assertions.cpp - BitVector.cpp - ByteArray.cpp - CryptographicallyRandomNumber.cpp - CurrentTime.cpp - DateMath.cpp - DataLog.cpp - DecimalNumber.cpp - DynamicAnnotations.cpp - FastMalloc.cpp - HashTable.cpp - MD5.cpp - MainThread.cpp - MetaAllocator.cpp - OSRandomSource.cpp - NumberOfCores.cpp - PageAllocationAligned.cpp - PageBlock.cpp - ParallelJobsGeneric.cpp - RandomNumber.cpp - RefCountedLeakCounter.cpp - SHA1.cpp - StackBounds.cpp - StringExtras.cpp - Threading.cpp - TypeTraits.cpp - WTFThreadData.cpp - dtoa.cpp - - dtoa/bignum-dtoa.cc - dtoa/bignum.cc - dtoa/cached-powers.cc - dtoa/diy-fp.cc - dtoa/double-conversion.cc - dtoa/fast-dtoa.cc - dtoa/fixed-dtoa.cc - dtoa/strtod.cc - - text/AtomicString.cpp - text/CString.cpp - text/StringBuilder.cpp - text/StringImpl.cpp - text/StringStatics.cpp - text/WTFString.cpp - - threads/BinarySemaphore.cpp - - unicode/UTF8.cpp -) - -SET(WTF_INCLUDE_DIRECTORIES - "${JAVASCRIPTCORE_DIR}" - "${JAVASCRIPTCORE_DIR}/wtf" - "${JAVASCRIPTCORE_DIR}/wtf/unicode" - "${JAVASCRIPTCORE_DIR}/wtf/dtoa" - "${JavaScriptCore_INCLUDE_DIRECTORIES}" - "${THIRDPARTY_DIR}" -) - -IF (ENABLE_FAST_MALLOC) - LIST(APPEND WTF_SOURCES - TCSystemAlloc.cpp - ) -ELSE () - ADD_DEFINITIONS(-DUSE_SYSTEM_MALLOC=1) -ENDIF() - -WEBKIT_INCLUDE_CONFIG_FILES_IF_EXISTS() - -WEBKIT_WRAP_SOURCELIST(${WTF_SOURCES}) -INCLUDE_DIRECTORIES(${WTF_INCLUDE_DIRECTORIES}) -ADD_DEFINITIONS(-DBUILDING_WTF) -ADD_LIBRARY(${WTF_LIBRARY_NAME} STATIC ${WTF_HEADERS} ${WTF_SOURCES}) -TARGET_LINK_LIBRARIES(${WTF_LIBRARY_NAME} ${WTF_LIBRARIES}) - -IF (WTF_LINK_FLAGS) - ADD_TARGET_PROPERTIES(${WTF_LIBRARY_NAME} LINK_FLAGS "${WTF_LINK_FLAGS}") -ENDIF () diff --git a/Source/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 b/Source/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 deleted file mode 100644 index 7de0f2606..000000000 --- a/Source/JavaScriptCore/wtf/CONTRIBUTORS.pthreads-win32 +++ /dev/null @@ -1,137 +0,0 @@ -This is a copy of CONTRIBUTORS file for the Pthreads-win32 library, downloaded -from http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/pthreads/CONTRIBUTORS?rev=1.32&cvsroot=pthreads-win32 - -Included here to compliment the Pthreads-win32 license header in wtf/ThreadingWin.cpp file. -WebKit is using derived sources of ThreadCondition code from Pthreads-win32. - -------------------------------------------------------------------------------- - -Contributors (in approximate order of appearance) - -[See also the ChangeLog file where individuals are -attributed in log entries. Likewise in the FAQ file.] - -Ben Elliston bje at cygnus dot com - Initiated the project; - setup the project infrastructure (CVS, web page, etc.); - early prototype routines. -Ross Johnson rpj at callisto dot canberra dot edu dot au - early prototype routines; - ongoing project coordination/maintenance; - implementation of spin locks and barriers; - various enhancements; - bug fixes; - documentation; - testsuite. -Robert Colquhoun rjc at trump dot net dot au - Early bug fixes. -John E. Bossom John dot Bossom at cognos dot com - Contributed substantial original working implementation; - bug fixes; - ongoing guidance and standards interpretation. -Anders Norlander anorland at hem2 dot passagen dot se - Early enhancements and runtime checking for supported - Win32 routines. -Tor Lillqvist tml at iki dot fi - General enhancements; - early bug fixes to condition variables. -Scott Lightner scott at curriculum dot com - Bug fix. -Kevin Ruland Kevin dot Ruland at anheuser-busch dot com - Various bug fixes. -Mike Russo miker at eai dot com - Bug fix. -Mark E. Armstrong avail at pacbell dot net - Bug fixes. -Lorin Hochstein lmh at xiphos dot ca - general bug fixes; bug fixes to condition variables. -Peter Slacik Peter dot Slacik at tatramed dot sk - Bug fixes. -Mumit Khan khan at xraylith dot wisc dot edu - Fixes to work with Mingw32. -Milan Gardian mg at tatramed dot sk - Bug fixes and reports/analyses of obscure problems. -Aurelio Medina aureliom at crt dot com - First implementation of read-write locks. -Graham Dumpleton Graham dot Dumpleton at ra dot pad dot otc dot telstra dot com dot au - Bug fix in condition variables. -Tristan Savatier tristan at mpegtv dot com - WinCE port. -Erik Hensema erik at hensema dot xs4all dot nl - Bug fixes. -Rich Peters rpeters at micro-magic dot com -Todd Owen towen at lucidcalm dot dropbear dot id dot au - Bug fixes to dll loading. -Jason Nye jnye at nbnet dot nb dot ca - Implementation of async cancelation. -Fred Forester fforest at eticomm dot net -Kevin D. Clark kclark at cabletron dot com -David Baggett dmb at itasoftware dot com - Bug fixes. -Paul Redondo paul at matchvision dot com -Scott McCaskill scott at 3dfx dot com - Bug fixes. -Jef Gearhart jgearhart at tpssys dot com - Bug fix. -Arthur Kantor akantor at bexusa dot com - Mutex enhancements. -Steven Reddie smr at essemer dot com dot au - Bug fix. -Alexander Terekhov TEREKHOV at de dot ibm dot com - Re-implemented and improved read-write locks; - (with Louis Thomas) re-implemented and improved - condition variables; - enhancements to semaphores; - enhancements to mutexes; - new mutex implementation in 'futex' style; - suggested a robust implementation of pthread_once - similar to that implemented by V.Kliathcko; - system clock change handling re CV timeouts; - bug fixes. -Thomas Pfaff tpfaff at gmx dot net - Changes to make C version usable with C++ applications; - re-implemented mutex routines to avoid Win32 mutexes - and TryEnterCriticalSection; - procedure to fix Mingw32 thread-safety issues. -Franco Bez franco dot bez at gmx dot de - procedure to fix Mingw32 thread-safety issues. -Louis Thomas lthomas at arbitrade dot com - (with Alexander Terekhov) re-implemented and improved - condition variables. -David Korn dgk at research dot att dot com - Ported to UWIN. -Phil Frisbie, Jr. phil at hawksoft dot com - Bug fix. -Ralf Brese Ralf dot Brese at pdb4 dot siemens dot de - Bug fix. -prionx at juno dot com prionx at juno dot com - Bug fixes. -Max Woodbury mtew at cds dot duke dot edu - POSIX versioning conditionals; - reduced namespace pollution; - idea to separate routines to reduce statically - linked image sizes. -Rob Fanner rfanner at stonethree dot com - Bug fix. -Michael Johnson michaelj at maine dot rr dot com - Bug fix. -Nicolas Barry boozai at yahoo dot com - Bug fixes. -Piet van Bruggen pietvb at newbridges dot nl - Bug fix. -Makoto Kato raven at oldskool dot jp - AMD64 port. -Panagiotis E. Hadjidoukas peh at hpclab dot ceid dot upatras dot gr - Contributed the QueueUserAPCEx package which - makes preemptive async cancelation possible. -Will Bryant will dot bryant at ecosm dot com - Borland compiler patch and makefile. -Anuj Goyal anuj dot goyal at gmail dot com - Port to Digital Mars compiler. -Gottlob Frege gottlobfrege at gmail dot com - re-implemented pthread_once (version 2) - (pthread_once cancellation added by rpj). -Vladimir Kliatchko vladimir at kliatchko dot com - reimplemented pthread_once with the same form - as described by A.Terekhov (later version 2); - implementation of MCS (Mellor-Crummey/Scott) locks.
\ No newline at end of file diff --git a/Source/JavaScriptCore/wtf/CheckedArithmetic.h b/Source/JavaScriptCore/wtf/CheckedArithmetic.h deleted file mode 100644 index b18916538..000000000 --- a/Source/JavaScriptCore/wtf/CheckedArithmetic.h +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Copyright (C) 2011 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 CheckedArithmetic_h -#define CheckedArithmetic_h - -#include <wtf/Assertions.h> -#include <wtf/TypeTraits.h> - -#include <limits> -#include <stdint.h> - -/* Checked<T> - * - * This class provides a mechanism to perform overflow-safe integer arithmetic - * without having to manually ensure that you have all the required bounds checks - * directly in your code. - * - * There are two modes of operation: - * - The default is Checked<T, CrashOnOverflow>, and crashes at the point - * and overflow has occurred. - * - The alternative is Checked<T, RecordOverflow>, which uses an additional - * byte of storage to track whether an overflow has occurred, subsequent - * unchecked operations will crash if an overflow has occured - * - * It is possible to provide a custom overflow handler, in which case you need - * to support these functions: - * - void overflowed(); - * This function is called when an operation has produced an overflow. - * - bool hasOverflowed(); - * This function must return true if overflowed() has been called on an - * instance and false if it has not. - * - void clearOverflow(); - * Used to reset overflow tracking when a value is being overwritten with - * a new value. - * - * Checked<T> works for all integer types, with the following caveats: - * - Mixing signedness of operands is only supported for types narrower than - * 64bits. - * - It does have a performance impact, so tight loops may want to be careful - * when using it. - * - */ - -namespace WTF { - -class CrashOnOverflow { -protected: - NO_RETURN_DUE_TO_CRASH void overflowed() - { - CRASH(); - } - - void clearOverflow() { } - -public: - bool hasOverflowed() const { return false; } -}; - -class RecordOverflow { -protected: - RecordOverflow() - : m_overflowed(false) - { - } - - void overflowed() - { - m_overflowed = true; - } - - void clearOverflow() - { - m_overflowed = false; - } - -public: - bool hasOverflowed() const { return m_overflowed; } - -private: - unsigned char m_overflowed; -}; - -template <typename T, class OverflowHandler = CrashOnOverflow> class Checked; -template <typename T> struct RemoveChecked; -template <typename T> struct RemoveChecked<Checked<T> >; - -template <typename Target, typename Source, bool targetSigned = std::numeric_limits<Target>::is_signed, bool sourceSigned = std::numeric_limits<Source>::is_signed> struct BoundsChecker; -template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, false> { - static bool inBounds(Source value) - { - // Same signedness so implicit type conversion will always increase precision - // to widest type - return value <= std::numeric_limits<Target>::max(); - } -}; - -template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, true> { - static bool inBounds(Source value) - { - // Same signedness so implicit type conversion will always increase precision - // to widest type - return std::numeric_limits<Target>::min() <= value && value <= std::numeric_limits<Target>::max(); - } -}; - -template <typename Target, typename Source> struct BoundsChecker<Target, Source, false, true> { - static bool inBounds(Source value) - { - // Target is unsigned so any value less than zero is clearly unsafe - if (value < 0) - return false; - // If our (unsigned) Target is the same or greater width we can - // convert value to type Target without losing precision - if (sizeof(Target) >= sizeof(Source)) - return static_cast<Target>(value) <= std::numeric_limits<Target>::max(); - // The signed Source type has greater precision than the target so - // max(Target) -> Source will widen. - return value <= static_cast<Source>(std::numeric_limits<Target>::max()); - } -}; - -template <typename Target, typename Source> struct BoundsChecker<Target, Source, true, false> { - static bool inBounds(Source value) - { - // Signed target with an unsigned source - if (sizeof(Target) <= sizeof(Source)) - return value <= static_cast<Source>(std::numeric_limits<Target>::max()); - // Target is Wider than Source so we're guaranteed to fit any value in - // unsigned Source - return true; - } -}; - -template <typename Target, typename Source, bool SameType = IsSameType<Target, Source>::value> struct BoundsCheckElider; -template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, true> { - static bool inBounds(Source) { return true; } -}; -template <typename Target, typename Source> struct BoundsCheckElider<Target, Source, false> : public BoundsChecker<Target, Source> { -}; - -template <typename Target, typename Source> static inline bool isInBounds(Source value) -{ - return BoundsCheckElider<Target, Source>::inBounds(value); -} - -template <typename T> struct RemoveChecked { - typedef T CleanType; - static const CleanType DefaultValue = 0; -}; - -template <typename T> struct RemoveChecked<Checked<T, CrashOnOverflow> > { - typedef typename RemoveChecked<T>::CleanType CleanType; - static const CleanType DefaultValue = 0; -}; - -template <typename T> struct RemoveChecked<Checked<T, RecordOverflow> > { - typedef typename RemoveChecked<T>::CleanType CleanType; - static const CleanType DefaultValue = 0; -}; - -// The ResultBase and SignednessSelector are used to workaround typeof not being -// available in MSVC -template <typename U, typename V, bool uIsBigger = (sizeof(U) > sizeof(V)), bool sameSize = (sizeof(U) == sizeof(V))> struct ResultBase; -template <typename U, typename V> struct ResultBase<U, V, true, false> { - typedef U ResultType; -}; - -template <typename U, typename V> struct ResultBase<U, V, false, false> { - typedef V ResultType; -}; - -template <typename U> struct ResultBase<U, U, false, true> { - typedef U ResultType; -}; - -template <typename U, typename V, bool uIsSigned = std::numeric_limits<U>::is_signed, bool vIsSigned = std::numeric_limits<V>::is_signed> struct SignednessSelector; -template <typename U, typename V> struct SignednessSelector<U, V, true, true> { - typedef U ResultType; -}; - -template <typename U, typename V> struct SignednessSelector<U, V, false, false> { - typedef U ResultType; -}; - -template <typename U, typename V> struct SignednessSelector<U, V, true, false> { - typedef V ResultType; -}; - -template <typename U, typename V> struct SignednessSelector<U, V, false, true> { - typedef U ResultType; -}; - -template <typename U, typename V> struct ResultBase<U, V, false, true> { - typedef typename SignednessSelector<U, V>::ResultType ResultType; -}; - -template <typename U, typename V> struct Result : ResultBase<typename RemoveChecked<U>::CleanType, typename RemoveChecked<V>::CleanType> { -}; - -template <typename LHS, typename RHS, typename ResultType = typename Result<LHS, RHS>::ResultType, - bool lhsSigned = std::numeric_limits<LHS>::is_signed, bool rhsSigned = std::numeric_limits<RHS>::is_signed> struct ArithmeticOperations; - -template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, true, true> { - // LHS and RHS are signed types - - // Helper function - static inline bool signsMatch(LHS lhs, RHS rhs) - { - return (lhs ^ rhs) >= 0; - } - - static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN - { - if (signsMatch(lhs, rhs)) { - if (lhs >= 0) { - if ((std::numeric_limits<ResultType>::max() - rhs) < lhs) - return false; - } else { - ResultType temp = lhs - std::numeric_limits<ResultType>::min(); - if (rhs < -temp) - return false; - } - } // if the signs do not match this operation can't overflow - result = lhs + rhs; - return true; - } - - static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN - { - if (!signsMatch(lhs, rhs)) { - if (lhs >= 0) { - if (lhs > std::numeric_limits<ResultType>::max() + rhs) - return false; - } else { - if (rhs > std::numeric_limits<ResultType>::max() + lhs) - return false; - } - } // if the signs match this operation can't overflow - result = lhs - rhs; - return true; - } - - static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN - { - if (signsMatch(lhs, rhs)) { - if (lhs >= 0) { - if (lhs && (std::numeric_limits<ResultType>::max() / lhs) < rhs) - return false; - } else { - if (lhs == std::numeric_limits<ResultType>::min() || rhs == std::numeric_limits<ResultType>::min()) - return false; - if ((std::numeric_limits<ResultType>::max() / -lhs) < -rhs) - return false; - } - } else { - if (lhs < 0) { - if (rhs && lhs < (std::numeric_limits<ResultType>::min() / rhs)) - return false; - } else { - if (lhs && rhs < (std::numeric_limits<ResultType>::min() / lhs)) - return false; - } - } - result = lhs * rhs; - return true; - } - - static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; } - -}; - -template <typename LHS, typename RHS, typename ResultType> struct ArithmeticOperations<LHS, RHS, ResultType, false, false> { - // LHS and RHS are unsigned types so bounds checks are nice and easy - static inline bool add(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN - { - ResultType temp = lhs + rhs; - if (temp < lhs) - return false; - result = temp; - return true; - } - - static inline bool sub(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN - { - ResultType temp = lhs - rhs; - if (temp > lhs) - return false; - result = temp; - return true; - } - - static inline bool multiply(LHS lhs, RHS rhs, ResultType& result) WARN_UNUSED_RETURN - { - ResultType temp = lhs * rhs; - if (temp < lhs) - return false; - result = temp; - return true; - } - - static inline bool equals(LHS lhs, RHS rhs) { return lhs == rhs; } - -}; - -template <typename ResultType> struct ArithmeticOperations<int, unsigned, ResultType, true, false> { - static inline bool add(int64_t lhs, int64_t rhs, ResultType& result) - { - int64_t temp = lhs + rhs; - if (temp < std::numeric_limits<ResultType>::min()) - return false; - if (temp > std::numeric_limits<ResultType>::max()) - return false; - result = static_cast<ResultType>(temp); - return true; - } - - static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result) - { - int64_t temp = lhs - rhs; - if (temp < std::numeric_limits<ResultType>::min()) - return false; - if (temp > std::numeric_limits<ResultType>::max()) - return false; - result = static_cast<ResultType>(temp); - return true; - } - - static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result) - { - int64_t temp = lhs * rhs; - if (temp < std::numeric_limits<ResultType>::min()) - return false; - if (temp > std::numeric_limits<ResultType>::max()) - return false; - result = static_cast<ResultType>(temp); - return true; - } - - static inline bool equals(int lhs, unsigned rhs) - { - return static_cast<int64_t>(lhs) == static_cast<int64_t>(rhs); - } -}; - -template <typename ResultType> struct ArithmeticOperations<unsigned, int, ResultType, false, true> { - static inline bool add(int64_t lhs, int64_t rhs, ResultType& result) - { - return ArithmeticOperations<int, unsigned, ResultType>::add(rhs, lhs, result); - } - - static inline bool sub(int64_t lhs, int64_t rhs, ResultType& result) - { - return ArithmeticOperations<int, unsigned, ResultType>::sub(lhs, rhs, result); - } - - static inline bool multiply(int64_t lhs, int64_t rhs, ResultType& result) - { - return ArithmeticOperations<int, unsigned, ResultType>::multiply(rhs, lhs, result); - } - - static inline bool equals(unsigned lhs, int rhs) - { - return ArithmeticOperations<int, unsigned, ResultType>::equals(rhs, lhs); - } -}; - -template <typename U, typename V, typename R> static inline bool safeAdd(U lhs, V rhs, R& result) -{ - return ArithmeticOperations<U, V, R>::add(lhs, rhs, result); -} - -template <typename U, typename V, typename R> static inline bool safeSub(U lhs, V rhs, R& result) -{ - return ArithmeticOperations<U, V, R>::sub(lhs, rhs, result); -} - -template <typename U, typename V, typename R> static inline bool safeMultiply(U lhs, V rhs, R& result) -{ - return ArithmeticOperations<U, V, R>::multiply(lhs, rhs, result); -} - -template <typename U, typename V> static inline bool safeEquals(U lhs, V rhs) -{ - return ArithmeticOperations<U, V>::equals(lhs, rhs); -} - -enum ResultOverflowedTag { ResultOverflowed }; - -// FIXME: Needed to workaround http://llvm.org/bugs/show_bug.cgi?id=10801 -static inline bool workAroundClangBug() { return true; } - -template <typename T, class OverflowHandler> class Checked : public OverflowHandler { -public: - template <typename _T, class _OverflowHandler> friend class Checked; - Checked() - : m_value(0) - { - } - - Checked(ResultOverflowedTag) - : m_value(0) - { - // FIXME: Remove this when clang fixes http://llvm.org/bugs/show_bug.cgi?id=10801 - if (workAroundClangBug()) - this->overflowed(); - } - - template <typename U> Checked(U value) - { - if (!isInBounds<T>(value)) - this->overflowed(); - m_value = static_cast<T>(value); - } - - template <typename V> Checked(const Checked<T, V>& rhs) - : m_value(rhs.m_value) - { - if (rhs.hasOverflowed()) - this->overflowed(); - } - - template <typename U> Checked(const Checked<U, OverflowHandler>& rhs) - : OverflowHandler(rhs) - { - if (!isInBounds<T>(rhs.m_value)) - this->overflowed(); - m_value = static_cast<T>(rhs.m_value); - } - - template <typename U, typename V> Checked(const Checked<U, V>& rhs) - { - if (rhs.hasOverflowed()) - this->overflowed(); - if (!isInBounds<T>(rhs.m_value)) - this->overflowed(); - m_value = static_cast<T>(rhs.m_value); - } - - const Checked& operator=(Checked rhs) - { - this->clearOverflow(); - if (rhs.hasOverflowed()) - this->overflowed(); - m_value = static_cast<T>(rhs.m_value); - return *this; - } - - template <typename U> const Checked& operator=(U value) - { - return *this = Checked(value); - } - - template <typename U, typename V> const Checked& operator=(const Checked<U, V>& rhs) - { - return *this = Checked(rhs); - } - - // prefix - const Checked& operator++() - { - if (m_value == std::numeric_limits<T>::max()) - this->overflowed(); - m_value++; - return *this; - } - - const Checked& operator--() - { - if (m_value == std::numeric_limits<T>::min()) - this->overflowed(); - m_value--; - return *this; - } - - // postfix operators - const Checked operator++(int) - { - if (m_value == std::numeric_limits<T>::max()) - this->overflowed(); - return Checked(m_value++); - } - - const Checked operator--(int) - { - if (m_value == std::numeric_limits<T>::min()) - this->overflowed(); - return Checked(m_value--); - } - - // Boolean operators - bool operator!() const - { - if (this->hasOverflowed()) - CRASH(); - return !m_value; - } - - typedef void* (Checked::*UnspecifiedBoolType); - operator UnspecifiedBoolType*() const - { - if (this->hasOverflowed()) - CRASH(); - return (m_value) ? reinterpret_cast<UnspecifiedBoolType*>(1) : 0; - } - - // Value accessors. unsafeGet() will crash if there's been an overflow. - T unsafeGet() const - { - if (this->hasOverflowed()) - CRASH(); - return m_value; - } - - bool safeGet(T& value) const WARN_UNUSED_RETURN - { - value = m_value; - return this->hasOverflowed(); - } - - // Mutating assignment - template <typename U> const Checked operator+=(U rhs) - { - if (!safeAdd(m_value, rhs, m_value)) - this->overflowed(); - return *this; - } - - template <typename U> const Checked operator-=(U rhs) - { - if (!safeSub(m_value, rhs, m_value)) - this->overflowed(); - return *this; - } - - template <typename U> const Checked operator*=(U rhs) - { - if (!safeMultiply(m_value, rhs, m_value)) - this->overflowed(); - return *this; - } - - template <typename U, typename V> const Checked operator+=(Checked<U, V> rhs) - { - if (rhs.hasOverflowed()) - this->overflowed(); - return *this += rhs.m_value; - } - - template <typename U, typename V> const Checked operator-=(Checked<U, V> rhs) - { - if (rhs.hasOverflowed()) - this->overflowed(); - return *this -= rhs.m_value; - } - - template <typename U, typename V> const Checked operator*=(Checked<U, V> rhs) - { - if (rhs.hasOverflowed()) - this->overflowed(); - return *this *= rhs.m_value; - } - - // Equality comparisons - template <typename V> bool operator==(Checked<T, V> rhs) - { - return unsafeGet() == rhs.unsafeGet(); - } - - template <typename U> bool operator==(U rhs) - { - if (this->hasOverflowed()) - this->overflowed(); - return safeEquals(m_value, rhs); - } - - template <typename U, typename V> const Checked operator==(Checked<U, V> rhs) - { - return unsafeGet() == Checked(rhs.unsafeGet()); - } - - template <typename U> bool operator!=(U rhs) - { - return !(*this == rhs); - } - -private: - // Disallow implicit conversion of floating point to integer types - Checked(float); - Checked(double); - void operator=(float); - void operator=(double); - void operator+=(float); - void operator+=(double); - void operator-=(float); - void operator-=(double); - T m_value; -}; - -template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs) -{ - U x = 0; - V y = 0; - bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); - typename Result<U, V>::ResultType result = 0; - overflowed |= !safeAdd(x, y, result); - if (overflowed) - return ResultOverflowed; - return result; -} - -template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs) -{ - U x = 0; - V y = 0; - bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); - typename Result<U, V>::ResultType result = 0; - overflowed |= !safeSub(x, y, result); - if (overflowed) - return ResultOverflowed; - return result; -} - -template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, Checked<V, OverflowHandler> rhs) -{ - U x = 0; - V y = 0; - bool overflowed = lhs.safeGet(x) || rhs.safeGet(y); - typename Result<U, V>::ResultType result = 0; - overflowed |= !safeMultiply(x, y, result); - if (overflowed) - return ResultOverflowed; - return result; -} - -template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(Checked<U, OverflowHandler> lhs, V rhs) -{ - return lhs + Checked<V, OverflowHandler>(rhs); -} - -template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(Checked<U, OverflowHandler> lhs, V rhs) -{ - return lhs - Checked<V, OverflowHandler>(rhs); -} - -template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(Checked<U, OverflowHandler> lhs, V rhs) -{ - return lhs * Checked<V, OverflowHandler>(rhs); -} - -template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator+(U lhs, Checked<V, OverflowHandler> rhs) -{ - return Checked<U, OverflowHandler>(lhs) + rhs; -} - -template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator-(U lhs, Checked<V, OverflowHandler> rhs) -{ - return Checked<U, OverflowHandler>(lhs) - rhs; -} - -template <typename U, typename V, typename OverflowHandler> static inline Checked<typename Result<U, V>::ResultType, OverflowHandler> operator*(U lhs, Checked<V, OverflowHandler> rhs) -{ - return Checked<U, OverflowHandler>(lhs) * rhs; -} - -} - -using WTF::Checked; -using WTF::RecordOverflow; - -#endif diff --git a/Source/JavaScriptCore/wtf/Compiler.h b/Source/JavaScriptCore/wtf/Compiler.h deleted file mode 100644 index b8a019299..000000000 --- a/Source/JavaScriptCore/wtf/Compiler.h +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (C) 2011, 2012 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 WTF_Compiler_h -#define WTF_Compiler_h - -/* COMPILER() - the compiler being used to build the project */ -#define COMPILER(WTF_FEATURE) (defined WTF_COMPILER_##WTF_FEATURE && WTF_COMPILER_##WTF_FEATURE) - -/* COMPILER_SUPPORTS() - whether the compiler being used to build the project supports the given feature. */ -#define COMPILER_SUPPORTS(WTF_COMPILER_FEATURE) (defined WTF_COMPILER_SUPPORTS_##WTF_COMPILER_FEATURE && WTF_COMPILER_SUPPORTS_##WTF_COMPILER_FEATURE) - -/* ==== COMPILER() - the compiler being used to build the project ==== */ - -/* COMPILER(CLANG) - Clang */ -#if defined(__clang__) -#define WTF_COMPILER_CLANG 1 - -#ifndef __has_extension -#define __has_extension __has_feature /* Compatibility with older versions of clang */ -#endif - -/* Specific compiler features */ -#define WTF_COMPILER_SUPPORTS_CXX_VARIADIC_TEMPLATES __has_feature(cxx_variadic_templates) -#define WTF_COMPILER_SUPPORTS_CXX_RVALUE_REFERENCES __has_feature(cxx_rvalue_references) -#define WTF_COMPILER_SUPPORTS_CXX_DELETED_FUNCTIONS __has_feature(cxx_deleted_functions) -#define WTF_COMPILER_SUPPORTS_CXX_NULLPTR __has_feature(cxx_nullptr) -#define WTF_COMPILER_SUPPORTS_BLOCKS __has_feature(blocks) -#define WTF_COMPILER_SUPPORTS_C_STATIC_ASSERT __has_extension(c_static_assert) - -#define WTF_COMPILER_SUPPORTS_HAS_TRIVIAL_DESTRUCTOR __has_extension(has_trivial_destructor) - -#endif - -/* COMPILER(MSVC) - Microsoft Visual C++ */ -/* COMPILER(MSVC7_OR_LOWER) - Microsoft Visual C++ 2003 or lower*/ -/* COMPILER(MSVC9_OR_LOWER) - Microsoft Visual C++ 2008 or lower*/ -#if defined(_MSC_VER) -#define WTF_COMPILER_MSVC 1 -#if _MSC_VER < 1400 -#define WTF_COMPILER_MSVC7_OR_LOWER 1 -#elif _MSC_VER < 1600 -#define WTF_COMPILER_MSVC9_OR_LOWER 1 -#endif - -/* Specific compiler features */ -#if _MSC_VER >= 1600 -#define WTF_COMPILER_SUPPORTS_CXX_NULLPTR 1 -#endif - -#endif - -/* COMPILER(RVCT) - ARM RealView Compilation Tools */ -/* COMPILER(RVCT4_OR_GREATER) - ARM RealView Compilation Tools 4.0 or greater */ -#if defined(__CC_ARM) || defined(__ARMCC__) -#define WTF_COMPILER_RVCT 1 -#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) (__ARMCC_VERSION >= (major * 100000 + minor * 10000 + patch * 1000 + build)) -#else -/* Define this for !RVCT compilers, just so we can write things like RVCT_VERSION_AT_LEAST(3, 0, 0, 0). */ -#define RVCT_VERSION_AT_LEAST(major, minor, patch, build) 0 -#endif - -/* COMPILER(GCCE) - GNU Compiler Collection for Embedded */ -#if defined(__GCCE__) -#define WTF_COMPILER_GCCE 1 -#define GCCE_VERSION (__GCCE__ * 10000 + __GCCE_MINOR__ * 100 + __GCCE_PATCHLEVEL__) -#define GCCE_VERSION_AT_LEAST(major, minor, patch) (GCCE_VERSION >= (major * 10000 + minor * 100 + patch)) -#endif - -/* COMPILER(GCC) - GNU Compiler Collection */ -/* --gnu option of the RVCT compiler also defines __GNUC__ */ -#if defined(__GNUC__) && !COMPILER(RVCT) -#define WTF_COMPILER_GCC 1 -#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#define GCC_VERSION_AT_LEAST(major, minor, patch) (GCC_VERSION >= (major * 10000 + minor * 100 + patch)) - -/* Specific compiler features */ -#if !COMPILER(CLANG) && GCC_VERSION_AT_LEAST(4, 6, 0) && defined(__GXX_EXPERIMENTAL_CXX0X__) -#define WTF_COMPILER_SUPPORTS_CXX_NULLPTR 1 -#endif - -#else -/* Define this for !GCC compilers, just so we can write things like GCC_VERSION_AT_LEAST(4, 1, 0). */ -#define GCC_VERSION_AT_LEAST(major, minor, patch) 0 -#endif - -/* COMPILER(MINGW) - MinGW GCC */ -/* COMPILER(MINGW64) - mingw-w64 GCC - only used as additional check to exclude mingw.org specific functions */ -#if defined(__MINGW32__) -#define WTF_COMPILER_MINGW 1 -#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(INTEL) - Intel C++ Compiler */ -#if defined(__INTEL_COMPILER) -#define WTF_COMPILER_INTEL 1 -#endif - -/* COMPILER(SUNCC) */ -#if defined(__SUNPRO_CC) || defined(__SUNPRO_C) -#define WTF_COMPILER_SUNCC 1 -#endif - -/* ==== Compiler features ==== */ - - -/* ALWAYS_INLINE */ - -#ifndef ALWAYS_INLINE -#if COMPILER(GCC) && defined(NDEBUG) && !COMPILER(MINGW) -#define ALWAYS_INLINE inline __attribute__((__always_inline__)) -#elif (COMPILER(MSVC) || COMPILER(RVCT)) && defined(NDEBUG) -#define ALWAYS_INLINE __forceinline -#else -#define ALWAYS_INLINE inline -#endif -#endif - - -/* NEVER_INLINE */ - -#ifndef NEVER_INLINE -#if COMPILER(GCC) -#define NEVER_INLINE __attribute__((__noinline__)) -#elif COMPILER(RVCT) -#define NEVER_INLINE __declspec(noinline) -#else -#define NEVER_INLINE -#endif -#endif - - -/* UNLIKELY */ - -#ifndef UNLIKELY -#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__)) -#define UNLIKELY(x) __builtin_expect((x), 0) -#else -#define UNLIKELY(x) (x) -#endif -#endif - - -/* LIKELY */ - -#ifndef LIKELY -#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(3, 0, 0, 0) && defined(__GNUC__)) -#define LIKELY(x) __builtin_expect((x), 1) -#else -#define LIKELY(x) (x) -#endif -#endif - - -/* NO_RETURN */ - - -#ifndef NO_RETURN -#if COMPILER(GCC) -#define NO_RETURN __attribute((__noreturn__)) -#elif COMPILER(MSVC) || COMPILER(RVCT) -#define NO_RETURN __declspec(noreturn) -#else -#define NO_RETURN -#endif -#endif - - -/* NO_RETURN_WITH_VALUE */ - -#ifndef NO_RETURN_WITH_VALUE -#if !COMPILER(MSVC) -#define NO_RETURN_WITH_VALUE NO_RETURN -#else -#define NO_RETURN_WITH_VALUE -#endif -#endif - - -/* WARN_UNUSED_RETURN */ - -#if COMPILER(GCC) -#define WARN_UNUSED_RETURN __attribute__ ((warn_unused_result)) -#else -#define WARN_UNUSED_RETURN -#endif - -/* OVERRIDE */ - -#ifndef OVERRIDE -#if COMPILER(CLANG) -#if __has_extension(cxx_override_control) -#define OVERRIDE override -#endif -#elif COMPILER(MSVC) -#define OVERRIDE override -#endif -#endif - -#ifndef OVERRIDE -#define OVERRIDE -#endif - -/* FINAL */ - -#ifndef FINAL -#if COMPILER(CLANG) -#if __has_extension(cxx_override_control) -#define FINAL final -#endif -#elif COMPILER(MSVC) -#define FINAL sealed -#endif -#endif - -#ifndef FINAL -#define FINAL -#endif - -/* OBJC_CLASS */ - -#ifndef OBJC_CLASS -#ifdef __OBJC__ -#define OBJC_CLASS @class -#else -#define OBJC_CLASS class -#endif -#endif - -#endif /* WTF_Compiler_h */ diff --git a/Source/JavaScriptCore/wtf/Complex.h b/Source/JavaScriptCore/wtf/Complex.h deleted file mode 100644 index 40fe56a7b..000000000 --- a/Source/JavaScriptCore/wtf/Complex.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * 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 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 WTF_Complex_h -#define WTF_Complex_h - -#include <complex> -#include <wtf/MathExtras.h> - -namespace WTF { - -typedef std::complex<double> Complex; - -inline Complex complexFromMagnitudePhase(double magnitude, double phase) -{ - return Complex(magnitude * cos(phase), magnitude * sin(phase)); -} - -} // namespace WTF - -using WTF::Complex; -using WTF::complexFromMagnitudePhase; - -#endif // WTF_Complex_h diff --git a/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.cpp b/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.cpp deleted file mode 100644 index 8c16f5314..000000000 --- a/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 1996, David Mazieres <dm@uun.org> - * Copyright (c) 2008, Damien Miller <djm@openbsd.org> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * Arc4 random number generator for OpenBSD. - * - * This code is derived from section 17.1 of Applied Cryptography, - * second edition, which describes a stream cipher allegedly - * compatible with RSA Labs "RC4" cipher (the actual description of - * which is a trade secret). The same algorithm is used as a stream - * cipher called "arcfour" in Tatu Ylonen's ssh package. - * - * RC4 is a registered trademark of RSA Laboratories. - */ - -#include "config.h" -#include "CryptographicallyRandomNumber.h" - -#include "OSRandomSource.h" -#include "StdLibExtras.h" -#include "ThreadingPrimitives.h" - -namespace WTF { - -#if USE(OS_RANDOMNESS) - -namespace { - -class ARC4Stream { -public: - ARC4Stream(); - - uint8_t i; - uint8_t j; - uint8_t s[256]; -}; - -class ARC4RandomNumberGenerator { -public: - ARC4RandomNumberGenerator(); - - uint32_t randomNumber(); - void randomValues(void* buffer, size_t length); - -private: - inline void addRandomData(unsigned char *data, int length); - void stir(); - void stirIfNeeded(); - inline uint8_t getByte(); - inline uint32_t getWord(); - - ARC4Stream m_stream; - int m_count; - Mutex m_mutex; -}; - -ARC4Stream::ARC4Stream() -{ - for (int n = 0; n < 256; n++) - s[n] = n; - i = 0; - j = 0; -} - -ARC4RandomNumberGenerator::ARC4RandomNumberGenerator() - : m_count(0) -{ -} - -void ARC4RandomNumberGenerator::addRandomData(unsigned char* data, int length) -{ - m_stream.i--; - for (int n = 0; n < 256; n++) { - m_stream.i++; - uint8_t si = m_stream.s[m_stream.i]; - m_stream.j += si + data[n % length]; - m_stream.s[m_stream.i] = m_stream.s[m_stream.j]; - m_stream.s[m_stream.j] = si; - } - m_stream.j = m_stream.i; -} - -void ARC4RandomNumberGenerator::stir() -{ - unsigned char randomness[128]; - size_t length = sizeof(randomness); - cryptographicallyRandomValuesFromOS(randomness, length); - addRandomData(randomness, length); - - // Discard early keystream, as per recommendations in: - // http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps - for (int i = 0; i < 256; i++) - getByte(); - m_count = 1600000; -} - -void ARC4RandomNumberGenerator::stirIfNeeded() -{ - if (m_count <= 0) - stir(); -} - -uint8_t ARC4RandomNumberGenerator::getByte() -{ - m_stream.i++; - uint8_t si = m_stream.s[m_stream.i]; - m_stream.j += si; - uint8_t sj = m_stream.s[m_stream.j]; - m_stream.s[m_stream.i] = sj; - m_stream.s[m_stream.j] = si; - return (m_stream.s[(si + sj) & 0xff]); -} - -uint32_t ARC4RandomNumberGenerator::getWord() -{ - uint32_t val; - val = getByte() << 24; - val |= getByte() << 16; - val |= getByte() << 8; - val |= getByte(); - return val; -} - -uint32_t ARC4RandomNumberGenerator::randomNumber() -{ - MutexLocker locker(m_mutex); - - m_count -= 4; - stirIfNeeded(); - return getWord(); -} - -void ARC4RandomNumberGenerator::randomValues(void* buffer, size_t length) -{ - MutexLocker locker(m_mutex); - - unsigned char* result = reinterpret_cast<unsigned char*>(buffer); - stirIfNeeded(); - while (length--) { - m_count--; - stirIfNeeded(); - result[length] = getByte(); - } -} - -ARC4RandomNumberGenerator& sharedRandomNumberGenerator() -{ - DEFINE_STATIC_LOCAL(ARC4RandomNumberGenerator, randomNumberGenerator, ()); - return randomNumberGenerator; -} - -} - -uint32_t cryptographicallyRandomNumber() -{ - return sharedRandomNumberGenerator().randomNumber(); -} - -void cryptographicallyRandomValues(void* buffer, size_t length) -{ - sharedRandomNumberGenerator().randomValues(buffer, length); -} - -#endif - -} diff --git a/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h b/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h deleted file mode 100644 index 2262b6c3b..000000000 --- a/Source/JavaScriptCore/wtf/CryptographicallyRandomNumber.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * - * 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 WTF_CryptographicallyRandomNumber_h -#define WTF_CryptographicallyRandomNumber_h - -#include <stdint.h> - -namespace WTF { - -#if USE(OS_RANDOMNESS) -WTF_EXPORT_PRIVATE uint32_t cryptographicallyRandomNumber(); -WTF_EXPORT_PRIVATE void cryptographicallyRandomValues(void* buffer, size_t length); -#endif - -} - -#if USE(OS_RANDOMNESS) -using WTF::cryptographicallyRandomNumber; -using WTF::cryptographicallyRandomValues; -#endif - -#endif diff --git a/Source/JavaScriptCore/wtf/CurrentTime.cpp b/Source/JavaScriptCore/wtf/CurrentTime.cpp deleted file mode 100644 index 1ebd084d8..000000000 --- a/Source/JavaScriptCore/wtf/CurrentTime.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2008 Google Inc. All rights reserved. - * Copyright (C) 2007-2009 Torch Mobile, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "CurrentTime.h" - -#if PLATFORM(MAC) -#include <mach/mach_time.h> -#include <sys/time.h> -#elif OS(WINDOWS) - -// Windows is first since we want to use hires timers, despite USE(CF) -// being defined. -// If defined, WIN32_LEAN_AND_MEAN disables timeBeginPeriod/timeEndPeriod. -#undef WIN32_LEAN_AND_MEAN -#include <windows.h> -#include <math.h> -#include <stdint.h> -#include <time.h> - -#if USE(QUERY_PERFORMANCE_COUNTER) -#if OS(WINCE) -extern "C" time_t mktime(struct tm *t); -#else -#include <sys/timeb.h> -#include <sys/types.h> -#endif -#endif - -#elif PLATFORM(WX) -#include <wx/datetime.h> -#elif PLATFORM(EFL) -#include <Ecore.h> -#else -#include <sys/time.h> -#endif - -#if PLATFORM(GTK) -#include <glib.h> -#endif - -#if PLATFORM(QT) -#include <QElapsedTimer> -#endif - -#if PLATFORM(CHROMIUM) -#error Chromium uses a different timer implementation -#endif - -namespace WTF { - -const double msPerSecond = 1000.0; - -#if OS(WINDOWS) - -#if USE(QUERY_PERFORMANCE_COUNTER) - -static LARGE_INTEGER qpcFrequency; -static bool syncedTime; - -static double highResUpTime() -{ - // We use QPC, but only after sanity checking its result, due to bugs: - // http://support.microsoft.com/kb/274323 - // http://support.microsoft.com/kb/895980 - // http://msdn.microsoft.com/en-us/library/ms644904.aspx ("...you can get different results on different processors due to bugs in the basic input/output system (BIOS) or the hardware abstraction layer (HAL)." - - static LARGE_INTEGER qpcLast; - static DWORD tickCountLast; - static bool inited; - - LARGE_INTEGER qpc; - QueryPerformanceCounter(&qpc); - DWORD tickCount = GetTickCount(); - - if (inited) { - __int64 qpcElapsed = ((qpc.QuadPart - qpcLast.QuadPart) * 1000) / qpcFrequency.QuadPart; - __int64 tickCountElapsed; - if (tickCount >= tickCountLast) - tickCountElapsed = (tickCount - tickCountLast); - else { -#if COMPILER(MINGW) - __int64 tickCountLarge = tickCount + 0x100000000ULL; -#else - __int64 tickCountLarge = tickCount + 0x100000000I64; -#endif - tickCountElapsed = tickCountLarge - tickCountLast; - } - - // force a re-sync if QueryPerformanceCounter differs from GetTickCount by more than 500ms. - // (500ms value is from http://support.microsoft.com/kb/274323) - __int64 diff = tickCountElapsed - qpcElapsed; - if (diff > 500 || diff < -500) - syncedTime = false; - } else - inited = true; - - qpcLast = qpc; - tickCountLast = tickCount; - - return (1000.0 * qpc.QuadPart) / static_cast<double>(qpcFrequency.QuadPart); -} - -static double lowResUTCTime() -{ -#if OS(WINCE) - SYSTEMTIME systemTime; - GetSystemTime(&systemTime); - struct tm tmtime; - tmtime.tm_year = systemTime.wYear - 1900; - tmtime.tm_mon = systemTime.wMonth - 1; - tmtime.tm_mday = systemTime.wDay; - tmtime.tm_wday = systemTime.wDayOfWeek; - tmtime.tm_hour = systemTime.wHour; - tmtime.tm_min = systemTime.wMinute; - tmtime.tm_sec = systemTime.wSecond; - time_t timet = mktime(&tmtime); - return timet * msPerSecond + systemTime.wMilliseconds; -#else - struct _timeb timebuffer; - _ftime(&timebuffer); - return timebuffer.time * msPerSecond + timebuffer.millitm; -#endif -} - -static bool qpcAvailable() -{ - static bool available; - static bool checked; - - if (checked) - return available; - - available = QueryPerformanceFrequency(&qpcFrequency); - checked = true; - return available; -} - -double currentTime() -{ - // Use a combination of ftime and QueryPerformanceCounter. - // ftime returns the information we want, but doesn't have sufficient resolution. - // QueryPerformanceCounter has high resolution, but is only usable to measure time intervals. - // To combine them, we call ftime and QueryPerformanceCounter initially. Later calls will use QueryPerformanceCounter - // by itself, adding the delta to the saved ftime. We periodically re-sync to correct for drift. - static double syncLowResUTCTime; - static double syncHighResUpTime; - static double lastUTCTime; - - double lowResTime = lowResUTCTime(); - - if (!qpcAvailable()) - return lowResTime / 1000.0; - - double highResTime = highResUpTime(); - - if (!syncedTime) { - timeBeginPeriod(1); // increase time resolution around low-res time getter - syncLowResUTCTime = lowResTime = lowResUTCTime(); - timeEndPeriod(1); // restore time resolution - syncHighResUpTime = highResTime; - syncedTime = true; - } - - double highResElapsed = highResTime - syncHighResUpTime; - double utc = syncLowResUTCTime + highResElapsed; - - // force a clock re-sync if we've drifted - double lowResElapsed = lowResTime - syncLowResUTCTime; - const double maximumAllowedDriftMsec = 15.625 * 2.0; // 2x the typical low-res accuracy - if (fabs(highResElapsed - lowResElapsed) > maximumAllowedDriftMsec) - syncedTime = false; - - // make sure time doesn't run backwards (only correct if difference is < 2 seconds, since DST or clock changes could occur) - const double backwardTimeLimit = 2000.0; - if (utc < lastUTCTime && (lastUTCTime - utc) < backwardTimeLimit) - return lastUTCTime / 1000.0; - lastUTCTime = utc; - return utc / 1000.0; -} - -#else - -static double currentSystemTime() -{ - FILETIME ft; - GetCurrentFT(&ft); - - // As per Windows documentation for FILETIME, copy the resulting FILETIME structure to a - // ULARGE_INTEGER structure using memcpy (using memcpy instead of direct assignment can - // prevent alignment faults on 64-bit Windows). - - ULARGE_INTEGER t; - memcpy(&t, &ft, sizeof(t)); - - // Windows file times are in 100s of nanoseconds. - // To convert to seconds, we have to divide by 10,000,000, which is more quickly - // done by multiplying by 0.0000001. - - // Between January 1, 1601 and January 1, 1970, there were 369 complete years, - // of which 89 were leap years (1700, 1800, and 1900 were not leap years). - // That is a total of 134774 days, which is 11644473600 seconds. - - return t.QuadPart * 0.0000001 - 11644473600.0; -} - -double currentTime() -{ - static bool init = false; - static double lastTime; - static DWORD lastTickCount; - if (!init) { - lastTime = currentSystemTime(); - lastTickCount = GetTickCount(); - init = true; - return lastTime; - } - - DWORD tickCountNow = GetTickCount(); - DWORD elapsed = tickCountNow - lastTickCount; - double timeNow = lastTime + (double)elapsed / 1000.; - if (elapsed >= 0x7FFFFFFF) { - lastTime = timeNow; - lastTickCount = tickCountNow; - } - return timeNow; -} - -#endif // USE(QUERY_PERFORMANCE_COUNTER) - -#elif PLATFORM(GTK) - -// Note: GTK on Windows will pick up the PLATFORM(WIN) implementation above which provides -// better accuracy compared with Windows implementation of g_get_current_time: -// (http://www.google.com/codesearch/p?hl=en#HHnNRjks1t0/glib-2.5.2/glib/gmain.c&q=g_get_current_time). -// Non-Windows GTK builds could use gettimeofday() directly but for the sake of consistency lets use GTK function. -double currentTime() -{ - GTimeVal now; - g_get_current_time(&now); - return static_cast<double>(now.tv_sec) + static_cast<double>(now.tv_usec / 1000000.0); -} - -#elif PLATFORM(WX) - -double currentTime() -{ - wxDateTime now = wxDateTime::UNow(); - return (double)now.GetTicks() + (double)(now.GetMillisecond() / 1000.0); -} - -#elif PLATFORM(EFL) - -double currentTime() -{ - return ecore_time_unix_get(); -} - -#else - -double currentTime() -{ - struct timeval now; - gettimeofday(&now, 0); - return now.tv_sec + now.tv_usec / 1000000.0; -} - -#endif - -#if PLATFORM(MAC) - -double monotonicallyIncreasingTime() -{ - // Based on listing #2 from Apple QA 1398. - static mach_timebase_info_data_t timebaseInfo; - if (!timebaseInfo.denom) { - kern_return_t kr = mach_timebase_info(&timebaseInfo); - ASSERT_UNUSED(kr, kr == KERN_SUCCESS); - } - return (mach_absolute_time() * timebaseInfo.numer) / (1.0e9 * timebaseInfo.denom); -} - -#elif PLATFORM(EFL) - -double monotonicallyIncreasingTime() -{ - return ecore_time_get(); -} - -#elif PLATFORM(GTK) - -double monotonicallyIncreasingTime() -{ - return static_cast<double>(g_get_monotonic_time() / 1000000.0); -} - -#elif PLATFORM(QT) - -double monotonicallyIncreasingTime() -{ - ASSERT(QElapsedTimer::isMonotonic()); - static QElapsedTimer timer; - return timer.nsecsElapsed() / 1.0e9; -} - -#else - -double monotonicallyIncreasingTime() -{ - static double lastTime = 0; - double currentTimeNow = currentTime(); - if (currentTimeNow < lastTime) - return lastTime; - lastTime = currentTimeNow; - return currentTimeNow; -} - -#endif - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/CurrentTime.h b/Source/JavaScriptCore/wtf/CurrentTime.h deleted file mode 100644 index ee49f8d25..000000000 --- a/Source/JavaScriptCore/wtf/CurrentTime.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2006 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2008 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CurrentTime_h -#define CurrentTime_h - -#include <time.h> - -namespace WTF { - -// Returns the current UTC time in seconds, counted from January 1, 1970. -// Precision varies depending on platform but is usually as good or better -// than a millisecond. -WTF_EXPORT_PRIVATE double currentTime(); - -// Same thing, in milliseconds. -inline double currentTimeMS() -{ - return currentTime() * 1000.0; -} - -inline void getLocalTime(const time_t* localTime, struct tm* localTM) -{ -#if COMPILER(MSVC7_OR_LOWER) || COMPILER(MINGW) || OS(WINCE) - *localTM = *localtime(localTime); -#elif COMPILER(MSVC) - localtime_s(localTM, localTime); -#else - localtime_r(localTime, localTM); -#endif -} - -// Provides a monotonically increasing time in seconds since an arbitrary point in the past. -// On unsupported platforms, this function only guarantees the result will be non-decreasing. -WTF_EXPORT_PRIVATE double monotonicallyIncreasingTime(); - -} // namespace WTF - -using WTF::currentTime; -using WTF::currentTimeMS; -using WTF::getLocalTime; -using WTF::monotonicallyIncreasingTime; - -#endif // CurrentTime_h diff --git a/Source/JavaScriptCore/wtf/DataLog.cpp b/Source/JavaScriptCore/wtf/DataLog.cpp deleted file mode 100644 index 5a290e45a..000000000 --- a/Source/JavaScriptCore/wtf/DataLog.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2012 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 "DataLog.h" -#include <stdarg.h> -#include <wtf/Threading.h> - -#define DATA_LOG_TO_FILE 0 - -// Uncomment to force logging to the given file regardless of what the environment variable says. -// #define DATA_LOG_FILENAME "/tmp/WTFLog.txt" - -namespace WTF { - -#if DATA_LOG_TO_FILE -static FILE* file; - -static void initializeLogFileOnce() -{ -#ifdef DATA_LOG_FILENAME - const char* filename = DATA_LOG_FILENAME -#else - const char* filename = getenv("WTF_DATA_LOG_FILENAME"); -#endif - if (filename) { - file = fopen(filename, "w"); - if (!file) - fprintf(stderr, "Warning: Could not open log file %s for writing.\n", filename); - } - if (!file) - file = stderr; - - setvbuf(file, 0, _IONBF, 0); // Prefer unbuffered output, so that we get a full log upon crash or deadlock. -} - -#if OS(DARWIN) -static pthread_once_t initializeLogFileOnceKey = PTHREAD_ONCE_INIT; -#endif - -static void initializeLogFile() -{ -#if OS(DARWIN) - pthread_once(&initializeLogFileOnceKey, initializeLogFileOnce); -#else - if (!file) - initializeLogFileOnce(); -#endif -} - -FILE* dataFile() -{ - initializeLogFile(); - return file; -} -#else // DATA_LOG_TO_FILE -FILE* dataFile() -{ - return stderr; -} -#endif // DATA_LOG_TO_FILE - -void dataLogV(const char* format, va_list argList) -{ - vfprintf(dataFile(), format, argList); -} - -void dataLog(const char* format, ...) -{ - va_list argList; - va_start(argList, format); - dataLogV(format, argList); - va_end(argList); -} - -} // namespace WTF - diff --git a/Source/JavaScriptCore/wtf/DateMath.cpp b/Source/JavaScriptCore/wtf/DateMath.cpp deleted file mode 100644 index cf601a5ec..000000000 --- a/Source/JavaScriptCore/wtf/DateMath.cpp +++ /dev/null @@ -1,1070 +0,0 @@ -/* - * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2007-2009 Torch Mobile, Inc. - * Copyright (C) 2010 &yet, LLC. (nate@andyet.net) - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * 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.1 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 - * - * Alternatively, the contents of this file may be used under the terms - * of either the Mozilla Public License Version 1.1, found at - * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public - * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html - * (the "GPL"), in which case the provisions of the MPL or the GPL are - * applicable instead of those above. If you wish to allow use of your - * version of this file only under the terms of one of those two - * licenses (the MPL or the GPL) and not to allow others to use your - * version of this file under the LGPL, indicate your decision by - * deletingthe provisions above and replace them with the notice and - * other provisions required by the MPL or the GPL, as the case may be. - * If you do not delete the provisions above, a recipient may use your - * version of this file under any of the LGPL, the MPL or the GPL. - - * Copyright 2006-2008 the V8 project authors. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "DateMath.h" - -#include "Assertions.h" -#include "ASCIICType.h" -#include "CurrentTime.h" -#include "MathExtras.h" -#include "StdLibExtras.h" -#include "StringExtras.h" - -#include <algorithm> -#include <limits.h> -#include <limits> -#include <stdint.h> -#include <time.h> -#include <wtf/text/StringBuilder.h> - -#if HAVE(ERRNO_H) -#include <errno.h> -#endif - -#if OS(WINCE) -extern "C" size_t strftime(char * const s, const size_t maxsize, const char * const format, const struct tm * const t); -extern "C" struct tm * localtime(const time_t *timer); -#endif - -#if HAVE(SYS_TIME_H) -#include <sys/time.h> -#endif - -#if HAVE(SYS_TIMEB_H) -#include <sys/timeb.h> -#endif - -using namespace WTF; - -namespace WTF { - -/* Constants */ - -static const double minutesPerDay = 24.0 * 60.0; -static const double secondsPerDay = 24.0 * 60.0 * 60.0; -static const double secondsPerYear = 24.0 * 60.0 * 60.0 * 365.0; - -static const double usecPerSec = 1000000.0; - -static const double maxUnixTime = 2145859200.0; // 12/31/2037 -// ECMAScript asks not to support for a date of which total -// millisecond value is larger than the following value. -// See 15.9.1.14 of ECMA-262 5th edition. -static const double maxECMAScriptTime = 8.64E15; - -// Day of year for the first day of each month, where index 0 is January, and day 0 is January 1. -// First for non-leap years, then for leap years. -static const int firstDayOfMonth[2][12] = { - {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334}, - {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335} -}; - -bool isLeapYear(int year) -{ - if (year % 4 != 0) - return false; - if (year % 400 == 0) - return true; - if (year % 100 == 0) - return false; - return true; -} - -static inline int daysInYear(int year) -{ - return 365 + isLeapYear(year); -} - -static inline double daysFrom1970ToYear(int year) -{ - // The Gregorian Calendar rules for leap years: - // Every fourth year is a leap year. 2004, 2008, and 2012 are leap years. - // However, every hundredth year is not a leap year. 1900 and 2100 are not leap years. - // Every four hundred years, there's a leap year after all. 2000 and 2400 are leap years. - - static const int leapDaysBefore1971By4Rule = 1970 / 4; - static const int excludedLeapDaysBefore1971By100Rule = 1970 / 100; - static const int leapDaysBefore1971By400Rule = 1970 / 400; - - const double yearMinusOne = year - 1; - const double yearsToAddBy4Rule = floor(yearMinusOne / 4.0) - leapDaysBefore1971By4Rule; - const double yearsToExcludeBy100Rule = floor(yearMinusOne / 100.0) - excludedLeapDaysBefore1971By100Rule; - const double yearsToAddBy400Rule = floor(yearMinusOne / 400.0) - leapDaysBefore1971By400Rule; - - return 365.0 * (year - 1970) + yearsToAddBy4Rule - yearsToExcludeBy100Rule + yearsToAddBy400Rule; -} - -double msToDays(double ms) -{ - return floor(ms / msPerDay); -} - -static String twoDigitStringFromNumber(int number) -{ - ASSERT(number >= 0 && number < 100); - if (number > 9) - return String::number(number); - return makeString("0", String::number(number)); -} - -int msToYear(double ms) -{ - int approxYear = static_cast<int>(floor(ms / (msPerDay * 365.2425)) + 1970); - double msFromApproxYearTo1970 = msPerDay * daysFrom1970ToYear(approxYear); - if (msFromApproxYearTo1970 > ms) - return approxYear - 1; - if (msFromApproxYearTo1970 + msPerDay * daysInYear(approxYear) <= ms) - return approxYear + 1; - return approxYear; -} - -int dayInYear(double ms, int year) -{ - return static_cast<int>(msToDays(ms) - daysFrom1970ToYear(year)); -} - -static inline double msToMilliseconds(double ms) -{ - double result = fmod(ms, msPerDay); - if (result < 0) - result += msPerDay; - return result; -} - -int msToMinutes(double ms) -{ - double result = fmod(floor(ms / msPerMinute), minutesPerHour); - if (result < 0) - result += minutesPerHour; - return static_cast<int>(result); -} - -int msToHours(double ms) -{ - double result = fmod(floor(ms/msPerHour), hoursPerDay); - if (result < 0) - result += hoursPerDay; - return static_cast<int>(result); -} - -int monthFromDayInYear(int dayInYear, bool leapYear) -{ - const int d = dayInYear; - int step; - - if (d < (step = 31)) - return 0; - step += (leapYear ? 29 : 28); - if (d < step) - return 1; - if (d < (step += 31)) - return 2; - if (d < (step += 30)) - return 3; - if (d < (step += 31)) - return 4; - if (d < (step += 30)) - return 5; - if (d < (step += 31)) - return 6; - if (d < (step += 31)) - return 7; - if (d < (step += 30)) - return 8; - if (d < (step += 31)) - return 9; - if (d < (step += 30)) - return 10; - return 11; -} - -static inline bool checkMonth(int dayInYear, int& startDayOfThisMonth, int& startDayOfNextMonth, int daysInThisMonth) -{ - startDayOfThisMonth = startDayOfNextMonth; - startDayOfNextMonth += daysInThisMonth; - return (dayInYear <= startDayOfNextMonth); -} - -int dayInMonthFromDayInYear(int dayInYear, bool leapYear) -{ - const int d = dayInYear; - int step; - int next = 30; - - if (d <= next) - return d + 1; - const int daysInFeb = (leapYear ? 29 : 28); - if (checkMonth(d, step, next, daysInFeb)) - return d - step; - if (checkMonth(d, step, next, 31)) - return d - step; - if (checkMonth(d, step, next, 30)) - return d - step; - if (checkMonth(d, step, next, 31)) - return d - step; - if (checkMonth(d, step, next, 30)) - return d - step; - if (checkMonth(d, step, next, 31)) - return d - step; - if (checkMonth(d, step, next, 31)) - return d - step; - if (checkMonth(d, step, next, 30)) - return d - step; - if (checkMonth(d, step, next, 31)) - return d - step; - if (checkMonth(d, step, next, 30)) - return d - step; - step = next; - return d - step; -} - -static inline int monthToDayInYear(int month, bool isLeapYear) -{ - return firstDayOfMonth[isLeapYear][month]; -} - -double dateToDaysFrom1970(int year, int month, int day) -{ - year += month / 12; - - month %= 12; - if (month < 0) { - month += 12; - --year; - } - - double yearday = floor(daysFrom1970ToYear(year)); - ASSERT((year >= 1970 && yearday >= 0) || (year < 1970 && yearday < 0)); - int monthday = monthToDayInYear(month, isLeapYear(year)); - - return yearday + monthday + day - 1; -} - -// There is a hard limit at 2038 that we currently do not have a workaround -// for (rdar://problem/5052975). -static inline int maximumYearForDST() -{ - return 2037; -} - -static inline int minimumYearForDST() -{ - // Because of the 2038 issue (see maximumYearForDST) if the current year is - // greater than the max year minus 27 (2010), we want to use the max year - // minus 27 instead, to ensure there is a range of 28 years that all years - // can map to. - return std::min(msToYear(jsCurrentTime()), maximumYearForDST() - 27) ; -} - -/* - * Find an equivalent year for the one given, where equivalence is deterined by - * the two years having the same leapness and the first day of the year, falling - * on the same day of the week. - * - * This function returns a year between this current year and 2037, however this - * function will potentially return incorrect results if the current year is after - * 2010, (rdar://problem/5052975), if the year passed in is before 1900 or after - * 2100, (rdar://problem/5055038). - */ -int equivalentYearForDST(int year) -{ - // It is ok if the cached year is not the current year as long as the rules - // for DST did not change between the two years; if they did the app would need - // to be restarted. - static int minYear = minimumYearForDST(); - int maxYear = maximumYearForDST(); - - int difference; - if (year > maxYear) - difference = minYear - year; - else if (year < minYear) - difference = maxYear - year; - else - return year; - - int quotient = difference / 28; - int product = (quotient) * 28; - - year += product; - ASSERT((year >= minYear && year <= maxYear) || (product - year == static_cast<int>(std::numeric_limits<double>::quiet_NaN()))); - return year; -} - -int32_t calculateUTCOffset() -{ - time_t localTime = time(0); - tm localt; - getLocalTime(&localTime, &localt); - - // Get the difference between this time zone and UTC on the 1st of January of this year. - localt.tm_sec = 0; - localt.tm_min = 0; - localt.tm_hour = 0; - localt.tm_mday = 1; - localt.tm_mon = 0; - // Not setting localt.tm_year! - localt.tm_wday = 0; - localt.tm_yday = 0; - localt.tm_isdst = 0; -#if HAVE(TM_GMTOFF) - localt.tm_gmtoff = 0; -#endif -#if HAVE(TM_ZONE) - localt.tm_zone = 0; -#endif - -#if HAVE(TIMEGM) - time_t utcOffset = timegm(&localt) - mktime(&localt); -#else - // Using a canned date of 01/01/2009 on platforms with weaker date-handling foo. - localt.tm_year = 109; - time_t utcOffset = 1230768000 - mktime(&localt); -#endif - - return static_cast<int32_t>(utcOffset * 1000); -} - -/* - * Get the DST offset for the time passed in. - */ -static double calculateDSTOffsetSimple(double localTimeSeconds, double utcOffset) -{ - if (localTimeSeconds > maxUnixTime) - localTimeSeconds = maxUnixTime; - else if (localTimeSeconds < 0) // Go ahead a day to make localtime work (does not work with 0) - localTimeSeconds += secondsPerDay; - - //input is UTC so we have to shift back to local time to determine DST thus the + getUTCOffset() - double offsetTime = (localTimeSeconds * msPerSecond) + utcOffset; - - // Offset from UTC but doesn't include DST obviously - int offsetHour = msToHours(offsetTime); - int offsetMinute = msToMinutes(offsetTime); - - // FIXME: time_t has a potential problem in 2038 - time_t localTime = static_cast<time_t>(localTimeSeconds); - - tm localTM; - getLocalTime(&localTime, &localTM); - - double diff = ((localTM.tm_hour - offsetHour) * secondsPerHour) + ((localTM.tm_min - offsetMinute) * 60); - - if (diff < 0) - diff += secondsPerDay; - - return (diff * msPerSecond); -} - -// Get the DST offset, given a time in UTC -double calculateDSTOffset(double ms, double utcOffset) -{ - // On Mac OS X, the call to localtime (see calculateDSTOffsetSimple) will return historically accurate - // DST information (e.g. New Zealand did not have DST from 1946 to 1974) however the JavaScript - // standard explicitly dictates that historical information should not be considered when - // determining DST. For this reason we shift away from years that localtime can handle but would - // return historically accurate information. - int year = msToYear(ms); - int equivalentYear = equivalentYearForDST(year); - if (year != equivalentYear) { - bool leapYear = isLeapYear(year); - int dayInYearLocal = dayInYear(ms, year); - int dayInMonth = dayInMonthFromDayInYear(dayInYearLocal, leapYear); - int month = monthFromDayInYear(dayInYearLocal, leapYear); - double day = dateToDaysFrom1970(equivalentYear, month, dayInMonth); - ms = (day * msPerDay) + msToMilliseconds(ms); - } - - return calculateDSTOffsetSimple(ms / msPerSecond, utcOffset); -} - -void initializeDates() -{ -#if !ASSERT_DISABLED - static bool alreadyInitialized; - ASSERT(!alreadyInitialized); - alreadyInitialized = true; -#endif - - equivalentYearForDST(2000); // Need to call once to initialize a static used in this function. -} - -static inline double ymdhmsToSeconds(long year, int mon, int day, int hour, int minute, double second) -{ - double days = (day - 32075) - + floor(1461 * (year + 4800.0 + (mon - 14) / 12) / 4) - + 367 * (mon - 2 - (mon - 14) / 12 * 12) / 12 - - floor(3 * ((year + 4900.0 + (mon - 14) / 12) / 100) / 4) - - 2440588; - return ((days * hoursPerDay + hour) * minutesPerHour + minute) * secondsPerMinute + second; -} - -// We follow the recommendation of RFC 2822 to consider all -// obsolete time zones not listed here equivalent to "-0000". -static const struct KnownZone { -#if !OS(WINDOWS) - const -#endif - char tzName[4]; - int tzOffset; -} known_zones[] = { - { "UT", 0 }, - { "GMT", 0 }, - { "EST", -300 }, - { "EDT", -240 }, - { "CST", -360 }, - { "CDT", -300 }, - { "MST", -420 }, - { "MDT", -360 }, - { "PST", -480 }, - { "PDT", -420 } -}; - -inline static void skipSpacesAndComments(const char*& s) -{ - int nesting = 0; - char ch; - while ((ch = *s)) { - if (!isASCIISpace(ch)) { - if (ch == '(') - nesting++; - else if (ch == ')' && nesting > 0) - nesting--; - else if (nesting == 0) - break; - } - s++; - } -} - -// returns 0-11 (Jan-Dec); -1 on failure -static int findMonth(const char* monthStr) -{ - ASSERT(monthStr); - char needle[4]; - for (int i = 0; i < 3; ++i) { - if (!*monthStr) - return -1; - needle[i] = static_cast<char>(toASCIILower(*monthStr++)); - } - needle[3] = '\0'; - const char *haystack = "janfebmaraprmayjunjulaugsepoctnovdec"; - const char *str = strstr(haystack, needle); - if (str) { - int position = static_cast<int>(str - haystack); - if (position % 3 == 0) - return position / 3; - } - return -1; -} - -static bool parseLong(const char* string, char** stopPosition, int base, long* result) -{ - *result = strtol(string, stopPosition, base); - // Avoid the use of errno as it is not available on Windows CE - if (string == *stopPosition || *result == LONG_MIN || *result == LONG_MAX) - return false; - return true; -} - -// Parses a date with the format YYYY[-MM[-DD]]. -// Year parsing is lenient, allows any number of digits, and +/-. -// Returns 0 if a parse error occurs, else returns the end of the parsed portion of the string. -static char* parseES5DatePortion(const char* currentPosition, long& year, long& month, long& day) -{ - char* postParsePosition; - - // This is a bit more lenient on the year string than ES5 specifies: - // instead of restricting to 4 digits (or 6 digits with mandatory +/-), - // it accepts any integer value. Consider this an implementation fallback. - if (!parseLong(currentPosition, &postParsePosition, 10, &year)) - return 0; - - // Check for presence of -MM portion. - if (*postParsePosition != '-') - return postParsePosition; - currentPosition = postParsePosition + 1; - - if (!isASCIIDigit(*currentPosition)) - return 0; - if (!parseLong(currentPosition, &postParsePosition, 10, &month)) - return 0; - if ((postParsePosition - currentPosition) != 2) - return 0; - - // Check for presence of -DD portion. - if (*postParsePosition != '-') - return postParsePosition; - currentPosition = postParsePosition + 1; - - if (!isASCIIDigit(*currentPosition)) - return 0; - if (!parseLong(currentPosition, &postParsePosition, 10, &day)) - return 0; - if ((postParsePosition - currentPosition) != 2) - return 0; - return postParsePosition; -} - -// Parses a time with the format HH:mm[:ss[.sss]][Z|(+|-)00:00]. -// Fractional seconds parsing is lenient, allows any number of digits. -// Returns 0 if a parse error occurs, else returns the end of the parsed portion of the string. -static char* parseES5TimePortion(char* currentPosition, long& hours, long& minutes, double& seconds, long& timeZoneSeconds) -{ - char* postParsePosition; - if (!isASCIIDigit(*currentPosition)) - return 0; - if (!parseLong(currentPosition, &postParsePosition, 10, &hours)) - return 0; - if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2) - return 0; - currentPosition = postParsePosition + 1; - - if (!isASCIIDigit(*currentPosition)) - return 0; - if (!parseLong(currentPosition, &postParsePosition, 10, &minutes)) - return 0; - if ((postParsePosition - currentPosition) != 2) - return 0; - currentPosition = postParsePosition; - - // Seconds are optional. - if (*currentPosition == ':') { - ++currentPosition; - - long intSeconds; - if (!isASCIIDigit(*currentPosition)) - return 0; - if (!parseLong(currentPosition, &postParsePosition, 10, &intSeconds)) - return 0; - if ((postParsePosition - currentPosition) != 2) - return 0; - seconds = intSeconds; - if (*postParsePosition == '.') { - currentPosition = postParsePosition + 1; - - // In ECMA-262-5 it's a bit unclear if '.' can be present without milliseconds, but - // a reasonable interpretation guided by the given examples and RFC 3339 says "no". - // We check the next character to avoid reading +/- timezone hours after an invalid decimal. - if (!isASCIIDigit(*currentPosition)) - return 0; - - // We are more lenient than ES5 by accepting more or less than 3 fraction digits. - long fracSeconds; - if (!parseLong(currentPosition, &postParsePosition, 10, &fracSeconds)) - return 0; - - long numFracDigits = postParsePosition - currentPosition; - seconds += fracSeconds * pow(10.0, static_cast<double>(-numFracDigits)); - } - currentPosition = postParsePosition; - } - - if (*currentPosition == 'Z') - return currentPosition + 1; - - bool tzNegative; - if (*currentPosition == '-') - tzNegative = true; - else if (*currentPosition == '+') - tzNegative = false; - else - return currentPosition; // no timezone - ++currentPosition; - - long tzHours; - long tzHoursAbs; - long tzMinutes; - - if (!isASCIIDigit(*currentPosition)) - return 0; - if (!parseLong(currentPosition, &postParsePosition, 10, &tzHours)) - return 0; - if (*postParsePosition != ':' || (postParsePosition - currentPosition) != 2) - return 0; - tzHoursAbs = labs(tzHours); - currentPosition = postParsePosition + 1; - - if (!isASCIIDigit(*currentPosition)) - return 0; - if (!parseLong(currentPosition, &postParsePosition, 10, &tzMinutes)) - return 0; - if ((postParsePosition - currentPosition) != 2) - return 0; - currentPosition = postParsePosition; - - if (tzHoursAbs > 24) - return 0; - if (tzMinutes < 0 || tzMinutes > 59) - return 0; - - timeZoneSeconds = 60 * (tzMinutes + (60 * tzHoursAbs)); - if (tzNegative) - timeZoneSeconds = -timeZoneSeconds; - - return currentPosition; -} - -double parseES5DateFromNullTerminatedCharacters(const char* dateString) -{ - // This parses a date of the form defined in ECMA-262-5, section 15.9.1.15 - // (similar to RFC 3339 / ISO 8601: YYYY-MM-DDTHH:mm:ss[.sss]Z). - // In most cases it is intentionally strict (e.g. correct field widths, no stray whitespace). - - static const long daysPerMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - - // The year must be present, but the other fields may be omitted - see ES5.1 15.9.1.15. - long year = 0; - long month = 1; - long day = 1; - long hours = 0; - long minutes = 0; - double seconds = 0; - long timeZoneSeconds = 0; - - // Parse the date YYYY[-MM[-DD]] - char* currentPosition = parseES5DatePortion(dateString, year, month, day); - if (!currentPosition) - return std::numeric_limits<double>::quiet_NaN(); - // Look for a time portion. - if (*currentPosition == 'T') { - // Parse the time HH:mm[:ss[.sss]][Z|(+|-)00:00] - currentPosition = parseES5TimePortion(currentPosition + 1, hours, minutes, seconds, timeZoneSeconds); - if (!currentPosition) - return std::numeric_limits<double>::quiet_NaN(); - } - // Check that we have parsed all characters in the string. - if (*currentPosition) - return std::numeric_limits<double>::quiet_NaN(); - - // A few of these checks could be done inline above, but since many of them are interrelated - // we would be sacrificing readability to "optimize" the (presumably less common) failure path. - if (month < 1 || month > 12) - return std::numeric_limits<double>::quiet_NaN(); - if (day < 1 || day > daysPerMonth[month - 1]) - return std::numeric_limits<double>::quiet_NaN(); - if (month == 2 && day > 28 && !isLeapYear(year)) - return std::numeric_limits<double>::quiet_NaN(); - if (hours < 0 || hours > 24) - return std::numeric_limits<double>::quiet_NaN(); - if (hours == 24 && (minutes || seconds)) - return std::numeric_limits<double>::quiet_NaN(); - if (minutes < 0 || minutes > 59) - return std::numeric_limits<double>::quiet_NaN(); - if (seconds < 0 || seconds >= 61) - return std::numeric_limits<double>::quiet_NaN(); - if (seconds > 60) { - // Discard leap seconds by clamping to the end of a minute. - seconds = 60; - } - - double dateSeconds = ymdhmsToSeconds(year, month, day, hours, minutes, seconds) - timeZoneSeconds; - return dateSeconds * msPerSecond; -} - -// Odd case where 'exec' is allowed to be 0, to accomodate a caller in WebCore. -double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset) -{ - haveTZ = false; - offset = 0; - - // This parses a date in the form: - // Tuesday, 09-Nov-99 23:12:40 GMT - // or - // Sat, 01-Jan-2000 08:00:00 GMT - // or - // Sat, 01 Jan 2000 08:00:00 GMT - // or - // 01 Jan 99 22:00 +0100 (exceptions in rfc822/rfc2822) - // ### non RFC formats, added for Javascript: - // [Wednesday] January 09 1999 23:12:40 GMT - // [Wednesday] January 09 23:12:40 GMT 1999 - // - // We ignore the weekday. - - // Skip leading space - skipSpacesAndComments(dateString); - - long month = -1; - const char *wordStart = dateString; - // Check contents of first words if not number - while (*dateString && !isASCIIDigit(*dateString)) { - if (isASCIISpace(*dateString) || *dateString == '(') { - if (dateString - wordStart >= 3) - month = findMonth(wordStart); - skipSpacesAndComments(dateString); - wordStart = dateString; - } else - dateString++; - } - - // Missing delimiter between month and day (like "January29")? - if (month == -1 && wordStart != dateString) - month = findMonth(wordStart); - - skipSpacesAndComments(dateString); - - if (!*dateString) - return std::numeric_limits<double>::quiet_NaN(); - - // ' 09-Nov-99 23:12:40 GMT' - char* newPosStr; - long day; - if (!parseLong(dateString, &newPosStr, 10, &day)) - return std::numeric_limits<double>::quiet_NaN(); - dateString = newPosStr; - - if (!*dateString) - return std::numeric_limits<double>::quiet_NaN(); - - if (day < 0) - return std::numeric_limits<double>::quiet_NaN(); - - long year = 0; - if (day > 31) { - // ### where is the boundary and what happens below? - if (*dateString != '/') - return std::numeric_limits<double>::quiet_NaN(); - // looks like a YYYY/MM/DD date - if (!*++dateString) - return std::numeric_limits<double>::quiet_NaN(); - year = day; - if (!parseLong(dateString, &newPosStr, 10, &month)) - return std::numeric_limits<double>::quiet_NaN(); - month -= 1; - dateString = newPosStr; - if (*dateString++ != '/' || !*dateString) - return std::numeric_limits<double>::quiet_NaN(); - if (!parseLong(dateString, &newPosStr, 10, &day)) - return std::numeric_limits<double>::quiet_NaN(); - dateString = newPosStr; - } else if (*dateString == '/' && month == -1) { - dateString++; - // This looks like a MM/DD/YYYY date, not an RFC date. - month = day - 1; // 0-based - if (!parseLong(dateString, &newPosStr, 10, &day)) - return std::numeric_limits<double>::quiet_NaN(); - if (day < 1 || day > 31) - return std::numeric_limits<double>::quiet_NaN(); - dateString = newPosStr; - if (*dateString == '/') - dateString++; - if (!*dateString) - return std::numeric_limits<double>::quiet_NaN(); - } else { - if (*dateString == '-') - dateString++; - - skipSpacesAndComments(dateString); - - if (*dateString == ',') - dateString++; - - if (month == -1) { // not found yet - month = findMonth(dateString); - if (month == -1) - return std::numeric_limits<double>::quiet_NaN(); - - while (*dateString && *dateString != '-' && *dateString != ',' && !isASCIISpace(*dateString)) - dateString++; - - if (!*dateString) - return std::numeric_limits<double>::quiet_NaN(); - - // '-99 23:12:40 GMT' - if (*dateString != '-' && *dateString != '/' && *dateString != ',' && !isASCIISpace(*dateString)) - return std::numeric_limits<double>::quiet_NaN(); - dateString++; - } - } - - if (month < 0 || month > 11) - return std::numeric_limits<double>::quiet_NaN(); - - // '99 23:12:40 GMT' - if (year <= 0 && *dateString) { - if (!parseLong(dateString, &newPosStr, 10, &year)) - return std::numeric_limits<double>::quiet_NaN(); - } - - // Don't fail if the time is missing. - long hour = 0; - long minute = 0; - long second = 0; - if (!*newPosStr) - dateString = newPosStr; - else { - // ' 23:12:40 GMT' - if (!(isASCIISpace(*newPosStr) || *newPosStr == ',')) { - if (*newPosStr != ':') - return std::numeric_limits<double>::quiet_NaN(); - // There was no year; the number was the hour. - year = -1; - } else { - // in the normal case (we parsed the year), advance to the next number - dateString = ++newPosStr; - skipSpacesAndComments(dateString); - } - - parseLong(dateString, &newPosStr, 10, &hour); - // Do not check for errno here since we want to continue - // even if errno was set becasue we are still looking - // for the timezone! - - // Read a number? If not, this might be a timezone name. - if (newPosStr != dateString) { - dateString = newPosStr; - - if (hour < 0 || hour > 23) - return std::numeric_limits<double>::quiet_NaN(); - - if (!*dateString) - return std::numeric_limits<double>::quiet_NaN(); - - // ':12:40 GMT' - if (*dateString++ != ':') - return std::numeric_limits<double>::quiet_NaN(); - - if (!parseLong(dateString, &newPosStr, 10, &minute)) - return std::numeric_limits<double>::quiet_NaN(); - dateString = newPosStr; - - if (minute < 0 || minute > 59) - return std::numeric_limits<double>::quiet_NaN(); - - // ':40 GMT' - if (*dateString && *dateString != ':' && !isASCIISpace(*dateString)) - return std::numeric_limits<double>::quiet_NaN(); - - // seconds are optional in rfc822 + rfc2822 - if (*dateString ==':') { - dateString++; - - if (!parseLong(dateString, &newPosStr, 10, &second)) - return std::numeric_limits<double>::quiet_NaN(); - dateString = newPosStr; - - if (second < 0 || second > 59) - return std::numeric_limits<double>::quiet_NaN(); - } - - skipSpacesAndComments(dateString); - - if (strncasecmp(dateString, "AM", 2) == 0) { - if (hour > 12) - return std::numeric_limits<double>::quiet_NaN(); - if (hour == 12) - hour = 0; - dateString += 2; - skipSpacesAndComments(dateString); - } else if (strncasecmp(dateString, "PM", 2) == 0) { - if (hour > 12) - return std::numeric_limits<double>::quiet_NaN(); - if (hour != 12) - hour += 12; - dateString += 2; - skipSpacesAndComments(dateString); - } - } - } - - // The year may be after the time but before the time zone. - if (isASCIIDigit(*dateString) && year == -1) { - if (!parseLong(dateString, &newPosStr, 10, &year)) - return std::numeric_limits<double>::quiet_NaN(); - dateString = newPosStr; - skipSpacesAndComments(dateString); - } - - // Don't fail if the time zone is missing. - // Some websites omit the time zone (4275206). - if (*dateString) { - if (strncasecmp(dateString, "GMT", 3) == 0 || strncasecmp(dateString, "UTC", 3) == 0) { - dateString += 3; - haveTZ = true; - } - - if (*dateString == '+' || *dateString == '-') { - long o; - if (!parseLong(dateString, &newPosStr, 10, &o)) - return std::numeric_limits<double>::quiet_NaN(); - dateString = newPosStr; - - if (o < -9959 || o > 9959) - return std::numeric_limits<double>::quiet_NaN(); - - int sgn = (o < 0) ? -1 : 1; - o = labs(o); - if (*dateString != ':') { - if (o >= 24) - offset = ((o / 100) * 60 + (o % 100)) * sgn; - else - offset = o * 60 * sgn; - } else { // GMT+05:00 - ++dateString; // skip the ':' - long o2; - if (!parseLong(dateString, &newPosStr, 10, &o2)) - return std::numeric_limits<double>::quiet_NaN(); - dateString = newPosStr; - offset = (o * 60 + o2) * sgn; - } - haveTZ = true; - } else { - for (size_t i = 0; i < WTF_ARRAY_LENGTH(known_zones); ++i) { - if (0 == strncasecmp(dateString, known_zones[i].tzName, strlen(known_zones[i].tzName))) { - offset = known_zones[i].tzOffset; - dateString += strlen(known_zones[i].tzName); - haveTZ = true; - break; - } - } - } - } - - skipSpacesAndComments(dateString); - - if (*dateString && year == -1) { - if (!parseLong(dateString, &newPosStr, 10, &year)) - return std::numeric_limits<double>::quiet_NaN(); - dateString = newPosStr; - skipSpacesAndComments(dateString); - } - - // Trailing garbage - if (*dateString) - return std::numeric_limits<double>::quiet_NaN(); - - // Y2K: Handle 2 digit years. - if (year >= 0 && year < 100) { - if (year < 50) - year += 2000; - else - year += 1900; - } - - return ymdhmsToSeconds(year, month + 1, day, hour, minute, second) * msPerSecond; -} - -double parseDateFromNullTerminatedCharacters(const char* dateString) -{ - bool haveTZ; - int offset; - double ms = parseDateFromNullTerminatedCharacters(dateString, haveTZ, offset); - if (isnan(ms)) - return std::numeric_limits<double>::quiet_NaN(); - - // fall back to local timezone - if (!haveTZ) { - double utcOffset = calculateUTCOffset(); - double dstOffset = calculateDSTOffset(ms, utcOffset); - offset = static_cast<int>((utcOffset + dstOffset) / msPerMinute); - } - return ms - (offset * msPerMinute); -} - -double timeClip(double t) -{ - if (!isfinite(t)) - return std::numeric_limits<double>::quiet_NaN(); - if (fabs(t) > maxECMAScriptTime) - return std::numeric_limits<double>::quiet_NaN(); - return trunc(t); -} - -// See http://tools.ietf.org/html/rfc2822#section-3.3 for more information. -String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, unsigned year, unsigned hours, unsigned minutes, unsigned seconds, int utcOffset) -{ - StringBuilder stringBuilder; - stringBuilder.append(weekdayName[dayOfWeek]); - stringBuilder.append(", "); - stringBuilder.append(String::number(day)); - stringBuilder.append(" "); - stringBuilder.append(monthName[month]); - stringBuilder.append(" "); - stringBuilder.append(String::number(year)); - stringBuilder.append(" "); - - stringBuilder.append(twoDigitStringFromNumber(hours)); - stringBuilder.append(':'); - stringBuilder.append(twoDigitStringFromNumber(minutes)); - stringBuilder.append(':'); - stringBuilder.append(twoDigitStringFromNumber(seconds)); - stringBuilder.append(' '); - - stringBuilder.append(utcOffset > 0 ? "+" : "-"); - int absoluteUTCOffset = abs(utcOffset); - stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset / 60)); - stringBuilder.append(twoDigitStringFromNumber(absoluteUTCOffset % 60)); - - return stringBuilder.toString(); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/DateMath.h b/Source/JavaScriptCore/wtf/DateMath.h deleted file mode 100644 index fc1a8d8e4..000000000 --- a/Source/JavaScriptCore/wtf/DateMath.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2010 Research In Motion Limited. All rights reserved. - * - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Mozilla Communicator client code, released - * March 31, 1998. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - */ - -#ifndef DateMath_h -#define DateMath_h - -#include <math.h> -#include <stdint.h> -#include <string.h> -#include <time.h> -#include <wtf/CurrentTime.h> -#include <wtf/Noncopyable.h> -#include <wtf/OwnArrayPtr.h> -#include <wtf/PassOwnArrayPtr.h> -#include <wtf/text/WTFString.h> -#include <wtf/UnusedParam.h> - -namespace WTF { - -void initializeDates(); -int equivalentYearForDST(int year); - -// Not really math related, but this is currently the only shared place to put these. -double parseES5DateFromNullTerminatedCharacters(const char* dateString); -WTF_EXPORT_PRIVATE double parseDateFromNullTerminatedCharacters(const char* dateString); -double parseDateFromNullTerminatedCharacters(const char* dateString, bool& haveTZ, int& offset); -double timeClip(double); -// dayOfWeek: [0, 6] 0 being Monday, day: [1, 31], month: [0, 11], year: ex: 2011, hours: [0, 23], minutes: [0, 59], seconds: [0, 59], utcOffset: [-720,720]. -String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, unsigned year, unsigned hours, unsigned minutes, unsigned seconds, int utcOffset); - -inline double jsCurrentTime() -{ - // JavaScript doesn't recognize fractions of a millisecond. - return floor(WTF::currentTimeMS()); -} - -const char* const weekdayName[7] = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" }; -const char* const monthName[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; - -const double hoursPerDay = 24.0; -const double minutesPerHour = 60.0; -const double secondsPerHour = 60.0 * 60.0; -const double secondsPerMinute = 60.0; -const double msPerSecond = 1000.0; -const double msPerMinute = 60.0 * 1000.0; -const double msPerHour = 60.0 * 60.0 * 1000.0; -const double msPerDay = 24.0 * 60.0 * 60.0 * 1000.0; -const double msPerMonth = 2592000000.0; - -bool isLeapYear(int year); - -// Returns the number of days from 1970-01-01 to the specified date. -WTF_EXPORT_PRIVATE double dateToDaysFrom1970(int year, int month, int day); -WTF_EXPORT_PRIVATE int msToYear(double ms); -double msToDays(double ms); -int msToMinutes(double ms); -int msToHours(double ms); -WTF_EXPORT_PRIVATE int dayInYear(double ms, int year); -WTF_EXPORT_PRIVATE int monthFromDayInYear(int dayInYear, bool leapYear); -WTF_EXPORT_PRIVATE int dayInMonthFromDayInYear(int dayInYear, bool leapYear); - -// Returns offset milliseconds for UTC and DST. -WTF_EXPORT_PRIVATE int32_t calculateUTCOffset(); -WTF_EXPORT_PRIVATE double calculateDSTOffset(double ms, double utcOffset); - -} // namespace WTF - -using WTF::isLeapYear; -using WTF::dateToDaysFrom1970; -using WTF::dayInMonthFromDayInYear; -using WTF::dayInYear; -using WTF::minutesPerHour; -using WTF::monthFromDayInYear; -using WTF::msPerDay; -using WTF::msPerMinute; -using WTF::msPerSecond; -using WTF::msToYear; -using WTF::msToDays; -using WTF::msToMinutes; -using WTF::msToHours; -using WTF::secondsPerMinute; -using WTF::parseDateFromNullTerminatedCharacters; -using WTF::makeRFC2822DateString; -using WTF::calculateUTCOffset; -using WTF::calculateDSTOffset; - -#endif // DateMath_h diff --git a/Source/JavaScriptCore/wtf/DecimalNumber.cpp b/Source/JavaScriptCore/wtf/DecimalNumber.cpp deleted file mode 100644 index 70304e2e5..000000000 --- a/Source/JavaScriptCore/wtf/DecimalNumber.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/* - * 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. - */ - -#include "config.h" -#include "DecimalNumber.h" -#include <math.h> -#include <wtf/MathExtras.h> -#include <wtf/text/WTFString.h> - -namespace WTF { - -unsigned DecimalNumber::bufferLengthForStringDecimal() const -{ - unsigned length = 0; - // if the exponent is negative the number decimal representation is of the form: - // [<sign>]0.[<zeros>]<significand> - if (m_exponent < 0) { - if (m_sign) - ++length; - length += 2; // for "0." - length += -m_exponent - 1; - length += m_precision; - return length; - } - - unsigned digitsBeforeDecimalPoint = m_exponent + 1; - - // If the precision is <= than the number of digits to get up to the decimal - // point, then there is no fractional part, number is of the form: - // [<sign>]<significand>[<zeros>] - if (m_precision <= digitsBeforeDecimalPoint) { - if (m_sign) - ++length; - length += m_precision; - length += digitsBeforeDecimalPoint - m_precision; - return length; - } - - // If we get here, number starts before the decimal point, and ends after it, - // as such is of the form: - // [<sign>]<significand-begin>.<significand-end> - if (m_sign) - ++length; - length += digitsBeforeDecimalPoint; - ++length; // for decimal point - length += m_precision - digitsBeforeDecimalPoint; - - return length; -} - -unsigned DecimalNumber::bufferLengthForStringExponential() const -{ - unsigned length = 0; - if (m_sign) - ++length; - - // Add the significand - ++length; - - if (m_precision > 1) { - ++length; // for decimal point - length += m_precision - 1; - } - - // Add "e+" or "e-" - length += 2; - - int exponent = (m_exponent >= 0) ? m_exponent : -m_exponent; - - // Add the exponent - if (exponent >= 100) - ++length; - if (exponent >= 10) - ++length; - ++length; - - return length; -} - -unsigned DecimalNumber::toStringDecimal(UChar* buffer, unsigned bufferLength) const -{ - ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringDecimal()); - - // Should always be at least one digit to add to the string! - ASSERT(m_precision); - UChar* next = buffer; - - // if the exponent is negative the number decimal representation is of the form: - // [<sign>]0.[<zeros>]<significand> - if (m_exponent < 0) { - unsigned zeros = -m_exponent - 1; - - if (m_sign) - *next++ = '-'; - *next++ = '0'; - *next++ = '.'; - for (unsigned i = 0; i < zeros; ++i) - *next++ = '0'; - for (unsigned i = 0; i < m_precision; ++i) - *next++ = m_significand[i]; - - return next - buffer; - } - - unsigned digitsBeforeDecimalPoint = m_exponent + 1; - - // If the precision is <= than the number of digits to get up to the decimal - // point, then there is no fractional part, number is of the form: - // [<sign>]<significand>[<zeros>] - if (m_precision <= digitsBeforeDecimalPoint) { - if (m_sign) - *next++ = '-'; - for (unsigned i = 0; i < m_precision; ++i) - *next++ = m_significand[i]; - for (unsigned i = 0; i < (digitsBeforeDecimalPoint - m_precision); ++i) - *next++ = '0'; - - return next - buffer; - } - - // If we get here, number starts before the decimal point, and ends after it, - // as such is of the form: - // [<sign>]<significand-begin>.<significand-end> - - if (m_sign) - *next++ = '-'; - for (unsigned i = 0; i < digitsBeforeDecimalPoint; ++i) - *next++ = m_significand[i]; - *next++ = '.'; - for (unsigned i = digitsBeforeDecimalPoint; i < m_precision; ++i) - *next++ = m_significand[i]; - - return next - buffer; -} - -unsigned DecimalNumber::toStringExponential(UChar* buffer, unsigned bufferLength) const -{ - ASSERT_UNUSED(bufferLength, bufferLength >= bufferLengthForStringExponential()); - - // Should always be at least one digit to add to the string! - ASSERT(m_precision); - UChar* next = buffer; - - // Add the sign - if (m_sign) - *next++ = '-'; - - // Add the significand - *next++ = m_significand[0]; - if (m_precision > 1) { - *next++ = '.'; - for (unsigned i = 1; i < m_precision; ++i) - *next++ = m_significand[i]; - } - - // Add "e+" or "e-" - *next++ = 'e'; - int exponent; - if (m_exponent >= 0) { - *next++ = '+'; - exponent = m_exponent; - } else { - *next++ = '-'; - exponent = -m_exponent; - } - - // Add the exponent - if (exponent >= 100) - *next++ = '0' + exponent / 100; - if (exponent >= 10) - *next++ = '0' + (exponent % 100) / 10; - *next++ = '0' + exponent % 10; - - return next - buffer; -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/DecimalNumber.h b/Source/JavaScriptCore/wtf/DecimalNumber.h deleted file mode 100644 index 61effcdd3..000000000 --- a/Source/JavaScriptCore/wtf/DecimalNumber.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * 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 DecimalNumber_h -#define DecimalNumber_h - -#include <math.h> -#include <wtf/dtoa.h> -#include <wtf/MathExtras.h> -#include <wtf/text/WTFString.h> - -namespace WTF { - -enum RoundingSignificantFiguresType { RoundingSignificantFigures }; -enum RoundingDecimalPlacesType { RoundingDecimalPlaces }; - -class DecimalNumber { -public: - DecimalNumber(double d) - { - ASSERT(isfinite(d)); - dtoa(m_significand, d, m_sign, m_exponent, m_precision); - - ASSERT(m_precision); - // Zero should always have exponent 0. - ASSERT(m_significand[0] != '0' || !m_exponent); - // No values other than zero should have a leading zero. - ASSERT(m_significand[0] != '0' || m_precision == 1); - // No values other than zero should have trailing zeros. - ASSERT(m_significand[0] == '0' || m_significand[m_precision - 1] != '0'); - } - - DecimalNumber(double d, RoundingSignificantFiguresType, unsigned significantFigures) - { - ASSERT(isfinite(d)); - dtoaRoundSF(m_significand, d, significantFigures, m_sign, m_exponent, m_precision); - - ASSERT(significantFigures && significantFigures <= sizeof(DtoaBuffer)); - while (m_precision < significantFigures) - m_significand[m_precision++] = '0'; - - ASSERT(m_precision); - // Zero should always have exponent 0. - ASSERT(m_significand[0] != '0' || !m_exponent); - } - - DecimalNumber(double d, RoundingDecimalPlacesType, unsigned decimalPlaces) - { - ASSERT(isfinite(d)); - dtoaRoundDP(m_significand, d, decimalPlaces, m_sign, m_exponent, m_precision); - - unsigned significantFigures = 1 + m_exponent + decimalPlaces; - ASSERT(significantFigures && significantFigures <= sizeof(DtoaBuffer)); - while (m_precision < significantFigures) - m_significand[m_precision++] = '0'; - - ASSERT(m_precision); - // Zero should always have exponent 0. - ASSERT(m_significand[0] != '0' || !m_exponent); - } - - WTF_EXPORT_PRIVATE unsigned bufferLengthForStringDecimal() const; - WTF_EXPORT_PRIVATE unsigned bufferLengthForStringExponential() const; - - WTF_EXPORT_PRIVATE unsigned toStringDecimal(UChar* buffer, unsigned bufferLength) const; - WTF_EXPORT_PRIVATE unsigned toStringExponential(UChar* buffer, unsigned bufferLength) const; - - bool sign() const { return m_sign; } - int exponent() const { return m_exponent; } - const char* significand() const { return m_significand; } // significand contains precision characters, is not null-terminated. - unsigned precision() const { return m_precision; } - -private: - bool m_sign; - int m_exponent; - DtoaBuffer m_significand; - unsigned m_precision; -}; - -} // namespace WTF - -using WTF::DecimalNumber; -using WTF::RoundingSignificantFigures; -using WTF::RoundingDecimalPlaces; - -#endif // DecimalNumber_h diff --git a/Source/JavaScriptCore/wtf/Decoder.h b/Source/JavaScriptCore/wtf/Decoder.h deleted file mode 100644 index 341d58d73..000000000 --- a/Source/JavaScriptCore/wtf/Decoder.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 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 Decoder_h -#define Decoder_h - -#include <wtf/Vector.h> - -namespace WTF { - -class String; - -class Decoder { -protected: - Decoder() { } - virtual ~Decoder() { } - -public: - virtual bool decodeBytes(Vector<uint8_t>&) = 0; - - virtual bool decodeBool(bool&) = 0; - virtual bool decodeUInt32(uint32_t&) = 0; - virtual bool decodeUInt64(uint64_t&) = 0; - virtual bool decodeInt32(int32_t&) = 0; - virtual bool decodeInt64(int64_t&) = 0; - virtual bool decodeFloat(float&) = 0; - virtual bool decodeDouble(double&) = 0; - virtual bool decodeString(String&) = 0; -}; - -} // namespace WTF - -using WTF::Decoder; - -#endif // Decoder_h diff --git a/Source/JavaScriptCore/wtf/Deque.h b/Source/JavaScriptCore/wtf/Deque.h deleted file mode 100644 index 47c0dfffa..000000000 --- a/Source/JavaScriptCore/wtf/Deque.h +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright (C) 2007, 2008 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. - * 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 WTF_Deque_h -#define WTF_Deque_h - -// FIXME: Could move what Vector and Deque share into a separate file. -// Deque doesn't actually use Vector. - -#include <wtf/PassTraits.h> -#include <wtf/Vector.h> - -namespace WTF { - - template<typename T, size_t inlineCapacity> class DequeIteratorBase; - template<typename T, size_t inlineCapacity> class DequeIterator; - template<typename T, size_t inlineCapacity> class DequeConstIterator; - template<typename T, size_t inlineCapacity> class DequeReverseIterator; - template<typename T, size_t inlineCapacity> class DequeConstReverseIterator; - - template<typename T, size_t inlineCapacity = 0> - class Deque { - WTF_MAKE_FAST_ALLOCATED; - public: - typedef DequeIterator<T, inlineCapacity> iterator; - typedef DequeConstIterator<T, inlineCapacity> const_iterator; - typedef DequeReverseIterator<T, inlineCapacity> reverse_iterator; - typedef DequeConstReverseIterator<T, inlineCapacity> const_reverse_iterator; - typedef PassTraits<T> Pass; - typedef typename PassTraits<T>::PassType PassType; - - Deque(); - Deque(const Deque<T, inlineCapacity>&); - Deque& operator=(const Deque<T, inlineCapacity>&); - ~Deque(); - - void swap(Deque<T, inlineCapacity>&); - - size_t size() const { return m_start <= m_end ? m_end - m_start : m_end + m_buffer.capacity() - m_start; } - bool isEmpty() const { return m_start == m_end; } - - iterator begin() { return iterator(this, m_start); } - iterator end() { return iterator(this, m_end); } - const_iterator begin() const { return const_iterator(this, m_start); } - const_iterator end() const { return const_iterator(this, m_end); } - reverse_iterator rbegin() { return reverse_iterator(this, m_end); } - reverse_iterator rend() { return reverse_iterator(this, m_start); } - const_reverse_iterator rbegin() const { return const_reverse_iterator(this, m_end); } - const_reverse_iterator rend() const { return const_reverse_iterator(this, m_start); } - - T& first() { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } - const T& first() const { ASSERT(m_start != m_end); return m_buffer.buffer()[m_start]; } - PassType takeFirst(); - - T& last() { ASSERT(m_start != m_end); return *(--end()); } - const T& last() const { ASSERT(m_start != m_end); return *(--end()); } - - template<typename U> void append(const U&); - template<typename U> void prepend(const U&); - void removeFirst(); - void remove(iterator&); - void remove(const_iterator&); - - void clear(); - - template<typename Predicate> - iterator findIf(Predicate&); - - private: - friend class DequeIteratorBase<T, inlineCapacity>; - - typedef VectorBuffer<T, inlineCapacity> Buffer; - typedef VectorTypeOperations<T> TypeOperations; - typedef DequeIteratorBase<T, inlineCapacity> IteratorBase; - - void remove(size_t position); - void invalidateIterators(); - void destroyAll(); - void checkValidity() const; - void checkIndexValidity(size_t) const; - void expandCapacityIfNeeded(); - void expandCapacity(); - - size_t m_start; - size_t m_end; - Buffer m_buffer; -#ifndef NDEBUG - mutable IteratorBase* m_iterators; -#endif - }; - - template<typename T, size_t inlineCapacity = 0> - class DequeIteratorBase { - private: - typedef DequeIteratorBase<T, inlineCapacity> Base; - - protected: - DequeIteratorBase(); - DequeIteratorBase(const Deque<T, inlineCapacity>*, size_t); - DequeIteratorBase(const Base&); - Base& operator=(const Base&); - ~DequeIteratorBase(); - - void assign(const Base& other) { *this = other; } - - void increment(); - void decrement(); - - T* before() const; - T* after() const; - - bool isEqual(const Base&) const; - - private: - void addToIteratorsList(); - void removeFromIteratorsList(); - void checkValidity() const; - void checkValidity(const Base&) const; - - Deque<T, inlineCapacity>* m_deque; - size_t m_index; - - friend class Deque<T, inlineCapacity>; - -#ifndef NDEBUG - mutable DequeIteratorBase* m_next; - mutable DequeIteratorBase* m_previous; -#endif - }; - - template<typename T, size_t inlineCapacity = 0> - class DequeIterator : public DequeIteratorBase<T, inlineCapacity> { - private: - typedef DequeIteratorBase<T, inlineCapacity> Base; - typedef DequeIterator<T, inlineCapacity> Iterator; - - public: - DequeIterator(Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } - - DequeIterator(const Iterator& other) : Base(other) { } - DequeIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } - - T& operator*() const { return *Base::after(); } - T* operator->() const { return Base::after(); } - - bool operator==(const Iterator& other) const { return Base::isEqual(other); } - bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } - - Iterator& operator++() { Base::increment(); return *this; } - // postfix ++ intentionally omitted - Iterator& operator--() { Base::decrement(); return *this; } - // postfix -- intentionally omitted - }; - - template<typename T, size_t inlineCapacity = 0> - class DequeConstIterator : public DequeIteratorBase<T, inlineCapacity> { - private: - typedef DequeIteratorBase<T, inlineCapacity> Base; - typedef DequeConstIterator<T, inlineCapacity> Iterator; - typedef DequeIterator<T, inlineCapacity> NonConstIterator; - - public: - DequeConstIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } - - DequeConstIterator(const Iterator& other) : Base(other) { } - DequeConstIterator(const NonConstIterator& other) : Base(other) { } - DequeConstIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } - DequeConstIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; } - - const T& operator*() const { return *Base::after(); } - const T* operator->() const { return Base::after(); } - - bool operator==(const Iterator& other) const { return Base::isEqual(other); } - bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } - - Iterator& operator++() { Base::increment(); return *this; } - // postfix ++ intentionally omitted - Iterator& operator--() { Base::decrement(); return *this; } - // postfix -- intentionally omitted - }; - - template<typename T, size_t inlineCapacity = 0> - class DequeReverseIterator : public DequeIteratorBase<T, inlineCapacity> { - private: - typedef DequeIteratorBase<T, inlineCapacity> Base; - typedef DequeReverseIterator<T, inlineCapacity> Iterator; - - public: - DequeReverseIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } - - DequeReverseIterator(const Iterator& other) : Base(other) { } - DequeReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } - - T& operator*() const { return *Base::before(); } - T* operator->() const { return Base::before(); } - - bool operator==(const Iterator& other) const { return Base::isEqual(other); } - bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } - - Iterator& operator++() { Base::decrement(); return *this; } - // postfix ++ intentionally omitted - Iterator& operator--() { Base::increment(); return *this; } - // postfix -- intentionally omitted - }; - - template<typename T, size_t inlineCapacity = 0> - class DequeConstReverseIterator : public DequeIteratorBase<T, inlineCapacity> { - private: - typedef DequeIteratorBase<T, inlineCapacity> Base; - typedef DequeConstReverseIterator<T, inlineCapacity> Iterator; - typedef DequeReverseIterator<T, inlineCapacity> NonConstIterator; - - public: - DequeConstReverseIterator(const Deque<T, inlineCapacity>* deque, size_t index) : Base(deque, index) { } - - DequeConstReverseIterator(const Iterator& other) : Base(other) { } - DequeConstReverseIterator(const NonConstIterator& other) : Base(other) { } - DequeConstReverseIterator& operator=(const Iterator& other) { Base::assign(other); return *this; } - DequeConstReverseIterator& operator=(const NonConstIterator& other) { Base::assign(other); return *this; } - - const T& operator*() const { return *Base::before(); } - const T* operator->() const { return Base::before(); } - - bool operator==(const Iterator& other) const { return Base::isEqual(other); } - bool operator!=(const Iterator& other) const { return !Base::isEqual(other); } - - Iterator& operator++() { Base::decrement(); return *this; } - // postfix ++ intentionally omitted - Iterator& operator--() { Base::increment(); return *this; } - // postfix -- intentionally omitted - }; - -#ifdef NDEBUG - template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkValidity() const { } - template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::checkIndexValidity(size_t) const { } - template<typename T, size_t inlineCapacity> inline void Deque<T, inlineCapacity>::invalidateIterators() { } -#else - template<typename T, size_t inlineCapacity> - void Deque<T, inlineCapacity>::checkValidity() const - { - // In this implementation a capacity of 1 would confuse append() and - // other places that assume the index after capacity - 1 is 0. - ASSERT(m_buffer.capacity() != 1); - - if (!m_buffer.capacity()) { - ASSERT(!m_start); - ASSERT(!m_end); - } else { - ASSERT(m_start < m_buffer.capacity()); - ASSERT(m_end < m_buffer.capacity()); - } - } - - template<typename T, size_t inlineCapacity> - void Deque<T, inlineCapacity>::checkIndexValidity(size_t index) const - { - ASSERT_UNUSED(index, index <= m_buffer.capacity()); - if (m_start <= m_end) { - ASSERT(index >= m_start); - ASSERT(index <= m_end); - } else { - ASSERT(index >= m_start || index <= m_end); - } - } - - template<typename T, size_t inlineCapacity> - void Deque<T, inlineCapacity>::invalidateIterators() - { - IteratorBase* next; - for (IteratorBase* p = m_iterators; p; p = next) { - next = p->m_next; - p->m_deque = 0; - p->m_next = 0; - p->m_previous = 0; - } - m_iterators = 0; - } -#endif - - template<typename T, size_t inlineCapacity> - inline Deque<T, inlineCapacity>::Deque() - : m_start(0) - , m_end(0) -#ifndef NDEBUG - , m_iterators(0) -#endif - { - checkValidity(); - } - - template<typename T, size_t inlineCapacity> - inline Deque<T, inlineCapacity>::Deque(const Deque<T, inlineCapacity>& other) - : m_start(other.m_start) - , m_end(other.m_end) - , m_buffer(other.m_buffer.capacity()) -#ifndef NDEBUG - , m_iterators(0) -#endif - { - const T* otherBuffer = other.m_buffer.buffer(); - if (m_start <= m_end) - TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_end, m_buffer.buffer() + m_start); - else { - TypeOperations::uninitializedCopy(otherBuffer, otherBuffer + m_end, m_buffer.buffer()); - TypeOperations::uninitializedCopy(otherBuffer + m_start, otherBuffer + m_buffer.capacity(), m_buffer.buffer() + m_start); - } - } - - template<typename T, size_t inlineCapacity> - void deleteAllValues(const Deque<T, inlineCapacity>& collection) - { - typedef typename Deque<T, inlineCapacity>::const_iterator iterator; - iterator end = collection.end(); - for (iterator it = collection.begin(); it != end; ++it) - delete *it; - } - - template<typename T, size_t inlineCapacity> - inline Deque<T, inlineCapacity>& Deque<T, inlineCapacity>::operator=(const Deque<T, inlineCapacity>& other) - { - // FIXME: This is inefficient if we're using an inline buffer and T is - // expensive to copy since it will copy the buffer twice instead of once. - Deque<T> copy(other); - swap(copy); - return *this; - } - - template<typename T, size_t inlineCapacity> - inline void Deque<T, inlineCapacity>::destroyAll() - { - if (m_start <= m_end) - TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_end); - else { - TypeOperations::destruct(m_buffer.buffer(), m_buffer.buffer() + m_end); - TypeOperations::destruct(m_buffer.buffer() + m_start, m_buffer.buffer() + m_buffer.capacity()); - } - } - - template<typename T, size_t inlineCapacity> - inline Deque<T, inlineCapacity>::~Deque() - { - checkValidity(); - invalidateIterators(); - destroyAll(); - } - - template<typename T, size_t inlineCapacity> - inline void Deque<T, inlineCapacity>::swap(Deque<T, inlineCapacity>& other) - { - checkValidity(); - other.checkValidity(); - invalidateIterators(); - std::swap(m_start, other.m_start); - std::swap(m_end, other.m_end); - m_buffer.swap(other.m_buffer); - checkValidity(); - other.checkValidity(); - } - - template<typename T, size_t inlineCapacity> - inline void Deque<T, inlineCapacity>::clear() - { - checkValidity(); - invalidateIterators(); - destroyAll(); - m_start = 0; - m_end = 0; - checkValidity(); - } - - template<typename T, size_t inlineCapacity> - template<typename Predicate> - inline DequeIterator<T, inlineCapacity> Deque<T, inlineCapacity>::findIf(Predicate& predicate) - { - iterator end_iterator = end(); - for (iterator it = begin(); it != end_iterator; ++it) { - if (predicate(*it)) - return it; - } - return end_iterator; - } - - template<typename T, size_t inlineCapacity> - inline void Deque<T, inlineCapacity>::expandCapacityIfNeeded() - { - if (m_start) { - if (m_end + 1 != m_start) - return; - } else if (m_end) { - if (m_end != m_buffer.capacity() - 1) - return; - } else if (m_buffer.capacity()) - return; - - expandCapacity(); - } - - template<typename T, size_t inlineCapacity> - void Deque<T, inlineCapacity>::expandCapacity() - { - checkValidity(); - size_t oldCapacity = m_buffer.capacity(); - size_t newCapacity = max(static_cast<size_t>(16), oldCapacity + oldCapacity / 4 + 1); - T* oldBuffer = m_buffer.buffer(); - m_buffer.allocateBuffer(newCapacity); - if (m_start <= m_end) - TypeOperations::move(oldBuffer + m_start, oldBuffer + m_end, m_buffer.buffer() + m_start); - else { - TypeOperations::move(oldBuffer, oldBuffer + m_end, m_buffer.buffer()); - size_t newStart = newCapacity - (oldCapacity - m_start); - TypeOperations::move(oldBuffer + m_start, oldBuffer + oldCapacity, m_buffer.buffer() + newStart); - m_start = newStart; - } - m_buffer.deallocateBuffer(oldBuffer); - checkValidity(); - } - - template<typename T, size_t inlineCapacity> - inline typename Deque<T, inlineCapacity>::PassType Deque<T, inlineCapacity>::takeFirst() - { - T oldFirst = Pass::transfer(first()); - removeFirst(); - return Pass::transfer(oldFirst); - } - - template<typename T, size_t inlineCapacity> template<typename U> - inline void Deque<T, inlineCapacity>::append(const U& value) - { - checkValidity(); - expandCapacityIfNeeded(); - new (NotNull, &m_buffer.buffer()[m_end]) T(value); - if (m_end == m_buffer.capacity() - 1) - m_end = 0; - else - ++m_end; - checkValidity(); - } - - template<typename T, size_t inlineCapacity> template<typename U> - inline void Deque<T, inlineCapacity>::prepend(const U& value) - { - checkValidity(); - expandCapacityIfNeeded(); - if (!m_start) - m_start = m_buffer.capacity() - 1; - else - --m_start; - new (NotNull, &m_buffer.buffer()[m_start]) T(value); - checkValidity(); - } - - template<typename T, size_t inlineCapacity> - inline void Deque<T, inlineCapacity>::removeFirst() - { - checkValidity(); - invalidateIterators(); - ASSERT(!isEmpty()); - TypeOperations::destruct(&m_buffer.buffer()[m_start], &m_buffer.buffer()[m_start + 1]); - if (m_start == m_buffer.capacity() - 1) - m_start = 0; - else - ++m_start; - checkValidity(); - } - - template<typename T, size_t inlineCapacity> - inline void Deque<T, inlineCapacity>::remove(iterator& it) - { - it.checkValidity(); - remove(it.m_index); - } - - template<typename T, size_t inlineCapacity> - inline void Deque<T, inlineCapacity>::remove(const_iterator& it) - { - it.checkValidity(); - remove(it.m_index); - } - - template<typename T, size_t inlineCapacity> - inline void Deque<T, inlineCapacity>::remove(size_t position) - { - if (position == m_end) - return; - - checkValidity(); - invalidateIterators(); - - T* buffer = m_buffer.buffer(); - TypeOperations::destruct(&buffer[position], &buffer[position + 1]); - - // Find which segment of the circular buffer contained the remove element, and only move elements in that part. - if (position >= m_start) { - TypeOperations::moveOverlapping(buffer + m_start, buffer + position, buffer + m_start + 1); - m_start = (m_start + 1) % m_buffer.capacity(); - } else { - TypeOperations::moveOverlapping(buffer + position + 1, buffer + m_end, buffer + position); - m_end = (m_end - 1 + m_buffer.capacity()) % m_buffer.capacity(); - } - checkValidity(); - } - -#ifdef NDEBUG - template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity() const { } - template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::checkValidity(const DequeIteratorBase<T, inlineCapacity>&) const { } - template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList() { } - template<typename T, size_t inlineCapacity> inline void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList() { } -#else - template<typename T, size_t inlineCapacity> - void DequeIteratorBase<T, inlineCapacity>::checkValidity() const - { - ASSERT(m_deque); - m_deque->checkIndexValidity(m_index); - } - - template<typename T, size_t inlineCapacity> - void DequeIteratorBase<T, inlineCapacity>::checkValidity(const Base& other) const - { - checkValidity(); - other.checkValidity(); - ASSERT(m_deque == other.m_deque); - } - - template<typename T, size_t inlineCapacity> - void DequeIteratorBase<T, inlineCapacity>::addToIteratorsList() - { - if (!m_deque) - m_next = 0; - else { - m_next = m_deque->m_iterators; - m_deque->m_iterators = this; - if (m_next) - m_next->m_previous = this; - } - m_previous = 0; - } - - template<typename T, size_t inlineCapacity> - void DequeIteratorBase<T, inlineCapacity>::removeFromIteratorsList() - { - if (!m_deque) { - ASSERT(!m_next); - ASSERT(!m_previous); - } else { - if (m_next) { - ASSERT(m_next->m_previous == this); - m_next->m_previous = m_previous; - } - if (m_previous) { - ASSERT(m_deque->m_iterators != this); - ASSERT(m_previous->m_next == this); - m_previous->m_next = m_next; - } else { - ASSERT(m_deque->m_iterators == this); - m_deque->m_iterators = m_next; - } - } - m_next = 0; - m_previous = 0; - } -#endif - - template<typename T, size_t inlineCapacity> - inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase() - : m_deque(0) - { - } - - template<typename T, size_t inlineCapacity> - inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Deque<T, inlineCapacity>* deque, size_t index) - : m_deque(const_cast<Deque<T, inlineCapacity>*>(deque)) - , m_index(index) - { - addToIteratorsList(); - checkValidity(); - } - - template<typename T, size_t inlineCapacity> - inline DequeIteratorBase<T, inlineCapacity>::DequeIteratorBase(const Base& other) - : m_deque(other.m_deque) - , m_index(other.m_index) - { - addToIteratorsList(); - checkValidity(); - } - - template<typename T, size_t inlineCapacity> - inline DequeIteratorBase<T, inlineCapacity>& DequeIteratorBase<T, inlineCapacity>::operator=(const Base& other) - { - other.checkValidity(); - removeFromIteratorsList(); - - m_deque = other.m_deque; - m_index = other.m_index; - addToIteratorsList(); - checkValidity(); - return *this; - } - - template<typename T, size_t inlineCapacity> - inline DequeIteratorBase<T, inlineCapacity>::~DequeIteratorBase() - { -#ifndef NDEBUG - removeFromIteratorsList(); - m_deque = 0; -#endif - } - - template<typename T, size_t inlineCapacity> - inline bool DequeIteratorBase<T, inlineCapacity>::isEqual(const Base& other) const - { - checkValidity(other); - return m_index == other.m_index; - } - - template<typename T, size_t inlineCapacity> - inline void DequeIteratorBase<T, inlineCapacity>::increment() - { - checkValidity(); - ASSERT(m_index != m_deque->m_end); - ASSERT(m_deque->m_buffer.capacity()); - if (m_index == m_deque->m_buffer.capacity() - 1) - m_index = 0; - else - ++m_index; - checkValidity(); - } - - template<typename T, size_t inlineCapacity> - inline void DequeIteratorBase<T, inlineCapacity>::decrement() - { - checkValidity(); - ASSERT(m_index != m_deque->m_start); - ASSERT(m_deque->m_buffer.capacity()); - if (!m_index) - m_index = m_deque->m_buffer.capacity() - 1; - else - --m_index; - checkValidity(); - } - - template<typename T, size_t inlineCapacity> - inline T* DequeIteratorBase<T, inlineCapacity>::after() const - { - checkValidity(); - ASSERT(m_index != m_deque->m_end); - return &m_deque->m_buffer.buffer()[m_index]; - } - - template<typename T, size_t inlineCapacity> - inline T* DequeIteratorBase<T, inlineCapacity>::before() const - { - checkValidity(); - ASSERT(m_index != m_deque->m_start); - if (!m_index) - return &m_deque->m_buffer.buffer()[m_deque->m_buffer.capacity() - 1]; - return &m_deque->m_buffer.buffer()[m_index - 1]; - } - -} // namespace WTF - -using WTF::Deque; - -#endif // WTF_Deque_h diff --git a/Source/JavaScriptCore/wtf/DisallowCType.h b/Source/JavaScriptCore/wtf/DisallowCType.h deleted file mode 100644 index 436f7f214..000000000 --- a/Source/JavaScriptCore/wtf/DisallowCType.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2007 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 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 WTF_DisallowCType_h -#define WTF_DisallowCType_h - -// The behavior of many of the functions in the <ctype.h> header is dependent -// on the current locale. But almost all uses of these functions are for -// locale-independent, ASCII-specific purposes. In WebKit code we use our own -// ASCII-specific functions instead. This header makes sure we get a compile-time -// error if we use one of the <ctype.h> functions by accident. - -#include <ctype.h> - -#undef isalnum -#undef isalpha -#undef isascii -#undef isblank -#undef iscntrl -#undef isdigit -#undef isgraph -#undef islower -#undef isprint -#undef ispunct -#undef isspace -#undef isupper -#undef isxdigit -#undef toascii -#undef tolower -#undef toupper - -#define isalnum isalnum_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define isalpha isalpha_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define isascii isascii_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define isblank isblank_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define iscntrl iscntrl_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define isdigit isdigit_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define isgraph isgraph_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define islower islower_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define isprint isprint_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define ispunct ispunct_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define isspace isspace_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define isupper isupper_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define isxdigit isxdigit_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define toascii toascii_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define tolower tolower_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h -#define toupper toupper_WTF_Please_use_ASCIICType_instead_of_ctype_see_comment_in_ASCIICType_h - -#endif diff --git a/Source/JavaScriptCore/wtf/DoublyLinkedList.h b/Source/JavaScriptCore/wtf/DoublyLinkedList.h deleted file mode 100644 index cd067ef0a..000000000 --- a/Source/JavaScriptCore/wtf/DoublyLinkedList.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright (C) 2011 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 DoublyLinkedList_h -#define DoublyLinkedList_h - -namespace WTF { - -// This class allows nodes to share code without dictating data member layout. -template<typename T> class DoublyLinkedListNode { -public: - DoublyLinkedListNode(); - - void setPrev(T*); - void setNext(T*); - - T* prev() const; - T* next() const; -}; - -template<typename T> inline DoublyLinkedListNode<T>::DoublyLinkedListNode() -{ - setPrev(0); - setNext(0); -} - -template<typename T> inline void DoublyLinkedListNode<T>::setPrev(T* prev) -{ - static_cast<T*>(this)->m_prev = prev; -} - -template<typename T> inline void DoublyLinkedListNode<T>::setNext(T* next) -{ - static_cast<T*>(this)->m_next = next; -} - -template<typename T> inline T* DoublyLinkedListNode<T>::prev() const -{ - return static_cast<const T*>(this)->m_prev; -} - -template<typename T> inline T* DoublyLinkedListNode<T>::next() const -{ - return static_cast<const T*>(this)->m_next; -} - -template<typename T> class DoublyLinkedList { -public: - DoublyLinkedList(); - - bool isEmpty() const; - size_t size() const; // This is O(n). - void clear(); - - T* head() const; - T* removeHead(); - - T* tail() const; - - void push(T*); - void append(T*); - void remove(T*); - -private: - T* m_head; - T* m_tail; -}; - -template<typename T> inline DoublyLinkedList<T>::DoublyLinkedList() - : m_head(0) - , m_tail(0) -{ -} - -template<typename T> inline bool DoublyLinkedList<T>::isEmpty() const -{ - return !m_head; -} - -template<typename T> inline size_t DoublyLinkedList<T>::size() const -{ - size_t size = 0; - for (T* node = m_head; node; node = node->next()) - ++size; - return size; -} - -template<typename T> inline void DoublyLinkedList<T>::clear() -{ - m_head = 0; - m_tail = 0; -} - -template<typename T> inline T* DoublyLinkedList<T>::head() const -{ - return m_head; -} - -template<typename T> inline T* DoublyLinkedList<T>::tail() const -{ - return m_tail; -} - -template<typename T> inline void DoublyLinkedList<T>::push(T* node) -{ - if (!m_head) { - ASSERT(!m_tail); - m_head = node; - m_tail = node; - node->setPrev(0); - node->setNext(0); - return; - } - - ASSERT(m_tail); - m_head->setPrev(node); - node->setNext(m_head); - node->setPrev(0); - m_head = node; -} - -template<typename T> inline void DoublyLinkedList<T>::append(T* node) -{ - if (!m_tail) { - ASSERT(!m_head); - m_head = node; - m_tail = node; - node->setPrev(0); - node->setNext(0); - return; - } - - ASSERT(m_head); - m_tail->setNext(node); - node->setPrev(m_tail); - node->setNext(0); - m_tail = node; -} - -template<typename T> inline void DoublyLinkedList<T>::remove(T* node) -{ - if (node->prev()) { - ASSERT(node != m_head); - node->prev()->setNext(node->next()); - } else { - ASSERT(node == m_head); - m_head = node->next(); - } - - if (node->next()) { - ASSERT(node != m_tail); - node->next()->setPrev(node->prev()); - } else { - ASSERT(node == m_tail); - m_tail = node->prev(); - } -} - -template<typename T> inline T* DoublyLinkedList<T>::removeHead() -{ - T* node = head(); - if (node) - remove(node); - return node; -} - -} // namespace WTF - -using WTF::DoublyLinkedListNode; -using WTF::DoublyLinkedList; - -#endif diff --git a/Source/JavaScriptCore/wtf/DynamicAnnotations.cpp b/Source/JavaScriptCore/wtf/DynamicAnnotations.cpp deleted file mode 100644 index b662877a5..000000000 --- a/Source/JavaScriptCore/wtf/DynamicAnnotations.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include "DynamicAnnotations.h" - -#if USE(DYNAMIC_ANNOTATIONS) && !USE(DYNAMIC_ANNOTATIONS_NOIMPL) - -// Identical code folding(-Wl,--icf=all) countermeasures. -// This makes all Annotate* functions different, which prevents the linker from -// folding them. -#ifdef __COUNTER__ -#define DYNAMIC_ANNOTATIONS_IMPL \ - volatile short lineno = (__LINE__ << 8) + __COUNTER__; \ - (void)lineno; -#else -#define DYNAMIC_ANNOTATIONS_IMPL \ - volatile short lineno = (__LINE__ << 8); \ - (void)lineno; -#endif - -void WTFAnnotateBenignRaceSized(const char*, int, const volatile void*, long, const char*) -{ - DYNAMIC_ANNOTATIONS_IMPL -} - -void WTFAnnotateHappensBefore(const char*, int, const volatile void*) -{ - DYNAMIC_ANNOTATIONS_IMPL -} - -void WTFAnnotateHappensAfter(const char*, int, const volatile void*) -{ - DYNAMIC_ANNOTATIONS_IMPL -} - -#endif // USE(DYNAMIC_ANNOTATIONS) && !USE(DYNAMIC_ANNOTATIONS_NOIMPL) diff --git a/Source/JavaScriptCore/wtf/DynamicAnnotations.h b/Source/JavaScriptCore/wtf/DynamicAnnotations.h deleted file mode 100644 index 38acce35e..000000000 --- a/Source/JavaScriptCore/wtf/DynamicAnnotations.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WTF_DynamicAnnotations_h -#define WTF_DynamicAnnotations_h - -/* This file defines dynamic annotations for use with dynamic analysis - * tool such as ThreadSanitizer, Valgrind, etc. - * - * Dynamic annotation is a source code annotation that affects - * the generated code (that is, the annotation is not a comment). - * Each such annotation is attached to a particular - * instruction and/or to a particular object (address) in the program. - * - * By using dynamic annotations a developer can give more details to the dynamic - * analysis tool to improve its precision. - * - * In C/C++ program the annotations are represented as C macros. - * With the default build flags, these macros are empty, hence don't affect - * performance of a compiled binary. - * If dynamic annotations are enabled, they just call no-op functions. - * The dynamic analysis tools can intercept these functions and replace them - * with their own implementations. - * - * See http://code.google.com/p/data-race-test/wiki/DynamicAnnotations for more information. - */ - -#if USE(DYNAMIC_ANNOTATIONS) -/* Tell data race detector that we're not interested in reports on the given address range. */ -#define WTF_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) WTFAnnotateBenignRaceSized(__FILE__, __LINE__, address, size, description) -#define WTF_ANNOTATE_BENIGN_RACE(pointer, description) WTFAnnotateBenignRaceSized(__FILE__, __LINE__, pointer, sizeof(*(pointer)), description) - -/* Annotations for user-defined synchronization mechanisms. - * These annotations can be used to define happens-before arcs in user-defined - * synchronization mechanisms: the race detector will infer an arc from - * the former to the latter when they share the same argument pointer. - * - * The most common case requiring annotations is atomic reference counting: - * bool deref() { - * ANNOTATE_HAPPENS_BEFORE(&m_refCount); - * if (!atomicDecrement(&m_refCount)) { - * // m_refCount is now 0 - * ANNOTATE_HAPPENS_AFTER(&m_refCount); - * // "return true; happens-after each atomicDecrement of m_refCount" - * return true; - * } - * return false; - * } - */ -#define WTF_ANNOTATE_HAPPENS_BEFORE(address) WTFAnnotateHappensBefore(__FILE__, __LINE__, address) -#define WTF_ANNOTATE_HAPPENS_AFTER(address) WTFAnnotateHappensAfter(__FILE__, __LINE__, address) - -#ifdef __cplusplus -extern "C" { -#endif -/* Don't use these directly, use the above macros instead. */ -void WTFAnnotateBenignRaceSized(const char* file, int line, const volatile void* memory, long size, const char* description); -void WTFAnnotateHappensBefore(const char* file, int line, const volatile void* address); -void WTFAnnotateHappensAfter(const char* file, int line, const volatile void* address); -#ifdef __cplusplus -} // extern "C" -#endif - -#else // USE(DYNAMIC_ANNOTATIONS) -/* These macros are empty when dynamic annotations are not enabled so you can - * use them without affecting the performance of release binaries. */ -#define WTF_ANNOTATE_BENIGN_RACE_SIZED(address, size, description) -#define WTF_ANNOTATE_BENIGN_RACE(pointer, description) -#define WTF_ANNOTATE_HAPPENS_BEFORE(address) -#define WTF_ANNOTATE_HAPPENS_AFTER(address) -#endif // USE(DYNAMIC_ANNOTATIONS) - -#endif // WTF_DynamicAnnotations_h diff --git a/Source/JavaScriptCore/wtf/Encoder.h b/Source/JavaScriptCore/wtf/Encoder.h deleted file mode 100644 index 109b0db8d..000000000 --- a/Source/JavaScriptCore/wtf/Encoder.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011 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 Encoder_h -#define Encoder_h - -#include <stdint.h> - -namespace WTF { - -class String; - -class Encoder { -protected: - Encoder() { } - virtual ~Encoder() { } - -public: - virtual void encodeBytes(const uint8_t*, size_t) = 0; - - virtual void encodeBool(bool) = 0; - virtual void encodeUInt32(uint32_t) = 0; - virtual void encodeUInt64(uint64_t) = 0; - virtual void encodeInt32(int32_t) = 0; - virtual void encodeInt64(int64_t) = 0; - virtual void encodeFloat(float) = 0; - virtual void encodeDouble(double) = 0; - virtual void encodeString(const String&) = 0; -}; - -} // namespace WTF - -using WTF::Encoder; - -#endif // Encoder_h diff --git a/Source/JavaScriptCore/wtf/ExportMacros.h b/Source/JavaScriptCore/wtf/ExportMacros.h deleted file mode 100644 index 4d3219329..000000000 --- a/Source/JavaScriptCore/wtf/ExportMacros.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2011 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. - * - * This file handles shared library symbol export decorations. It is recommended - * that all WebKit projects use these definitions so that symbol exports work - * properly on all platforms and compilers that WebKit builds under. - */ - -#ifndef ExportMacros_h -#define ExportMacros_h - -#include <wtf/Platform.h> - -// See note in wtf/Platform.h for more info on EXPORT_MACROS. -#if USE(EXPORT_MACROS) - -#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !COMPILER(GCC) -#define WTF_EXPORT __declspec(dllexport) -#define WTF_IMPORT __declspec(dllimport) -#define WTF_HIDDEN -#elif defined(__GNUC__) && !defined(__CC_ARM) && !defined(__ARMCC__) -#define WTF_EXPORT __attribute__((visibility("default"))) -#define WTF_IMPORT WTF_EXPORT -#define WTF_HIDDEN __attribute__((visibility("hidden"))) -#else -#define WTF_EXPORT -#define WTF_IMPORT -#define WTF_HIDDEN -#endif - -// FIXME: When all ports are using the export macros, we should replace -// WTF_EXPORTDATA with WTF_EXPORT_PRIVATE macros. -#if defined(BUILDING_WTF) -#define WTF_EXPORTDATA WTF_EXPORT -#else -#define WTF_EXPORTDATA WTF_IMPORT -#endif - -#else // !USE(EXPORT_MACROS) - -#if !PLATFORM(CHROMIUM) && OS(WINDOWS) && !COMPILER(GCC) -#if defined(BUILDING_WTF) -#define WTF_EXPORTDATA __declspec(dllexport) -#else -#define WTF_EXPORTDATA __declspec(dllimport) -#endif -#else // PLATFORM(CHROMIUM) || !OS(WINDOWS) || COMPILER(GCC) -#define WTF_EXPORTDATA -#endif // !PLATFORM(CHROMIUM)... - -#define WTF_EXPORTCLASS WTF_EXPORTDATA - -#define WTF_EXPORT -#define WTF_IMPORT -#define WTF_HIDDEN - -#endif // USE(EXPORT_MACROS) - -#if defined(BUILDING_WTF) -#define WTF_EXPORT_PRIVATE WTF_EXPORT -#else -#define WTF_EXPORT_PRIVATE WTF_IMPORT -#endif - -// wxWebKit uses RTTI because wx itself does, so use a special macro for -// extra exports it needs. -#if PLATFORM(WX) -#define WTF_EXPORT_PRIVATE_RTTI WTF_EXPORT_PRIVATE -#else -#define WTF_EXPORT_PRIVATE_RTTI -#endif - -#define WTF_EXPORT_HIDDEN WTF_HIDDEN - -#define HIDDEN_INLINE WTF_EXPORT_HIDDEN inline - -#endif // ExportMacros_h diff --git a/Source/JavaScriptCore/wtf/FastAllocBase.h b/Source/JavaScriptCore/wtf/FastAllocBase.h deleted file mode 100644 index a0804ad3d..000000000 --- a/Source/JavaScriptCore/wtf/FastAllocBase.h +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright (C) 2008, 2009 Paul Pedriana <ppedriana@ea.com>. 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 FastAllocBase_h -#define FastAllocBase_h - -// Provides customizable overrides of fastMalloc/fastFree and operator new/delete -// -// Provided functionality: -// Macro: WTF_MAKE_FAST_ALLOCATED -// namespace WTF { -// -// T* fastNew<T>(); -// T* fastNew<T>(arg); -// T* fastNew<T>(arg, arg); -// T* fastNewArray<T>(count); -// void fastDelete(T* p); -// void fastDeleteArray(T* p); -// void fastNonNullDelete(T* p); -// void fastNonNullDeleteArray(T* p); -// } -// -// FastDelete assumes that the underlying -// -// Example usage: -// class Widget { -// WTF_MAKE_FAST_ALLOCATED -// ... -// }; -// -// struct Data { -// WTF_MAKE_FAST_ALLOCATED -// public: -// ... -// }; -// -// char* charPtr = fastNew<char>(); -// fastDelete(charPtr); -// -// char* charArrayPtr = fastNewArray<char>(37); -// fastDeleteArray(charArrayPtr); -// -// void** voidPtrPtr = fastNew<void*>(); -// fastDelete(voidPtrPtr); -// -// void** voidPtrArrayPtr = fastNewArray<void*>(37); -// fastDeleteArray(voidPtrArrayPtr); -// -// POD* podPtr = fastNew<POD>(); -// fastDelete(podPtr); -// -// POD* podArrayPtr = fastNewArray<POD>(37); -// fastDeleteArray(podArrayPtr); -// -// Object* objectPtr = fastNew<Object>(); -// fastDelete(objectPtr); -// -// Object* objectArrayPtr = fastNewArray<Object>(37); -// fastDeleteArray(objectArrayPtr); -// - -#include <new> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> -#include <wtf/Assertions.h> -#include <wtf/FastMalloc.h> -#include <wtf/StdLibExtras.h> -#include <wtf/TypeTraits.h> - -#define WTF_MAKE_FAST_ALLOCATED \ -public: \ - void* operator new(size_t, void* p) { return p; } \ - void* operator new[](size_t, void* p) { return p; } \ - \ - void* operator new(size_t size) \ - { \ - void* p = ::WTF::fastMalloc(size); \ - ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNew); \ - return p; \ - } \ - \ - void operator delete(void* p) \ - { \ - ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNew); \ - ::WTF::fastFree(p); \ - } \ - \ - void* operator new[](size_t size) \ - { \ - void* p = ::WTF::fastMalloc(size); \ - ::WTF::fastMallocMatchValidateMalloc(p, ::WTF::Internal::AllocTypeClassNewArray); \ - return p; \ - } \ - \ - void operator delete[](void* p) \ - { \ - ::WTF::fastMallocMatchValidateFree(p, ::WTF::Internal::AllocTypeClassNewArray); \ - ::WTF::fastFree(p); \ - } \ - void* operator new(size_t, NotNullTag, void* location) \ - { \ - ASSERT(location); \ - return location; \ - } \ -private: \ -typedef int __thisIsHereToForceASemicolonAfterThisMacro - -namespace WTF { - - // fastNew / fastDelete - - template <typename T> - inline T* fastNew() - { - void* p = fastMalloc(sizeof(T)); - - if (!p) - return 0; - - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); - return ::new (p) T; - } - - template <typename T, typename Arg1> - inline T* fastNew(Arg1 arg1) - { - void* p = fastMalloc(sizeof(T)); - - if (!p) - return 0; - - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); - return ::new (p) T(arg1); - } - - template <typename T, typename Arg1, typename Arg2> - inline T* fastNew(Arg1 arg1, Arg2 arg2) - { - void* p = fastMalloc(sizeof(T)); - - if (!p) - return 0; - - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); - return ::new (p) T(arg1, arg2); - } - - template <typename T, typename Arg1, typename Arg2, typename Arg3> - inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3) - { - void* p = fastMalloc(sizeof(T)); - - if (!p) - return 0; - - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); - return ::new (p) T(arg1, arg2, arg3); - } - - template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4> - inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) - { - void* p = fastMalloc(sizeof(T)); - - if (!p) - return 0; - - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); - return ::new (p) T(arg1, arg2, arg3, arg4); - } - - template <typename T, typename Arg1, typename Arg2, typename Arg3, typename Arg4, typename Arg5> - inline T* fastNew(Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5) - { - void* p = fastMalloc(sizeof(T)); - - if (!p) - return 0; - - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNew); - return ::new (p) T(arg1, arg2, arg3, arg4, arg5); - } - - namespace Internal { - - // We define a union of pointer to an integer and pointer to T. - // When non-POD arrays are allocated we add a few leading bytes to tell what - // the size of the array is. We return to the user the pointer to T. - // The way to think of it is as if we allocate a struct like so: - // struct Array { - // AllocAlignmentInteger m_size; - // T m_T[array count]; - // }; - - template <typename T> - union ArraySize { - AllocAlignmentInteger* size; - T* t; - }; - - // This is a support template for fastNewArray. - // This handles the case wherein T has a trivial ctor and a trivial dtor. - template <typename T, bool trivialCtor, bool trivialDtor> - struct NewArrayImpl { - static T* fastNewArray(size_t count) - { - T* p = static_cast<T*>(fastMalloc(sizeof(T) * count)); - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); - return p; - } - }; - - // This is a support template for fastNewArray. - // This handles the case wherein T has a non-trivial ctor and a trivial dtor. - template <typename T> - struct NewArrayImpl<T, false, true> { - static T* fastNewArray(size_t count) - { - T* p = static_cast<T*>(fastMalloc(sizeof(T) * count)); - - if (!p) - return 0; - - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); - - for (T* pObject = p, *pObjectEnd = pObject + count; pObject != pObjectEnd; ++pObject) - ::new (pObject) T; - - return p; - } - }; - - // This is a support template for fastNewArray. - // This handles the case wherein T has a trivial ctor and a non-trivial dtor. - template <typename T> - struct NewArrayImpl<T, true, false> { - static T* fastNewArray(size_t count) - { - void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); - ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) }; - - if (!p) - return 0; - - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); - *a.size++ = count; - // No need to construct the objects in this case. - - return a.t; - } - }; - - // This is a support template for fastNewArray. - // This handles the case wherein T has a non-trivial ctor and a non-trivial dtor. - template <typename T> - struct NewArrayImpl<T, false, false> { - static T* fastNewArray(size_t count) - { - void* p = fastMalloc(sizeof(AllocAlignmentInteger) + (sizeof(T) * count)); - ArraySize<T> a = { static_cast<AllocAlignmentInteger*>(p) }; - - if (!p) - return 0; - - fastMallocMatchValidateMalloc(p, Internal::AllocTypeFastNewArray); - *a.size++ = count; - - for (T* pT = a.t, *pTEnd = pT + count; pT != pTEnd; ++pT) - ::new (pT) T; - - return a.t; - } - }; - } // namespace Internal - - template <typename T> - inline T* fastNewArray(size_t count) - { - return Internal::NewArrayImpl<T, WTF::HasTrivialConstructor<T>::value, WTF::HasTrivialDestructor<T>::value>::fastNewArray(count); - } - - template <typename T> - inline void fastDelete(T* p) - { - if (!p) - return; - - fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); - p->~T(); - fastFree(p); - } - - template <typename T> - inline void fastDeleteSkippingDestructor(T* p) - { - if (!p) - return; - - fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); - fastFree(p); - } - - namespace Internal { - // This is a support template for fastDeleteArray. - // This handles the case wherein T has a trivial dtor. - template <typename T, bool trivialDtor> - struct DeleteArrayImpl { - static void fastDeleteArray(void* p) - { - // No need to destruct the objects in this case. - // We expect that fastFree checks for null. - fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); - fastFree(p); - } - }; - - // This is a support template for fastDeleteArray. - // This handles the case wherein T has a non-trivial dtor. - template <typename T> - struct DeleteArrayImpl<T, false> { - static void fastDeleteArray(T* p) - { - if (!p) - return; - - ArraySize<T> a; - a.t = p; - a.size--; // Decrement size pointer - - T* pEnd = p + *a.size; - while (pEnd-- != p) - pEnd->~T(); - - fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); - fastFree(a.size); - } - }; - - } // namespace Internal - - template <typename T> - void fastDeleteArray(T* p) - { - Internal::DeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastDeleteArray(p); - } - - - template <typename T> - inline void fastNonNullDelete(T* p) - { - fastMallocMatchValidateFree(p, Internal::AllocTypeFastNew); - p->~T(); - fastFree(p); - } - - namespace Internal { - // This is a support template for fastDeleteArray. - // This handles the case wherein T has a trivial dtor. - template <typename T, bool trivialDtor> - struct NonNullDeleteArrayImpl { - static void fastNonNullDeleteArray(void* p) - { - fastMallocMatchValidateFree(p, Internal::AllocTypeFastNewArray); - // No need to destruct the objects in this case. - fastFree(p); - } - }; - - // This is a support template for fastDeleteArray. - // This handles the case wherein T has a non-trivial dtor. - template <typename T> - struct NonNullDeleteArrayImpl<T, false> { - static void fastNonNullDeleteArray(T* p) - { - ArraySize<T> a; - a.t = p; - a.size--; - - T* pEnd = p + *a.size; - while (pEnd-- != p) - pEnd->~T(); - - fastMallocMatchValidateFree(a.size, Internal::AllocTypeFastNewArray); - fastFree(a.size); - } - }; - - } // namespace Internal - - template <typename T> - void fastNonNullDeleteArray(T* p) - { - Internal::NonNullDeleteArrayImpl<T, WTF::HasTrivialDestructor<T>::value>::fastNonNullDeleteArray(p); - } - - -} // namespace WTF - -using WTF::fastDeleteSkippingDestructor; - -#endif // FastAllocBase_h diff --git a/Source/JavaScriptCore/wtf/FastMalloc.cpp b/Source/JavaScriptCore/wtf/FastMalloc.cpp deleted file mode 100644 index 6b92f5542..000000000 --- a/Source/JavaScriptCore/wtf/FastMalloc.cpp +++ /dev/null @@ -1,4708 +0,0 @@ -// Copyright (c) 2005, 2007, Google Inc. -// All rights reserved. -// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2011 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Sanjay Ghemawat <opensource@google.com> -// -// A malloc that uses a per-thread cache to satisfy small malloc requests. -// (The time for malloc/free of a small object drops from 300 ns to 50 ns.) -// -// See doc/tcmalloc.html for a high-level -// description of how this malloc works. -// -// SYNCHRONIZATION -// 1. The thread-specific lists are accessed without acquiring any locks. -// This is safe because each such list is only accessed by one thread. -// 2. We have a lock per central free-list, and hold it while manipulating -// the central free list for a particular size. -// 3. The central page allocator is protected by "pageheap_lock". -// 4. The pagemap (which maps from page-number to descriptor), -// can be read without holding any locks, and written while holding -// the "pageheap_lock". -// 5. To improve performance, a subset of the information one can get -// from the pagemap is cached in a data structure, pagemap_cache_, -// that atomically reads and writes its entries. This cache can be -// read and written without locking. -// -// This multi-threaded access to the pagemap is safe for fairly -// subtle reasons. We basically assume that when an object X is -// allocated by thread A and deallocated by thread B, there must -// have been appropriate synchronization in the handoff of object -// X from thread A to thread B. The same logic applies to pagemap_cache_. -// -// THE PAGEID-TO-SIZECLASS CACHE -// Hot PageID-to-sizeclass mappings are held by pagemap_cache_. If this cache -// returns 0 for a particular PageID then that means "no information," not that -// the sizeclass is 0. The cache may have stale information for pages that do -// not hold the beginning of any free()'able object. Staleness is eliminated -// in Populate() for pages with sizeclass > 0 objects, and in do_malloc() and -// do_memalign() for all other relevant pages. -// -// TODO: Bias reclamation to larger addresses -// TODO: implement mallinfo/mallopt -// TODO: Better testing -// -// 9/28/2003 (new page-level allocator replaces ptmalloc2): -// * malloc/free of small objects goes from ~300 ns to ~50 ns. -// * allocation of a reasonably complicated struct -// goes from about 1100 ns to about 300 ns. - -#include "config.h" -#include "FastMalloc.h" - -#include "Assertions.h" -#include <limits> -#if OS(WINDOWS) -#include <windows.h> -#else -#include <pthread.h> -#endif -#include <wtf/StdLibExtras.h> -#include <string.h> - -#ifndef NO_TCMALLOC_SAMPLES -#ifdef WTF_CHANGES -#define NO_TCMALLOC_SAMPLES -#endif -#endif - -#if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) && defined(NDEBUG) -#define FORCE_SYSTEM_MALLOC 0 -#else -#define FORCE_SYSTEM_MALLOC 1 -#endif - -// Use a background thread to periodically scavenge memory to release back to the system -#if PLATFORM(IOS) -#define USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY 0 -#else -#define USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY 1 -#endif - -#ifndef NDEBUG -namespace WTF { - -#if OS(WINDOWS) - -// TLS_OUT_OF_INDEXES is not defined on WinCE. -#ifndef TLS_OUT_OF_INDEXES -#define TLS_OUT_OF_INDEXES 0xffffffff -#endif - -static DWORD isForibiddenTlsIndex = TLS_OUT_OF_INDEXES; -static const LPVOID kTlsAllowValue = reinterpret_cast<LPVOID>(0); // Must be zero. -static const LPVOID kTlsForbiddenValue = reinterpret_cast<LPVOID>(1); - -#if !ASSERT_DISABLED -static bool isForbidden() -{ - // By default, fastMalloc is allowed so we don't allocate the - // tls index unless we're asked to make it forbidden. If TlsSetValue - // has not been called on a thread, the value returned by TlsGetValue is 0. - return (isForibiddenTlsIndex != TLS_OUT_OF_INDEXES) && (TlsGetValue(isForibiddenTlsIndex) == kTlsForbiddenValue); -} -#endif - -void fastMallocForbid() -{ - if (isForibiddenTlsIndex == TLS_OUT_OF_INDEXES) - isForibiddenTlsIndex = TlsAlloc(); // a little racey, but close enough for debug only - TlsSetValue(isForibiddenTlsIndex, kTlsForbiddenValue); -} - -void fastMallocAllow() -{ - if (isForibiddenTlsIndex == TLS_OUT_OF_INDEXES) - return; - TlsSetValue(isForibiddenTlsIndex, kTlsAllowValue); -} - -#else // !OS(WINDOWS) - -static pthread_key_t isForbiddenKey; -static pthread_once_t isForbiddenKeyOnce = PTHREAD_ONCE_INIT; -static void initializeIsForbiddenKey() -{ - pthread_key_create(&isForbiddenKey, 0); -} - -#if !ASSERT_DISABLED -static bool isForbidden() -{ - pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey); - return !!pthread_getspecific(isForbiddenKey); -} -#endif - -void fastMallocForbid() -{ - pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey); - pthread_setspecific(isForbiddenKey, &isForbiddenKey); -} - -void fastMallocAllow() -{ - pthread_once(&isForbiddenKeyOnce, initializeIsForbiddenKey); - pthread_setspecific(isForbiddenKey, 0); -} -#endif // OS(WINDOWS) - -} // namespace WTF -#endif // NDEBUG - -namespace WTF { - - -namespace Internal { -#if !ENABLE(WTF_MALLOC_VALIDATION) -WTF_EXPORT_PRIVATE void fastMallocMatchFailed(void*); -#else -COMPILE_ASSERT(((sizeof(ValidationHeader) % sizeof(AllocAlignmentInteger)) == 0), ValidationHeader_must_produce_correct_alignment); -#endif - -NO_RETURN_DUE_TO_CRASH void fastMallocMatchFailed(void*) -{ - CRASH(); -} - -} // namespace Internal - - -void* fastZeroedMalloc(size_t n) -{ - void* result = fastMalloc(n); - memset(result, 0, n); - return result; -} - -char* fastStrDup(const char* src) -{ - size_t len = strlen(src) + 1; - char* dup = static_cast<char*>(fastMalloc(len)); - memcpy(dup, src, len); - return dup; -} - -TryMallocReturnValue tryFastZeroedMalloc(size_t n) -{ - void* result; - if (!tryFastMalloc(n).getValue(result)) - return 0; - memset(result, 0, n); - return result; -} - -} // namespace WTF - -#if FORCE_SYSTEM_MALLOC - -#if OS(DARWIN) -#include <malloc/malloc.h> -#elif OS(WINDOWS) -#include <malloc.h> -#endif - -namespace WTF { - -TryMallocReturnValue tryFastMalloc(size_t n) -{ - ASSERT(!isForbidden()); - -#if ENABLE(WTF_MALLOC_VALIDATION) - if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= n) // If overflow would occur... - return 0; - - void* result = malloc(n + Internal::ValidationBufferSize); - if (!result) - return 0; - Internal::ValidationHeader* header = static_cast<Internal::ValidationHeader*>(result); - header->m_size = n; - header->m_type = Internal::AllocTypeMalloc; - header->m_prefix = static_cast<unsigned>(Internal::ValidationPrefix); - result = header + 1; - *Internal::fastMallocValidationSuffix(result) = Internal::ValidationSuffix; - fastMallocValidate(result); - return result; -#else - return malloc(n); -#endif -} - -void* fastMalloc(size_t n) -{ - ASSERT(!isForbidden()); - -#if ENABLE(WTF_MALLOC_VALIDATION) - TryMallocReturnValue returnValue = tryFastMalloc(n); - void* result; - if (!returnValue.getValue(result)) - CRASH(); -#else - void* result = malloc(n); -#endif - - if (!result) - CRASH(); - - return result; -} - -TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size) -{ - ASSERT(!isForbidden()); - -#if ENABLE(WTF_MALLOC_VALIDATION) - size_t totalBytes = n_elements * element_size; - if (n_elements > 1 && element_size && (totalBytes / element_size) != n_elements) - return 0; - - TryMallocReturnValue returnValue = tryFastMalloc(totalBytes); - void* result; - if (!returnValue.getValue(result)) - return 0; - memset(result, 0, totalBytes); - fastMallocValidate(result); - return result; -#else - return calloc(n_elements, element_size); -#endif -} - -void* fastCalloc(size_t n_elements, size_t element_size) -{ - ASSERT(!isForbidden()); - -#if ENABLE(WTF_MALLOC_VALIDATION) - TryMallocReturnValue returnValue = tryFastCalloc(n_elements, element_size); - void* result; - if (!returnValue.getValue(result)) - CRASH(); -#else - void* result = calloc(n_elements, element_size); -#endif - - if (!result) - CRASH(); - - return result; -} - -void fastFree(void* p) -{ - ASSERT(!isForbidden()); - -#if ENABLE(WTF_MALLOC_VALIDATION) - if (!p) - return; - - fastMallocMatchValidateFree(p, Internal::AllocTypeMalloc); - Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p); - memset(p, 0xCC, header->m_size); - free(header); -#else - free(p); -#endif -} - -TryMallocReturnValue tryFastRealloc(void* p, size_t n) -{ - ASSERT(!isForbidden()); - -#if ENABLE(WTF_MALLOC_VALIDATION) - if (p) { - if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= n) // If overflow would occur... - return 0; - fastMallocValidate(p); - Internal::ValidationHeader* result = static_cast<Internal::ValidationHeader*>(realloc(Internal::fastMallocValidationHeader(p), n + Internal::ValidationBufferSize)); - if (!result) - return 0; - result->m_size = n; - result = result + 1; - *fastMallocValidationSuffix(result) = Internal::ValidationSuffix; - fastMallocValidate(result); - return result; - } else { - return fastMalloc(n); - } -#else - return realloc(p, n); -#endif -} - -void* fastRealloc(void* p, size_t n) -{ - ASSERT(!isForbidden()); - -#if ENABLE(WTF_MALLOC_VALIDATION) - TryMallocReturnValue returnValue = tryFastRealloc(p, n); - void* result; - if (!returnValue.getValue(result)) - CRASH(); -#else - void* result = realloc(p, n); -#endif - - if (!result) - CRASH(); - return result; -} - -void releaseFastMallocFreeMemory() { } - -FastMallocStatistics fastMallocStatistics() -{ - FastMallocStatistics statistics = { 0, 0, 0 }; - return statistics; -} - -size_t fastMallocSize(const void* p) -{ -#if ENABLE(WTF_MALLOC_VALIDATION) - return Internal::fastMallocValidationHeader(const_cast<void*>(p))->m_size; -#elif OS(DARWIN) - return malloc_size(p); -#elif OS(WINDOWS) - return _msize(const_cast<void*>(p)); -#else - return 1; -#endif -} - -} // namespace WTF - -#if OS(DARWIN) -// This symbol is present in the JavaScriptCore exports file even when FastMalloc is disabled. -// It will never be used in this case, so it's type and value are less interesting than its presence. -extern "C" WTF_EXPORT_PRIVATE const int jscore_fastmalloc_introspection = 0; -#endif - -#else // FORCE_SYSTEM_MALLOC - -#if HAVE(STDINT_H) -#include <stdint.h> -#elif HAVE(INTTYPES_H) -#include <inttypes.h> -#else -#include <sys/types.h> -#endif - -#include "AlwaysInline.h" -#include "Assertions.h" -#include "TCPackedCache.h" -#include "TCPageMap.h" -#include "TCSpinLock.h" -#include "TCSystemAlloc.h" -#include <algorithm> -#include <limits> -#include <pthread.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#if HAVE(ERRNO_H) -#include <errno.h> -#endif -#if OS(UNIX) -#include <unistd.h> -#endif -#if OS(WINDOWS) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include <windows.h> -#endif - -#ifdef WTF_CHANGES - -#if OS(DARWIN) -#include "MallocZoneSupport.h" -#include <wtf/HashSet.h> -#include <wtf/Vector.h> -#endif - -#if HAVE(HEADER_DETECTION_H) -#include "HeaderDetection.h" -#endif - -#if HAVE(DISPATCH_H) -#include <dispatch/dispatch.h> -#endif - -#if HAVE(PTHREAD_MACHDEP_H) -#include <System/pthread_machdep.h> - -#if defined(__PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0) -#define WTF_USE_PTHREAD_GETSPECIFIC_DIRECT 1 -#endif -#endif - -#ifndef PRIuS -#define PRIuS "zu" -#endif - -// Calling pthread_getspecific through a global function pointer is faster than a normal -// call to the function on Mac OS X, and it's used in performance-critical code. So we -// use a function pointer. But that's not necessarily faster on other platforms, and we had -// problems with this technique on Windows, so we'll do this only on Mac OS X. -#if OS(DARWIN) -#if !USE(PTHREAD_GETSPECIFIC_DIRECT) -static void* (*pthread_getspecific_function_pointer)(pthread_key_t) = pthread_getspecific; -#define pthread_getspecific(key) pthread_getspecific_function_pointer(key) -#else -#define pthread_getspecific(key) _pthread_getspecific_direct(key) -#define pthread_setspecific(key, val) _pthread_setspecific_direct(key, (val)) -#endif -#endif - -#define DEFINE_VARIABLE(type, name, value, meaning) \ - namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead { \ - type FLAGS_##name(value); \ - char FLAGS_no##name; \ - } \ - using FLAG__namespace_do_not_use_directly_use_DECLARE_##type##_instead::FLAGS_##name - -#define DEFINE_int64(name, value, meaning) \ - DEFINE_VARIABLE(int64_t, name, value, meaning) - -#define DEFINE_double(name, value, meaning) \ - DEFINE_VARIABLE(double, name, value, meaning) - -namespace WTF { - -#define malloc fastMalloc -#define calloc fastCalloc -#define free fastFree -#define realloc fastRealloc - -#define MESSAGE LOG_ERROR -#define CHECK_CONDITION ASSERT - -#if OS(DARWIN) -struct Span; -class TCMalloc_Central_FreeListPadded; -class TCMalloc_PageHeap; -class TCMalloc_ThreadCache; -template <typename T> class PageHeapAllocator; - -class FastMallocZone { -public: - static void init(); - - static kern_return_t enumerate(task_t, void*, unsigned typeMmask, vm_address_t zoneAddress, memory_reader_t, vm_range_recorder_t); - static size_t goodSize(malloc_zone_t*, size_t size) { return size; } - static boolean_t check(malloc_zone_t*) { return true; } - static void print(malloc_zone_t*, boolean_t) { } - static void log(malloc_zone_t*, void*) { } - static void forceLock(malloc_zone_t*) { } - static void forceUnlock(malloc_zone_t*) { } - static void statistics(malloc_zone_t*, malloc_statistics_t* stats) { memset(stats, 0, sizeof(malloc_statistics_t)); } - -private: - FastMallocZone(TCMalloc_PageHeap*, TCMalloc_ThreadCache**, TCMalloc_Central_FreeListPadded*, PageHeapAllocator<Span>*, PageHeapAllocator<TCMalloc_ThreadCache>*); - static size_t size(malloc_zone_t*, const void*); - static void* zoneMalloc(malloc_zone_t*, size_t); - static void* zoneCalloc(malloc_zone_t*, size_t numItems, size_t size); - static void zoneFree(malloc_zone_t*, void*); - static void* zoneRealloc(malloc_zone_t*, void*, size_t); - static void* zoneValloc(malloc_zone_t*, size_t) { LOG_ERROR("valloc is not supported"); return 0; } - static void zoneDestroy(malloc_zone_t*) { } - - malloc_zone_t m_zone; - TCMalloc_PageHeap* m_pageHeap; - TCMalloc_ThreadCache** m_threadHeaps; - TCMalloc_Central_FreeListPadded* m_centralCaches; - PageHeapAllocator<Span>* m_spanAllocator; - PageHeapAllocator<TCMalloc_ThreadCache>* m_pageHeapAllocator; -}; - -#endif - -#endif - -#ifndef WTF_CHANGES -// This #ifdef should almost never be set. Set NO_TCMALLOC_SAMPLES if -// you're porting to a system where you really can't get a stacktrace. -#ifdef NO_TCMALLOC_SAMPLES -// We use #define so code compiles even if you #include stacktrace.h somehow. -# define GetStackTrace(stack, depth, skip) (0) -#else -# include <google/stacktrace.h> -#endif -#endif - -// Even if we have support for thread-local storage in the compiler -// and linker, the OS may not support it. We need to check that at -// runtime. Right now, we have to keep a manual set of "bad" OSes. -#if defined(HAVE_TLS) - static bool kernel_supports_tls = false; // be conservative - static inline bool KernelSupportsTLS() { - return kernel_supports_tls; - } -# if !HAVE_DECL_UNAME // if too old for uname, probably too old for TLS - static void CheckIfKernelSupportsTLS() { - kernel_supports_tls = false; - } -# else -# include <sys/utsname.h> // DECL_UNAME checked for <sys/utsname.h> too - static void CheckIfKernelSupportsTLS() { - struct utsname buf; - if (uname(&buf) != 0) { // should be impossible - MESSAGE("uname failed assuming no TLS support (errno=%d)\n", errno); - kernel_supports_tls = false; - } else if (strcasecmp(buf.sysname, "linux") == 0) { - // The linux case: the first kernel to support TLS was 2.6.0 - if (buf.release[0] < '2' && buf.release[1] == '.') // 0.x or 1.x - kernel_supports_tls = false; - else if (buf.release[0] == '2' && buf.release[1] == '.' && - buf.release[2] >= '0' && buf.release[2] < '6' && - buf.release[3] == '.') // 2.0 - 2.5 - kernel_supports_tls = false; - else - kernel_supports_tls = true; - } else { // some other kernel, we'll be optimisitic - kernel_supports_tls = true; - } - // TODO(csilvers): VLOG(1) the tls status once we support RAW_VLOG - } -# endif // HAVE_DECL_UNAME -#endif // HAVE_TLS - -// __THROW is defined in glibc systems. It means, counter-intuitively, -// "This function will never throw an exception." It's an optional -// optimization tool, but we may need to use it to match glibc prototypes. -#ifndef __THROW // I guess we're not on a glibc system -# define __THROW // __THROW is just an optimization, so ok to make it "" -#endif - -//------------------------------------------------------------------- -// Configuration -//------------------------------------------------------------------- - -// Not all possible combinations of the following parameters make -// sense. In particular, if kMaxSize increases, you may have to -// increase kNumClasses as well. -static const size_t kPageShift = 12; -static const size_t kPageSize = 1 << kPageShift; -static const size_t kMaxSize = 8u * kPageSize; -static const size_t kAlignShift = 3; -static const size_t kAlignment = 1 << kAlignShift; -static const size_t kNumClasses = 68; - -// Allocates a big block of memory for the pagemap once we reach more than -// 128MB -static const size_t kPageMapBigAllocationThreshold = 128 << 20; - -// Minimum number of pages to fetch from system at a time. Must be -// significantly bigger than kPageSize to amortize system-call -// overhead, and also to reduce external fragementation. Also, we -// should keep this value big because various incarnations of Linux -// have small limits on the number of mmap() regions per -// address-space. -static const size_t kMinSystemAlloc = 1 << (20 - kPageShift); - -// Number of objects to move between a per-thread list and a central -// list in one shot. We want this to be not too small so we can -// amortize the lock overhead for accessing the central list. Making -// it too big may temporarily cause unnecessary memory wastage in the -// per-thread free list until the scavenger cleans up the list. -static int num_objects_to_move[kNumClasses]; - -// Maximum length we allow a per-thread free-list to have before we -// move objects from it into the corresponding central free-list. We -// want this big to avoid locking the central free-list too often. It -// should not hurt to make this list somewhat big because the -// scavenging code will shrink it down when its contents are not in use. -static const int kMaxFreeListLength = 256; - -// Lower and upper bounds on the per-thread cache sizes -static const size_t kMinThreadCacheSize = kMaxSize * 2; -#if PLATFORM(IOS) -static const size_t kMaxThreadCacheSize = 512 * 1024; -#else -static const size_t kMaxThreadCacheSize = 2 << 20; -#endif - -// Default bound on the total amount of thread caches -static const size_t kDefaultOverallThreadCacheSize = 16 << 20; - -// For all span-lengths < kMaxPages we keep an exact-size list. -// REQUIRED: kMaxPages >= kMinSystemAlloc; -static const size_t kMaxPages = kMinSystemAlloc; - -/* The smallest prime > 2^n */ -static int primes_list[] = { - // Small values might cause high rates of sampling - // and hence commented out. - // 2, 5, 11, 17, 37, 67, 131, 257, - // 521, 1031, 2053, 4099, 8209, 16411, - 32771, 65537, 131101, 262147, 524309, 1048583, - 2097169, 4194319, 8388617, 16777259, 33554467 }; - -// Twice the approximate gap between sampling actions. -// I.e., we take one sample approximately once every -// tcmalloc_sample_parameter/2 -// bytes of allocation, i.e., ~ once every 128KB. -// Must be a prime number. -#ifdef NO_TCMALLOC_SAMPLES -DEFINE_int64(tcmalloc_sample_parameter, 0, - "Unused: code is compiled with NO_TCMALLOC_SAMPLES"); -static size_t sample_period = 0; -#else -DEFINE_int64(tcmalloc_sample_parameter, 262147, - "Twice the approximate gap between sampling actions." - " Must be a prime number. Otherwise will be rounded up to a " - " larger prime number"); -static size_t sample_period = 262147; -#endif - -// Protects sample_period above -static SpinLock sample_period_lock = SPINLOCK_INITIALIZER; - -// Parameters for controlling how fast memory is returned to the OS. - -DEFINE_double(tcmalloc_release_rate, 1, - "Rate at which we release unused memory to the system. " - "Zero means we never release memory back to the system. " - "Increase this flag to return memory faster; decrease it " - "to return memory slower. Reasonable rates are in the " - "range [0,10]"); - -//------------------------------------------------------------------- -// Mapping from size to size_class and vice versa -//------------------------------------------------------------------- - -// Sizes <= 1024 have an alignment >= 8. So for such sizes we have an -// array indexed by ceil(size/8). Sizes > 1024 have an alignment >= 128. -// So for these larger sizes we have an array indexed by ceil(size/128). -// -// We flatten both logical arrays into one physical array and use -// arithmetic to compute an appropriate index. The constants used by -// ClassIndex() were selected to make the flattening work. -// -// Examples: -// Size Expression Index -// ------------------------------------------------------- -// 0 (0 + 7) / 8 0 -// 1 (1 + 7) / 8 1 -// ... -// 1024 (1024 + 7) / 8 128 -// 1025 (1025 + 127 + (120<<7)) / 128 129 -// ... -// 32768 (32768 + 127 + (120<<7)) / 128 376 -static const size_t kMaxSmallSize = 1024; -static const int shift_amount[2] = { 3, 7 }; // For divides by 8 or 128 -static const int add_amount[2] = { 7, 127 + (120 << 7) }; -static unsigned char class_array[377]; - -// Compute index of the class_array[] entry for a given size -static inline int ClassIndex(size_t s) { - const int i = (s > kMaxSmallSize); - return static_cast<int>((s + add_amount[i]) >> shift_amount[i]); -} - -// Mapping from size class to max size storable in that class -static size_t class_to_size[kNumClasses]; - -// Mapping from size class to number of pages to allocate at a time -static size_t class_to_pages[kNumClasses]; - -// TransferCache is used to cache transfers of num_objects_to_move[size_class] -// back and forth between thread caches and the central cache for a given size -// class. -struct TCEntry { - void *head; // Head of chain of objects. - void *tail; // Tail of chain of objects. -}; -// A central cache freelist can have anywhere from 0 to kNumTransferEntries -// slots to put link list chains into. To keep memory usage bounded the total -// number of TCEntries across size classes is fixed. Currently each size -// class is initially given one TCEntry which also means that the maximum any -// one class can have is kNumClasses. -static const int kNumTransferEntries = kNumClasses; - -// Note: the following only works for "n"s that fit in 32-bits, but -// that is fine since we only use it for small sizes. -static inline int LgFloor(size_t n) { - int log = 0; - for (int i = 4; i >= 0; --i) { - int shift = (1 << i); - size_t x = n >> shift; - if (x != 0) { - n = x; - log += shift; - } - } - ASSERT(n == 1); - return log; -} - -// Some very basic linked list functions for dealing with using void * as -// storage. - -static inline void *SLL_Next(void *t) { - return *(reinterpret_cast<void**>(t)); -} - -static inline void SLL_SetNext(void *t, void *n) { - *(reinterpret_cast<void**>(t)) = n; -} - -static inline void SLL_Push(void **list, void *element) { - SLL_SetNext(element, *list); - *list = element; -} - -static inline void *SLL_Pop(void **list) { - void *result = *list; - *list = SLL_Next(*list); - return result; -} - - -// Remove N elements from a linked list to which head points. head will be -// modified to point to the new head. start and end will point to the first -// and last nodes of the range. Note that end will point to NULL after this -// function is called. -static inline void SLL_PopRange(void **head, int N, void **start, void **end) { - if (N == 0) { - *start = NULL; - *end = NULL; - return; - } - - void *tmp = *head; - for (int i = 1; i < N; ++i) { - tmp = SLL_Next(tmp); - } - - *start = *head; - *end = tmp; - *head = SLL_Next(tmp); - // Unlink range from list. - SLL_SetNext(tmp, NULL); -} - -static inline void SLL_PushRange(void **head, void *start, void *end) { - if (!start) return; - SLL_SetNext(end, *head); - *head = start; -} - -static inline size_t SLL_Size(void *head) { - int count = 0; - while (head) { - count++; - head = SLL_Next(head); - } - return count; -} - -// Setup helper functions. - -static ALWAYS_INLINE size_t SizeClass(size_t size) { - return class_array[ClassIndex(size)]; -} - -// Get the byte-size for a specified class -static ALWAYS_INLINE size_t ByteSizeForClass(size_t cl) { - return class_to_size[cl]; -} -static int NumMoveSize(size_t size) { - if (size == 0) return 0; - // Use approx 64k transfers between thread and central caches. - int num = static_cast<int>(64.0 * 1024.0 / size); - if (num < 2) num = 2; - // Clamp well below kMaxFreeListLength to avoid ping pong between central - // and thread caches. - if (num > static_cast<int>(0.8 * kMaxFreeListLength)) - num = static_cast<int>(0.8 * kMaxFreeListLength); - - // Also, avoid bringing in too many objects into small object free - // lists. There are lots of such lists, and if we allow each one to - // fetch too many at a time, we end up having to scavenge too often - // (especially when there are lots of threads and each thread gets a - // small allowance for its thread cache). - // - // TODO: Make thread cache free list sizes dynamic so that we do not - // have to equally divide a fixed resource amongst lots of threads. - if (num > 32) num = 32; - - return num; -} - -// Initialize the mapping arrays -static void InitSizeClasses() { - // Do some sanity checking on add_amount[]/shift_amount[]/class_array[] - if (ClassIndex(0) < 0) { - MESSAGE("Invalid class index %d for size 0\n", ClassIndex(0)); - CRASH(); - } - if (static_cast<size_t>(ClassIndex(kMaxSize)) >= sizeof(class_array)) { - MESSAGE("Invalid class index %d for kMaxSize\n", ClassIndex(kMaxSize)); - CRASH(); - } - - // Compute the size classes we want to use - size_t sc = 1; // Next size class to assign - unsigned char alignshift = kAlignShift; - int last_lg = -1; - for (size_t size = kAlignment; size <= kMaxSize; size += (1 << alignshift)) { - int lg = LgFloor(size); - if (lg > last_lg) { - // Increase alignment every so often. - // - // Since we double the alignment every time size doubles and - // size >= 128, this means that space wasted due to alignment is - // at most 16/128 i.e., 12.5%. Plus we cap the alignment at 256 - // bytes, so the space wasted as a percentage starts falling for - // sizes > 2K. - if ((lg >= 7) && (alignshift < 8)) { - alignshift++; - } - last_lg = lg; - } - - // Allocate enough pages so leftover is less than 1/8 of total. - // This bounds wasted space to at most 12.5%. - size_t psize = kPageSize; - while ((psize % size) > (psize >> 3)) { - psize += kPageSize; - } - const size_t my_pages = psize >> kPageShift; - - if (sc > 1 && my_pages == class_to_pages[sc-1]) { - // See if we can merge this into the previous class without - // increasing the fragmentation of the previous class. - const size_t my_objects = (my_pages << kPageShift) / size; - const size_t prev_objects = (class_to_pages[sc-1] << kPageShift) - / class_to_size[sc-1]; - if (my_objects == prev_objects) { - // Adjust last class to include this size - class_to_size[sc-1] = size; - continue; - } - } - - // Add new class - class_to_pages[sc] = my_pages; - class_to_size[sc] = size; - sc++; - } - if (sc != kNumClasses) { - MESSAGE("wrong number of size classes: found %" PRIuS " instead of %d\n", - sc, int(kNumClasses)); - CRASH(); - } - - // Initialize the mapping arrays - int next_size = 0; - for (unsigned char c = 1; c < kNumClasses; c++) { - const size_t max_size_in_class = class_to_size[c]; - for (size_t s = next_size; s <= max_size_in_class; s += kAlignment) { - class_array[ClassIndex(s)] = c; - } - next_size = static_cast<int>(max_size_in_class + kAlignment); - } - - // Double-check sizes just to be safe - for (size_t size = 0; size <= kMaxSize; size++) { - const size_t sc = SizeClass(size); - if (sc == 0) { - MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size); - CRASH(); - } - if (sc > 1 && size <= class_to_size[sc-1]) { - MESSAGE("Allocating unnecessarily large class %" PRIuS " for %" PRIuS - "\n", sc, size); - CRASH(); - } - if (sc >= kNumClasses) { - MESSAGE("Bad size class %" PRIuS " for %" PRIuS "\n", sc, size); - CRASH(); - } - const size_t s = class_to_size[sc]; - if (size > s) { - MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc); - CRASH(); - } - if (s == 0) { - MESSAGE("Bad size %" PRIuS " for %" PRIuS " (sc = %" PRIuS ")\n", s, size, sc); - CRASH(); - } - } - - // Initialize the num_objects_to_move array. - for (size_t cl = 1; cl < kNumClasses; ++cl) { - num_objects_to_move[cl] = NumMoveSize(ByteSizeForClass(cl)); - } - -#ifndef WTF_CHANGES - if (false) { - // Dump class sizes and maximum external wastage per size class - for (size_t cl = 1; cl < kNumClasses; ++cl) { - const int alloc_size = class_to_pages[cl] << kPageShift; - const int alloc_objs = alloc_size / class_to_size[cl]; - const int min_used = (class_to_size[cl-1] + 1) * alloc_objs; - const int max_waste = alloc_size - min_used; - MESSAGE("SC %3d [ %8d .. %8d ] from %8d ; %2.0f%% maxwaste\n", - int(cl), - int(class_to_size[cl-1] + 1), - int(class_to_size[cl]), - int(class_to_pages[cl] << kPageShift), - max_waste * 100.0 / alloc_size - ); - } - } -#endif -} - -// ------------------------------------------------------------------------- -// Simple allocator for objects of a specified type. External locking -// is required before accessing one of these objects. -// ------------------------------------------------------------------------- - -// Metadata allocator -- keeps stats about how many bytes allocated -static uint64_t metadata_system_bytes = 0; -static void* MetaDataAlloc(size_t bytes) { - void* result = TCMalloc_SystemAlloc(bytes, 0); - if (result != NULL) { - metadata_system_bytes += bytes; - } - return result; -} - -template <class T> -class PageHeapAllocator { - private: - // How much to allocate from system at a time - static const size_t kAllocIncrement = 32 << 10; - - // Aligned size of T - static const size_t kAlignedSize - = (((sizeof(T) + kAlignment - 1) / kAlignment) * kAlignment); - - // Free area from which to carve new objects - char* free_area_; - size_t free_avail_; - - // Linked list of all regions allocated by this allocator - void* allocated_regions_; - - // Free list of already carved objects - void* free_list_; - - // Number of allocated but unfreed objects - int inuse_; - - public: - void Init() { - ASSERT(kAlignedSize <= kAllocIncrement); - inuse_ = 0; - allocated_regions_ = 0; - free_area_ = NULL; - free_avail_ = 0; - free_list_ = NULL; - } - - T* New() { - // Consult free list - void* result; - if (free_list_ != NULL) { - result = free_list_; - free_list_ = *(reinterpret_cast<void**>(result)); - } else { - if (free_avail_ < kAlignedSize) { - // Need more room - char* new_allocation = reinterpret_cast<char*>(MetaDataAlloc(kAllocIncrement)); - if (!new_allocation) - CRASH(); - - *reinterpret_cast_ptr<void**>(new_allocation) = allocated_regions_; - allocated_regions_ = new_allocation; - free_area_ = new_allocation + kAlignedSize; - free_avail_ = kAllocIncrement - kAlignedSize; - } - result = free_area_; - free_area_ += kAlignedSize; - free_avail_ -= kAlignedSize; - } - inuse_++; - return reinterpret_cast<T*>(result); - } - - void Delete(T* p) { - *(reinterpret_cast<void**>(p)) = free_list_; - free_list_ = p; - inuse_--; - } - - int inuse() const { return inuse_; } - -#if defined(WTF_CHANGES) && OS(DARWIN) - template <class Recorder> - void recordAdministrativeRegions(Recorder& recorder, const RemoteMemoryReader& reader) - { - for (void* adminAllocation = allocated_regions_; adminAllocation; adminAllocation = reader.nextEntryInLinkedList(reinterpret_cast<void**>(adminAllocation))) - recorder.recordRegion(reinterpret_cast<vm_address_t>(adminAllocation), kAllocIncrement); - } -#endif -}; - -// ------------------------------------------------------------------------- -// Span - a contiguous run of pages -// ------------------------------------------------------------------------- - -// Type that can hold a page number -typedef uintptr_t PageID; - -// Type that can hold the length of a run of pages -typedef uintptr_t Length; - -static const Length kMaxValidPages = (~static_cast<Length>(0)) >> kPageShift; - -// Convert byte size into pages. This won't overflow, but may return -// an unreasonably large value if bytes is huge enough. -static inline Length pages(size_t bytes) { - return (bytes >> kPageShift) + - ((bytes & (kPageSize - 1)) > 0 ? 1 : 0); -} - -// Convert a user size into the number of bytes that will actually be -// allocated -static size_t AllocationSize(size_t bytes) { - if (bytes > kMaxSize) { - // Large object: we allocate an integral number of pages - ASSERT(bytes <= (kMaxValidPages << kPageShift)); - return pages(bytes) << kPageShift; - } else { - // Small object: find the size class to which it belongs - return ByteSizeForClass(SizeClass(bytes)); - } -} - -// Information kept for a span (a contiguous run of pages). -struct Span { - PageID start; // Starting page number - Length length; // Number of pages in span - Span* next; // Used when in link list - Span* prev; // Used when in link list - void* objects; // Linked list of free objects - unsigned int free : 1; // Is the span free -#ifndef NO_TCMALLOC_SAMPLES - unsigned int sample : 1; // Sampled object? -#endif - unsigned int sizeclass : 8; // Size-class for small objects (or 0) - unsigned int refcount : 11; // Number of non-free objects - bool decommitted : 1; - -#undef SPAN_HISTORY -#ifdef SPAN_HISTORY - // For debugging, we can keep a log events per span - int nexthistory; - char history[64]; - int value[64]; -#endif -}; - -#define ASSERT_SPAN_COMMITTED(span) ASSERT(!span->decommitted) - -#ifdef SPAN_HISTORY -void Event(Span* span, char op, int v = 0) { - span->history[span->nexthistory] = op; - span->value[span->nexthistory] = v; - span->nexthistory++; - if (span->nexthistory == sizeof(span->history)) span->nexthistory = 0; -} -#else -#define Event(s,o,v) ((void) 0) -#endif - -// Allocator/deallocator for spans -static PageHeapAllocator<Span> span_allocator; -static Span* NewSpan(PageID p, Length len) { - Span* result = span_allocator.New(); - memset(result, 0, sizeof(*result)); - result->start = p; - result->length = len; -#ifdef SPAN_HISTORY - result->nexthistory = 0; -#endif - return result; -} - -static inline void DeleteSpan(Span* span) { -#ifndef NDEBUG - // In debug mode, trash the contents of deleted Spans - memset(span, 0x3f, sizeof(*span)); -#endif - span_allocator.Delete(span); -} - -// ------------------------------------------------------------------------- -// Doubly linked list of spans. -// ------------------------------------------------------------------------- - -static inline void DLL_Init(Span* list) { - list->next = list; - list->prev = list; -} - -static inline void DLL_Remove(Span* span) { - span->prev->next = span->next; - span->next->prev = span->prev; - span->prev = NULL; - span->next = NULL; -} - -static ALWAYS_INLINE bool DLL_IsEmpty(const Span* list) { - return list->next == list; -} - -static int DLL_Length(const Span* list) { - int result = 0; - for (Span* s = list->next; s != list; s = s->next) { - result++; - } - return result; -} - -#if 0 /* Not needed at the moment -- causes compiler warnings if not used */ -static void DLL_Print(const char* label, const Span* list) { - MESSAGE("%-10s %p:", label, list); - for (const Span* s = list->next; s != list; s = s->next) { - MESSAGE(" <%p,%u,%u>", s, s->start, s->length); - } - MESSAGE("\n"); -} -#endif - -static inline void DLL_Prepend(Span* list, Span* span) { - ASSERT(span->next == NULL); - ASSERT(span->prev == NULL); - span->next = list->next; - span->prev = list; - list->next->prev = span; - list->next = span; -} - -// ------------------------------------------------------------------------- -// Stack traces kept for sampled allocations -// The following state is protected by pageheap_lock_. -// ------------------------------------------------------------------------- - -// size/depth are made the same size as a pointer so that some generic -// code below can conveniently cast them back and forth to void*. -static const int kMaxStackDepth = 31; -struct StackTrace { - uintptr_t size; // Size of object - uintptr_t depth; // Number of PC values stored in array below - void* stack[kMaxStackDepth]; -}; -static PageHeapAllocator<StackTrace> stacktrace_allocator; -static Span sampled_objects; - -// ------------------------------------------------------------------------- -// Map from page-id to per-page data -// ------------------------------------------------------------------------- - -// We use PageMap2<> for 32-bit and PageMap3<> for 64-bit machines. -// We also use a simple one-level cache for hot PageID-to-sizeclass mappings, -// because sometimes the sizeclass is all the information we need. - -// Selector class -- general selector uses 3-level map -template <int BITS> class MapSelector { - public: - typedef TCMalloc_PageMap3<BITS-kPageShift> Type; - typedef PackedCache<BITS, uint64_t> CacheType; -}; - -#if defined(WTF_CHANGES) -#if CPU(X86_64) -// On all known X86-64 platforms, the upper 16 bits are always unused and therefore -// can be excluded from the PageMap key. -// See http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details - -static const size_t kBitsUnusedOn64Bit = 16; -#else -static const size_t kBitsUnusedOn64Bit = 0; -#endif - -// A three-level map for 64-bit machines -template <> class MapSelector<64> { - public: - typedef TCMalloc_PageMap3<64 - kPageShift - kBitsUnusedOn64Bit> Type; - typedef PackedCache<64, uint64_t> CacheType; -}; -#endif - -// A two-level map for 32-bit machines -template <> class MapSelector<32> { - public: - typedef TCMalloc_PageMap2<32 - kPageShift> Type; - typedef PackedCache<32 - kPageShift, uint16_t> CacheType; -}; - -// ------------------------------------------------------------------------- -// Page-level allocator -// * Eager coalescing -// -// Heap for page-level allocation. We allow allocating and freeing a -// contiguous runs of pages (called a "span"). -// ------------------------------------------------------------------------- - -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY -// 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 span lists to keep spans in when memory is returned. -static const int kMinSpanListsWithSpans = 32; - -// Number of free committed pages that we want to keep around. The minimum number of pages used when there -// is 1 span in each of the first kMinSpanListsWithSpans spanlists. Currently 528 pages. -static const size_t kMinimumFreeCommittedPageCount = kMinSpanListsWithSpans * ((1.0f+kMinSpanListsWithSpans) / 2.0f); - -#endif - -static SpinLock pageheap_lock = SPINLOCK_INITIALIZER; - -class TCMalloc_PageHeap { - public: - void init(); - - // Allocate a run of "n" pages. Returns zero if out of memory. - Span* New(Length n); - - // Delete the span "[p, p+n-1]". - // REQUIRES: span was returned by earlier call to New() and - // has not yet been deleted. - void Delete(Span* span); - - // Mark an allocated span as being used for small objects of the - // specified size-class. - // REQUIRES: span was returned by an earlier call to New() - // and has not yet been deleted. - void RegisterSizeClass(Span* span, size_t sc); - - // Split an allocated span into two spans: one of length "n" pages - // followed by another span of length "span->length - n" pages. - // Modifies "*span" to point to the first span of length "n" pages. - // Returns a pointer to the second span. - // - // REQUIRES: "0 < n < span->length" - // REQUIRES: !span->free - // REQUIRES: span->sizeclass == 0 - Span* Split(Span* span, Length n); - - // Return the descriptor for the specified page. - inline Span* GetDescriptor(PageID p) const { - return reinterpret_cast<Span*>(pagemap_.get(p)); - } - -#ifdef WTF_CHANGES - inline Span* GetDescriptorEnsureSafe(PageID p) - { - pagemap_.Ensure(p, 1); - return GetDescriptor(p); - } - - size_t ReturnedBytes() const; -#endif - - // Dump state to stderr -#ifndef WTF_CHANGES - void Dump(TCMalloc_Printer* out); -#endif - - // Return number of bytes allocated from system - inline uint64_t SystemBytes() const { return system_bytes_; } - - // Return number of free bytes in heap - uint64_t FreeBytes() const { - return (static_cast<uint64_t>(free_pages_) << kPageShift); - } - - bool Check(); - size_t CheckList(Span* list, Length min_pages, Length max_pages, bool decommitted); - - // Release all pages on the free list for reuse by the OS: - void ReleaseFreePages(); - void ReleaseFreeList(Span*, Span*); - - // Return 0 if we have no information, or else the correct sizeclass for p. - // Reads and writes to pagemap_cache_ do not require locking. - // The entries are 64 bits on 64-bit hardware and 16 bits on - // 32-bit hardware, and we don't mind raciness as long as each read of - // an entry yields a valid entry, not a partially updated entry. - size_t GetSizeClassIfCached(PageID p) const { - return pagemap_cache_.GetOrDefault(p, 0); - } - void CacheSizeClass(PageID p, size_t cl) const { pagemap_cache_.Put(p, cl); } - - private: - // Pick the appropriate map and cache types based on pointer size - typedef MapSelector<8*sizeof(uintptr_t)>::Type PageMap; - typedef MapSelector<8*sizeof(uintptr_t)>::CacheType PageMapCache; - PageMap pagemap_; - mutable PageMapCache pagemap_cache_; - - // We segregate spans of a given size into two circular linked - // lists: one for normal spans, and one for spans whose memory - // has been returned to the system. - struct SpanList { - Span normal; - Span returned; - }; - - // List of free spans of length >= kMaxPages - SpanList large_; - - // Array mapping from span length to a doubly linked list of free spans - SpanList free_[kMaxPages]; - - // Number of pages kept in free lists - uintptr_t free_pages_; - - // Bytes allocated from system - uint64_t system_bytes_; - -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - // Number of pages kept in free lists that are still committed. - Length free_committed_pages_; - - // 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); - - // REQUIRES span->length >= n - // Remove span from its free list, and move any leftover part of - // span into appropriate free lists. Also update "span" to have - // length exactly "n" and mark it as non-free so it can be returned - // to the client. - // - // "released" is true iff "span" was found on a "returned" list. - void Carve(Span* span, Length n, bool released); - - void RecordSpan(Span* span) { - pagemap_.set(span->start, span); - if (span->length > 1) { - pagemap_.set(span->start + span->length - 1, span); - } - } - - // Allocate a large span of length == n. If successful, returns a - // span of exactly the specified length. Else, returns NULL. - Span* AllocLarge(Length n); - -#if !USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - // Incrementally release some memory to the system. - // IncrementalScavenge(n) is called whenever n pages are freed. - void IncrementalScavenge(Length n); -#endif - - // Number of pages to deallocate before doing more scavenging - int64_t scavenge_counter_; - - // Index of last free list we scavenged - size_t scavenge_index_; - -#if defined(WTF_CHANGES) && OS(DARWIN) - friend class FastMallocZone; -#endif - -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - void initializeScavenger(); - ALWAYS_INLINE void signalScavenger(); - void scavenge(); - ALWAYS_INLINE bool shouldScavenge() const; - -#if HAVE(DISPATCH_H) || OS(WINDOWS) - void periodicScavenge(); - ALWAYS_INLINE bool isScavengerSuspended(); - ALWAYS_INLINE void scheduleScavenger(); - ALWAYS_INLINE void rescheduleScavenger(); - ALWAYS_INLINE void suspendScavenger(); -#endif - -#if HAVE(DISPATCH_H) - dispatch_queue_t m_scavengeQueue; - dispatch_source_t m_scavengeTimer; - bool m_scavengingSuspended; -#elif OS(WINDOWS) - static void CALLBACK scavengerTimerFired(void*, BOOLEAN); - HANDLE m_scavengeQueueTimer; -#else - static NO_RETURN_WITH_VALUE void* runScavengerThread(void*); - NO_RETURN void scavengerThread(); - - // 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; - - pthread_mutex_t m_scavengeMutex; - pthread_cond_t m_scavengeCondition; -#endif - -#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY -}; - -void TCMalloc_PageHeap::init() -{ - pagemap_.init(MetaDataAlloc); - pagemap_cache_ = PageMapCache(0); - free_pages_ = 0; - system_bytes_ = 0; - -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - free_committed_pages_ = 0; - min_free_committed_pages_since_last_scavenge_ = 0; -#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - - scavenge_counter_ = 0; - // Start scavenging at kMaxPages list - scavenge_index_ = kMaxPages-1; - COMPILE_ASSERT(kNumClasses <= (1 << PageMapCache::kValuebits), valuebits); - DLL_Init(&large_.normal); - DLL_Init(&large_.returned); - for (size_t i = 0; i < kMaxPages; i++) { - DLL_Init(&free_[i].normal); - DLL_Init(&free_[i].returned); - } - -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - initializeScavenger(); -#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY -} - -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - -#if HAVE(DISPATCH_H) - -void TCMalloc_PageHeap::initializeScavenger() -{ - 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, 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_scavengingSuspended = true; -} - -ALWAYS_INLINE bool TCMalloc_PageHeap::isScavengerSuspended() -{ - ASSERT(pageheap_lock.IsHeld()); - return m_scavengingSuspended; -} - -ALWAYS_INLINE void TCMalloc_PageHeap::scheduleScavenger() -{ - ASSERT(pageheap_lock.IsHeld()); - m_scavengingSuspended = false; - dispatch_resume(m_scavengeTimer); -} - -ALWAYS_INLINE void TCMalloc_PageHeap::rescheduleScavenger() -{ - // Nothing to do here for libdispatch. -} - -ALWAYS_INLINE void TCMalloc_PageHeap::suspendScavenger() -{ - ASSERT(pageheap_lock.IsHeld()); - m_scavengingSuspended = true; - dispatch_suspend(m_scavengeTimer); -} - -#elif OS(WINDOWS) - -void TCMalloc_PageHeap::scavengerTimerFired(void* context, BOOLEAN) -{ - static_cast<TCMalloc_PageHeap*>(context)->periodicScavenge(); -} - -void TCMalloc_PageHeap::initializeScavenger() -{ - m_scavengeQueueTimer = 0; -} - -ALWAYS_INLINE bool TCMalloc_PageHeap::isScavengerSuspended() -{ - ASSERT(IsHeld(pageheap_lock)); - return !m_scavengeQueueTimer; -} - -ALWAYS_INLINE void TCMalloc_PageHeap::scheduleScavenger() -{ - // We need to use WT_EXECUTEONLYONCE here and reschedule the timer, because - // Windows will fire the timer event even when the function is already running. - ASSERT(IsHeld(pageheap_lock)); - CreateTimerQueueTimer(&m_scavengeQueueTimer, 0, scavengerTimerFired, this, kScavengeDelayInSeconds * 1000, 0, WT_EXECUTEONLYONCE); -} - -ALWAYS_INLINE void TCMalloc_PageHeap::rescheduleScavenger() -{ - // We must delete the timer and create it again, because it is not possible to retrigger a timer on Windows. - suspendScavenger(); - scheduleScavenger(); -} - -ALWAYS_INLINE void TCMalloc_PageHeap::suspendScavenger() -{ - ASSERT(IsHeld(pageheap_lock)); - HANDLE scavengeQueueTimer = m_scavengeQueueTimer; - m_scavengeQueueTimer = 0; - DeleteTimerQueueTimer(0, scavengeQueueTimer, 0); -} - -#else - -void TCMalloc_PageHeap::initializeScavenger() -{ - // Create a non-recursive mutex. -#if !defined(PTHREAD_MUTEX_NORMAL) || PTHREAD_MUTEX_NORMAL == PTHREAD_MUTEX_DEFAULT - pthread_mutex_init(&m_scavengeMutex, 0); -#else - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); - - pthread_mutex_init(&m_scavengeMutex, &attr); - - pthread_mutexattr_destroy(&attr); -#endif - - pthread_cond_init(&m_scavengeCondition, 0); - m_scavengeThreadActive = true; - pthread_t thread; - pthread_create(&thread, 0, runScavengerThread, this); -} - -void* TCMalloc_PageHeap::runScavengerThread(void* context) -{ - static_cast<TCMalloc_PageHeap*>(context)->scavengerThread(); -#if (COMPILER(MSVC) || COMPILER(SUNCC)) - // Without this, Visual Studio and Sun Studio will complain that this method does not return a value. - return 0; -#endif -} - -ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger() -{ - // m_scavengeMutex should be held before accessing m_scavengeThreadActive. - ASSERT(pthread_mutex_trylock(m_scavengeMutex)); - if (!m_scavengeThreadActive && shouldScavenge()) - pthread_cond_signal(&m_scavengeCondition); -} - -#endif - -void TCMalloc_PageHeap::scavenge() -{ - size_t pagesToRelease = min_free_committed_pages_since_last_scavenge_ * kScavengePercentage; - size_t targetPageCount = std::max<size_t>(kMinimumFreeCommittedPageCount, free_committed_pages_ - pagesToRelease); - - Length lastFreeCommittedPages = free_committed_pages_; - while (free_committed_pages_ > targetPageCount) { - ASSERT(Check()); - for (int i = kMaxPages; i > 0 && free_committed_pages_ >= targetPageCount; i--) { - SpanList* slist = (static_cast<size_t>(i) == kMaxPages) ? &large_ : &free_[i]; - // If the span size is bigger than kMinSpanListsWithSpans pages return all the spans in the list, else return all but 1 span. - // Return only 50% of a spanlist at a time so spans of size 1 are not the only ones left. - size_t length = DLL_Length(&slist->normal); - size_t numSpansToReturn = (i > kMinSpanListsWithSpans) ? length : length / 2; - for (int j = 0; static_cast<size_t>(j) < numSpansToReturn && !DLL_IsEmpty(&slist->normal) && free_committed_pages_ > targetPageCount; j++) { - Span* s = slist->normal.prev; - DLL_Remove(s); - ASSERT(!s->decommitted); - if (!s->decommitted) { - TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), - static_cast<size_t>(s->length << kPageShift)); - ASSERT(free_committed_pages_ >= s->length); - free_committed_pages_ -= s->length; - s->decommitted = true; - } - DLL_Prepend(&slist->returned, s); - } - } - - if (lastFreeCommittedPages == free_committed_pages_) - break; - lastFreeCommittedPages = free_committed_pages_; - } - - min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; -} - -ALWAYS_INLINE bool TCMalloc_PageHeap::shouldScavenge() const -{ - return free_committed_pages_ > kMinimumFreeCommittedPageCount; -} - -#endif // USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - -inline Span* TCMalloc_PageHeap::New(Length n) { - ASSERT(Check()); - ASSERT(n > 0); - - // Find first size >= n that has a non-empty list - for (Length s = n; s < kMaxPages; s++) { - Span* ll = NULL; - bool released = false; - if (!DLL_IsEmpty(&free_[s].normal)) { - // Found normal span - ll = &free_[s].normal; - } else if (!DLL_IsEmpty(&free_[s].returned)) { - // Found returned span; reallocate it - ll = &free_[s].returned; - released = true; - } else { - // Keep looking in larger classes - continue; - } - - Span* result = ll->next; - Carve(result, n, released); -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - // The newly allocated memory is from a span that's in the normal span list (already committed). Update the - // 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()); - free_pages_ -= n; - return result; - } - - Span* result = AllocLarge(n); - if (result != NULL) { - ASSERT_SPAN_COMMITTED(result); - return result; - } - - // Grow the heap and try again - if (!GrowHeap(n)) { - ASSERT(Check()); - return NULL; - } - - return AllocLarge(n); -} - -Span* TCMalloc_PageHeap::AllocLarge(Length n) { - // find the best span (closest to n in size). - // The following loops implements address-ordered best-fit. - bool from_released = false; - Span *best = NULL; - - // Search through normal list - for (Span* span = large_.normal.next; - span != &large_.normal; - span = span->next) { - if (span->length >= n) { - if ((best == NULL) - || (span->length < best->length) - || ((span->length == best->length) && (span->start < best->start))) { - best = span; - from_released = false; - } - } - } - - // Search through released list in case it has a better fit - for (Span* span = large_.returned.next; - span != &large_.returned; - span = span->next) { - if (span->length >= n) { - if ((best == NULL) - || (span->length < best->length) - || ((span->length == best->length) && (span->start < best->start))) { - best = span; - from_released = true; - } - } - } - - if (best != NULL) { - Carve(best, n, from_released); -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - // The newly allocated memory is from a span that's in the normal span list (already committed). Update the - // 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()); - free_pages_ -= n; - return best; - } - return NULL; -} - -Span* TCMalloc_PageHeap::Split(Span* span, Length n) { - ASSERT(0 < n); - ASSERT(n < span->length); - ASSERT(!span->free); - ASSERT(span->sizeclass == 0); - Event(span, 'T', n); - - const Length extra = span->length - n; - Span* leftover = NewSpan(span->start + n, extra); - Event(leftover, 'U', extra); - RecordSpan(leftover); - pagemap_.set(span->start + n - 1, span); // Update map from pageid to span - span->length = n; - - return leftover; -} - -inline void TCMalloc_PageHeap::Carve(Span* span, Length n, bool released) { - ASSERT(n > 0); - DLL_Remove(span); - span->free = 0; - Event(span, 'A', n); - - if (released) { - // If the span chosen to carve from is decommited, commit the entire span at once to avoid committing spans 1 page at a time. - ASSERT(span->decommitted); - TCMalloc_SystemCommit(reinterpret_cast<void*>(span->start << kPageShift), static_cast<size_t>(span->length << kPageShift)); - span->decommitted = false; -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - free_committed_pages_ += span->length; -#endif - } - - const int extra = static_cast<int>(span->length - n); - ASSERT(extra >= 0); - if (extra > 0) { - Span* leftover = NewSpan(span->start + n, extra); - leftover->free = 1; - leftover->decommitted = false; - Event(leftover, 'S', extra); - RecordSpan(leftover); - - // Place leftover span on appropriate free list - SpanList* listpair = (static_cast<size_t>(extra) < kMaxPages) ? &free_[extra] : &large_; - Span* dst = &listpair->normal; - DLL_Prepend(dst, leftover); - - span->length = n; - pagemap_.set(span->start + n - 1, span); - } -} - -static ALWAYS_INLINE void mergeDecommittedStates(Span* destination, Span* other) -{ - if (destination->decommitted && !other->decommitted) { - TCMalloc_SystemRelease(reinterpret_cast<void*>(other->start << kPageShift), - static_cast<size_t>(other->length << kPageShift)); - } else if (other->decommitted && !destination->decommitted) { - TCMalloc_SystemRelease(reinterpret_cast<void*>(destination->start << kPageShift), - static_cast<size_t>(destination->length << kPageShift)); - destination->decommitted = true; - } -} - -inline void TCMalloc_PageHeap::Delete(Span* span) { - ASSERT(Check()); - ASSERT(!span->free); - ASSERT(span->length > 0); - ASSERT(GetDescriptor(span->start) == span); - ASSERT(GetDescriptor(span->start + span->length - 1) == span); - span->sizeclass = 0; -#ifndef NO_TCMALLOC_SAMPLES - span->sample = 0; -#endif - - // Coalesce -- we guarantee that "p" != 0, so no bounds checking - // necessary. We do not bother resetting the stale pagemap - // entries for the pieces we are merging together because we only - // care about the pagemap entries for the boundaries. -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - // Track the total size of the neighboring free spans that are committed. - Length neighboringCommittedSpansLength = 0; -#endif - const PageID p = span->start; - const Length n = span->length; - Span* prev = GetDescriptor(p-1); - if (prev != NULL && prev->free) { - // Merge preceding span into this span - ASSERT(prev->start + prev->length == p); - const Length len = prev->length; -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - if (!prev->decommitted) - neighboringCommittedSpansLength += len; -#endif - mergeDecommittedStates(span, prev); - DLL_Remove(prev); - DeleteSpan(prev); - span->start -= len; - span->length += len; - pagemap_.set(span->start, span); - Event(span, 'L', len); - } - Span* next = GetDescriptor(p+n); - if (next != NULL && next->free) { - // Merge next span into this span - ASSERT(next->start == p+n); - const Length len = next->length; -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - if (!next->decommitted) - neighboringCommittedSpansLength += len; -#endif - mergeDecommittedStates(span, next); - DLL_Remove(next); - DeleteSpan(next); - span->length += len; - pagemap_.set(span->start + span->length - 1, span); - Event(span, 'R', len); - } - - Event(span, 'D', span->length); - span->free = 1; - if (span->decommitted) { - if (span->length < kMaxPages) - DLL_Prepend(&free_[span->length].returned, span); - else - DLL_Prepend(&large_.returned, span); - } else { - if (span->length < kMaxPages) - DLL_Prepend(&free_[span->length].normal, span); - else - DLL_Prepend(&large_.normal, span); - } - free_pages_ += n; - -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - if (span->decommitted) { - // 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; - } - - // Make sure the scavenge thread becomes active if we have enough freed pages to release some back to the system. - signalScavenger(); -#else - IncrementalScavenge(n); -#endif - - ASSERT(Check()); -} - -#if !USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY -void TCMalloc_PageHeap::IncrementalScavenge(Length n) { - // Fast path; not yet time to release memory - scavenge_counter_ -= n; - if (scavenge_counter_ >= 0) return; // Not yet time to scavenge - -#if PLATFORM(IOS) - static const size_t kDefaultReleaseDelay = 64; -#else - // If there is nothing to release, wait for so many pages before - // scavenging again. With 4K pages, this comes to 16MB of memory. - static const size_t kDefaultReleaseDelay = 1 << 8; -#endif - - // Find index of free list to scavenge - size_t index = scavenge_index_ + 1; - for (size_t i = 0; i < kMaxPages+1; i++) { - if (index > kMaxPages) index = 0; - SpanList* slist = (index == kMaxPages) ? &large_ : &free_[index]; - if (!DLL_IsEmpty(&slist->normal)) { - // Release the last span on the normal portion of this list - Span* s = slist->normal.prev; - DLL_Remove(s); - TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), - static_cast<size_t>(s->length << kPageShift)); - s->decommitted = true; - DLL_Prepend(&slist->returned, s); - -#if PLATFORM(IOS) - scavenge_counter_ = std::max<size_t>(16UL, std::min<size_t>(kDefaultReleaseDelay, kDefaultReleaseDelay - (free_pages_ / kDefaultReleaseDelay))); -#else - scavenge_counter_ = std::max<size_t>(64UL, std::min<size_t>(kDefaultReleaseDelay, kDefaultReleaseDelay - (free_pages_ / kDefaultReleaseDelay))); -#endif - - if (index == kMaxPages && !DLL_IsEmpty(&slist->normal)) - scavenge_index_ = index - 1; - else - scavenge_index_ = index; - return; - } - index++; - } - - // Nothing to scavenge, delay for a while - scavenge_counter_ = kDefaultReleaseDelay; -} -#endif - -void TCMalloc_PageHeap::RegisterSizeClass(Span* span, size_t sc) { - // Associate span object with all interior pages as well - ASSERT(!span->free); - ASSERT(GetDescriptor(span->start) == span); - ASSERT(GetDescriptor(span->start+span->length-1) == span); - Event(span, 'C', sc); - span->sizeclass = static_cast<unsigned int>(sc); - for (Length i = 1; i < span->length-1; i++) { - pagemap_.set(span->start+i, span); - } -} - -#ifdef WTF_CHANGES -size_t TCMalloc_PageHeap::ReturnedBytes() const { - size_t result = 0; - for (unsigned s = 0; s < kMaxPages; s++) { - const int r_length = DLL_Length(&free_[s].returned); - unsigned r_pages = s * r_length; - result += r_pages << kPageShift; - } - - for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) - result += s->length << kPageShift; - return result; -} -#endif - -#ifndef WTF_CHANGES -static double PagesToMB(uint64_t pages) { - return (pages << kPageShift) / 1048576.0; -} - -void TCMalloc_PageHeap::Dump(TCMalloc_Printer* out) { - int nonempty_sizes = 0; - for (int s = 0; s < kMaxPages; s++) { - if (!DLL_IsEmpty(&free_[s].normal) || !DLL_IsEmpty(&free_[s].returned)) { - nonempty_sizes++; - } - } - out->printf("------------------------------------------------\n"); - out->printf("PageHeap: %d sizes; %6.1f MB free\n", - nonempty_sizes, PagesToMB(free_pages_)); - out->printf("------------------------------------------------\n"); - uint64_t total_normal = 0; - uint64_t total_returned = 0; - for (int s = 0; s < kMaxPages; s++) { - const int n_length = DLL_Length(&free_[s].normal); - const int r_length = DLL_Length(&free_[s].returned); - if (n_length + r_length > 0) { - uint64_t n_pages = s * n_length; - uint64_t r_pages = s * r_length; - total_normal += n_pages; - total_returned += r_pages; - out->printf("%6u pages * %6u spans ~ %6.1f MB; %6.1f MB cum" - "; unmapped: %6.1f MB; %6.1f MB cum\n", - s, - (n_length + r_length), - PagesToMB(n_pages + r_pages), - PagesToMB(total_normal + total_returned), - PagesToMB(r_pages), - PagesToMB(total_returned)); - } - } - - uint64_t n_pages = 0; - uint64_t r_pages = 0; - int n_spans = 0; - int r_spans = 0; - out->printf("Normal large spans:\n"); - for (Span* s = large_.normal.next; s != &large_.normal; s = s->next) { - out->printf(" [ %6" PRIuS " pages ] %6.1f MB\n", - s->length, PagesToMB(s->length)); - n_pages += s->length; - n_spans++; - } - out->printf("Unmapped large spans:\n"); - for (Span* s = large_.returned.next; s != &large_.returned; s = s->next) { - out->printf(" [ %6" PRIuS " pages ] %6.1f MB\n", - s->length, PagesToMB(s->length)); - r_pages += s->length; - r_spans++; - } - total_normal += n_pages; - total_returned += r_pages; - out->printf(">255 large * %6u spans ~ %6.1f MB; %6.1f MB cum" - "; unmapped: %6.1f MB; %6.1f MB cum\n", - (n_spans + r_spans), - PagesToMB(n_pages + r_pages), - PagesToMB(total_normal + total_returned), - PagesToMB(r_pages), - PagesToMB(total_returned)); -} -#endif - -bool TCMalloc_PageHeap::GrowHeap(Length n) { - ASSERT(kMaxPages >= kMinSystemAlloc); - if (n > kMaxValidPages) return false; - Length ask = (n>kMinSystemAlloc) ? n : static_cast<Length>(kMinSystemAlloc); - size_t actual_size; - void* ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize); - if (ptr == NULL) { - if (n < ask) { - // Try growing just "n" pages - ask = n; - ptr = TCMalloc_SystemAlloc(ask << kPageShift, &actual_size, kPageSize); - } - if (ptr == NULL) return false; - } - ask = actual_size >> kPageShift; - - uint64_t old_system_bytes = system_bytes_; - system_bytes_ += (ask << kPageShift); - const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; - ASSERT(p > 0); - - // If we have already a lot of pages allocated, just pre allocate a bunch of - // memory for the page map. This prevents fragmentation by pagemap metadata - // when a program keeps allocating and freeing large blocks. - - if (old_system_bytes < kPageMapBigAllocationThreshold - && system_bytes_ >= kPageMapBigAllocationThreshold) { - pagemap_.PreallocateMoreMemory(); - } - - // Make sure pagemap_ has entries for all of the new pages. - // Plus ensure one before and one after so coalescing code - // does not need bounds-checking. - if (pagemap_.Ensure(p-1, ask+2)) { - // Pretend the new area is allocated and then Delete() it to - // cause any necessary coalescing to occur. - // - // We do not adjust free_pages_ here since Delete() will do it for us. - Span* span = NewSpan(p, ask); - RecordSpan(span); - Delete(span); - ASSERT(Check()); - return true; - } else { - // We could not allocate memory within "pagemap_" - // TODO: Once we can return memory to the system, return the new span - return false; - } -} - -bool TCMalloc_PageHeap::Check() { -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - size_t totalFreeCommitted = 0; -#endif - ASSERT(free_[0].normal.next == &free_[0].normal); - ASSERT(free_[0].returned.next == &free_[0].returned); -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - totalFreeCommitted = CheckList(&large_.normal, kMaxPages, 1000000000, false); -#else - CheckList(&large_.normal, kMaxPages, 1000000000, false); -#endif - CheckList(&large_.returned, kMaxPages, 1000000000, true); - for (Length s = 1; s < kMaxPages; s++) { -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - totalFreeCommitted += CheckList(&free_[s].normal, s, s, false); -#else - CheckList(&free_[s].normal, s, s, false); -#endif - CheckList(&free_[s].returned, s, s, true); - } -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - ASSERT(totalFreeCommitted == free_committed_pages_); -#endif - return true; -} - -#if ASSERT_DISABLED -size_t TCMalloc_PageHeap::CheckList(Span*, Length, Length, bool) { - return 0; -} -#else -size_t TCMalloc_PageHeap::CheckList(Span* list, Length min_pages, Length max_pages, bool decommitted) { - size_t freeCount = 0; - for (Span* s = list->next; s != list; s = s->next) { - CHECK_CONDITION(s->free); - CHECK_CONDITION(s->length >= min_pages); - CHECK_CONDITION(s->length <= max_pages); - CHECK_CONDITION(GetDescriptor(s->start) == s); - CHECK_CONDITION(GetDescriptor(s->start+s->length-1) == s); - CHECK_CONDITION(s->decommitted == decommitted); - freeCount += s->length; - } - return freeCount; -} -#endif - -void TCMalloc_PageHeap::ReleaseFreeList(Span* list, Span* returned) { - // Walk backwards through list so that when we push these - // spans on the "returned" list, we preserve the order. -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - size_t freePageReduction = 0; -#endif - - while (!DLL_IsEmpty(list)) { - Span* s = list->prev; - - DLL_Remove(s); - s->decommitted = true; - DLL_Prepend(returned, s); - TCMalloc_SystemRelease(reinterpret_cast<void*>(s->start << kPageShift), - static_cast<size_t>(s->length << kPageShift)); -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - freePageReduction += s->length; -#endif - } - -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - free_committed_pages_ -= freePageReduction; - if (free_committed_pages_ < min_free_committed_pages_since_last_scavenge_) - min_free_committed_pages_since_last_scavenge_ = free_committed_pages_; -#endif -} - -void TCMalloc_PageHeap::ReleaseFreePages() { - for (Length s = 0; s < kMaxPages; s++) { - ReleaseFreeList(&free_[s].normal, &free_[s].returned); - } - ReleaseFreeList(&large_.normal, &large_.returned); - ASSERT(Check()); -} - -//------------------------------------------------------------------- -// Free list -//------------------------------------------------------------------- - -class TCMalloc_ThreadCache_FreeList { - private: - void* list_; // Linked list of nodes - uint16_t length_; // Current length - uint16_t lowater_; // Low water mark for list length - - public: - void Init() { - list_ = NULL; - length_ = 0; - lowater_ = 0; - } - - // Return current length of list - int length() const { - return length_; - } - - // Is list empty? - bool empty() const { - return list_ == NULL; - } - - // Low-water mark management - int lowwatermark() const { return lowater_; } - void clear_lowwatermark() { lowater_ = length_; } - - ALWAYS_INLINE void Push(void* ptr) { - SLL_Push(&list_, ptr); - length_++; - } - - void PushRange(int N, void *start, void *end) { - SLL_PushRange(&list_, start, end); - length_ = length_ + static_cast<uint16_t>(N); - } - - void PopRange(int N, void **start, void **end) { - SLL_PopRange(&list_, N, start, end); - ASSERT(length_ >= N); - length_ = length_ - static_cast<uint16_t>(N); - if (length_ < lowater_) lowater_ = length_; - } - - ALWAYS_INLINE void* Pop() { - ASSERT(list_ != NULL); - length_--; - if (length_ < lowater_) lowater_ = length_; - return SLL_Pop(&list_); - } - -#ifdef WTF_CHANGES - template <class Finder, class Reader> - void enumerateFreeObjects(Finder& finder, const Reader& reader) - { - for (void* nextObject = list_; nextObject; nextObject = reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject))) - finder.visit(nextObject); - } -#endif -}; - -//------------------------------------------------------------------- -// Data kept per thread -//------------------------------------------------------------------- - -class TCMalloc_ThreadCache { - private: - typedef TCMalloc_ThreadCache_FreeList FreeList; -#if OS(WINDOWS) - typedef DWORD ThreadIdentifier; -#else - typedef pthread_t ThreadIdentifier; -#endif - - size_t size_; // Combined size of data - ThreadIdentifier tid_; // Which thread owns it - bool in_setspecific_; // Called pthread_setspecific? - FreeList list_[kNumClasses]; // Array indexed by size-class - - // We sample allocations, biased by the size of the allocation - uint32_t rnd_; // Cheap random number generator - size_t bytes_until_sample_; // Bytes until we sample next - - // Allocate a new heap. REQUIRES: pageheap_lock is held. - static inline TCMalloc_ThreadCache* NewHeap(ThreadIdentifier tid); - - // Use only as pthread thread-specific destructor function. - static void DestroyThreadCache(void* ptr); - public: - // All ThreadCache objects are kept in a linked list (for stats collection) - TCMalloc_ThreadCache* next_; - TCMalloc_ThreadCache* prev_; - - void Init(ThreadIdentifier tid); - void Cleanup(); - - // Accessors (mostly just for printing stats) - int freelist_length(size_t cl) const { return list_[cl].length(); } - - // Total byte size in cache - size_t Size() const { return size_; } - - ALWAYS_INLINE void* Allocate(size_t size); - void Deallocate(void* ptr, size_t size_class); - - ALWAYS_INLINE void FetchFromCentralCache(size_t cl, size_t allocationSize); - void ReleaseToCentralCache(size_t cl, int N); - void Scavenge(); - void Print() const; - - // Record allocation of "k" bytes. Return true iff allocation - // should be sampled - bool SampleAllocation(size_t k); - - // Pick next sampling point - void PickNextSample(size_t k); - - static void InitModule(); - static void InitTSD(); - static TCMalloc_ThreadCache* GetThreadHeap(); - static TCMalloc_ThreadCache* GetCache(); - static TCMalloc_ThreadCache* GetCacheIfPresent(); - static TCMalloc_ThreadCache* CreateCacheIfNecessary(); - static void DeleteCache(TCMalloc_ThreadCache* heap); - static void BecomeIdle(); - static void RecomputeThreadCacheSize(); - -#ifdef WTF_CHANGES - template <class Finder, class Reader> - void enumerateFreeObjects(Finder& finder, const Reader& reader) - { - for (unsigned sizeClass = 0; sizeClass < kNumClasses; sizeClass++) - list_[sizeClass].enumerateFreeObjects(finder, reader); - } -#endif -}; - -//------------------------------------------------------------------- -// Data kept per size-class in central cache -//------------------------------------------------------------------- - -class TCMalloc_Central_FreeList { - public: - void Init(size_t cl); - - // These methods all do internal locking. - - // Insert the specified range into the central freelist. N is the number of - // elements in the range. - void InsertRange(void *start, void *end, int N); - - // Returns the actual number of fetched elements into N. - void RemoveRange(void **start, void **end, int *N); - - // Returns the number of free objects in cache. - size_t length() { - SpinLockHolder h(&lock_); - return counter_; - } - - // Returns the number of free objects in the transfer cache. - int tc_length() { - SpinLockHolder h(&lock_); - return used_slots_ * num_objects_to_move[size_class_]; - } - -#ifdef WTF_CHANGES - template <class Finder, class Reader> - void enumerateFreeObjects(Finder& finder, const Reader& reader, TCMalloc_Central_FreeList* remoteCentralFreeList) - { - for (Span* span = &empty_; span && span != &empty_; span = (span->next ? reader(span->next) : 0)) - ASSERT(!span->objects); - - ASSERT(!nonempty_.objects); - static const ptrdiff_t nonemptyOffset = reinterpret_cast<const char*>(&nonempty_) - reinterpret_cast<const char*>(this); - - Span* remoteNonempty = reinterpret_cast<Span*>(reinterpret_cast<char*>(remoteCentralFreeList) + nonemptyOffset); - Span* remoteSpan = nonempty_.next; - - for (Span* span = reader(remoteSpan); span && remoteSpan != remoteNonempty; remoteSpan = span->next, span = (span->next ? reader(span->next) : 0)) { - for (void* nextObject = span->objects; nextObject; nextObject = reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject))) - finder.visit(nextObject); - } - } -#endif - - private: - // REQUIRES: lock_ is held - // Remove object from cache and return. - // Return NULL if no free entries in cache. - void* FetchFromSpans(); - - // REQUIRES: lock_ is held - // Remove object from cache and return. Fetches - // from pageheap if cache is empty. Only returns - // NULL on allocation failure. - void* FetchFromSpansSafe(); - - // REQUIRES: lock_ is held - // Release a linked list of objects to spans. - // May temporarily release lock_. - void ReleaseListToSpans(void *start); - - // REQUIRES: lock_ is held - // Release an object to spans. - // May temporarily release lock_. - ALWAYS_INLINE void ReleaseToSpans(void* object); - - // REQUIRES: lock_ is held - // Populate cache by fetching from the page heap. - // May temporarily release lock_. - ALWAYS_INLINE void Populate(); - - // REQUIRES: lock is held. - // Tries to make room for a TCEntry. If the cache is full it will try to - // expand it at the cost of some other cache size. Return false if there is - // no space. - bool MakeCacheSpace(); - - // REQUIRES: lock_ for locked_size_class is held. - // Picks a "random" size class to steal TCEntry slot from. In reality it - // just iterates over the sizeclasses but does so without taking a lock. - // Returns true on success. - // May temporarily lock a "random" size class. - static ALWAYS_INLINE bool EvictRandomSizeClass(size_t locked_size_class, bool force); - - // REQUIRES: lock_ is *not* held. - // Tries to shrink the Cache. If force is true it will relase objects to - // spans if it allows it to shrink the cache. Return false if it failed to - // shrink the cache. Decrements cache_size_ on succeess. - // May temporarily take lock_. If it takes lock_, the locked_size_class - // lock is released to the thread from holding two size class locks - // concurrently which could lead to a deadlock. - bool ShrinkCache(int locked_size_class, bool force); - - // This lock protects all the data members. cached_entries and cache_size_ - // may be looked at without holding the lock. - SpinLock lock_; - - // We keep linked lists of empty and non-empty spans. - size_t size_class_; // My size class - Span empty_; // Dummy header for list of empty spans - Span nonempty_; // Dummy header for list of non-empty spans - size_t counter_; // Number of free objects in cache entry - - // Here we reserve space for TCEntry cache slots. Since one size class can - // end up getting all the TCEntries quota in the system we just preallocate - // sufficient number of entries here. - TCEntry tc_slots_[kNumTransferEntries]; - - // Number of currently used cached entries in tc_slots_. This variable is - // updated under a lock but can be read without one. - int32_t used_slots_; - // The current number of slots for this size class. This is an - // adaptive value that is increased if there is lots of traffic - // on a given size class. - int32_t cache_size_; -}; - -// Pad each CentralCache object to multiple of 64 bytes -class TCMalloc_Central_FreeListPadded : public TCMalloc_Central_FreeList { - private: - char pad_[(64 - (sizeof(TCMalloc_Central_FreeList) % 64)) % 64]; -}; - -//------------------------------------------------------------------- -// Global variables -//------------------------------------------------------------------- - -// Central cache -- a collection of free-lists, one per size-class. -// We have a separate lock per free-list to reduce contention. -static TCMalloc_Central_FreeListPadded central_cache[kNumClasses]; - -// Page-level allocator -static AllocAlignmentInteger pageheap_memory[(sizeof(TCMalloc_PageHeap) + sizeof(AllocAlignmentInteger) - 1) / sizeof(AllocAlignmentInteger)]; -static bool phinited = false; - -// Avoid extra level of indirection by making "pageheap" be just an alias -// of pageheap_memory. -typedef union { - void* m_memory; - TCMalloc_PageHeap* m_pageHeap; -} PageHeapUnion; - -static inline TCMalloc_PageHeap* getPageHeap() -{ - PageHeapUnion u = { &pageheap_memory[0] }; - return u.m_pageHeap; -} - -#define pageheap getPageHeap() - -#if USE_BACKGROUND_THREAD_TO_SCAVENGE_MEMORY - -#if HAVE(DISPATCH_H) || OS(WINDOWS) - -void TCMalloc_PageHeap::periodicScavenge() -{ - SpinLockHolder h(&pageheap_lock); - pageheap->scavenge(); - - if (shouldScavenge()) { - rescheduleScavenger(); - return; - } - - suspendScavenger(); -} - -ALWAYS_INLINE void TCMalloc_PageHeap::signalScavenger() -{ - ASSERT(pageheap_lock.IsHeld()); - if (isScavengerSuspended() && shouldScavenge()) - scheduleScavenger(); -} - -#else - -void TCMalloc_PageHeap::scavengerThread() -{ -#if HAVE(PTHREAD_SETNAME_NP) - pthread_setname_np("JavaScriptCore: FastMalloc scavenger"); -#endif - - while (1) { - if (!shouldScavenge()) { - pthread_mutex_lock(&m_scavengeMutex); - m_scavengeThreadActive = false; - // 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(kScavengeDelayInSeconds); - { - SpinLockHolder h(&pageheap_lock); - pageheap->scavenge(); - } - } -} - -#endif - -#endif - -// If TLS is available, we also store a copy -// of the per-thread object in a __thread variable -// since __thread variables are faster to read -// than pthread_getspecific(). We still need -// pthread_setspecific() because __thread -// variables provide no way to run cleanup -// code when a thread is destroyed. -#ifdef HAVE_TLS -static __thread TCMalloc_ThreadCache *threadlocal_heap; -#endif -// Thread-specific key. Initialization here is somewhat tricky -// because some Linux startup code invokes malloc() before it -// is in a good enough state to handle pthread_keycreate(). -// Therefore, we use TSD keys only after tsd_inited is set to true. -// Until then, we use a slow path to get the heap object. -static bool tsd_inited = false; -#if USE(PTHREAD_GETSPECIFIC_DIRECT) -static const pthread_key_t heap_key = __PTK_FRAMEWORK_JAVASCRIPTCORE_KEY0; -#else -static pthread_key_t heap_key; -#endif -#if OS(WINDOWS) -DWORD tlsIndex = TLS_OUT_OF_INDEXES; -#endif - -static ALWAYS_INLINE void setThreadHeap(TCMalloc_ThreadCache* heap) -{ -#if USE(PTHREAD_GETSPECIFIC_DIRECT) - // Can't have two libraries both doing this in the same process, - // so check and make this crash right away. - if (pthread_getspecific(heap_key)) - CRASH(); -#endif - - // Still do pthread_setspecific even if there's an alternate form - // of thread-local storage in use, to benefit from the delete callback. - pthread_setspecific(heap_key, heap); - -#if OS(WINDOWS) - TlsSetValue(tlsIndex, heap); -#endif -} - -// Allocator for thread heaps -static PageHeapAllocator<TCMalloc_ThreadCache> threadheap_allocator; - -// Linked list of heap objects. Protected by pageheap_lock. -static TCMalloc_ThreadCache* thread_heaps = NULL; -static int thread_heap_count = 0; - -// Overall thread cache size. Protected by pageheap_lock. -static size_t overall_thread_cache_size = kDefaultOverallThreadCacheSize; - -// Global per-thread cache size. Writes are protected by -// pageheap_lock. Reads are done without any locking, which should be -// fine as long as size_t can be written atomically and we don't place -// invariants between this variable and other pieces of state. -static volatile size_t per_thread_cache_size = kMaxThreadCacheSize; - -//------------------------------------------------------------------- -// Central cache implementation -//------------------------------------------------------------------- - -void TCMalloc_Central_FreeList::Init(size_t cl) { - lock_.Init(); - size_class_ = cl; - DLL_Init(&empty_); - DLL_Init(&nonempty_); - counter_ = 0; - - cache_size_ = 1; - used_slots_ = 0; - ASSERT(cache_size_ <= kNumTransferEntries); -} - -void TCMalloc_Central_FreeList::ReleaseListToSpans(void* start) { - while (start) { - void *next = SLL_Next(start); - ReleaseToSpans(start); - start = next; - } -} - -ALWAYS_INLINE void TCMalloc_Central_FreeList::ReleaseToSpans(void* object) { - const PageID p = reinterpret_cast<uintptr_t>(object) >> kPageShift; - Span* span = pageheap->GetDescriptor(p); - ASSERT(span != NULL); - ASSERT(span->refcount > 0); - - // If span is empty, move it to non-empty list - if (span->objects == NULL) { - DLL_Remove(span); - DLL_Prepend(&nonempty_, span); - Event(span, 'N', 0); - } - - // The following check is expensive, so it is disabled by default - if (false) { - // Check that object does not occur in list - unsigned got = 0; - for (void* p = span->objects; p != NULL; p = *((void**) p)) { - ASSERT(p != object); - got++; - } - ASSERT(got + span->refcount == - (span->length<<kPageShift)/ByteSizeForClass(span->sizeclass)); - } - - counter_++; - span->refcount--; - if (span->refcount == 0) { - Event(span, '#', 0); - counter_ -= (span->length<<kPageShift) / ByteSizeForClass(span->sizeclass); - DLL_Remove(span); - - // Release central list lock while operating on pageheap - lock_.Unlock(); - { - SpinLockHolder h(&pageheap_lock); - pageheap->Delete(span); - } - lock_.Lock(); - } else { - *(reinterpret_cast<void**>(object)) = span->objects; - span->objects = object; - } -} - -ALWAYS_INLINE bool TCMalloc_Central_FreeList::EvictRandomSizeClass( - size_t locked_size_class, bool force) { - static int race_counter = 0; - int t = race_counter++; // Updated without a lock, but who cares. - if (t >= static_cast<int>(kNumClasses)) { - while (t >= static_cast<int>(kNumClasses)) { - t -= kNumClasses; - } - race_counter = t; - } - ASSERT(t >= 0); - ASSERT(t < static_cast<int>(kNumClasses)); - if (t == static_cast<int>(locked_size_class)) return false; - return central_cache[t].ShrinkCache(static_cast<int>(locked_size_class), force); -} - -bool TCMalloc_Central_FreeList::MakeCacheSpace() { - // Is there room in the cache? - if (used_slots_ < cache_size_) return true; - // Check if we can expand this cache? - if (cache_size_ == kNumTransferEntries) return false; - // Ok, we'll try to grab an entry from some other size class. - if (EvictRandomSizeClass(size_class_, false) || - EvictRandomSizeClass(size_class_, true)) { - // Succeeded in evicting, we're going to make our cache larger. - cache_size_++; - return true; - } - return false; -} - - -namespace { -class LockInverter { - private: - SpinLock *held_, *temp_; - public: - inline explicit LockInverter(SpinLock* held, SpinLock *temp) - : held_(held), temp_(temp) { held_->Unlock(); temp_->Lock(); } - inline ~LockInverter() { temp_->Unlock(); held_->Lock(); } -}; -} - -bool TCMalloc_Central_FreeList::ShrinkCache(int locked_size_class, bool force) { - // Start with a quick check without taking a lock. - if (cache_size_ == 0) return false; - // We don't evict from a full cache unless we are 'forcing'. - if (force == false && used_slots_ == cache_size_) return false; - - // Grab lock, but first release the other lock held by this thread. We use - // the lock inverter to ensure that we never hold two size class locks - // concurrently. That can create a deadlock because there is no well - // defined nesting order. - LockInverter li(¢ral_cache[locked_size_class].lock_, &lock_); - ASSERT(used_slots_ <= cache_size_); - ASSERT(0 <= cache_size_); - if (cache_size_ == 0) return false; - if (used_slots_ == cache_size_) { - if (force == false) return false; - // ReleaseListToSpans releases the lock, so we have to make all the - // updates to the central list before calling it. - cache_size_--; - used_slots_--; - ReleaseListToSpans(tc_slots_[used_slots_].head); - return true; - } - cache_size_--; - return true; -} - -void TCMalloc_Central_FreeList::InsertRange(void *start, void *end, int N) { - SpinLockHolder h(&lock_); - if (N == num_objects_to_move[size_class_] && - MakeCacheSpace()) { - int slot = used_slots_++; - ASSERT(slot >=0); - ASSERT(slot < kNumTransferEntries); - TCEntry *entry = &tc_slots_[slot]; - entry->head = start; - entry->tail = end; - return; - } - ReleaseListToSpans(start); -} - -void TCMalloc_Central_FreeList::RemoveRange(void **start, void **end, int *N) { - int num = *N; - ASSERT(num > 0); - - SpinLockHolder h(&lock_); - if (num == num_objects_to_move[size_class_] && used_slots_ > 0) { - int slot = --used_slots_; - ASSERT(slot >= 0); - TCEntry *entry = &tc_slots_[slot]; - *start = entry->head; - *end = entry->tail; - return; - } - - // TODO: Prefetch multiple TCEntries? - void *tail = FetchFromSpansSafe(); - if (!tail) { - // We are completely out of memory. - *start = *end = NULL; - *N = 0; - return; - } - - SLL_SetNext(tail, NULL); - void *head = tail; - int count = 1; - while (count < num) { - void *t = FetchFromSpans(); - if (!t) break; - SLL_Push(&head, t); - count++; - } - *start = head; - *end = tail; - *N = count; -} - - -void* TCMalloc_Central_FreeList::FetchFromSpansSafe() { - void *t = FetchFromSpans(); - if (!t) { - Populate(); - t = FetchFromSpans(); - } - return t; -} - -void* TCMalloc_Central_FreeList::FetchFromSpans() { - if (DLL_IsEmpty(&nonempty_)) return NULL; - Span* span = nonempty_.next; - - ASSERT(span->objects != NULL); - ASSERT_SPAN_COMMITTED(span); - span->refcount++; - void* result = span->objects; - span->objects = *(reinterpret_cast<void**>(result)); - if (span->objects == NULL) { - // Move to empty list - DLL_Remove(span); - DLL_Prepend(&empty_, span); - Event(span, 'E', 0); - } - counter_--; - return result; -} - -// Fetch memory from the system and add to the central cache freelist. -ALWAYS_INLINE void TCMalloc_Central_FreeList::Populate() { - // Release central list lock while operating on pageheap - lock_.Unlock(); - const size_t npages = class_to_pages[size_class_]; - - Span* span; - { - SpinLockHolder h(&pageheap_lock); - span = pageheap->New(npages); - if (span) pageheap->RegisterSizeClass(span, size_class_); - } - if (span == NULL) { -#if HAVE(ERRNO_H) - MESSAGE("allocation failed: %d\n", errno); -#elif OS(WINDOWS) - MESSAGE("allocation failed: %d\n", ::GetLastError()); -#else - MESSAGE("allocation failed\n"); -#endif - lock_.Lock(); - return; - } - ASSERT_SPAN_COMMITTED(span); - ASSERT(span->length == npages); - // Cache sizeclass info eagerly. Locking is not necessary. - // (Instead of being eager, we could just replace any stale info - // about this span, but that seems to be no better in practice.) - for (size_t i = 0; i < npages; i++) { - pageheap->CacheSizeClass(span->start + i, size_class_); - } - - // Split the block into pieces and add to the free-list - // TODO: coloring of objects to avoid cache conflicts? - void** tail = &span->objects; - char* ptr = reinterpret_cast<char*>(span->start << kPageShift); - char* limit = ptr + (npages << kPageShift); - const size_t size = ByteSizeForClass(size_class_); - int num = 0; - char* nptr; - while ((nptr = ptr + size) <= limit) { - *tail = ptr; - tail = reinterpret_cast_ptr<void**>(ptr); - ptr = nptr; - num++; - } - ASSERT(ptr <= limit); - *tail = NULL; - span->refcount = 0; // No sub-object in use yet - - // Add span to list of non-empty spans - lock_.Lock(); - DLL_Prepend(&nonempty_, span); - counter_ += num; -} - -//------------------------------------------------------------------- -// TCMalloc_ThreadCache implementation -//------------------------------------------------------------------- - -inline bool TCMalloc_ThreadCache::SampleAllocation(size_t k) { - if (bytes_until_sample_ < k) { - PickNextSample(k); - return true; - } else { - bytes_until_sample_ -= k; - return false; - } -} - -void TCMalloc_ThreadCache::Init(ThreadIdentifier tid) { - size_ = 0; - next_ = NULL; - prev_ = NULL; - tid_ = tid; - in_setspecific_ = false; - for (size_t cl = 0; cl < kNumClasses; ++cl) { - list_[cl].Init(); - } - - // Initialize RNG -- run it for a bit to get to good values - bytes_until_sample_ = 0; - rnd_ = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(this)); - for (int i = 0; i < 100; i++) { - PickNextSample(static_cast<size_t>(FLAGS_tcmalloc_sample_parameter * 2)); - } -} - -void TCMalloc_ThreadCache::Cleanup() { - // Put unused memory back into central cache - for (size_t cl = 0; cl < kNumClasses; ++cl) { - if (list_[cl].length() > 0) { - ReleaseToCentralCache(cl, list_[cl].length()); - } - } -} - -ALWAYS_INLINE void* TCMalloc_ThreadCache::Allocate(size_t size) { - ASSERT(size <= kMaxSize); - const size_t cl = SizeClass(size); - FreeList* list = &list_[cl]; - size_t allocationSize = ByteSizeForClass(cl); - if (list->empty()) { - FetchFromCentralCache(cl, allocationSize); - if (list->empty()) return NULL; - } - size_ -= allocationSize; - return list->Pop(); -} - -inline void TCMalloc_ThreadCache::Deallocate(void* ptr, size_t cl) { - size_ += ByteSizeForClass(cl); - FreeList* list = &list_[cl]; - list->Push(ptr); - // If enough data is free, put back into central cache - if (list->length() > kMaxFreeListLength) { - ReleaseToCentralCache(cl, num_objects_to_move[cl]); - } - if (size_ >= per_thread_cache_size) Scavenge(); -} - -// Remove some objects of class "cl" from central cache and add to thread heap -ALWAYS_INLINE void TCMalloc_ThreadCache::FetchFromCentralCache(size_t cl, size_t allocationSize) { - int fetch_count = num_objects_to_move[cl]; - void *start, *end; - central_cache[cl].RemoveRange(&start, &end, &fetch_count); - list_[cl].PushRange(fetch_count, start, end); - size_ += allocationSize * fetch_count; -} - -// Remove some objects of class "cl" from thread heap and add to central cache -inline void TCMalloc_ThreadCache::ReleaseToCentralCache(size_t cl, int N) { - ASSERT(N > 0); - FreeList* src = &list_[cl]; - if (N > src->length()) N = src->length(); - size_ -= N*ByteSizeForClass(cl); - - // We return prepackaged chains of the correct size to the central cache. - // TODO: Use the same format internally in the thread caches? - int batch_size = num_objects_to_move[cl]; - while (N > batch_size) { - void *tail, *head; - src->PopRange(batch_size, &head, &tail); - central_cache[cl].InsertRange(head, tail, batch_size); - N -= batch_size; - } - void *tail, *head; - src->PopRange(N, &head, &tail); - central_cache[cl].InsertRange(head, tail, N); -} - -// Release idle memory to the central cache -inline void TCMalloc_ThreadCache::Scavenge() { - // If the low-water mark for the free list is L, it means we would - // not have had to allocate anything from the central cache even if - // we had reduced the free list size by L. We aim to get closer to - // that situation by dropping L/2 nodes from the free list. This - // may not release much memory, but if so we will call scavenge again - // pretty soon and the low-water marks will be high on that call. - //int64 start = CycleClock::Now(); - - for (size_t cl = 0; cl < kNumClasses; cl++) { - FreeList* list = &list_[cl]; - const int lowmark = list->lowwatermark(); - if (lowmark > 0) { - const int drop = (lowmark > 1) ? lowmark/2 : 1; - ReleaseToCentralCache(cl, drop); - } - list->clear_lowwatermark(); - } - - //int64 finish = CycleClock::Now(); - //CycleTimer ct; - //MESSAGE("GC: %.0f ns\n", ct.CyclesToUsec(finish-start)*1000.0); -} - -void TCMalloc_ThreadCache::PickNextSample(size_t k) { - // Make next "random" number - // x^32+x^22+x^2+x^1+1 is a primitive polynomial for random numbers - static const uint32_t kPoly = (1 << 22) | (1 << 2) | (1 << 1) | (1 << 0); - uint32_t r = rnd_; - rnd_ = (r << 1) ^ ((static_cast<int32_t>(r) >> 31) & kPoly); - - // Next point is "rnd_ % (sample_period)". I.e., average - // increment is "sample_period/2". - const int flag_value = static_cast<int>(FLAGS_tcmalloc_sample_parameter); - static int last_flag_value = -1; - - if (flag_value != last_flag_value) { - SpinLockHolder h(&sample_period_lock); - int i; - for (i = 0; i < (static_cast<int>(sizeof(primes_list)/sizeof(primes_list[0])) - 1); i++) { - if (primes_list[i] >= flag_value) { - break; - } - } - sample_period = primes_list[i]; - last_flag_value = flag_value; - } - - bytes_until_sample_ += rnd_ % sample_period; - - if (k > (static_cast<size_t>(-1) >> 2)) { - // If the user has asked for a huge allocation then it is possible - // for the code below to loop infinitely. Just return (note that - // this throws off the sampling accuracy somewhat, but a user who - // is allocating more than 1G of memory at a time can live with a - // minor inaccuracy in profiling of small allocations, and also - // would rather not wait for the loop below to terminate). - return; - } - - while (bytes_until_sample_ < k) { - // Increase bytes_until_sample_ by enough average sampling periods - // (sample_period >> 1) to allow us to sample past the current - // allocation. - bytes_until_sample_ += (sample_period >> 1); - } - - bytes_until_sample_ -= k; -} - -void TCMalloc_ThreadCache::InitModule() { - // There is a slight potential race here because of double-checked - // locking idiom. However, as long as the program does a small - // allocation before switching to multi-threaded mode, we will be - // fine. We increase the chances of doing such a small allocation - // by doing one in the constructor of the module_enter_exit_hook - // object declared below. - SpinLockHolder h(&pageheap_lock); - if (!phinited) { -#ifdef WTF_CHANGES - InitTSD(); -#endif - InitSizeClasses(); - threadheap_allocator.Init(); - span_allocator.Init(); - span_allocator.New(); // Reduce cache conflicts - span_allocator.New(); // Reduce cache conflicts - stacktrace_allocator.Init(); - DLL_Init(&sampled_objects); - for (size_t i = 0; i < kNumClasses; ++i) { - central_cache[i].Init(i); - } - pageheap->init(); - phinited = 1; -#if defined(WTF_CHANGES) && OS(DARWIN) - FastMallocZone::init(); -#endif - } -} - -inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::NewHeap(ThreadIdentifier tid) { - // Create the heap and add it to the linked list - TCMalloc_ThreadCache *heap = threadheap_allocator.New(); - heap->Init(tid); - heap->next_ = thread_heaps; - heap->prev_ = NULL; - if (thread_heaps != NULL) thread_heaps->prev_ = heap; - thread_heaps = heap; - thread_heap_count++; - RecomputeThreadCacheSize(); - return heap; -} - -inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetThreadHeap() { -#ifdef HAVE_TLS - // __thread is faster, but only when the kernel supports it - if (KernelSupportsTLS()) - return threadlocal_heap; -#elif OS(WINDOWS) - return static_cast<TCMalloc_ThreadCache*>(TlsGetValue(tlsIndex)); -#else - return static_cast<TCMalloc_ThreadCache*>(pthread_getspecific(heap_key)); -#endif -} - -inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCache() { - TCMalloc_ThreadCache* ptr = NULL; - if (!tsd_inited) { - InitModule(); - } else { - ptr = GetThreadHeap(); - } - if (ptr == NULL) ptr = CreateCacheIfNecessary(); - return ptr; -} - -// In deletion paths, we do not try to create a thread-cache. This is -// because we may be in the thread destruction code and may have -// already cleaned up the cache for this thread. -inline TCMalloc_ThreadCache* TCMalloc_ThreadCache::GetCacheIfPresent() { - if (!tsd_inited) return NULL; - void* const p = GetThreadHeap(); - return reinterpret_cast<TCMalloc_ThreadCache*>(p); -} - -void TCMalloc_ThreadCache::InitTSD() { - ASSERT(!tsd_inited); -#if USE(PTHREAD_GETSPECIFIC_DIRECT) - pthread_key_init_np(heap_key, DestroyThreadCache); -#else - pthread_key_create(&heap_key, DestroyThreadCache); -#endif -#if OS(WINDOWS) - tlsIndex = TlsAlloc(); -#endif - tsd_inited = true; - -#if !OS(WINDOWS) - // We may have used a fake pthread_t for the main thread. Fix it. - pthread_t zero; - memset(&zero, 0, sizeof(zero)); -#endif -#ifndef WTF_CHANGES - SpinLockHolder h(&pageheap_lock); -#else - ASSERT(pageheap_lock.IsHeld()); -#endif - for (TCMalloc_ThreadCache* h = thread_heaps; h != NULL; h = h->next_) { -#if OS(WINDOWS) - if (h->tid_ == 0) { - h->tid_ = GetCurrentThreadId(); - } -#else - if (pthread_equal(h->tid_, zero)) { - h->tid_ = pthread_self(); - } -#endif - } -} - -TCMalloc_ThreadCache* TCMalloc_ThreadCache::CreateCacheIfNecessary() { - // Initialize per-thread data if necessary - TCMalloc_ThreadCache* heap = NULL; - { - SpinLockHolder h(&pageheap_lock); - -#if OS(WINDOWS) - DWORD me; - if (!tsd_inited) { - me = 0; - } else { - me = GetCurrentThreadId(); - } -#else - // Early on in glibc's life, we cannot even call pthread_self() - pthread_t me; - if (!tsd_inited) { - memset(&me, 0, sizeof(me)); - } else { - me = pthread_self(); - } -#endif - - // This may be a recursive malloc call from pthread_setspecific() - // In that case, the heap for this thread has already been created - // and added to the linked list. So we search for that first. - for (TCMalloc_ThreadCache* h = thread_heaps; h != NULL; h = h->next_) { -#if OS(WINDOWS) - if (h->tid_ == me) { -#else - if (pthread_equal(h->tid_, me)) { -#endif - heap = h; - break; - } - } - - if (heap == NULL) heap = NewHeap(me); - } - - // We call pthread_setspecific() outside the lock because it may - // call malloc() recursively. The recursive call will never get - // here again because it will find the already allocated heap in the - // linked list of heaps. - if (!heap->in_setspecific_ && tsd_inited) { - heap->in_setspecific_ = true; - setThreadHeap(heap); - } - return heap; -} - -void TCMalloc_ThreadCache::BecomeIdle() { - if (!tsd_inited) return; // No caches yet - TCMalloc_ThreadCache* heap = GetThreadHeap(); - if (heap == NULL) return; // No thread cache to remove - if (heap->in_setspecific_) return; // Do not disturb the active caller - - heap->in_setspecific_ = true; - setThreadHeap(NULL); -#ifdef HAVE_TLS - // Also update the copy in __thread - threadlocal_heap = NULL; -#endif - heap->in_setspecific_ = false; - if (GetThreadHeap() == heap) { - // Somehow heap got reinstated by a recursive call to malloc - // from pthread_setspecific. We give up in this case. - return; - } - - // We can now get rid of the heap - DeleteCache(heap); -} - -void TCMalloc_ThreadCache::DestroyThreadCache(void* ptr) { - // Note that "ptr" cannot be NULL since pthread promises not - // to invoke the destructor on NULL values, but for safety, - // we check anyway. - if (ptr == NULL) return; -#ifdef HAVE_TLS - // Prevent fast path of GetThreadHeap() from returning heap. - threadlocal_heap = NULL; -#endif - DeleteCache(reinterpret_cast<TCMalloc_ThreadCache*>(ptr)); -} - -void TCMalloc_ThreadCache::DeleteCache(TCMalloc_ThreadCache* heap) { - // Remove all memory from heap - heap->Cleanup(); - - // Remove from linked list - SpinLockHolder h(&pageheap_lock); - if (heap->next_ != NULL) heap->next_->prev_ = heap->prev_; - if (heap->prev_ != NULL) heap->prev_->next_ = heap->next_; - if (thread_heaps == heap) thread_heaps = heap->next_; - thread_heap_count--; - RecomputeThreadCacheSize(); - - threadheap_allocator.Delete(heap); -} - -void TCMalloc_ThreadCache::RecomputeThreadCacheSize() { - // Divide available space across threads - int n = thread_heap_count > 0 ? thread_heap_count : 1; - size_t space = overall_thread_cache_size / n; - - // Limit to allowed range - if (space < kMinThreadCacheSize) space = kMinThreadCacheSize; - if (space > kMaxThreadCacheSize) space = kMaxThreadCacheSize; - - per_thread_cache_size = space; -} - -void TCMalloc_ThreadCache::Print() const { - for (size_t cl = 0; cl < kNumClasses; ++cl) { - MESSAGE(" %5" PRIuS " : %4d len; %4d lo\n", - ByteSizeForClass(cl), - list_[cl].length(), - list_[cl].lowwatermark()); - } -} - -// Extract interesting stats -struct TCMallocStats { - uint64_t system_bytes; // Bytes alloced from system - uint64_t thread_bytes; // Bytes in thread caches - uint64_t central_bytes; // Bytes in central cache - uint64_t transfer_bytes; // Bytes in central transfer cache - uint64_t pageheap_bytes; // Bytes in page heap - uint64_t metadata_bytes; // Bytes alloced for metadata -}; - -#ifndef WTF_CHANGES -// Get stats into "r". Also get per-size-class counts if class_count != NULL -static void ExtractStats(TCMallocStats* r, uint64_t* class_count) { - r->central_bytes = 0; - r->transfer_bytes = 0; - for (int cl = 0; cl < kNumClasses; ++cl) { - const int length = central_cache[cl].length(); - const int tc_length = central_cache[cl].tc_length(); - r->central_bytes += static_cast<uint64_t>(ByteSizeForClass(cl)) * length; - r->transfer_bytes += - static_cast<uint64_t>(ByteSizeForClass(cl)) * tc_length; - if (class_count) class_count[cl] = length + tc_length; - } - - // Add stats from per-thread heaps - r->thread_bytes = 0; - { // scope - SpinLockHolder h(&pageheap_lock); - for (TCMalloc_ThreadCache* h = thread_heaps; h != NULL; h = h->next_) { - r->thread_bytes += h->Size(); - if (class_count) { - for (size_t cl = 0; cl < kNumClasses; ++cl) { - class_count[cl] += h->freelist_length(cl); - } - } - } - } - - { //scope - SpinLockHolder h(&pageheap_lock); - r->system_bytes = pageheap->SystemBytes(); - r->metadata_bytes = metadata_system_bytes; - r->pageheap_bytes = pageheap->FreeBytes(); - } -} -#endif - -#ifndef WTF_CHANGES -// WRITE stats to "out" -static void DumpStats(TCMalloc_Printer* out, int level) { - TCMallocStats stats; - uint64_t class_count[kNumClasses]; - ExtractStats(&stats, (level >= 2 ? class_count : NULL)); - - if (level >= 2) { - out->printf("------------------------------------------------\n"); - uint64_t cumulative = 0; - for (int cl = 0; cl < kNumClasses; ++cl) { - if (class_count[cl] > 0) { - uint64_t class_bytes = class_count[cl] * ByteSizeForClass(cl); - cumulative += class_bytes; - out->printf("class %3d [ %8" PRIuS " bytes ] : " - "%8" PRIu64 " objs; %5.1f MB; %5.1f cum MB\n", - cl, ByteSizeForClass(cl), - class_count[cl], - class_bytes / 1048576.0, - cumulative / 1048576.0); - } - } - - SpinLockHolder h(&pageheap_lock); - pageheap->Dump(out); - } - - const uint64_t bytes_in_use = stats.system_bytes - - stats.pageheap_bytes - - stats.central_bytes - - stats.transfer_bytes - - stats.thread_bytes; - - out->printf("------------------------------------------------\n" - "MALLOC: %12" PRIu64 " Heap size\n" - "MALLOC: %12" PRIu64 " Bytes in use by application\n" - "MALLOC: %12" PRIu64 " Bytes free in page heap\n" - "MALLOC: %12" PRIu64 " Bytes free in central cache\n" - "MALLOC: %12" PRIu64 " Bytes free in transfer cache\n" - "MALLOC: %12" PRIu64 " Bytes free in thread caches\n" - "MALLOC: %12" PRIu64 " Spans in use\n" - "MALLOC: %12" PRIu64 " Thread heaps in use\n" - "MALLOC: %12" PRIu64 " Metadata allocated\n" - "------------------------------------------------\n", - stats.system_bytes, - bytes_in_use, - stats.pageheap_bytes, - stats.central_bytes, - stats.transfer_bytes, - stats.thread_bytes, - uint64_t(span_allocator.inuse()), - uint64_t(threadheap_allocator.inuse()), - stats.metadata_bytes); -} - -static void PrintStats(int level) { - const int kBufferSize = 16 << 10; - char* buffer = new char[kBufferSize]; - TCMalloc_Printer printer(buffer, kBufferSize); - DumpStats(&printer, level); - write(STDERR_FILENO, buffer, strlen(buffer)); - delete[] buffer; -} - -static void** DumpStackTraces() { - // Count how much space we need - int needed_slots = 0; - { - SpinLockHolder h(&pageheap_lock); - for (Span* s = sampled_objects.next; s != &sampled_objects; s = s->next) { - StackTrace* stack = reinterpret_cast<StackTrace*>(s->objects); - needed_slots += 3 + stack->depth; - } - needed_slots += 100; // Slop in case sample grows - needed_slots += needed_slots/8; // An extra 12.5% slop - } - - void** result = new void*[needed_slots]; - if (result == NULL) { - MESSAGE("tcmalloc: could not allocate %d slots for stack traces\n", - needed_slots); - return NULL; - } - - SpinLockHolder h(&pageheap_lock); - int used_slots = 0; - for (Span* s = sampled_objects.next; s != &sampled_objects; s = s->next) { - ASSERT(used_slots < needed_slots); // Need to leave room for terminator - StackTrace* stack = reinterpret_cast<StackTrace*>(s->objects); - if (used_slots + 3 + stack->depth >= needed_slots) { - // No more room - break; - } - - result[used_slots+0] = reinterpret_cast<void*>(static_cast<uintptr_t>(1)); - result[used_slots+1] = reinterpret_cast<void*>(stack->size); - result[used_slots+2] = reinterpret_cast<void*>(stack->depth); - for (int d = 0; d < stack->depth; d++) { - result[used_slots+3+d] = stack->stack[d]; - } - used_slots += 3 + stack->depth; - } - result[used_slots] = reinterpret_cast<void*>(static_cast<uintptr_t>(0)); - return result; -} -#endif - -#ifndef WTF_CHANGES - -// TCMalloc's support for extra malloc interfaces -class TCMallocImplementation : public MallocExtension { - public: - virtual void GetStats(char* buffer, int buffer_length) { - ASSERT(buffer_length > 0); - TCMalloc_Printer printer(buffer, buffer_length); - - // Print level one stats unless lots of space is available - if (buffer_length < 10000) { - DumpStats(&printer, 1); - } else { - DumpStats(&printer, 2); - } - } - - virtual void** ReadStackTraces() { - return DumpStackTraces(); - } - - virtual bool GetNumericProperty(const char* name, size_t* value) { - ASSERT(name != NULL); - - if (strcmp(name, "generic.current_allocated_bytes") == 0) { - TCMallocStats stats; - ExtractStats(&stats, NULL); - *value = stats.system_bytes - - stats.thread_bytes - - stats.central_bytes - - stats.pageheap_bytes; - return true; - } - - if (strcmp(name, "generic.heap_size") == 0) { - TCMallocStats stats; - ExtractStats(&stats, NULL); - *value = stats.system_bytes; - return true; - } - - if (strcmp(name, "tcmalloc.slack_bytes") == 0) { - // We assume that bytes in the page heap are not fragmented too - // badly, and are therefore available for allocation. - SpinLockHolder l(&pageheap_lock); - *value = pageheap->FreeBytes(); - return true; - } - - if (strcmp(name, "tcmalloc.max_total_thread_cache_bytes") == 0) { - SpinLockHolder l(&pageheap_lock); - *value = overall_thread_cache_size; - return true; - } - - if (strcmp(name, "tcmalloc.current_total_thread_cache_bytes") == 0) { - TCMallocStats stats; - ExtractStats(&stats, NULL); - *value = stats.thread_bytes; - return true; - } - - return false; - } - - virtual bool SetNumericProperty(const char* name, size_t value) { - ASSERT(name != NULL); - - if (strcmp(name, "tcmalloc.max_total_thread_cache_bytes") == 0) { - // Clip the value to a reasonable range - if (value < kMinThreadCacheSize) value = kMinThreadCacheSize; - if (value > (1<<30)) value = (1<<30); // Limit to 1GB - - SpinLockHolder l(&pageheap_lock); - overall_thread_cache_size = static_cast<size_t>(value); - TCMalloc_ThreadCache::RecomputeThreadCacheSize(); - return true; - } - - return false; - } - - virtual void MarkThreadIdle() { - TCMalloc_ThreadCache::BecomeIdle(); - } - - virtual void ReleaseFreeMemory() { - SpinLockHolder h(&pageheap_lock); - pageheap->ReleaseFreePages(); - } -}; -#endif - -// The constructor allocates an object to ensure that initialization -// runs before main(), and therefore we do not have a chance to become -// multi-threaded before initialization. We also create the TSD key -// here. Presumably by the time this constructor runs, glibc is in -// good enough shape to handle pthread_key_create(). -// -// The constructor also takes the opportunity to tell STL to use -// tcmalloc. We want to do this early, before construct time, so -// all user STL allocations go through tcmalloc (which works really -// well for STL). -// -// The destructor prints stats when the program exits. -class TCMallocGuard { - public: - - TCMallocGuard() { -#ifdef HAVE_TLS // this is true if the cc/ld/libc combo support TLS - // Check whether the kernel also supports TLS (needs to happen at runtime) - CheckIfKernelSupportsTLS(); -#endif -#ifndef WTF_CHANGES -#ifdef WIN32 // patch the windows VirtualAlloc, etc. - PatchWindowsFunctions(); // defined in windows/patch_functions.cc -#endif -#endif - free(malloc(1)); - TCMalloc_ThreadCache::InitTSD(); - free(malloc(1)); -#ifndef WTF_CHANGES - MallocExtension::Register(new TCMallocImplementation); -#endif - } - -#ifndef WTF_CHANGES - ~TCMallocGuard() { - const char* env = getenv("MALLOCSTATS"); - if (env != NULL) { - int level = atoi(env); - if (level < 1) level = 1; - PrintStats(level); - } -#ifdef WIN32 - UnpatchWindowsFunctions(); -#endif - } -#endif -}; - -#ifndef WTF_CHANGES -static TCMallocGuard module_enter_exit_hook; -#endif - - -//------------------------------------------------------------------- -// Helpers for the exported routines below -//------------------------------------------------------------------- - -#ifndef WTF_CHANGES - -static Span* DoSampledAllocation(size_t size) { - - // Grab the stack trace outside the heap lock - StackTrace tmp; - tmp.depth = GetStackTrace(tmp.stack, kMaxStackDepth, 1); - tmp.size = size; - - SpinLockHolder h(&pageheap_lock); - // Allocate span - Span *span = pageheap->New(pages(size == 0 ? 1 : size)); - if (span == NULL) { - return NULL; - } - - // Allocate stack trace - StackTrace *stack = stacktrace_allocator.New(); - if (stack == NULL) { - // Sampling failed because of lack of memory - return span; - } - - *stack = tmp; - span->sample = 1; - span->objects = stack; - DLL_Prepend(&sampled_objects, span); - - return span; -} -#endif - -static inline bool CheckCachedSizeClass(void *ptr) { - PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; - size_t cached_value = pageheap->GetSizeClassIfCached(p); - return cached_value == 0 || - cached_value == pageheap->GetDescriptor(p)->sizeclass; -} - -static inline void* CheckedMallocResult(void *result) -{ - ASSERT(result == 0 || CheckCachedSizeClass(result)); - return result; -} - -static inline void* SpanToMallocResult(Span *span) { - ASSERT_SPAN_COMMITTED(span); - pageheap->CacheSizeClass(span->start, 0); - return - CheckedMallocResult(reinterpret_cast<void*>(span->start << kPageShift)); -} - -#ifdef WTF_CHANGES -template <bool crashOnFailure> -#endif -static ALWAYS_INLINE void* do_malloc(size_t size) { - void* ret = NULL; - -#ifdef WTF_CHANGES - ASSERT(!isForbidden()); -#endif - - // The following call forces module initialization - TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache(); -#ifndef WTF_CHANGES - if ((FLAGS_tcmalloc_sample_parameter > 0) && heap->SampleAllocation(size)) { - Span* span = DoSampledAllocation(size); - if (span != NULL) { - ret = SpanToMallocResult(span); - } - } else -#endif - if (size > kMaxSize) { - // Use page-level allocator - SpinLockHolder h(&pageheap_lock); - Span* span = pageheap->New(pages(size)); - if (span != NULL) { - ret = SpanToMallocResult(span); - } - } else { - // The common case, and also the simplest. This just pops the - // size-appropriate freelist, afer replenishing it if it's empty. - ret = CheckedMallocResult(heap->Allocate(size)); - } - if (!ret) { -#ifdef WTF_CHANGES - if (crashOnFailure) // This branch should be optimized out by the compiler. - CRASH(); -#else - errno = ENOMEM; -#endif - } - return ret; -} - -static ALWAYS_INLINE void do_free(void* ptr) { - if (ptr == NULL) return; - ASSERT(pageheap != NULL); // Should not call free() before malloc() - const PageID p = reinterpret_cast<uintptr_t>(ptr) >> kPageShift; - Span* span = NULL; - size_t cl = pageheap->GetSizeClassIfCached(p); - - if (cl == 0) { - span = pageheap->GetDescriptor(p); - cl = span->sizeclass; - pageheap->CacheSizeClass(p, cl); - } - if (cl != 0) { -#ifndef NO_TCMALLOC_SAMPLES - ASSERT(!pageheap->GetDescriptor(p)->sample); -#endif - TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCacheIfPresent(); - if (heap != NULL) { - heap->Deallocate(ptr, cl); - } else { - // Delete directly into central cache - SLL_SetNext(ptr, NULL); - central_cache[cl].InsertRange(ptr, ptr, 1); - } - } else { - SpinLockHolder h(&pageheap_lock); - ASSERT(reinterpret_cast<uintptr_t>(ptr) % kPageSize == 0); - ASSERT(span != NULL && span->start == p); -#ifndef NO_TCMALLOC_SAMPLES - if (span->sample) { - DLL_Remove(span); - stacktrace_allocator.Delete(reinterpret_cast<StackTrace*>(span->objects)); - span->objects = NULL; - } -#endif - pageheap->Delete(span); - } -} - -#ifndef WTF_CHANGES -// For use by exported routines below that want specific alignments -// -// Note: this code can be slow, and can significantly fragment memory. -// The expectation is that memalign/posix_memalign/valloc/pvalloc will -// not be invoked very often. This requirement simplifies our -// implementation and allows us to tune for expected allocation -// patterns. -static void* do_memalign(size_t align, size_t size) { - ASSERT((align & (align - 1)) == 0); - ASSERT(align > 0); - if (pageheap == NULL) TCMalloc_ThreadCache::InitModule(); - - // Allocate at least one byte to avoid boundary conditions below - if (size == 0) size = 1; - - if (size <= kMaxSize && align < kPageSize) { - // Search through acceptable size classes looking for one with - // enough alignment. This depends on the fact that - // InitSizeClasses() currently produces several size classes that - // are aligned at powers of two. We will waste time and space if - // we miss in the size class array, but that is deemed acceptable - // since memalign() should be used rarely. - size_t cl = SizeClass(size); - while (cl < kNumClasses && ((class_to_size[cl] & (align - 1)) != 0)) { - cl++; - } - if (cl < kNumClasses) { - TCMalloc_ThreadCache* heap = TCMalloc_ThreadCache::GetCache(); - return CheckedMallocResult(heap->Allocate(class_to_size[cl])); - } - } - - // We will allocate directly from the page heap - SpinLockHolder h(&pageheap_lock); - - if (align <= kPageSize) { - // Any page-level allocation will be fine - // TODO: We could put the rest of this page in the appropriate - // TODO: cache but it does not seem worth it. - Span* span = pageheap->New(pages(size)); - return span == NULL ? NULL : SpanToMallocResult(span); - } - - // Allocate extra pages and carve off an aligned portion - const Length alloc = pages(size + align); - Span* span = pageheap->New(alloc); - if (span == NULL) return NULL; - - // Skip starting portion so that we end up aligned - Length skip = 0; - while ((((span->start+skip) << kPageShift) & (align - 1)) != 0) { - skip++; - } - ASSERT(skip < alloc); - if (skip > 0) { - Span* rest = pageheap->Split(span, skip); - pageheap->Delete(span); - span = rest; - } - - // Skip trailing portion that we do not need to return - const Length needed = pages(size); - ASSERT(span->length >= needed); - if (span->length > needed) { - Span* trailer = pageheap->Split(span, needed); - pageheap->Delete(trailer); - } - return SpanToMallocResult(span); -} -#endif - -// Helpers for use by exported routines below: - -#ifndef WTF_CHANGES -static inline void do_malloc_stats() { - PrintStats(1); -} -#endif - -static inline int do_mallopt(int, int) { - return 1; // Indicates error -} - -#ifdef HAVE_STRUCT_MALLINFO // mallinfo isn't defined on freebsd, for instance -static inline struct mallinfo do_mallinfo() { - TCMallocStats stats; - ExtractStats(&stats, NULL); - - // Just some of the fields are filled in. - struct mallinfo info; - memset(&info, 0, sizeof(info)); - - // Unfortunately, the struct contains "int" field, so some of the - // size values will be truncated. - info.arena = static_cast<int>(stats.system_bytes); - info.fsmblks = static_cast<int>(stats.thread_bytes - + stats.central_bytes - + stats.transfer_bytes); - info.fordblks = static_cast<int>(stats.pageheap_bytes); - info.uordblks = static_cast<int>(stats.system_bytes - - stats.thread_bytes - - stats.central_bytes - - stats.transfer_bytes - - stats.pageheap_bytes); - - return info; -} -#endif - -//------------------------------------------------------------------- -// Exported routines -//------------------------------------------------------------------- - -// CAVEAT: The code structure below ensures that MallocHook methods are always -// called from the stack frame of the invoked allocation function. -// heap-checker.cc depends on this to start a stack trace from -// the call to the (de)allocation function. - -#ifndef WTF_CHANGES -extern "C" -#else -#define do_malloc do_malloc<crashOnFailure> - -template <bool crashOnFailure> -ALWAYS_INLINE void* malloc(size_t); - -void* fastMalloc(size_t size) -{ - return malloc<true>(size); -} - -TryMallocReturnValue tryFastMalloc(size_t size) -{ - return malloc<false>(size); -} - -template <bool crashOnFailure> -ALWAYS_INLINE -#endif -void* malloc(size_t size) { -#if ENABLE(WTF_MALLOC_VALIDATION) - if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= size) // If overflow would occur... - return 0; - void* result = do_malloc(size + Internal::ValidationBufferSize); - if (!result) - return 0; - - Internal::ValidationHeader* header = static_cast<Internal::ValidationHeader*>(result); - header->m_size = size; - header->m_type = Internal::AllocTypeMalloc; - header->m_prefix = static_cast<unsigned>(Internal::ValidationPrefix); - result = header + 1; - *Internal::fastMallocValidationSuffix(result) = Internal::ValidationSuffix; - fastMallocValidate(result); -#else - void* result = do_malloc(size); -#endif - -#ifndef WTF_CHANGES - MallocHook::InvokeNewHook(result, size); -#endif - return result; -} - -#ifndef WTF_CHANGES -extern "C" -#endif -void free(void* ptr) { -#ifndef WTF_CHANGES - MallocHook::InvokeDeleteHook(ptr); -#endif - -#if ENABLE(WTF_MALLOC_VALIDATION) - if (!ptr) - return; - - fastMallocValidate(ptr); - Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(ptr); - memset(ptr, 0xCC, header->m_size); - do_free(header); -#else - do_free(ptr); -#endif -} - -#ifndef WTF_CHANGES -extern "C" -#else -template <bool crashOnFailure> -ALWAYS_INLINE void* calloc(size_t, size_t); - -void* fastCalloc(size_t n, size_t elem_size) -{ - void* result = calloc<true>(n, elem_size); -#if ENABLE(WTF_MALLOC_VALIDATION) - fastMallocValidate(result); -#endif - return result; -} - -TryMallocReturnValue tryFastCalloc(size_t n, size_t elem_size) -{ - void* result = calloc<false>(n, elem_size); -#if ENABLE(WTF_MALLOC_VALIDATION) - fastMallocValidate(result); -#endif - return result; -} - -template <bool crashOnFailure> -ALWAYS_INLINE -#endif -void* calloc(size_t n, size_t elem_size) { - size_t totalBytes = n * elem_size; - - // Protect against overflow - if (n > 1 && elem_size && (totalBytes / elem_size) != n) - return 0; - -#if ENABLE(WTF_MALLOC_VALIDATION) - void* result = malloc<crashOnFailure>(totalBytes); - if (!result) - return 0; - - memset(result, 0, totalBytes); - fastMallocValidate(result); -#else - void* result = do_malloc(totalBytes); - if (result != NULL) { - memset(result, 0, totalBytes); - } -#endif - -#ifndef WTF_CHANGES - MallocHook::InvokeNewHook(result, totalBytes); -#endif - return result; -} - -// Since cfree isn't used anywhere, we don't compile it in. -#ifndef WTF_CHANGES -#ifndef WTF_CHANGES -extern "C" -#endif -void cfree(void* ptr) { -#ifndef WTF_CHANGES - MallocHook::InvokeDeleteHook(ptr); -#endif - do_free(ptr); -} -#endif - -#ifndef WTF_CHANGES -extern "C" -#else -template <bool crashOnFailure> -ALWAYS_INLINE void* realloc(void*, size_t); - -void* fastRealloc(void* old_ptr, size_t new_size) -{ -#if ENABLE(WTF_MALLOC_VALIDATION) - fastMallocValidate(old_ptr); -#endif - void* result = realloc<true>(old_ptr, new_size); -#if ENABLE(WTF_MALLOC_VALIDATION) - fastMallocValidate(result); -#endif - return result; -} - -TryMallocReturnValue tryFastRealloc(void* old_ptr, size_t new_size) -{ -#if ENABLE(WTF_MALLOC_VALIDATION) - fastMallocValidate(old_ptr); -#endif - void* result = realloc<false>(old_ptr, new_size); -#if ENABLE(WTF_MALLOC_VALIDATION) - fastMallocValidate(result); -#endif - return result; -} - -template <bool crashOnFailure> -ALWAYS_INLINE -#endif -void* realloc(void* old_ptr, size_t new_size) { - if (old_ptr == NULL) { -#if ENABLE(WTF_MALLOC_VALIDATION) - void* result = malloc<crashOnFailure>(new_size); -#else - void* result = do_malloc(new_size); -#ifndef WTF_CHANGES - MallocHook::InvokeNewHook(result, new_size); -#endif -#endif - return result; - } - if (new_size == 0) { -#ifndef WTF_CHANGES - MallocHook::InvokeDeleteHook(old_ptr); -#endif - free(old_ptr); - return NULL; - } - -#if ENABLE(WTF_MALLOC_VALIDATION) - if (std::numeric_limits<size_t>::max() - Internal::ValidationBufferSize <= new_size) // If overflow would occur... - return 0; - Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(old_ptr); - fastMallocValidate(old_ptr); - old_ptr = header; - header->m_size = new_size; - new_size += Internal::ValidationBufferSize; -#endif - - // Get the size of the old entry - const PageID p = reinterpret_cast<uintptr_t>(old_ptr) >> kPageShift; - size_t cl = pageheap->GetSizeClassIfCached(p); - Span *span = NULL; - size_t old_size; - if (cl == 0) { - span = pageheap->GetDescriptor(p); - cl = span->sizeclass; - pageheap->CacheSizeClass(p, cl); - } - if (cl != 0) { - old_size = ByteSizeForClass(cl); - } else { - ASSERT(span != NULL); - old_size = span->length << kPageShift; - } - - // Reallocate if the new size is larger than the old size, - // or if the new size is significantly smaller than the old size. - if ((new_size > old_size) || (AllocationSize(new_size) < old_size)) { - // Need to reallocate - void* new_ptr = do_malloc(new_size); - if (new_ptr == NULL) { - return NULL; - } -#ifndef WTF_CHANGES - MallocHook::InvokeNewHook(new_ptr, new_size); -#endif - memcpy(new_ptr, old_ptr, ((old_size < new_size) ? old_size : new_size)); -#ifndef WTF_CHANGES - MallocHook::InvokeDeleteHook(old_ptr); -#endif - // We could use a variant of do_free() that leverages the fact - // that we already know the sizeclass of old_ptr. The benefit - // would be small, so don't bother. - do_free(old_ptr); -#if ENABLE(WTF_MALLOC_VALIDATION) - new_ptr = static_cast<Internal::ValidationHeader*>(new_ptr) + 1; - *Internal::fastMallocValidationSuffix(new_ptr) = Internal::ValidationSuffix; -#endif - return new_ptr; - } else { -#if ENABLE(WTF_MALLOC_VALIDATION) - old_ptr = static_cast<Internal::ValidationHeader*>(old_ptr) + 1; // Set old_ptr back to the user pointer. - *Internal::fastMallocValidationSuffix(old_ptr) = Internal::ValidationSuffix; -#endif - return old_ptr; - } -} - -#ifdef WTF_CHANGES -#undef do_malloc -#else - -static SpinLock set_new_handler_lock = SPINLOCK_INITIALIZER; - -static inline void* cpp_alloc(size_t size, bool nothrow) { - for (;;) { - void* p = do_malloc(size); -#ifdef PREANSINEW - return p; -#else - if (p == NULL) { // allocation failed - // Get the current new handler. NB: this function is not - // thread-safe. We make a feeble stab at making it so here, but - // this lock only protects against tcmalloc interfering with - // itself, not with other libraries calling set_new_handler. - std::new_handler nh; - { - SpinLockHolder h(&set_new_handler_lock); - nh = std::set_new_handler(0); - (void) std::set_new_handler(nh); - } - // If no new_handler is established, the allocation failed. - if (!nh) { - if (nothrow) return 0; - throw std::bad_alloc(); - } - // Otherwise, try the new_handler. If it returns, retry the - // allocation. If it throws std::bad_alloc, fail the allocation. - // if it throws something else, don't interfere. - try { - (*nh)(); - } catch (const std::bad_alloc&) { - if (!nothrow) throw; - return p; - } - } else { // allocation success - return p; - } -#endif - } -} - -#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 - // it's in, and new just calls cpp_alloc, the optimizer may fold the - // new call into cpp_alloc, which messes up our whole section-based - // stacktracing (see ATTRIBUTE_SECTION, above). This ensures cpp_alloc - // isn't the last thing this fn calls, and prevents the folding. - MallocHook::InvokeNewHook(p, size); - return p; -} - -void* operator new(size_t size, const std::nothrow_t&) __THROW { - void* p = cpp_alloc(size, true); - MallocHook::InvokeNewHook(p, size); - return p; -} - -void operator delete(void* p) __THROW { - MallocHook::InvokeDeleteHook(p); - do_free(p); -} - -void operator delete(void* p, const std::nothrow_t&) __THROW { - MallocHook::InvokeDeleteHook(p); - do_free(p); -} - -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 - // it's in, and new just calls cpp_alloc, the optimizer may fold the - // new call into cpp_alloc, which messes up our whole section-based - // stacktracing (see ATTRIBUTE_SECTION, above). This ensures cpp_alloc - // isn't the last thing this fn calls, and prevents the folding. - MallocHook::InvokeNewHook(p, size); - return p; -} - -void* operator new[](size_t size, const std::nothrow_t&) __THROW { - void* p = cpp_alloc(size, true); - MallocHook::InvokeNewHook(p, size); - return p; -} - -void operator delete[](void* p) __THROW { - MallocHook::InvokeDeleteHook(p); - do_free(p); -} - -void operator delete[](void* p, const std::nothrow_t&) __THROW { - MallocHook::InvokeDeleteHook(p); - 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); - return result; -} - -extern "C" int posix_memalign(void** result_ptr, size_t align, size_t size) - __THROW { - if (((align % sizeof(void*)) != 0) || - ((align & (align - 1)) != 0) || - (align == 0)) { - return EINVAL; - } - - void* result = do_memalign(align, size); - MallocHook::InvokeNewHook(result, size); - if (result == NULL) { - return ENOMEM; - } else { - *result_ptr = result; - return 0; - } -} - -static size_t pagesize = 0; - -extern "C" void* valloc(size_t size) __THROW { - // Allocate page-aligned object of length >= size bytes - if (pagesize == 0) pagesize = getpagesize(); - void* result = do_memalign(pagesize, size); - MallocHook::InvokeNewHook(result, size); - return result; -} - -extern "C" void* pvalloc(size_t size) __THROW { - // Round up size to a multiple of pagesize - if (pagesize == 0) pagesize = getpagesize(); - size = (size + pagesize - 1) & ~(pagesize - 1); - void* result = do_memalign(pagesize, size); - MallocHook::InvokeNewHook(result, size); - return result; -} - -extern "C" void malloc_stats(void) { - do_malloc_stats(); -} - -extern "C" int mallopt(int cmd, int value) { - return do_mallopt(cmd, value); -} - -#ifdef HAVE_STRUCT_MALLINFO -extern "C" struct mallinfo mallinfo(void) { - return do_mallinfo(); -} -#endif - -//------------------------------------------------------------------- -// Some library routines on RedHat 9 allocate memory using malloc() -// and free it using __libc_free() (or vice-versa). Since we provide -// our own implementations of malloc/free, we need to make sure that -// the __libc_XXX variants (defined as part of glibc) also point to -// the same implementations. -//------------------------------------------------------------------- - -#if defined(__GLIBC__) -extern "C" { -#if COMPILER(GCC) && !defined(__MACH__) && defined(HAVE___ATTRIBUTE__) - // Potentially faster variants that use the gcc alias extension. - // Mach-O (Darwin) does not support weak aliases, hence the __MACH__ check. -# define ALIAS(x) __attribute__ ((weak, alias (x))) - void* __libc_malloc(size_t size) ALIAS("malloc"); - void __libc_free(void* ptr) ALIAS("free"); - void* __libc_realloc(void* ptr, size_t size) ALIAS("realloc"); - void* __libc_calloc(size_t n, size_t size) ALIAS("calloc"); - void __libc_cfree(void* ptr) ALIAS("cfree"); - void* __libc_memalign(size_t align, size_t s) ALIAS("memalign"); - void* __libc_valloc(size_t size) ALIAS("valloc"); - void* __libc_pvalloc(size_t size) ALIAS("pvalloc"); - int __posix_memalign(void** r, size_t a, size_t s) ALIAS("posix_memalign"); -# undef ALIAS -# else /* not __GNUC__ */ - // Portable wrappers - void* __libc_malloc(size_t size) { return malloc(size); } - void __libc_free(void* ptr) { free(ptr); } - void* __libc_realloc(void* ptr, size_t size) { return realloc(ptr, size); } - void* __libc_calloc(size_t n, size_t size) { return calloc(n, size); } - void __libc_cfree(void* ptr) { cfree(ptr); } - void* __libc_memalign(size_t align, size_t s) { return memalign(align, s); } - void* __libc_valloc(size_t size) { return valloc(size); } - void* __libc_pvalloc(size_t size) { return pvalloc(size); } - int __posix_memalign(void** r, size_t a, size_t s) { - return posix_memalign(r, a, s); - } -# endif /* __GNUC__ */ -} -#endif /* __GLIBC__ */ - -// Override __libc_memalign in libc on linux boxes specially. -// They have a bug in libc that causes them to (very rarely) allocate -// with __libc_memalign() yet deallocate with free() and the -// definitions above don't catch it. -// This function is an exception to the rule of calling MallocHook method -// from the stack frame of the allocation function; -// heap-checker handles this special case explicitly. -static void *MemalignOverride(size_t align, size_t size, const void *caller) - __THROW { - void* result = do_memalign(align, size); - MallocHook::InvokeNewHook(result, size); - return result; -} -void *(*__memalign_hook)(size_t, size_t, const void *) = MemalignOverride; - -#endif - -#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) -{ -#if ENABLE(WTF_MALLOC_VALIDATION) - return Internal::fastMallocValidationHeader(const_cast<void*>(ptr))->m_size; -#else - 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; -#endif -} - -#if OS(DARWIN) - -class FreeObjectFinder { - const RemoteMemoryReader& m_reader; - HashSet<void*> m_freeObjects; - -public: - FreeObjectFinder(const RemoteMemoryReader& reader) : m_reader(reader) { } - - void visit(void* ptr) { m_freeObjects.add(ptr); } - bool isFreeObject(void* ptr) const { return m_freeObjects.contains(ptr); } - bool isFreeObject(vm_address_t ptr) const { return isFreeObject(reinterpret_cast<void*>(ptr)); } - size_t freeObjectCount() const { return m_freeObjects.size(); } - - void findFreeObjects(TCMalloc_ThreadCache* threadCache) - { - for (; threadCache; threadCache = (threadCache->next_ ? m_reader(threadCache->next_) : 0)) - threadCache->enumerateFreeObjects(*this, m_reader); - } - - void findFreeObjects(TCMalloc_Central_FreeListPadded* centralFreeList, size_t numSizes, TCMalloc_Central_FreeListPadded* remoteCentralFreeList) - { - for (unsigned i = 0; i < numSizes; i++) - centralFreeList[i].enumerateFreeObjects(*this, m_reader, remoteCentralFreeList + i); - } -}; - -class PageMapFreeObjectFinder { - const RemoteMemoryReader& m_reader; - FreeObjectFinder& m_freeObjectFinder; - -public: - PageMapFreeObjectFinder(const RemoteMemoryReader& reader, FreeObjectFinder& freeObjectFinder) - : m_reader(reader) - , m_freeObjectFinder(freeObjectFinder) - { } - - int visit(void* ptr) const - { - if (!ptr) - return 1; - - Span* span = m_reader(reinterpret_cast<Span*>(ptr)); - if (!span) - return 1; - - if (span->free) { - void* ptr = reinterpret_cast<void*>(span->start << kPageShift); - m_freeObjectFinder.visit(ptr); - } else if (span->sizeclass) { - // Walk the free list of the small-object span, keeping track of each object seen - for (void* nextObject = span->objects; nextObject; nextObject = m_reader.nextEntryInLinkedList(reinterpret_cast<void**>(nextObject))) - m_freeObjectFinder.visit(nextObject); - } - return span->length; - } -}; - -class PageMapMemoryUsageRecorder { - task_t m_task; - void* m_context; - unsigned m_typeMask; - vm_range_recorder_t* m_recorder; - const RemoteMemoryReader& m_reader; - const FreeObjectFinder& m_freeObjectFinder; - - HashSet<void*> m_seenPointers; - Vector<Span*> m_coalescedSpans; - -public: - PageMapMemoryUsageRecorder(task_t task, void* context, unsigned typeMask, vm_range_recorder_t* recorder, const RemoteMemoryReader& reader, const FreeObjectFinder& freeObjectFinder) - : m_task(task) - , m_context(context) - , m_typeMask(typeMask) - , m_recorder(recorder) - , m_reader(reader) - , m_freeObjectFinder(freeObjectFinder) - { } - - ~PageMapMemoryUsageRecorder() - { - ASSERT(!m_coalescedSpans.size()); - } - - void recordPendingRegions() - { - Span* lastSpan = m_coalescedSpans[m_coalescedSpans.size() - 1]; - vm_range_t ptrRange = { m_coalescedSpans[0]->start << kPageShift, 0 }; - ptrRange.size = (lastSpan->start << kPageShift) - ptrRange.address + (lastSpan->length * kPageSize); - - // Mark the memory region the spans represent as a candidate for containing pointers - if (m_typeMask & MALLOC_PTR_REGION_RANGE_TYPE) - (*m_recorder)(m_task, m_context, MALLOC_PTR_REGION_RANGE_TYPE, &ptrRange, 1); - - if (!(m_typeMask & MALLOC_PTR_IN_USE_RANGE_TYPE)) { - m_coalescedSpans.clear(); - return; - } - - Vector<vm_range_t, 1024> allocatedPointers; - for (size_t i = 0; i < m_coalescedSpans.size(); ++i) { - Span *theSpan = m_coalescedSpans[i]; - if (theSpan->free) - continue; - - vm_address_t spanStartAddress = theSpan->start << kPageShift; - vm_size_t spanSizeInBytes = theSpan->length * kPageSize; - - if (!theSpan->sizeclass) { - // If it's an allocated large object span, mark it as in use - if (!m_freeObjectFinder.isFreeObject(spanStartAddress)) - allocatedPointers.append((vm_range_t){spanStartAddress, spanSizeInBytes}); - } else { - const size_t objectSize = ByteSizeForClass(theSpan->sizeclass); - - // Mark each allocated small object within the span as in use - const vm_address_t endOfSpan = spanStartAddress + spanSizeInBytes; - for (vm_address_t object = spanStartAddress; object + objectSize <= endOfSpan; object += objectSize) { - if (!m_freeObjectFinder.isFreeObject(object)) - allocatedPointers.append((vm_range_t){object, objectSize}); - } - } - } - - (*m_recorder)(m_task, m_context, MALLOC_PTR_IN_USE_RANGE_TYPE, allocatedPointers.data(), allocatedPointers.size()); - - m_coalescedSpans.clear(); - } - - int visit(void* ptr) - { - if (!ptr) - return 1; - - Span* span = m_reader(reinterpret_cast<Span*>(ptr)); - if (!span || !span->start) - return 1; - - if (m_seenPointers.contains(ptr)) - return span->length; - m_seenPointers.add(ptr); - - if (!m_coalescedSpans.size()) { - m_coalescedSpans.append(span); - return span->length; - } - - Span* previousSpan = m_coalescedSpans[m_coalescedSpans.size() - 1]; - vm_address_t previousSpanStartAddress = previousSpan->start << kPageShift; - vm_size_t previousSpanSizeInBytes = previousSpan->length * kPageSize; - - // If the new span is adjacent to the previous span, do nothing for now. - vm_address_t spanStartAddress = span->start << kPageShift; - if (spanStartAddress == previousSpanStartAddress + previousSpanSizeInBytes) { - m_coalescedSpans.append(span); - return span->length; - } - - // New span is not adjacent to previous span, so record the spans coalesced so far. - recordPendingRegions(); - m_coalescedSpans.append(span); - - return span->length; - } -}; - -class AdminRegionRecorder { - task_t m_task; - void* m_context; - unsigned m_typeMask; - vm_range_recorder_t* m_recorder; - const RemoteMemoryReader& m_reader; - - Vector<vm_range_t, 1024> m_pendingRegions; - -public: - AdminRegionRecorder(task_t task, void* context, unsigned typeMask, vm_range_recorder_t* recorder, const RemoteMemoryReader& reader) - : m_task(task) - , m_context(context) - , m_typeMask(typeMask) - , m_recorder(recorder) - , m_reader(reader) - { } - - void recordRegion(vm_address_t ptr, size_t size) - { - if (m_typeMask & MALLOC_ADMIN_REGION_RANGE_TYPE) - m_pendingRegions.append((vm_range_t){ ptr, size }); - } - - void visit(void *ptr, size_t size) - { - recordRegion(reinterpret_cast<vm_address_t>(ptr), size); - } - - void recordPendingRegions() - { - if (m_pendingRegions.size()) { - (*m_recorder)(m_task, m_context, MALLOC_ADMIN_REGION_RANGE_TYPE, m_pendingRegions.data(), m_pendingRegions.size()); - m_pendingRegions.clear(); - } - } - - ~AdminRegionRecorder() - { - ASSERT(!m_pendingRegions.size()); - } -}; - -kern_return_t FastMallocZone::enumerate(task_t task, void* context, unsigned typeMask, vm_address_t zoneAddress, memory_reader_t reader, vm_range_recorder_t recorder) -{ - RemoteMemoryReader memoryReader(task, reader); - - InitSizeClasses(); - - FastMallocZone* mzone = memoryReader(reinterpret_cast<FastMallocZone*>(zoneAddress)); - TCMalloc_PageHeap* pageHeap = memoryReader(mzone->m_pageHeap); - TCMalloc_ThreadCache** threadHeapsPointer = memoryReader(mzone->m_threadHeaps); - TCMalloc_ThreadCache* threadHeaps = memoryReader(*threadHeapsPointer); - - TCMalloc_Central_FreeListPadded* centralCaches = memoryReader(mzone->m_centralCaches, sizeof(TCMalloc_Central_FreeListPadded) * kNumClasses); - - FreeObjectFinder finder(memoryReader); - finder.findFreeObjects(threadHeaps); - finder.findFreeObjects(centralCaches, kNumClasses, mzone->m_centralCaches); - - TCMalloc_PageHeap::PageMap* pageMap = &pageHeap->pagemap_; - PageMapFreeObjectFinder pageMapFinder(memoryReader, finder); - pageMap->visitValues(pageMapFinder, memoryReader); - - PageMapMemoryUsageRecorder usageRecorder(task, context, typeMask, recorder, memoryReader, finder); - pageMap->visitValues(usageRecorder, memoryReader); - usageRecorder.recordPendingRegions(); - - AdminRegionRecorder adminRegionRecorder(task, context, typeMask, recorder, memoryReader); - pageMap->visitAllocations(adminRegionRecorder, memoryReader); - - PageHeapAllocator<Span>* spanAllocator = memoryReader(mzone->m_spanAllocator); - PageHeapAllocator<TCMalloc_ThreadCache>* pageHeapAllocator = memoryReader(mzone->m_pageHeapAllocator); - - spanAllocator->recordAdministrativeRegions(adminRegionRecorder, memoryReader); - pageHeapAllocator->recordAdministrativeRegions(adminRegionRecorder, memoryReader); - - adminRegionRecorder.recordPendingRegions(); - - return 0; -} - -size_t FastMallocZone::size(malloc_zone_t*, const void*) -{ - return 0; -} - -void* FastMallocZone::zoneMalloc(malloc_zone_t*, size_t) -{ - return 0; -} - -void* FastMallocZone::zoneCalloc(malloc_zone_t*, size_t, size_t) -{ - return 0; -} - -void FastMallocZone::zoneFree(malloc_zone_t*, void* ptr) -{ - // Due to <rdar://problem/5671357> zoneFree may be called by the system free even if the pointer - // is not in this zone. When this happens, the pointer being freed was not allocated by any - // zone so we need to print a useful error for the application developer. - malloc_printf("*** error for object %p: pointer being freed was not allocated\n", ptr); -} - -void* FastMallocZone::zoneRealloc(malloc_zone_t*, void*, size_t) -{ - return 0; -} - - -#undef malloc -#undef free -#undef realloc -#undef calloc - -extern "C" { -malloc_introspection_t jscore_fastmalloc_introspection = { &FastMallocZone::enumerate, &FastMallocZone::goodSize, &FastMallocZone::check, &FastMallocZone::print, - &FastMallocZone::log, &FastMallocZone::forceLock, &FastMallocZone::forceUnlock, &FastMallocZone::statistics - -#if !defined(BUILDING_ON_LEOPARD) || OS(IOS) - , 0 // zone_locked will not be called on the zone unless it advertises itself as version five or higher. -#endif -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) || OS(IOS) - , 0, 0, 0, 0 // These members will not be used unless the zone advertises itself as version seven or higher. -#endif - - }; -} - -FastMallocZone::FastMallocZone(TCMalloc_PageHeap* pageHeap, TCMalloc_ThreadCache** threadHeaps, TCMalloc_Central_FreeListPadded* centralCaches, PageHeapAllocator<Span>* spanAllocator, PageHeapAllocator<TCMalloc_ThreadCache>* pageHeapAllocator) - : m_pageHeap(pageHeap) - , m_threadHeaps(threadHeaps) - , m_centralCaches(centralCaches) - , m_spanAllocator(spanAllocator) - , m_pageHeapAllocator(pageHeapAllocator) -{ - memset(&m_zone, 0, sizeof(m_zone)); - m_zone.version = 4; - m_zone.zone_name = "JavaScriptCore FastMalloc"; - m_zone.size = &FastMallocZone::size; - m_zone.malloc = &FastMallocZone::zoneMalloc; - m_zone.calloc = &FastMallocZone::zoneCalloc; - m_zone.realloc = &FastMallocZone::zoneRealloc; - m_zone.free = &FastMallocZone::zoneFree; - m_zone.valloc = &FastMallocZone::zoneValloc; - m_zone.destroy = &FastMallocZone::zoneDestroy; - m_zone.introspect = &jscore_fastmalloc_introspection; - malloc_zone_register(&m_zone); -} - - -void FastMallocZone::init() -{ - static FastMallocZone zone(pageheap, &thread_heaps, static_cast<TCMalloc_Central_FreeListPadded*>(central_cache), &span_allocator, &threadheap_allocator); -} - -#endif // OS(DARWIN) - -} // namespace WTF -#endif // WTF_CHANGES - -#endif // FORCE_SYSTEM_MALLOC diff --git a/Source/JavaScriptCore/wtf/FastMalloc.h b/Source/JavaScriptCore/wtf/FastMalloc.h deleted file mode 100644 index 871be3756..000000000 --- a/Source/JavaScriptCore/wtf/FastMalloc.h +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_FastMalloc_h -#define WTF_FastMalloc_h - -#include <wtf/Platform.h> -#include <wtf/PossiblyNull.h> -#include <stdlib.h> -#include <new> - -namespace WTF { - - // These functions call CRASH() if an allocation fails. - WTF_EXPORT_PRIVATE void* fastMalloc(size_t); - WTF_EXPORT_PRIVATE void* fastZeroedMalloc(size_t); - WTF_EXPORT_PRIVATE void* fastCalloc(size_t numElements, size_t elementSize); - WTF_EXPORT_PRIVATE void* fastRealloc(void*, size_t); - WTF_EXPORT_PRIVATE char* fastStrDup(const char*); - WTF_EXPORT_PRIVATE size_t fastMallocSize(const void*); - - struct TryMallocReturnValue { - TryMallocReturnValue(void* data) - : m_data(data) - { - } - TryMallocReturnValue(const TryMallocReturnValue& source) - : m_data(source.m_data) - { - source.m_data = 0; - } - ~TryMallocReturnValue() { ASSERT(!m_data); } - template <typename T> bool getValue(T& data) WARN_UNUSED_RETURN; - template <typename T> operator PossiblyNull<T>() - { - T value; - getValue(value); - return PossiblyNull<T>(value); - } - private: - mutable void* m_data; - }; - - template <typename T> bool TryMallocReturnValue::getValue(T& data) - { - union u { void* data; T target; } res; - res.data = m_data; - data = res.target; - bool returnValue = !!m_data; - m_data = 0; - return returnValue; - } - - WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastMalloc(size_t n); - TryMallocReturnValue tryFastZeroedMalloc(size_t n); - WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size); - WTF_EXPORT_PRIVATE TryMallocReturnValue tryFastRealloc(void* p, size_t n); - - WTF_EXPORT_PRIVATE void fastFree(void*); - -#ifndef NDEBUG - void fastMallocForbid(); - void fastMallocAllow(); -#endif - - WTF_EXPORT_PRIVATE void releaseFastMallocFreeMemory(); - - struct FastMallocStatistics { - size_t reservedVMBytes; - size_t committedVMBytes; - size_t freeListBytes; - }; - WTF_EXPORT_PRIVATE FastMallocStatistics fastMallocStatistics(); - - // This defines a type which holds an unsigned integer and is the same - // size as the minimally aligned memory allocation. - typedef unsigned long long AllocAlignmentInteger; - - namespace Internal { - enum AllocType { // Start with an unusual number instead of zero, because zero is common. - AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc. - AllocTypeClassNew, // Encompasses class operator new from FastAllocBase. - AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase. - AllocTypeFastNew, // Encompasses fastNew. - AllocTypeFastNewArray, // Encompasses fastNewArray. - AllocTypeNew, // Encompasses global operator new. - AllocTypeNewArray // Encompasses global operator new[]. - }; - - enum { - ValidationPrefix = 0xf00df00d, - ValidationSuffix = 0x0badf00d - }; - - typedef unsigned ValidationTag; - - struct ValidationHeader { - AllocType m_type; - unsigned m_size; - ValidationTag m_prefix; - unsigned m_alignment; - }; - - static const int ValidationBufferSize = sizeof(ValidationHeader) + sizeof(ValidationTag); - } - -#if ENABLE(WTF_MALLOC_VALIDATION) - - // Malloc validation is a scheme whereby a tag is attached to an - // allocation which identifies how it was originally allocated. - // This allows us to verify that the freeing operation matches the - // allocation operation. If memory is allocated with operator new[] - // but freed with free or delete, this system would detect that. - // In the implementation here, the tag is an integer prepended to - // the allocation memory which is assigned one of the AllocType - // enumeration values. An alternative implementation of this - // scheme could store the tag somewhere else or ignore it. - // Users of FastMalloc don't need to know or care how this tagging - // is implemented. - - namespace Internal { - - // Handle a detected alloc/free mismatch. By default this calls CRASH(). - void fastMallocMatchFailed(void* p); - - inline ValidationHeader* fastMallocValidationHeader(void* p) - { - return reinterpret_cast<ValidationHeader*>(static_cast<char*>(p) - sizeof(ValidationHeader)); - } - - inline ValidationTag* fastMallocValidationSuffix(void* p) - { - ValidationHeader* header = fastMallocValidationHeader(p); - if (header->m_prefix != static_cast<unsigned>(ValidationPrefix)) - fastMallocMatchFailed(p); - - return reinterpret_cast<ValidationTag*>(static_cast<char*>(p) + header->m_size); - } - - // Return the AllocType tag associated with the allocated block p. - inline AllocType fastMallocMatchValidationType(void* p) - { - return fastMallocValidationHeader(p)->m_type; - } - - // Set the AllocType tag to be associaged with the allocated block p. - inline void setFastMallocMatchValidationType(void* p, AllocType allocType) - { - fastMallocValidationHeader(p)->m_type = allocType; - } - - } // namespace Internal - - // This is a higher level function which is used by FastMalloc-using code. - inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType) - { - if (!p) - return; - - Internal::setFastMallocMatchValidationType(p, allocType); - } - - // This is a higher level function which is used by FastMalloc-using code. - inline void fastMallocMatchValidateFree(void* p, Internal::AllocType) - { - if (!p) - return; - - Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p); - if (header->m_prefix != static_cast<unsigned>(Internal::ValidationPrefix)) - Internal::fastMallocMatchFailed(p); - - if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix) - Internal::fastMallocMatchFailed(p); - - Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK. - } - - inline void fastMallocValidate(void* p) - { - if (!p) - return; - - Internal::ValidationHeader* header = Internal::fastMallocValidationHeader(p); - if (header->m_prefix != static_cast<unsigned>(Internal::ValidationPrefix)) - Internal::fastMallocMatchFailed(p); - - if (*Internal::fastMallocValidationSuffix(p) != Internal::ValidationSuffix) - Internal::fastMallocMatchFailed(p); - } - -#else - - inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType) - { - } - - inline void fastMallocMatchValidateFree(void*, Internal::AllocType) - { - } - -#endif - -} // namespace WTF - -using WTF::fastCalloc; -using WTF::fastFree; -using WTF::fastMalloc; -using WTF::fastMallocSize; -using WTF::fastRealloc; -using WTF::fastStrDup; -using WTF::fastZeroedMalloc; -using WTF::tryFastCalloc; -using WTF::tryFastMalloc; -using WTF::tryFastRealloc; -using WTF::tryFastZeroedMalloc; - -#ifndef NDEBUG -using WTF::fastMallocForbid; -using WTF::fastMallocAllow; -#endif - -#if COMPILER(GCC) && OS(DARWIN) -#define WTF_PRIVATE_INLINE __private_extern__ inline __attribute__((always_inline)) -#elif COMPILER(GCC) -#define WTF_PRIVATE_INLINE inline __attribute__((always_inline)) -#elif COMPILER(MSVC) || COMPILER(RVCT) -#define WTF_PRIVATE_INLINE __forceinline -#else -#define WTF_PRIVATE_INLINE inline -#endif - -#if !defined(_CRTDBG_MAP_ALLOC) && !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) - -// The nothrow functions here are actually not all that helpful, because fastMalloc will -// call CRASH() rather than returning 0, and returning 0 is what nothrow is all about. -// But since WebKit code never uses exceptions or nothrow at all, this is probably OK. -// Long term we will adopt FastAllocBase.h everywhere, and and replace this with -// debug-only code to make sure we don't use the system malloc via the default operator -// new by accident. - -#if ENABLE(GLOBAL_FASTMALLOC_NEW) - -#if COMPILER(MSVC) -#pragma warning(push) -#pragma warning(disable: 4290) // Disable the C++ exception specification ignored warning. -#endif -WTF_PRIVATE_INLINE void* operator new(size_t size) throw (std::bad_alloc) { return fastMalloc(size); } -WTF_PRIVATE_INLINE void* operator new(size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } -WTF_PRIVATE_INLINE void operator delete(void* p) throw() { fastFree(p); } -WTF_PRIVATE_INLINE void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); } -WTF_PRIVATE_INLINE void* operator new[](size_t size) throw (std::bad_alloc) { return fastMalloc(size); } -WTF_PRIVATE_INLINE void* operator new[](size_t size, const std::nothrow_t&) throw() { return fastMalloc(size); } -WTF_PRIVATE_INLINE void operator delete[](void* p) throw() { fastFree(p); } -WTF_PRIVATE_INLINE void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); } -#if COMPILER(MSVC) -#pragma warning(pop) -#endif - -#endif - -#endif - -#endif /* WTF_FastMalloc_h */ diff --git a/Source/JavaScriptCore/wtf/Float32Array.h b/Source/JavaScriptCore/wtf/Float32Array.h deleted file mode 100644 index 55e61e006..000000000 --- a/Source/JavaScriptCore/wtf/Float32Array.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 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 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 Float32Array_h -#define Float32Array_h - -#include <wtf/TypedArrayBase.h> -#include <wtf/MathExtras.h> - -namespace WTF { - -class Float32Array : public TypedArrayBase<float> { -public: - static inline PassRefPtr<Float32Array> create(unsigned length); - static inline PassRefPtr<Float32Array> create(const float* array, unsigned length); - static inline PassRefPtr<Float32Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); - - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<float>* array, unsigned offset) { return TypedArrayBase<float>::set(array, offset); } - - void set(unsigned index, double value) - { - if (index >= TypedArrayBase<float>::m_length) - return; - TypedArrayBase<float>::data()[index] = static_cast<float>(value); - } - - // Invoked by the indexed getter. Does not perform range checks; caller - // is responsible for doing so and returning undefined as necessary. - float item(unsigned index) const - { - ASSERT(index < TypedArrayBase<float>::m_length); - float result = TypedArrayBase<float>::data()[index]; - return result; - } - - inline PassRefPtr<Float32Array> subarray(int start) const; - inline PassRefPtr<Float32Array> subarray(int start, int end) const; - -private: - inline Float32Array(PassRefPtr<ArrayBuffer>, - unsigned byteOffset, - unsigned length); - // Make constructor visible to superclass. - friend class TypedArrayBase<float>; - - // Overridden from ArrayBufferView. - virtual bool isFloatArray() const { return true; } -}; - -PassRefPtr<Float32Array> Float32Array::create(unsigned length) -{ - return TypedArrayBase<float>::create<Float32Array>(length); -} - -PassRefPtr<Float32Array> Float32Array::create(const float* array, unsigned length) -{ - return TypedArrayBase<float>::create<Float32Array>(array, length); -} - -PassRefPtr<Float32Array> Float32Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -{ - return TypedArrayBase<float>::create<Float32Array>(buffer, byteOffset, length); -} - -Float32Array::Float32Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) - : TypedArrayBase<float>(buffer, byteOffset, length) -{ -} - -PassRefPtr<Float32Array> Float32Array::subarray(int start) const -{ - return subarray(start, length()); -} - -PassRefPtr<Float32Array> Float32Array::subarray(int start, int end) const -{ - return subarrayImpl<Float32Array>(start, end); -} - -} // namespace WTF - -using WTF::Float32Array; - -#endif // Float32Array_h diff --git a/Source/JavaScriptCore/wtf/Float64Array.h b/Source/JavaScriptCore/wtf/Float64Array.h deleted file mode 100644 index 30633dbec..000000000 --- a/Source/JavaScriptCore/wtf/Float64Array.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * Copyright (C) 2011 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 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 Float64Array_h -#define Float64Array_h - -#include <wtf/TypedArrayBase.h> -#include <wtf/MathExtras.h> - -namespace WTF { - -class Float64Array : public TypedArrayBase<double> { -public: - static inline PassRefPtr<Float64Array> create(unsigned length); - static inline PassRefPtr<Float64Array> create(const double* array, unsigned length); - static inline PassRefPtr<Float64Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); - - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<double>* array, unsigned offset) { return TypedArrayBase<double>::set(array, offset); } - - void set(unsigned index, double value) - { - if (index >= TypedArrayBase<double>::m_length) - return; - TypedArrayBase<double>::data()[index] = static_cast<double>(value); - } - - // Invoked by the indexed getter. Does not perform range checks; caller - // is responsible for doing so and returning undefined as necessary. - double item(unsigned index) const - { - ASSERT(index < TypedArrayBase<double>::m_length); - double result = TypedArrayBase<double>::data()[index]; - return result; - } - - inline PassRefPtr<Float64Array> subarray(int start) const; - inline PassRefPtr<Float64Array> subarray(int start, int end) const; - -private: - inline Float64Array(PassRefPtr<ArrayBuffer>, - unsigned byteOffset, - unsigned length); - // Make constructor visible to superclass. - friend class TypedArrayBase<double>; - - // Overridden from ArrayBufferView. - virtual bool isDoubleArray() const { return true; } -}; - -PassRefPtr<Float64Array> Float64Array::create(unsigned length) -{ - return TypedArrayBase<double>::create<Float64Array>(length); -} - -PassRefPtr<Float64Array> Float64Array::create(const double* array, unsigned length) -{ - return TypedArrayBase<double>::create<Float64Array>(array, length); -} - -PassRefPtr<Float64Array> Float64Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -{ - return TypedArrayBase<double>::create<Float64Array>(buffer, byteOffset, length); -} - -Float64Array::Float64Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) - : TypedArrayBase<double>(buffer, byteOffset, length) -{ -} - -PassRefPtr<Float64Array> Float64Array::subarray(int start) const -{ - return subarray(start, length()); -} - -PassRefPtr<Float64Array> Float64Array::subarray(int start, int end) const -{ - return subarrayImpl<Float64Array>(start, end); -} - -} // namespace WTF - -using WTF::Float64Array; - -#endif // Float64Array_h diff --git a/Source/JavaScriptCore/wtf/Forward.h b/Source/JavaScriptCore/wtf/Forward.h deleted file mode 100644 index b81ab2580..000000000 --- a/Source/JavaScriptCore/wtf/Forward.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2006, 2009, 2011 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_Forward_h -#define WTF_Forward_h - -#include <stddef.h> - -namespace WTF { - template<typename T> class Function; - template<typename T> class ListRefPtr; - template<typename T> class OwnArrayPtr; - template<typename T> class OwnPtr; - template<typename T> class PassOwnArrayPtr; - template<typename T> class PassOwnPtr; - template<typename T> class PassRefPtr; - template<typename T> class RefPtr; - template<typename T, size_t inlineCapacity> class Vector; - - class ArrayBuffer; - class ArrayBufferView; - class AtomicString; - class AtomicStringImpl; - class CString; - class Decoder; - class Encoder; - class Float32Array; - class Float64Array; - class Int8Array; - class Int16Array; - class Int32Array; - class String; - template <typename T> class StringBuffer; - class StringBuilder; - class StringImpl; - class Uint8Array; - class Uint8ClampedArray; - class Uint16Array; - class Uint32Array; -} - -using WTF::Function; -using WTF::ListRefPtr; -using WTF::OwnArrayPtr; -using WTF::OwnPtr; -using WTF::PassOwnArrayPtr; -using WTF::PassOwnPtr; -using WTF::PassRefPtr; -using WTF::RefPtr; -using WTF::Vector; - -using WTF::ArrayBuffer; -using WTF::ArrayBufferView; -using WTF::AtomicString; -using WTF::AtomicStringImpl; -using WTF::CString; -using WTF::Encoder; -using WTF::Decoder; -using WTF::Float32Array; -using WTF::Float64Array; -using WTF::Int8Array; -using WTF::Int16Array; -using WTF::Int32Array; -using WTF::String; -using WTF::StringBuffer; -using WTF::StringBuilder; -using WTF::StringImpl; -using WTF::Uint8Array; -using WTF::Uint8ClampedArray; -using WTF::Uint16Array; -using WTF::Uint32Array; - -#endif // WTF_Forward_h diff --git a/Source/JavaScriptCore/wtf/Functional.h b/Source/JavaScriptCore/wtf/Functional.h deleted file mode 100644 index bfc813b2a..000000000 --- a/Source/JavaScriptCore/wtf/Functional.h +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Copyright (C) 2011 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 WTF_Functional_h -#define WTF_Functional_h - -#include <wtf/Assertions.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefPtr.h> -#include <wtf/ThreadSafeRefCounted.h> - -#if PLATFORM(MAC) && COMPILER_SUPPORTS(BLOCKS) -#include <objc/objc-runtime.h> -#endif - -namespace WTF { - -// Functional.h provides a very simple way to bind a function pointer and arguments together into a function object -// that can be stored, copied and invoked, similar to how boost::bind and std::bind in C++11. - -// Helper class template to determine whether a given type has ref and deref member functions -// with the right type signature. -template<typename T> -class HasRefAndDeref { - typedef char YesType; - struct NoType { - char padding[8]; - }; - - struct BaseMixin { - void deref(); - void ref(); - }; - - struct Base : public T, public BaseMixin { }; - - template<typename U, U> struct - TypeChecker { }; - - template<typename U> - static NoType refCheck(U*, TypeChecker<void (BaseMixin::*)(), &U::ref>* = 0); - static YesType refCheck(...); - - template<typename U> - static NoType derefCheck(U*, TypeChecker<void (BaseMixin::*)(), &U::deref>* = 0); - static YesType derefCheck(...); - -public: - static const bool value = sizeof(refCheck(static_cast<Base*>(0))) == sizeof(YesType) && sizeof(derefCheck(static_cast<Base*>(0))) == sizeof(YesType); -}; - -// A FunctionWrapper is a class template that can wrap a function pointer or a member function pointer and -// provide a unified interface for calling that function. -template<typename> -class FunctionWrapper; - -template<typename R> -class FunctionWrapper<R (*)()> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = false; - - explicit FunctionWrapper(R (*function)()) - : m_function(function) - { - } - - R operator()() - { - return m_function(); - } - -private: - R (*m_function)(); -}; - -template<typename R, typename P1> -class FunctionWrapper<R (*)(P1)> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = false; - - explicit FunctionWrapper(R (*function)(P1)) - : m_function(function) - { - } - - R operator()(P1 p1) - { - return m_function(p1); - } - -private: - R (*m_function)(P1); -}; - -template<typename R, typename P1, typename P2> -class FunctionWrapper<R (*)(P1, P2)> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = false; - - explicit FunctionWrapper(R (*function)(P1, P2)) - : m_function(function) - { - } - - R operator()(P1 p1, P2 p2) - { - return m_function(p1, p2); - } - -private: - R (*m_function)(P1, P2); -}; - -template<typename R, typename P1, typename P2, typename P3> -class FunctionWrapper<R (*)(P1, P2, P3)> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = false; - - explicit FunctionWrapper(R (*function)(P1, P2, P3)) - : m_function(function) - { - } - - R operator()(P1 p1, P2 p2, P3 p3) - { - return m_function(p1, p2, p3); - } - -private: - R (*m_function)(P1, P2, P3); -}; - -template<typename R, typename C> -class FunctionWrapper<R (C::*)()> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = HasRefAndDeref<C>::value; - - explicit FunctionWrapper(R (C::*function)()) - : m_function(function) - { - } - - R operator()(C* c) - { - return (c->*m_function)(); - } - -private: - R (C::*m_function)(); -}; - -template<typename R, typename C, typename P1> -class FunctionWrapper<R (C::*)(P1)> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = HasRefAndDeref<C>::value; - - explicit FunctionWrapper(R (C::*function)(P1)) - : m_function(function) - { - } - - R operator()(C* c, P1 p1) - { - return (c->*m_function)(p1); - } - -private: - R (C::*m_function)(P1); -}; - -template<typename R, typename C, typename P1, typename P2> -class FunctionWrapper<R (C::*)(P1, P2)> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = HasRefAndDeref<C>::value; - - explicit FunctionWrapper(R (C::*function)(P1, P2)) - : m_function(function) - { - } - - R operator()(C* c, P1 p1, P2 p2) - { - return (c->*m_function)(p1, p2); - } - -private: - R (C::*m_function)(P1, P2); -}; - -template<typename R, typename C, typename P1, typename P2, typename P3> -class FunctionWrapper<R (C::*)(P1, P2, P3)> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = HasRefAndDeref<C>::value; - - explicit FunctionWrapper(R (C::*function)(P1, P2, P3)) - : m_function(function) - { - } - - R operator()(C* c, P1 p1, P2 p2, P3 p3) - { - return (c->*m_function)(p1, p2, p3); - } - -private: - R (C::*m_function)(P1, P2, P3); -}; - -template<typename R, typename C, typename P1, typename P2, typename P3, typename P4> -class FunctionWrapper<R (C::*)(P1, P2, P3, P4)> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = HasRefAndDeref<C>::value; - - explicit FunctionWrapper(R (C::*function)(P1, P2, P3, P4)) - : m_function(function) - { - } - - R operator()(C* c, P1 p1, P2 p2, P3 p3, P4 p4) - { - return (c->*m_function)(p1, p2, p3, p4); - } - -private: - R (C::*m_function)(P1, P2, P3, P4); -}; - -template<typename R, typename C, typename P1, typename P2, typename P3, typename P4, typename P5> -class FunctionWrapper<R (C::*)(P1, P2, P3, P4, P5)> { -public: - typedef R ResultType; - static const bool shouldRefFirstParameter = HasRefAndDeref<C>::value; - - explicit FunctionWrapper(R (C::*function)(P1, P2, P3, P4, P5)) - : m_function(function) - { - } - - R operator()(C* c, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) - { - return (c->*m_function)(p1, p2, p3, p4, p5); - } - -private: - R (C::*m_function)(P1, P2, P3, P4, P5); -}; - -template<typename T, bool shouldRefAndDeref> struct RefAndDeref { - static void ref(T) { } - static void deref(T) { } -}; - -template<typename T> struct RefAndDeref<T*, true> { - static void ref(T* t) { t->ref(); } - static void deref(T* t) { t->deref(); } -}; - -template<typename T> struct ParamStorageTraits { - typedef T StorageType; - - static StorageType wrap(const T& value) { return value; } - static const T& unwrap(const StorageType& value) { return value; } -}; - -template<typename T> struct ParamStorageTraits<PassRefPtr<T> > { - typedef RefPtr<T> StorageType; - - static StorageType wrap(PassRefPtr<T> value) { return value; } - static T* unwrap(const StorageType& value) { return value.get(); } -}; - -template<typename T> struct ParamStorageTraits<RefPtr<T> > { - typedef RefPtr<T> StorageType; - - static StorageType wrap(RefPtr<T> value) { return value.release(); } - static T* unwrap(const StorageType& value) { return value.get(); } -}; - - -template<typename> class RetainPtr; - -template<typename T> struct ParamStorageTraits<RetainPtr<T> > { - typedef RetainPtr<T> StorageType; - - static StorageType wrap(const RetainPtr<T>& value) { return value; } - static typename RetainPtr<T>::PtrType unwrap(const StorageType& value) { return value.get(); } -}; - -class FunctionImplBase : public ThreadSafeRefCounted<FunctionImplBase> { -public: - virtual ~FunctionImplBase() { } -}; - -template<typename> -class FunctionImpl; - -template<typename R> -class FunctionImpl<R ()> : public FunctionImplBase { -public: - virtual R operator()() = 0; -}; - -template<typename FunctionWrapper, typename FunctionType> -class BoundFunctionImpl; - -template<typename FunctionWrapper, typename R> -class BoundFunctionImpl<FunctionWrapper, R ()> : public FunctionImpl<typename FunctionWrapper::ResultType ()> { -public: - explicit BoundFunctionImpl(FunctionWrapper functionWrapper) - : m_functionWrapper(functionWrapper) - { - } - - virtual R operator()() - { - return m_functionWrapper(); - } - -private: - FunctionWrapper m_functionWrapper; -}; - -template<typename FunctionWrapper, typename R, typename P1> -class BoundFunctionImpl<FunctionWrapper, R (P1)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> { - -public: - BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1) - : m_functionWrapper(functionWrapper) - , m_p1(ParamStorageTraits<P1>::wrap(p1)) - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::ref(m_p1); - } - - ~BoundFunctionImpl() - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::deref(m_p1); - } - - virtual R operator()() - { - return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1)); - } - -private: - FunctionWrapper m_functionWrapper; - typename ParamStorageTraits<P1>::StorageType m_p1; -}; - -template<typename FunctionWrapper, typename R, typename P1, typename P2> -class BoundFunctionImpl<FunctionWrapper, R (P1, P2)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> { -public: - BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2) - : m_functionWrapper(functionWrapper) - , m_p1(ParamStorageTraits<P1>::wrap(p1)) - , m_p2(ParamStorageTraits<P2>::wrap(p2)) - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::ref(m_p1); - } - - ~BoundFunctionImpl() - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::deref(m_p1); - } - - virtual typename FunctionWrapper::ResultType operator()() - { - return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2)); - } - -private: - FunctionWrapper m_functionWrapper; - typename ParamStorageTraits<P1>::StorageType m_p1; - typename ParamStorageTraits<P2>::StorageType m_p2; -}; - -template<typename FunctionWrapper, typename R, typename P1, typename P2, typename P3> -class BoundFunctionImpl<FunctionWrapper, R (P1, P2, P3)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> { -public: - BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3) - : m_functionWrapper(functionWrapper) - , m_p1(ParamStorageTraits<P1>::wrap(p1)) - , m_p2(ParamStorageTraits<P2>::wrap(p2)) - , m_p3(ParamStorageTraits<P3>::wrap(p3)) - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::ref(m_p1); - } - - ~BoundFunctionImpl() - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::deref(m_p1); - } - - virtual typename FunctionWrapper::ResultType operator()() - { - return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3)); - } - -private: - FunctionWrapper m_functionWrapper; - typename ParamStorageTraits<P1>::StorageType m_p1; - typename ParamStorageTraits<P2>::StorageType m_p2; - typename ParamStorageTraits<P3>::StorageType m_p3; -}; - -template<typename FunctionWrapper, typename R, typename P1, typename P2, typename P3, typename P4> -class BoundFunctionImpl<FunctionWrapper, R (P1, P2, P3, P4)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> { -public: - BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3, const P4& p4) - : m_functionWrapper(functionWrapper) - , m_p1(ParamStorageTraits<P1>::wrap(p1)) - , m_p2(ParamStorageTraits<P2>::wrap(p2)) - , m_p3(ParamStorageTraits<P3>::wrap(p3)) - , m_p4(ParamStorageTraits<P4>::wrap(p4)) - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::ref(m_p1); - } - - ~BoundFunctionImpl() - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::deref(m_p1); - } - - virtual typename FunctionWrapper::ResultType operator()() - { - return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageTraits<P4>::unwrap(m_p4)); - } - -private: - FunctionWrapper m_functionWrapper; - typename ParamStorageTraits<P1>::StorageType m_p1; - typename ParamStorageTraits<P2>::StorageType m_p2; - typename ParamStorageTraits<P3>::StorageType m_p3; - typename ParamStorageTraits<P4>::StorageType m_p4; -}; - -template<typename FunctionWrapper, typename R, typename P1, typename P2, typename P3, typename P4, typename P5> -class BoundFunctionImpl<FunctionWrapper, R (P1, P2, P3, P4, P5)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> { -public: - BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5) - : m_functionWrapper(functionWrapper) - , m_p1(ParamStorageTraits<P1>::wrap(p1)) - , m_p2(ParamStorageTraits<P2>::wrap(p2)) - , m_p3(ParamStorageTraits<P3>::wrap(p3)) - , m_p4(ParamStorageTraits<P4>::wrap(p4)) - , m_p5(ParamStorageTraits<P5>::wrap(p5)) - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::ref(m_p1); - } - - ~BoundFunctionImpl() - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::deref(m_p1); - } - - virtual typename FunctionWrapper::ResultType operator()() - { - return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageTraits<P4>::unwrap(m_p4), ParamStorageTraits<P5>::unwrap(m_p5)); - } - -private: - FunctionWrapper m_functionWrapper; - typename ParamStorageTraits<P1>::StorageType m_p1; - typename ParamStorageTraits<P2>::StorageType m_p2; - typename ParamStorageTraits<P3>::StorageType m_p3; - typename ParamStorageTraits<P4>::StorageType m_p4; - typename ParamStorageTraits<P5>::StorageType m_p5; -}; - -template<typename FunctionWrapper, typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6> -class BoundFunctionImpl<FunctionWrapper, R (P1, P2, P3, P4, P5, P6)> : public FunctionImpl<typename FunctionWrapper::ResultType ()> { -public: - BoundFunctionImpl(FunctionWrapper functionWrapper, const P1& p1, const P2& p2, const P3& p3, const P4& p4, const P5& p5, const P6& p6) - : m_functionWrapper(functionWrapper) - , m_p1(ParamStorageTraits<P1>::wrap(p1)) - , m_p2(ParamStorageTraits<P2>::wrap(p2)) - , m_p3(ParamStorageTraits<P3>::wrap(p3)) - , m_p4(ParamStorageTraits<P4>::wrap(p4)) - , m_p5(ParamStorageTraits<P5>::wrap(p5)) - , m_p6(ParamStorageTraits<P6>::wrap(p6)) - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::ref(m_p1); - } - - ~BoundFunctionImpl() - { - RefAndDeref<P1, FunctionWrapper::shouldRefFirstParameter>::deref(m_p1); - } - - virtual typename FunctionWrapper::ResultType operator()() - { - return m_functionWrapper(ParamStorageTraits<P1>::unwrap(m_p1), ParamStorageTraits<P2>::unwrap(m_p2), ParamStorageTraits<P3>::unwrap(m_p3), ParamStorageTraits<P4>::unwrap(m_p4), ParamStorageTraits<P5>::unwrap(m_p5), ParamStorageTraits<P6>::unwrap(m_p6)); - } - -private: - FunctionWrapper m_functionWrapper; - typename ParamStorageTraits<P1>::StorageType m_p1; - typename ParamStorageTraits<P2>::StorageType m_p2; - typename ParamStorageTraits<P3>::StorageType m_p3; - typename ParamStorageTraits<P4>::StorageType m_p4; - typename ParamStorageTraits<P5>::StorageType m_p5; - typename ParamStorageTraits<P6>::StorageType m_p6; -}; - -class FunctionBase { -public: - bool isNull() const - { - return !m_impl; - } - -protected: - FunctionBase() - { - } - - explicit FunctionBase(PassRefPtr<FunctionImplBase> impl) - : m_impl(impl) - { - } - - template<typename FunctionType> FunctionImpl<FunctionType>* impl() const - { - return static_cast<FunctionImpl<FunctionType>*>(m_impl.get()); - } - -private: - RefPtr<FunctionImplBase> m_impl; -}; - -template<typename> -class Function; - -template<typename R> -class Function<R ()> : public FunctionBase { -public: - Function() - { - } - - Function(PassRefPtr<FunctionImpl<R ()> > impl) - : FunctionBase(impl) - { - } - - R operator()() const - { - ASSERT(!isNull()); - - return impl<R ()>()->operator()(); - } - -#if PLATFORM(MAC) && COMPILER_SUPPORTS(BLOCKS) - typedef void (^BlockType)(); - operator BlockType() const - { - // Declare a RefPtr here so we'll be sure that the underlying FunctionImpl object's - // lifecycle is managed correctly. - RefPtr<FunctionImpl<R ()> > functionImpl = impl<R ()>(); - BlockType block = ^{ - functionImpl->operator()(); - }; - - // This is equivalent to: - // - // return [[block copy] autorelease]; - // - // We're using manual objc_msgSend calls here because we don't want to make the entire - // file Objective-C. It's useful to be able to implicitly convert a Function to - // a block even in C++ code, since that allows us to do things like: - // - // dispatch_async(queue, bind(...)); - // - id copiedBlock = objc_msgSend((id)block, sel_registerName("copy")); - id autoreleasedBlock = objc_msgSend(copiedBlock, sel_registerName("autorelease")); - return (BlockType)autoreleasedBlock; - } -#endif -}; - -template<typename FunctionType> -Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function) -{ - return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType ()>(FunctionWrapper<FunctionType>(function)))); -} - -template<typename FunctionType, typename A1> -Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1) -{ - return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1)>(FunctionWrapper<FunctionType>(function), a1))); -} - -template<typename FunctionType, typename A1, typename A2> -Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2) -{ - return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2)>(FunctionWrapper<FunctionType>(function), a1, a2))); -} - -template<typename FunctionType, typename A1, typename A2, typename A3> -Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3) -{ - return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2, A3)>(FunctionWrapper<FunctionType>(function), a1, a2, a3))); -} - -template<typename FunctionType, typename A1, typename A2, typename A3, typename A4> -Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3, const A4& a4) -{ - return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2, A3, A4)>(FunctionWrapper<FunctionType>(function), a1, a2, a3, a4))); -} - -template<typename FunctionType, typename A1, typename A2, typename A3, typename A4, typename A5> -Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5) -{ - return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2, A3, A4, A5)>(FunctionWrapper<FunctionType>(function), a1, a2, a3, a4, a5))); -} - -template<typename FunctionType, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6> -Function<typename FunctionWrapper<FunctionType>::ResultType ()> bind(FunctionType function, const A1& a1, const A2& a2, const A3& a3, const A4& a4, const A5& a5, const A6& a6) -{ - return Function<typename FunctionWrapper<FunctionType>::ResultType ()>(adoptRef(new BoundFunctionImpl<FunctionWrapper<FunctionType>, typename FunctionWrapper<FunctionType>::ResultType (A1, A2, A3, A4, A5, A6)>(FunctionWrapper<FunctionType>(function), a1, a2, a3, a4, a5, a6))); -} - -} - -using WTF::Function; -using WTF::bind; - -#endif // WTF_Functional_h diff --git a/Source/JavaScriptCore/wtf/GetPtr.h b/Source/JavaScriptCore/wtf/GetPtr.h deleted file mode 100644 index 25a0e6d9b..000000000 --- a/Source/JavaScriptCore/wtf/GetPtr.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 WTF_GetPtr_h -#define WTF_GetPtr_h - -namespace WTF { - - template <typename T> inline T* getPtr(T* p) - { - return p; - } - -} // namespace WTF - -#endif // WTF_GetPtr_h diff --git a/Source/JavaScriptCore/wtf/HashCountedSet.h b/Source/JavaScriptCore/wtf/HashCountedSet.h deleted file mode 100644 index cafb2649e..000000000 --- a/Source/JavaScriptCore/wtf/HashCountedSet.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 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 WTF_HashCountedSet_h -#define WTF_HashCountedSet_h - -#include <wtf/Assertions.h> -#include <wtf/HashMap.h> -#include <wtf/Vector.h> - -namespace WTF { - - template<typename Value, typename HashFunctions = typename DefaultHash<Value>::Hash, - typename Traits = HashTraits<Value> > class HashCountedSet { - WTF_MAKE_FAST_ALLOCATED; - private: - typedef HashMap<Value, unsigned, HashFunctions, Traits> ImplType; - public: - typedef Value ValueType; - typedef typename ImplType::iterator iterator; - typedef typename ImplType::const_iterator const_iterator; - - HashCountedSet() {} - - int size() const; - int capacity() const; - bool isEmpty() const; - - // Iterators iterate over pairs of values and counts. - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - - iterator find(const ValueType&); - const_iterator find(const ValueType&) const; - 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. - std::pair<iterator, bool> add(const ValueType&); - - // 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. - void removeAll(iterator); - void removeAll(const ValueType&); - - // Clears the whole set. - void clear(); - - private: - ImplType m_impl; - }; - - template<typename Value, typename HashFunctions, typename Traits> - inline int HashCountedSet<Value, HashFunctions, Traits>::size() const - { - return m_impl.size(); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline int HashCountedSet<Value, HashFunctions, Traits>::capacity() const - { - return m_impl.capacity(); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline bool HashCountedSet<Value, HashFunctions, Traits>::isEmpty() const - { - return size() == 0; - } - - template<typename Value, typename HashFunctions, typename Traits> - inline typename HashCountedSet<Value, HashFunctions, Traits>::iterator HashCountedSet<Value, HashFunctions, Traits>::begin() - { - return m_impl.begin(); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline typename HashCountedSet<Value, HashFunctions, Traits>::iterator HashCountedSet<Value, HashFunctions, Traits>::end() - { - return m_impl.end(); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator HashCountedSet<Value, HashFunctions, Traits>::begin() const - { - return m_impl.begin(); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator HashCountedSet<Value, HashFunctions, Traits>::end() const - { - return m_impl.end(); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline typename HashCountedSet<Value, HashFunctions, Traits>::iterator HashCountedSet<Value, HashFunctions, Traits>::find(const ValueType& value) - { - return m_impl.find(value); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator HashCountedSet<Value, HashFunctions, Traits>::find(const ValueType& value) const - { - return m_impl.find(value); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline bool HashCountedSet<Value, HashFunctions, Traits>::contains(const ValueType& value) const - { - return m_impl.contains(value); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline unsigned HashCountedSet<Value, HashFunctions, Traits>::count(const ValueType& value) const - { - return m_impl.get(value); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline std::pair<typename HashCountedSet<Value, HashFunctions, Traits>::iterator, bool> HashCountedSet<Value, HashFunctions, Traits>::add(const ValueType &value) - { - pair<iterator, bool> result = m_impl.add(value, 0); - ++result.first->second; - return result; - } - - template<typename Value, typename HashFunctions, typename Traits> - inline bool HashCountedSet<Value, HashFunctions, Traits>::remove(const ValueType& value) - { - return remove(find(value)); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline bool HashCountedSet<Value, HashFunctions, Traits>::remove(iterator it) - { - if (it == end()) - return false; - - unsigned oldVal = it->second; - ASSERT(oldVal); - unsigned newVal = oldVal - 1; - if (newVal) { - it->second = newVal; - return false; - } - - m_impl.remove(it); - return true; - } - - template<typename Value, typename HashFunctions, typename Traits> - inline void HashCountedSet<Value, HashFunctions, Traits>::removeAll(const ValueType& value) - { - removeAll(find(value)); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline void HashCountedSet<Value, HashFunctions, Traits>::removeAll(iterator it) - { - if (it == end()) - return; - - m_impl.remove(it); - } - - template<typename Value, typename HashFunctions, typename Traits> - inline void HashCountedSet<Value, HashFunctions, Traits>::clear() - { - m_impl.clear(); - } - - template<typename Value, typename HashFunctions, typename Traits, typename VectorType> - inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits>& collection, VectorType& vector) - { - typedef typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator iterator; - - vector.resize(collection.size()); - - iterator it = collection.begin(); - iterator end = collection.end(); - for (unsigned i = 0; it != end; ++it, ++i) - vector[i] = *it; - } - - template<typename Value, typename HashFunctions, typename Traits> - inline void copyToVector(const HashCountedSet<Value, HashFunctions, Traits>& collection, Vector<Value>& vector) - { - typedef typename HashCountedSet<Value, HashFunctions, Traits>::const_iterator iterator; - - vector.resize(collection.size()); - - iterator it = collection.begin(); - iterator end = collection.end(); - for (unsigned i = 0; it != end; ++it, ++i) - vector[i] = (*it).first; - } - - -} // namespace khtml - -using WTF::HashCountedSet; - -#endif /* WTF_HashCountedSet_h */ diff --git a/Source/JavaScriptCore/wtf/HashFunctions.h b/Source/JavaScriptCore/wtf/HashFunctions.h deleted file mode 100644 index 808b2b1e5..000000000 --- a/Source/JavaScriptCore/wtf/HashFunctions.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 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 WTF_HashFunctions_h -#define WTF_HashFunctions_h - -#include <wtf/RefPtr.h> -#include <stdint.h> - -namespace WTF { - - template<size_t size> struct IntTypes; - template<> struct IntTypes<1> { typedef int8_t SignedType; typedef uint8_t UnsignedType; }; - template<> struct IntTypes<2> { typedef int16_t SignedType; typedef uint16_t UnsignedType; }; - template<> struct IntTypes<4> { typedef int32_t SignedType; typedef uint32_t UnsignedType; }; - template<> struct IntTypes<8> { typedef int64_t SignedType; typedef uint64_t UnsignedType; }; - - // integer hash function - - // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm - inline unsigned intHash(uint8_t key8) - { - unsigned key = key8; - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; - } - - // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm - inline unsigned intHash(uint16_t key16) - { - unsigned key = key16; - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; - } - - // Thomas Wang's 32 Bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm - inline unsigned intHash(uint32_t key) - { - key += ~(key << 15); - key ^= (key >> 10); - key += (key << 3); - key ^= (key >> 6); - key += ~(key << 11); - key ^= (key >> 16); - return key; - } - - // Thomas Wang's 64 bit Mix Function: http://www.cris.com/~Ttwang/tech/inthash.htm - inline unsigned intHash(uint64_t key) - { - key += ~(key << 32); - key ^= (key >> 22); - key += ~(key << 13); - key ^= (key >> 8); - key += (key << 3); - key ^= (key >> 15); - key += ~(key << 27); - key ^= (key >> 31); - return static_cast<unsigned>(key); - } - - template<typename T> struct IntHash { - static unsigned hash(T key) { return intHash(static_cast<typename IntTypes<sizeof(T)>::UnsignedType>(key)); } - static bool equal(T a, T b) { return a == b; } - static const bool safeToCompareToEmptyOrDeleted = true; - }; - - template<typename T> struct FloatHash { - static unsigned hash(T key) - { - union { - T key; - typename IntTypes<sizeof(T)>::UnsignedType bits; - } u; - u.key = key; - return intHash(u.bits); - } - static bool equal(T a, T b) { return a == b; } - static const bool safeToCompareToEmptyOrDeleted = true; - }; - - // pointer identity hash function - - template<typename T> struct PtrHash { - static unsigned hash(T key) - { -#if COMPILER(MSVC) -#pragma warning(push) -#pragma warning(disable: 4244) // work around what seems to be a bug in MSVC's conversion warnings -#endif - return IntHash<uintptr_t>::hash(reinterpret_cast<uintptr_t>(key)); -#if COMPILER(MSVC) -#pragma warning(pop) -#endif - } - static bool equal(T a, T b) { return a == b; } - static const bool safeToCompareToEmptyOrDeleted = true; - }; - template<typename P> struct PtrHash<RefPtr<P> > : PtrHash<P*> { - using PtrHash<P*>::hash; - static unsigned hash(const RefPtr<P>& key) { return hash(key.get()); } - using PtrHash<P*>::equal; - static bool equal(const RefPtr<P>& a, const RefPtr<P>& b) { return a == b; } - static bool equal(P* a, const RefPtr<P>& b) { return a == b; } - static bool equal(const RefPtr<P>& a, P* b) { return a == b; } - }; - - // default hash function for each type - - template<typename T> struct DefaultHash; - - template<typename T, typename U> struct PairHash { - static unsigned hash(const std::pair<T, U>& p) - { - return intHash((static_cast<uint64_t>(DefaultHash<T>::Hash::hash(p.first)) << 32 | DefaultHash<U>::Hash::hash(p.second))); - } - static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b) - { - return DefaultHash<T>::Hash::equal(a.first, b.first) && DefaultHash<U>::Hash::equal(a.second, b.second); - } - static const bool safeToCompareToEmptyOrDeleted = DefaultHash<T>::Hash::safeToCompareToEmptyOrDeleted - && DefaultHash<U>::Hash::safeToCompareToEmptyOrDeleted; - }; - - // make IntHash the default hash function for many integer types - - template<> struct DefaultHash<short> { typedef IntHash<unsigned> Hash; }; - template<> struct DefaultHash<unsigned short> { typedef IntHash<unsigned> Hash; }; - template<> struct DefaultHash<int> { typedef IntHash<unsigned> Hash; }; - template<> struct DefaultHash<unsigned> { typedef IntHash<unsigned> Hash; }; - template<> struct DefaultHash<long> { typedef IntHash<unsigned long> Hash; }; - template<> struct DefaultHash<unsigned long> { typedef IntHash<unsigned long> Hash; }; - template<> struct DefaultHash<long long> { typedef IntHash<unsigned long long> Hash; }; - template<> struct DefaultHash<unsigned long long> { typedef IntHash<unsigned long long> Hash; }; - -#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) - template<> struct DefaultHash<wchar_t> { typedef IntHash<wchar_t> Hash; }; -#endif - - template<> struct DefaultHash<float> { typedef FloatHash<float> Hash; }; - template<> struct DefaultHash<double> { typedef FloatHash<double> Hash; }; - - // make PtrHash the default hash function for pointer types that don't specialize - - template<typename P> struct DefaultHash<P*> { typedef PtrHash<P*> Hash; }; - template<typename P> struct DefaultHash<RefPtr<P> > { typedef PtrHash<RefPtr<P> > Hash; }; - - template<typename T, typename U> struct DefaultHash<std::pair<T, U> > { typedef PairHash<T, U> Hash; }; - -} // namespace WTF - -using WTF::DefaultHash; -using WTF::IntHash; -using WTF::PtrHash; - -#endif // WTF_HashFunctions_h diff --git a/Source/JavaScriptCore/wtf/HashIterators.h b/Source/JavaScriptCore/wtf/HashIterators.h deleted file mode 100644 index 6afa2fa57..000000000 --- a/Source/JavaScriptCore/wtf/HashIterators.h +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2007 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 WTF_HashIterators_h -#define WTF_HashIterators_h - -namespace WTF { - - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstKeysIterator; - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstValuesIterator; - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableKeysIterator; - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableValuesIterator; - - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > { - private: - typedef std::pair<KeyType, MappedType> ValueType; - public: - typedef HashTableConstKeysIterator<HashTableType, KeyType, MappedType> Keys; - typedef HashTableConstValuesIterator<HashTableType, KeyType, MappedType> Values; - - HashTableConstIteratorAdapter() {} - HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {} - - const ValueType* get() const { return (const ValueType*)m_impl.get(); } - const ValueType& operator*() const { return *get(); } - const ValueType* operator->() const { return get(); } - - HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; } - // postfix ++ intentionally omitted - - Keys keys() { return Keys(*this); } - Values values() { return Values(*this); } - - typename HashTableType::const_iterator m_impl; - }; - - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > { - private: - typedef std::pair<KeyType, MappedType> ValueType; - public: - typedef HashTableKeysIterator<HashTableType, KeyType, MappedType> Keys; - typedef HashTableValuesIterator<HashTableType, KeyType, MappedType> Values; - - HashTableIteratorAdapter() {} - HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {} - - ValueType* get() const { return (ValueType*)m_impl.get(); } - ValueType& operator*() const { return *get(); } - ValueType* operator->() const { return get(); } - - HashTableIteratorAdapter& operator++() { ++m_impl; return *this; } - // postfix ++ intentionally omitted - - operator HashTableConstIteratorAdapter<HashTableType, ValueType>() { - typename HashTableType::const_iterator i = m_impl; - return i; - } - - Keys keys() { return Keys(*this); } - Values values() { return Values(*this); } - - typename HashTableType::iterator m_impl; - }; - - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstKeysIterator { - private: - typedef HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > ConstIterator; - - public: - HashTableConstKeysIterator(const ConstIterator& impl) : m_impl(impl) {} - - const KeyType* get() const { return &(m_impl.get()->first); } - const KeyType& operator*() const { return *get(); } - const KeyType* operator->() const { return get(); } - - HashTableConstKeysIterator& operator++() { ++m_impl; return *this; } - // postfix ++ intentionally omitted - - ConstIterator m_impl; - }; - - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableConstValuesIterator { - private: - typedef HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > ConstIterator; - - public: - HashTableConstValuesIterator(const ConstIterator& impl) : m_impl(impl) {} - - const MappedType* get() const { return &(m_impl.get()->second); } - const MappedType& operator*() const { return *get(); } - const MappedType* operator->() const { return get(); } - - HashTableConstValuesIterator& operator++() { ++m_impl; return *this; } - // postfix ++ intentionally omitted - - ConstIterator m_impl; - }; - - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableKeysIterator { - private: - typedef HashTableIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > Iterator; - typedef HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > ConstIterator; - - public: - HashTableKeysIterator(const Iterator& impl) : m_impl(impl) {} - - KeyType* get() const { return &(m_impl.get()->first); } - KeyType& operator*() const { return *get(); } - KeyType* operator->() const { return get(); } - - HashTableKeysIterator& operator++() { ++m_impl; return *this; } - // postfix ++ intentionally omitted - - operator HashTableConstKeysIterator<HashTableType, KeyType, MappedType>() { - ConstIterator i = m_impl; - return i; - } - - Iterator m_impl; - }; - - template<typename HashTableType, typename KeyType, typename MappedType> struct HashTableValuesIterator { - private: - typedef HashTableIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > Iterator; - typedef HashTableConstIteratorAdapter<HashTableType, std::pair<KeyType, MappedType> > ConstIterator; - - public: - HashTableValuesIterator(const Iterator& impl) : m_impl(impl) {} - - MappedType* get() const { return &(m_impl.get()->second); } - MappedType& operator*() const { return *get(); } - MappedType* operator->() const { return get(); } - - HashTableValuesIterator& operator++() { ++m_impl; return *this; } - // postfix ++ intentionally omitted - - operator HashTableConstValuesIterator<HashTableType, KeyType, MappedType>() { - ConstIterator i = m_impl; - return i; - } - - Iterator m_impl; - }; - - template<typename T, typename U, typename V> - inline bool operator==(const HashTableConstKeysIterator<T, U, V>& a, const HashTableConstKeysIterator<T, U, V>& b) - { - return a.m_impl == b.m_impl; - } - - template<typename T, typename U, typename V> - inline bool operator!=(const HashTableConstKeysIterator<T, U, V>& a, const HashTableConstKeysIterator<T, U, V>& b) - { - return a.m_impl != b.m_impl; - } - - template<typename T, typename U, typename V> - inline bool operator==(const HashTableConstValuesIterator<T, U, V>& a, const HashTableConstValuesIterator<T, U, V>& b) - { - return a.m_impl == b.m_impl; - } - - template<typename T, typename U, typename V> - inline bool operator!=(const HashTableConstValuesIterator<T, U, V>& a, const HashTableConstValuesIterator<T, U, V>& b) - { - return a.m_impl != b.m_impl; - } - - template<typename T, typename U, typename V> - inline bool operator==(const HashTableKeysIterator<T, U, V>& a, const HashTableKeysIterator<T, U, V>& b) - { - return a.m_impl == b.m_impl; - } - - template<typename T, typename U, typename V> - inline bool operator!=(const HashTableKeysIterator<T, U, V>& a, const HashTableKeysIterator<T, U, V>& b) - { - return a.m_impl != b.m_impl; - } - - template<typename T, typename U, typename V> - inline bool operator==(const HashTableValuesIterator<T, U, V>& a, const HashTableValuesIterator<T, U, V>& b) - { - return a.m_impl == b.m_impl; - } - - template<typename T, typename U, typename V> - inline bool operator!=(const HashTableValuesIterator<T, U, V>& a, const HashTableValuesIterator<T, U, V>& b) - { - return a.m_impl != b.m_impl; - } - - -} // namespace WTF - -#endif // WTF_HashIterators_h diff --git a/Source/JavaScriptCore/wtf/HashMap.h b/Source/JavaScriptCore/wtf/HashMap.h deleted file mode 100644 index be7e9ebed..000000000 --- a/Source/JavaScriptCore/wtf/HashMap.h +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_HashMap_h -#define WTF_HashMap_h - -#include <wtf/HashTable.h> - -namespace WTF { - - template<typename PairType> struct PairFirstExtractor; - - template<typename T> struct ReferenceTypeMaker { - typedef T& ReferenceType; - }; - template<typename T> struct ReferenceTypeMaker<T&> { - typedef T& ReferenceType; - }; - - template<typename KeyArg, typename MappedArg, typename HashArg = typename DefaultHash<KeyArg>::Hash, - typename KeyTraitsArg = HashTraits<KeyArg>, typename MappedTraitsArg = HashTraits<MappedArg> > - class HashMap { - WTF_MAKE_FAST_ALLOCATED; - private: - typedef KeyTraitsArg KeyTraits; - typedef MappedTraitsArg MappedTraits; - typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits; - - public: - typedef typename KeyTraits::TraitType KeyType; - typedef typename MappedTraits::TraitType MappedType; - typedef typename ValueTraits::TraitType ValueType; - - private: - typedef typename MappedTraits::PassInType MappedPassInType; - typedef typename MappedTraits::PassOutType MappedPassOutType; - typedef typename MappedTraits::PeekType MappedPeekType; - - typedef typename ReferenceTypeMaker<MappedPassInType>::ReferenceType MappedPassInReferenceType; - - typedef HashArg HashFunctions; - - typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>, - HashFunctions, ValueTraits, KeyTraits> HashTableType; - - class HashMapKeysProxy; - class HashMapValuesProxy; - - public: - typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator; - typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator; - - public: - void swap(HashMap&); - - int size() const; - int capacity() const; - bool isEmpty() const; - - // iterators iterate over pairs of keys and values - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - - HashMapKeysProxy& keys() { return static_cast<HashMapKeysProxy&>(*this); } - const HashMapKeysProxy& keys() const { return static_cast<const HashMapKeysProxy&>(*this); } - - HashMapValuesProxy& values() { return static_cast<HashMapValuesProxy&>(*this); } - const HashMapValuesProxy& values() const { return static_cast<const HashMapValuesProxy&>(*this); } - - iterator find(const KeyType&); - const_iterator find(const KeyType&) const; - bool contains(const KeyType&) const; - MappedPeekType get(const KeyType&) const; - - // replaces value but not key if key is already present - // return value is a pair of the iterator to the key location, - // and a boolean that's true if a new value was actually added - pair<iterator, bool> set(const KeyType&, MappedPassInType); - - // does nothing if key is already present - // return value is a pair of the iterator to the key location, - // and a boolean that's true if a new value was actually added - pair<iterator, bool> add(const KeyType&, MappedPassInType); - - void remove(const KeyType&); - void remove(iterator); - void clear(); - - MappedPassOutType take(const KeyType&); // efficient combination of get with remove - - // An alternate version of find() that finds the object by hashing and comparing - // with some other type, to avoid the cost of type conversion. HashTranslator - // must have the following function members: - // static unsigned hash(const T&); - // static bool equal(const ValueType&, const T&); - template<typename T, typename HashTranslator> iterator find(const T&); - template<typename T, typename HashTranslator> const_iterator find(const T&) const; - template<typename T, typename HashTranslator> bool contains(const T&) const; - - // An alternate version of add() that finds the object by hashing and comparing - // with some other type, to avoid the cost of type conversion if the object is already - // in the table. HashTranslator must have the following function members: - // static unsigned hash(const T&); - // static bool equal(const ValueType&, const T&); - // static translate(ValueType&, const T&, unsigned hashCode); - template<typename T, typename HashTranslator> pair<iterator, bool> add(const T&, MappedPassInType); - - void checkConsistency() const; - - private: - pair<iterator, bool> inlineAdd(const KeyType&, MappedPassInReferenceType); - - class HashMapKeysProxy : private HashMap { - public: - typedef typename HashMap::iterator::Keys iterator; - typedef typename HashMap::const_iterator::Keys const_iterator; - - iterator begin() - { - return HashMap::begin().keys(); - } - - iterator end() - { - return HashMap::end().keys(); - } - - const_iterator begin() const - { - return HashMap::begin().keys(); - } - - const_iterator end() const - { - return HashMap::end().keys(); - } - - private: - friend class HashMap; - - // These are intentionally not implemented. - HashMapKeysProxy(); - HashMapKeysProxy(const HashMapKeysProxy&); - HashMapKeysProxy& operator=(const HashMapKeysProxy&); - ~HashMapKeysProxy(); - }; - - class HashMapValuesProxy : private HashMap { - public: - typedef typename HashMap::iterator::Values iterator; - typedef typename HashMap::const_iterator::Values const_iterator; - - iterator begin() - { - return HashMap::begin().values(); - } - - iterator end() - { - return HashMap::end().values(); - } - - const_iterator begin() const - { - return HashMap::begin().values(); - } - - const_iterator end() const - { - return HashMap::end().values(); - } - - private: - friend class HashMap; - - // These are intentionally not implemented. - HashMapValuesProxy(); - HashMapValuesProxy(const HashMapValuesProxy&); - HashMapValuesProxy& operator=(const HashMapValuesProxy&); - ~HashMapValuesProxy(); - }; - - HashTableType m_impl; - }; - - template<typename PairType> struct PairFirstExtractor { - static const typename PairType::first_type& extract(const PairType& p) { return p.first; } - }; - - template<typename ValueTraits, typename HashFunctions> - struct HashMapTranslator { - template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); } - template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a, b); } - template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped) - { - location.first = key; - ValueTraits::SecondTraits::store(mapped, location.second); - } - }; - - template<typename ValueTraits, typename Translator> - struct HashMapTranslatorAdapter { - template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); } - template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); } - template<typename T, typename U, typename V> static void translate(T& location, const U& key, const V& mapped, unsigned hashCode) - { - Translator::translate(location.first, key, hashCode); - ValueTraits::SecondTraits::store(mapped, location.second); - } - }; - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<T, U, V, W, X>::swap(HashMap& other) - { - m_impl.swap(other.m_impl); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline int HashMap<T, U, V, W, X>::size() const - { - return m_impl.size(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline int HashMap<T, U, V, W, X>::capacity() const - { - return m_impl.capacity(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline bool HashMap<T, U, V, W, X>::isEmpty() const - { - return m_impl.isEmpty(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::begin() - { - return m_impl.begin(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::end() - { - return m_impl.end(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::begin() const - { - return m_impl.begin(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::end() const - { - return m_impl.end(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<T, U, V, W, X>::iterator HashMap<T, U, V, W, X>::find(const KeyType& key) - { - return m_impl.find(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<T, U, V, W, X>::const_iterator HashMap<T, U, V, W, X>::find(const KeyType& key) const - { - return m_impl.find(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline bool HashMap<T, U, V, W, X>::contains(const KeyType& key) const - { - return m_impl.contains(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - template<typename TYPE, typename HashTranslator> - inline typename HashMap<T, U, V, W, X>::iterator - HashMap<T, U, V, W, X>::find(const TYPE& value) - { - return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value); - } - - template<typename T, typename U, typename V, typename W, typename X> - template<typename TYPE, typename HashTranslator> - inline typename HashMap<T, U, V, W, X>::const_iterator - HashMap<T, U, V, W, X>::find(const TYPE& value) const - { - return m_impl.template find<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value); - } - - template<typename T, typename U, typename V, typename W, typename X> - template<typename TYPE, typename HashTranslator> - inline bool - HashMap<T, U, V, W, X>::contains(const TYPE& value) const - { - return m_impl.template contains<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(value); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline pair<typename HashMap<T, U, V, W, X>::iterator, bool> - HashMap<T, U, V, W, X>::inlineAdd(const KeyType& key, MappedPassInReferenceType mapped) - { - return m_impl.template add<HashMapTranslator<ValueTraits, HashFunctions> >(key, mapped); - } - - template<typename T, typename U, typename V, typename W, typename X> - pair<typename HashMap<T, U, V, W, X>::iterator, bool> - HashMap<T, U, V, W, X>::set(const KeyType& key, MappedPassInType mapped) - { - pair<iterator, bool> result = inlineAdd(key, mapped); - if (!result.second) { - // The inlineAdd call above found an existing hash table entry; we need to set the mapped value. - MappedTraits::store(mapped, result.first->second); - } - return result; - } - - template<typename T, typename U, typename V, typename W, typename X> - template<typename TYPE, typename HashTranslator> - pair<typename HashMap<T, U, V, W, X>::iterator, bool> - HashMap<T, U, V, W, X>::add(const TYPE& key, MappedPassInType value) - { - return m_impl.template addPassingHashCode<HashMapTranslatorAdapter<ValueTraits, HashTranslator> >(key, value); - } - - template<typename T, typename U, typename V, typename W, typename X> - pair<typename HashMap<T, U, V, W, X>::iterator, bool> - HashMap<T, U, V, W, X>::add(const KeyType& key, MappedPassInType mapped) - { - return inlineAdd(key, mapped); - } - - template<typename T, typename U, typename V, typename W, typename MappedTraits> - typename HashMap<T, U, V, W, MappedTraits>::MappedPeekType - HashMap<T, U, V, W, MappedTraits>::get(const KeyType& key) const - { - ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key); - if (!entry) - return MappedTraits::peek(MappedTraits::emptyValue()); - return MappedTraits::peek(entry->second); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<T, U, V, W, X>::remove(iterator it) - { - if (it.m_impl == m_impl.end()) - return; - m_impl.internalCheckTableConsistency(); - m_impl.removeWithoutEntryConsistencyCheck(it.m_impl); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<T, U, V, W, X>::remove(const KeyType& key) - { - remove(find(key)); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<T, U, V, W, X>::clear() - { - m_impl.clear(); - } - - template<typename T, typename U, typename V, typename W, typename MappedTraits> - typename HashMap<T, U, V, W, MappedTraits>::MappedPassOutType - HashMap<T, U, V, W, MappedTraits>::take(const KeyType& key) - { - iterator it = find(key); - if (it == end()) - return MappedTraits::passOut(MappedTraits::emptyValue()); - MappedPassOutType result = MappedTraits::passOut(it->second); - remove(it); - return result; - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<T, U, V, W, X>::checkConsistency() const - { - m_impl.checkTableConsistency(); - } - - template<typename T, typename U, typename V, typename W, typename X> - bool operator==(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b) - { - if (a.size() != b.size()) - return false; - - typedef typename HashMap<T, U, V, W, X>::const_iterator const_iterator; - - const_iterator end = a.end(); - const_iterator notFound = b.end(); - for (const_iterator it = a.begin(); it != end; ++it) { - const_iterator bPos = b.find(it->first); - if (bPos == notFound || it->second != bPos->second) - return false; - } - - return true; - } - - template<typename T, typename U, typename V, typename W, typename X> - inline bool operator!=(const HashMap<T, U, V, W, X>& a, const HashMap<T, U, V, W, X>& b) - { - return !(a == b); - } - - template<typename HashTableType> - void deleteAllPairSeconds(HashTableType& collection) - { - typedef typename HashTableType::const_iterator iterator; - iterator end = collection.end(); - for (iterator it = collection.begin(); it != end; ++it) - delete it->second; - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void deleteAllValues(const HashMap<T, U, V, W, X>& collection) - { - deleteAllPairSeconds(collection); - } - - template<typename HashTableType> - void deleteAllPairFirsts(HashTableType& collection) - { - typedef typename HashTableType::const_iterator iterator; - iterator end = collection.end(); - for (iterator it = collection.begin(); it != end; ++it) - delete it->first; - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void deleteAllKeys(const HashMap<T, U, V, W, X>& collection) - { - deleteAllPairFirsts(collection); - } - - template<typename T, typename U, typename V, typename W, typename X, typename Y> - inline void copyKeysToVector(const HashMap<T, U, V, W, X>& collection, Y& vector) - { - typedef typename HashMap<T, U, V, W, X>::const_iterator::Keys iterator; - - vector.resize(collection.size()); - - iterator it = collection.begin().keys(); - iterator end = collection.end().keys(); - for (unsigned i = 0; it != end; ++it, ++i) - vector[i] = *it; - } - - template<typename T, typename U, typename V, typename W, typename X, typename Y> - inline void copyValuesToVector(const HashMap<T, U, V, W, X>& collection, Y& vector) - { - typedef typename HashMap<T, U, V, W, X>::const_iterator::Values iterator; - - vector.resize(collection.size()); - - iterator it = collection.begin().values(); - iterator end = collection.end().values(); - for (unsigned i = 0; it != end; ++it, ++i) - vector[i] = *it; - } - -} // namespace WTF - -using WTF::HashMap; - -#include <wtf/RefPtrHashMap.h> - -#endif /* WTF_HashMap_h */ diff --git a/Source/JavaScriptCore/wtf/HashSet.h b/Source/JavaScriptCore/wtf/HashSet.h deleted file mode 100644 index 33cb14daa..000000000 --- a/Source/JavaScriptCore/wtf/HashSet.h +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_HashSet_h -#define WTF_HashSet_h - -#include <wtf/FastAllocBase.h> -#include <wtf/HashTable.h> - -namespace WTF { - - struct IdentityExtractor; - - template<typename Value, typename HashFunctions, typename Traits> class HashSet; - template<typename Value, typename HashFunctions, typename Traits> - void deleteAllValues(const HashSet<Value, HashFunctions, Traits>&); - template<typename Value, typename HashFunctions, typename Traits> - void fastDeleteAllValues(const HashSet<Value, HashFunctions, Traits>&); - - template<typename ValueArg, typename HashArg = typename DefaultHash<ValueArg>::Hash, - typename TraitsArg = HashTraits<ValueArg> > class HashSet { - WTF_MAKE_FAST_ALLOCATED; - private: - typedef HashArg HashFunctions; - typedef TraitsArg ValueTraits; - - public: - typedef typename ValueTraits::TraitType ValueType; - - private: - typedef HashTable<ValueType, ValueType, IdentityExtractor, - HashFunctions, ValueTraits, ValueTraits> HashTableType; - - public: - typedef HashTableConstIteratorAdapter<HashTableType, ValueType> iterator; - typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator; - - void swap(HashSet&); - - int size() const; - int capacity() const; - bool isEmpty() const; - - iterator begin() const; - iterator end() const; - - iterator find(const ValueType&) const; - bool contains(const ValueType&) const; - - // An alternate version of find() that finds the object by hashing and comparing - // with some other type, to avoid the cost of type conversion. HashTranslator - // must have the following function members: - // static unsigned hash(const T&); - // static bool equal(const ValueType&, const T&); - // FIXME: We should reverse the order of the template arguments so that callers - // can just pass the translator and let the compiler deduce T. - template<typename T, typename HashTranslator> iterator find(const T&) const; - template<typename T, typename HashTranslator> bool contains(const T&) const; - - // 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. - pair<iterator, bool> add(const ValueType&); - - // An alternate version of add() that finds the object by hashing and comparing - // with some other type, to avoid the cost of type conversion if the object is already - // in the table. HashTranslator must have the following function members: - // static unsigned hash(const T&); - // static bool equal(const ValueType&, const T&); - // static translate(ValueType&, const T&, unsigned hashCode); - // FIXME: We should reverse the order of the template arguments so that callers - // can just pass the translator and let the compiler deduce T. - template<typename T, typename HashTranslator> pair<iterator, bool> add(const T&); - - void remove(const ValueType&); - void remove(iterator); - void clear(); - - private: - friend void deleteAllValues<>(const HashSet&); - friend void fastDeleteAllValues<>(const HashSet&); - - HashTableType m_impl; - }; - - struct IdentityExtractor { - template<typename T> static const T& extract(const T& t) { return t; } - }; - - template<typename Translator> - struct HashSetTranslatorAdapter { - template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); } - template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a, b); } - template<typename T, typename U> static void translate(T& location, const U& key, const U&, unsigned hashCode) - { - Translator::translate(location, key, hashCode); - } - }; - - template<typename T, typename U, typename V> - inline void HashSet<T, U, V>::swap(HashSet& other) - { - m_impl.swap(other.m_impl); - } - - template<typename T, typename U, typename V> - inline int HashSet<T, U, V>::size() const - { - return m_impl.size(); - } - - template<typename T, typename U, typename V> - inline int HashSet<T, U, V>::capacity() const - { - return m_impl.capacity(); - } - - template<typename T, typename U, typename V> - inline bool HashSet<T, U, V>::isEmpty() const - { - return m_impl.isEmpty(); - } - - template<typename T, typename U, typename V> - inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::begin() const - { - return m_impl.begin(); - } - - template<typename T, typename U, typename V> - inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::end() const - { - return m_impl.end(); - } - - template<typename T, typename U, typename V> - inline typename HashSet<T, U, V>::iterator HashSet<T, U, V>::find(const ValueType& value) const - { - return m_impl.find(value); - } - - template<typename T, typename U, typename V> - inline bool HashSet<T, U, V>::contains(const ValueType& value) const - { - return m_impl.contains(value); - } - - template<typename Value, typename HashFunctions, typename Traits> - template<typename T, typename HashTranslator> - typename HashSet<Value, HashFunctions, Traits>::iterator - inline HashSet<Value, HashFunctions, Traits>::find(const T& value) const - { - return m_impl.template find<HashSetTranslatorAdapter<HashTranslator> >(value); - } - - template<typename Value, typename HashFunctions, typename Traits> - template<typename T, typename HashTranslator> - inline bool HashSet<Value, HashFunctions, Traits>::contains(const T& value) const - { - return m_impl.template contains<HashSetTranslatorAdapter<HashTranslator> >(value); - } - - template<typename T, typename U, typename V> - inline pair<typename HashSet<T, U, V>::iterator, bool> HashSet<T, U, V>::add(const ValueType& value) - { - return m_impl.add(value); - } - - template<typename Value, typename HashFunctions, typename Traits> - template<typename T, typename HashTranslator> - inline pair<typename HashSet<Value, HashFunctions, Traits>::iterator, bool> - HashSet<Value, HashFunctions, Traits>::add(const T& value) - { - return m_impl.template addPassingHashCode<HashSetTranslatorAdapter<HashTranslator> >(value, value); - } - - template<typename T, typename U, typename V> - inline void HashSet<T, U, V>::remove(iterator it) - { - if (it.m_impl == m_impl.end()) - return; - m_impl.internalCheckTableConsistency(); - m_impl.removeWithoutEntryConsistencyCheck(it.m_impl); - } - - template<typename T, typename U, typename V> - inline void HashSet<T, U, V>::remove(const ValueType& value) - { - remove(find(value)); - } - - template<typename T, typename U, typename V> - inline void HashSet<T, U, V>::clear() - { - m_impl.clear(); - } - - template<typename ValueType, typename HashTableType> - void deleteAllValues(HashTableType& collection) - { - typedef typename HashTableType::const_iterator iterator; - iterator end = collection.end(); - for (iterator it = collection.begin(); it != end; ++it) - delete *it; - } - - template<typename T, typename U, typename V> - inline void deleteAllValues(const HashSet<T, U, V>& collection) - { - deleteAllValues<typename HashSet<T, U, V>::ValueType>(collection.m_impl); - } - - template<typename ValueType, typename HashTableType> - void fastDeleteAllValues(HashTableType& collection) - { - typedef typename HashTableType::const_iterator iterator; - iterator end = collection.end(); - for (iterator it = collection.begin(); it != end; ++it) - fastDelete(*it); - } - - template<typename T, typename U, typename V> - inline void fastDeleteAllValues(const HashSet<T, U, V>& collection) - { - fastDeleteAllValues<typename HashSet<T, U, V>::ValueType>(collection.m_impl); - } - - template<typename T, typename U, typename V, typename W> - inline void copyToVector(const HashSet<T, U, V>& collection, W& vector) - { - typedef typename HashSet<T, U, V>::const_iterator iterator; - - vector.resize(collection.size()); - - iterator it = collection.begin(); - iterator end = collection.end(); - for (unsigned i = 0; it != end; ++it, ++i) - vector[i] = *it; - } - -} // namespace WTF - -using WTF::HashSet; - -#endif /* WTF_HashSet_h */ diff --git a/Source/JavaScriptCore/wtf/HashTable.cpp b/Source/JavaScriptCore/wtf/HashTable.cpp deleted file mode 100644 index 94bba9b32..000000000 --- a/Source/JavaScriptCore/wtf/HashTable.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2005 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" -#include "HashTable.h" - -namespace WTF { - -#if DUMP_HASHTABLE_STATS - -int HashTableStats::numAccesses; -int HashTableStats::numCollisions; -int HashTableStats::collisionGraph[4096]; -int HashTableStats::maxCollisions; -int HashTableStats::numRehashes; -int HashTableStats::numRemoves; -int HashTableStats::numReinserts; - -static HashTableStats logger; - -static Mutex& hashTableStatsMutex() -{ - AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); - return mutex; -} - -HashTableStats::~HashTableStats() -{ - // Don't lock hashTableStatsMutex here because it can cause deadlocks at shutdown - // if any thread was killed while holding the mutex. - dataLog("\nWTF::HashTable statistics\n\n"); - dataLog("%d accesses\n", numAccesses); - dataLog("%d total collisions, average %.2f probes per access\n", numCollisions, 1.0 * (numAccesses + numCollisions) / numAccesses); - dataLog("longest collision chain: %d\n", maxCollisions); - for (int i = 1; i <= maxCollisions; i++) { - dataLog(" %d lookups with exactly %d collisions (%.2f%% , %.2f%% with this many or more)\n", collisionGraph[i], i, 100.0 * (collisionGraph[i] - collisionGraph[i+1]) / numAccesses, 100.0 * collisionGraph[i] / numAccesses); - } - dataLog("%d rehashes\n", numRehashes); - dataLog("%d reinserts\n", numReinserts); -} - -void HashTableStats::recordCollisionAtCount(int count) -{ - MutexLocker lock(hashTableStatsMutex()); - if (count > maxCollisions) - maxCollisions = count; - numCollisions++; - collisionGraph[count]++; -} - -#endif - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/HashTable.h b/Source/JavaScriptCore/wtf/HashTable.h deleted file mode 100644 index 05722d9c5..000000000 --- a/Source/JavaScriptCore/wtf/HashTable.h +++ /dev/null @@ -1,1249 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. - * Copyright (C) 2008 David Levin <levin@chromium.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_HashTable_h -#define WTF_HashTable_h - -#include <wtf/Alignment.h> -#include <wtf/Assertions.h> -#include <wtf/FastMalloc.h> -#include <wtf/HashTraits.h> -#include <wtf/StdLibExtras.h> -#include <wtf/Threading.h> -#include <wtf/ValueCheck.h> - -namespace WTF { - -#define DUMP_HASHTABLE_STATS 0 - -// Enables internal WTF consistency checks that are invoked automatically. Non-WTF callers can call checkTableConsistency() even if internal checks are disabled. -#define CHECK_HASHTABLE_CONSISTENCY 0 - -#ifdef NDEBUG -#define CHECK_HASHTABLE_ITERATORS 0 -#define CHECK_HASHTABLE_USE_AFTER_DESTRUCTION 0 -#else -#define CHECK_HASHTABLE_ITERATORS 1 -#define CHECK_HASHTABLE_USE_AFTER_DESTRUCTION 1 -#endif - -#if DUMP_HASHTABLE_STATS - - struct HashTableStats { - ~HashTableStats(); - // All of the variables are accessed in ~HashTableStats when the static struct is destroyed. - - // The following variables are all atomically incremented when modified. - static int numAccesses; - static int numRehashes; - static int numRemoves; - static int numReinserts; - - // The following variables are only modified in the recordCollisionAtCount method within a mutex. - static int maxCollisions; - static int numCollisions; - static int collisionGraph[4096]; - - static void recordCollisionAtCount(int count); - }; - -#endif - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - class HashTable; - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - class HashTableIterator; - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - class HashTableConstIterator; - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*, - HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*); - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*); - -#if !CHECK_HASHTABLE_ITERATORS - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - inline void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*, - HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - inline void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>*) { } - -#endif - - typedef enum { HashItemKnownGood } HashItemKnownGoodTag; - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - class HashTableConstIterator { - private: - typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType; - typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> iterator; - typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator; - typedef Value ValueType; - typedef const ValueType& ReferenceType; - typedef const ValueType* PointerType; - - friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>; - friend class HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>; - - void skipEmptyBuckets() - { - while (m_position != m_endPosition && HashTableType::isEmptyOrDeletedBucket(*m_position)) - ++m_position; - } - - HashTableConstIterator(const HashTableType* table, PointerType position, PointerType endPosition) - : m_position(position), m_endPosition(endPosition) - { - addIterator(table, this); - skipEmptyBuckets(); - } - - HashTableConstIterator(const HashTableType* table, PointerType position, PointerType endPosition, HashItemKnownGoodTag) - : m_position(position), m_endPosition(endPosition) - { - addIterator(table, this); - } - - public: - HashTableConstIterator() - { - addIterator(static_cast<const HashTableType*>(0), this); - } - - // default copy, assignment and destructor are OK if CHECK_HASHTABLE_ITERATORS is 0 - -#if CHECK_HASHTABLE_ITERATORS - ~HashTableConstIterator() - { - removeIterator(this); - } - - HashTableConstIterator(const const_iterator& other) - : m_position(other.m_position), m_endPosition(other.m_endPosition) - { - addIterator(other.m_table, this); - } - - const_iterator& operator=(const const_iterator& other) - { - m_position = other.m_position; - m_endPosition = other.m_endPosition; - - removeIterator(this); - addIterator(other.m_table, this); - - return *this; - } -#endif - - PointerType get() const - { - checkValidity(); - return m_position; - } - ReferenceType operator*() const { return *get(); } - PointerType operator->() const { return get(); } - - const_iterator& operator++() - { - checkValidity(); - ASSERT(m_position != m_endPosition); - ++m_position; - skipEmptyBuckets(); - return *this; - } - - // postfix ++ intentionally omitted - - // Comparison. - bool operator==(const const_iterator& other) const - { - checkValidity(other); - return m_position == other.m_position; - } - bool operator!=(const const_iterator& other) const - { - checkValidity(other); - return m_position != other.m_position; - } - bool operator==(const iterator& other) const - { - return *this == static_cast<const_iterator>(other); - } - bool operator!=(const iterator& other) const - { - return *this != static_cast<const_iterator>(other); - } - - private: - void checkValidity() const - { -#if CHECK_HASHTABLE_ITERATORS - ASSERT(m_table); -#endif - } - - -#if CHECK_HASHTABLE_ITERATORS - void checkValidity(const const_iterator& other) const - { - ASSERT(m_table); - ASSERT_UNUSED(other, other.m_table); - ASSERT(m_table == other.m_table); - } -#else - void checkValidity(const const_iterator&) const { } -#endif - - PointerType m_position; - PointerType m_endPosition; - -#if CHECK_HASHTABLE_ITERATORS - public: - // Any modifications of the m_next or m_previous of an iterator that is in a linked list of a HashTable::m_iterator, - // should be guarded with m_table->m_mutex. - mutable const HashTableType* m_table; - mutable const_iterator* m_next; - mutable const_iterator* m_previous; -#endif - }; - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - class HashTableIterator { - private: - typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType; - typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> iterator; - typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator; - typedef Value ValueType; - typedef ValueType& ReferenceType; - typedef ValueType* PointerType; - - friend class HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>; - - HashTableIterator(HashTableType* table, PointerType pos, PointerType end) : m_iterator(table, pos, end) { } - HashTableIterator(HashTableType* table, PointerType pos, PointerType end, HashItemKnownGoodTag tag) : m_iterator(table, pos, end, tag) { } - - public: - HashTableIterator() { } - - // default copy, assignment and destructor are OK - - PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } - ReferenceType operator*() const { return *get(); } - PointerType operator->() const { return get(); } - - iterator& operator++() { ++m_iterator; return *this; } - - // postfix ++ intentionally omitted - - // Comparison. - bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; } - bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } - bool operator==(const const_iterator& other) const { return m_iterator == other; } - bool operator!=(const const_iterator& other) const { return m_iterator != other; } - - operator const_iterator() const { return m_iterator; } - - private: - const_iterator m_iterator; - }; - - using std::swap; - - // Work around MSVC's standard library, whose swap for pairs does not swap by component. - template<typename T> inline void hashTableSwap(T& a, T& b) - { - swap(a, b); - } - - // Swap pairs by component, in case of pair members that specialize swap. - template<typename T, typename U> inline void hashTableSwap(pair<T, U>& a, pair<T, U>& b) - { - swap(a.first, b.first); - swap(a.second, b.second); - } - - template<typename T, bool useSwap> struct Mover; - template<typename T> struct Mover<T, true> { static void move(T& from, T& to) { hashTableSwap(from, to); } }; - template<typename T> struct Mover<T, false> { static void move(T& from, T& to) { to = from; } }; - - template<typename HashFunctions> class IdentityHashTranslator { - public: - template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); } - template<typename T> static bool equal(const T& a, const T& b) { return HashFunctions::equal(a, b); } - template<typename T, typename U> static void translate(T& location, const U&, const T& value) { location = value; } - }; - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - class HashTable { - public: - typedef HashTableIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> iterator; - typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator; - typedef Traits ValueTraits; - typedef Key KeyType; - typedef Value ValueType; - typedef IdentityHashTranslator<HashFunctions> IdentityTranslatorType; - - HashTable(); - ~HashTable() - { - invalidateIterators(); - if (m_table) - deallocateTable(m_table, m_tableSize); -#if CHECK_HASHTABLE_USE_AFTER_DESTRUCTION - m_table = (ValueType*)(uintptr_t)0xbbadbeef; -#endif - } - - HashTable(const HashTable&); - void swap(HashTable&); - HashTable& operator=(const HashTable&); - - iterator begin() { return makeIterator(m_table); } - iterator end() { return makeKnownGoodIterator(m_table + m_tableSize); } - const_iterator begin() const { return makeConstIterator(m_table); } - const_iterator end() const { return makeKnownGoodConstIterator(m_table + m_tableSize); } - - int size() const { return m_keyCount; } - int capacity() const { return m_tableSize; } - bool isEmpty() const { return !m_keyCount; } - - pair<iterator, bool> add(const ValueType& value) { return add<IdentityTranslatorType>(Extractor::extract(value), value); } - - // A special version of add() that finds the object by hashing and comparing - // with some other type, to avoid the cost of type conversion if the object is already - // in the table. - template<typename HashTranslator, typename T, typename Extra> pair<iterator, bool> add(const T& key, const Extra&); - template<typename HashTranslator, typename T, typename Extra> pair<iterator, bool> addPassingHashCode(const T& key, const Extra&); - - iterator find(const KeyType& key) { return find<IdentityTranslatorType>(key); } - const_iterator find(const KeyType& key) const { return find<IdentityTranslatorType>(key); } - bool contains(const KeyType& key) const { return contains<IdentityTranslatorType>(key); } - - template<typename HashTranslator, typename T> iterator find(const T&); - template<typename HashTranslator, typename T> const_iterator find(const T&) const; - template<typename HashTranslator, typename T> bool contains(const T&) const; - - void remove(const KeyType&); - void remove(iterator); - void removeWithoutEntryConsistencyCheck(iterator); - void removeWithoutEntryConsistencyCheck(const_iterator); - void clear(); - - static bool isEmptyBucket(const ValueType& value) { return Extractor::extract(value) == KeyTraits::emptyValue(); } - static bool isDeletedBucket(const ValueType& value) { return KeyTraits::isDeletedValue(Extractor::extract(value)); } - static bool isEmptyOrDeletedBucket(const ValueType& value) { return isEmptyBucket(value) || isDeletedBucket(value); } - - ValueType* lookup(const Key& key) { return lookup<IdentityTranslatorType>(key); } - template<typename HashTranslator, typename T> ValueType* lookup(const T&); - -#if !ASSERT_DISABLED - void checkTableConsistency() const; -#else - static void checkTableConsistency() { } -#endif -#if CHECK_HASHTABLE_CONSISTENCY - void internalCheckTableConsistency() const { checkTableConsistency(); } - void internalCheckTableConsistencyExceptSize() const { checkTableConsistencyExceptSize(); } -#else - static void internalCheckTableConsistencyExceptSize() { } - static void internalCheckTableConsistency() { } -#endif - - private: - static ValueType* allocateTable(int size); - static void deallocateTable(ValueType* table, int size); - - typedef pair<ValueType*, bool> LookupType; - typedef pair<LookupType, unsigned> FullLookupType; - - LookupType lookupForWriting(const Key& key) { return lookupForWriting<IdentityTranslatorType>(key); }; - template<typename HashTranslator, typename T> FullLookupType fullLookupForWriting(const T&); - template<typename HashTranslator, typename T> LookupType lookupForWriting(const T&); - - template<typename HashTranslator, typename T> void checkKey(const T&); - - void removeAndInvalidateWithoutEntryConsistencyCheck(ValueType*); - void removeAndInvalidate(ValueType*); - void remove(ValueType*); - - bool shouldExpand() const { return (m_keyCount + m_deletedCount) * m_maxLoad >= m_tableSize; } - bool mustRehashInPlace() const { return m_keyCount * m_minLoad < m_tableSize * 2; } - bool shouldShrink() const { return m_keyCount * m_minLoad < m_tableSize && m_tableSize > KeyTraits::minimumTableSize; } - void expand(); - void shrink() { rehash(m_tableSize / 2); } - - void rehash(int newTableSize); - void reinsert(ValueType&); - - static void initializeBucket(ValueType& bucket); - static void deleteBucket(ValueType& bucket) { bucket.~ValueType(); Traits::constructDeletedValue(bucket); } - - FullLookupType makeLookupResult(ValueType* position, bool found, unsigned hash) - { return FullLookupType(LookupType(position, found), hash); } - - iterator makeIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize); } - const_iterator makeConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize); } - iterator makeKnownGoodIterator(ValueType* pos) { return iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); } - const_iterator makeKnownGoodConstIterator(ValueType* pos) const { return const_iterator(this, pos, m_table + m_tableSize, HashItemKnownGood); } - -#if !ASSERT_DISABLED - void checkTableConsistencyExceptSize() const; -#else - static void checkTableConsistencyExceptSize() { } -#endif - -#if CHECK_HASHTABLE_ITERATORS - void invalidateIterators(); -#else - static void invalidateIterators() { } -#endif - - static const int m_maxLoad = 2; - static const int m_minLoad = 6; - - ValueType* m_table; - int m_tableSize; - int m_tableSizeMask; - int m_keyCount; - int m_deletedCount; - -#if CHECK_HASHTABLE_ITERATORS - public: - // All access to m_iterators should be guarded with m_mutex. - mutable const_iterator* m_iterators; - mutable Mutex m_mutex; -#endif - }; - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - inline HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::HashTable() - : m_table(0) - , m_tableSize(0) - , m_tableSizeMask(0) - , m_keyCount(0) - , m_deletedCount(0) -#if CHECK_HASHTABLE_ITERATORS - , m_iterators(0) -#endif - { - } - - inline unsigned doubleHash(unsigned key) - { - key = ~key + (key >> 23); - key ^= (key << 12); - key ^= (key >> 7); - key ^= (key << 2); - key ^= (key >> 20); - return key; - } - -#if ASSERT_DISABLED - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template<typename HashTranslator, typename T> - inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkKey(const T&) - { - } - -#else - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template<typename HashTranslator, typename T> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkKey(const T& key) - { - if (!HashFunctions::safeToCompareToEmptyOrDeleted) - return; - ASSERT(!HashTranslator::equal(KeyTraits::emptyValue(), key)); - AlignedBuffer<sizeof(ValueType), WTF_ALIGN_OF(ValueType)> deletedValueBuffer; - ValueType* deletedValuePtr = reinterpret_cast_ptr<ValueType*>(deletedValueBuffer.buffer); - ValueType& deletedValue = *deletedValuePtr; - Traits::constructDeletedValue(deletedValue); - ASSERT(!HashTranslator::equal(Extractor::extract(deletedValue), key)); - } - -#endif - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template<typename HashTranslator, typename T> - inline Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookup(const T& key) - { - checkKey<HashTranslator>(key); - - int k = 0; - int sizeMask = m_tableSizeMask; - ValueType* table = m_table; - unsigned h = HashTranslator::hash(key); - int i = h & sizeMask; - - if (!table) - return 0; - -#if DUMP_HASHTABLE_STATS - atomicIncrement(&HashTableStats::numAccesses); - int probeCount = 0; -#endif - - while (1) { - ValueType* entry = table + i; - - // we count on the compiler to optimize out this branch - if (HashFunctions::safeToCompareToEmptyOrDeleted) { - if (HashTranslator::equal(Extractor::extract(*entry), key)) - return entry; - - if (isEmptyBucket(*entry)) - return 0; - } else { - if (isEmptyBucket(*entry)) - return 0; - - if (!isDeletedBucket(*entry) && HashTranslator::equal(Extractor::extract(*entry), key)) - return entry; - } -#if DUMP_HASHTABLE_STATS - ++probeCount; - HashTableStats::recordCollisionAtCount(probeCount); -#endif - if (k == 0) - k = 1 | doubleHash(h); - i = (i + k) & sizeMask; - } - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template<typename HashTranslator, typename T> - inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::LookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::lookupForWriting(const T& key) - { - ASSERT(m_table); - checkKey<HashTranslator>(key); - - int k = 0; - ValueType* table = m_table; - int sizeMask = m_tableSizeMask; - unsigned h = HashTranslator::hash(key); - int i = h & sizeMask; - -#if DUMP_HASHTABLE_STATS - atomicIncrement(&HashTableStats::numAccesses); - int probeCount = 0; -#endif - - ValueType* deletedEntry = 0; - - while (1) { - ValueType* entry = table + i; - - // we count on the compiler to optimize out this branch - if (HashFunctions::safeToCompareToEmptyOrDeleted) { - if (isEmptyBucket(*entry)) - return LookupType(deletedEntry ? deletedEntry : entry, false); - - if (HashTranslator::equal(Extractor::extract(*entry), key)) - return LookupType(entry, true); - - if (isDeletedBucket(*entry)) - deletedEntry = entry; - } else { - if (isEmptyBucket(*entry)) - return LookupType(deletedEntry ? deletedEntry : entry, false); - - if (isDeletedBucket(*entry)) - deletedEntry = entry; - else if (HashTranslator::equal(Extractor::extract(*entry), key)) - return LookupType(entry, true); - } -#if DUMP_HASHTABLE_STATS - ++probeCount; - HashTableStats::recordCollisionAtCount(probeCount); -#endif - if (k == 0) - k = 1 | doubleHash(h); - i = (i + k) & sizeMask; - } - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template<typename HashTranslator, typename T> - inline typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::FullLookupType HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::fullLookupForWriting(const T& key) - { - ASSERT(m_table); - checkKey<HashTranslator>(key); - - int k = 0; - ValueType* table = m_table; - int sizeMask = m_tableSizeMask; - unsigned h = HashTranslator::hash(key); - int i = h & sizeMask; - -#if DUMP_HASHTABLE_STATS - atomicIncrement(&HashTableStats::numAccesses); - int probeCount = 0; -#endif - - ValueType* deletedEntry = 0; - - while (1) { - ValueType* entry = table + i; - - // we count on the compiler to optimize out this branch - if (HashFunctions::safeToCompareToEmptyOrDeleted) { - if (isEmptyBucket(*entry)) - return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); - - if (HashTranslator::equal(Extractor::extract(*entry), key)) - return makeLookupResult(entry, true, h); - - if (isDeletedBucket(*entry)) - deletedEntry = entry; - } else { - if (isEmptyBucket(*entry)) - return makeLookupResult(deletedEntry ? deletedEntry : entry, false, h); - - if (isDeletedBucket(*entry)) - deletedEntry = entry; - else if (HashTranslator::equal(Extractor::extract(*entry), key)) - return makeLookupResult(entry, true, h); - } -#if DUMP_HASHTABLE_STATS - ++probeCount; - HashTableStats::recordCollisionAtCount(probeCount); -#endif - if (k == 0) - k = 1 | doubleHash(h); - i = (i + k) & sizeMask; - } - } - - template<bool emptyValueIsZero> struct HashTableBucketInitializer; - - template<> struct HashTableBucketInitializer<false> { - template<typename Traits, typename Value> static void initialize(Value& bucket) - { - new (NotNull, &bucket) Value(Traits::emptyValue()); - } - }; - - template<> struct HashTableBucketInitializer<true> { - template<typename Traits, typename Value> static void initialize(Value& bucket) - { - // This initializes the bucket without copying the empty value. - // That makes it possible to use this with types that don't support copying. - // The memset to 0 looks like a slow operation but is optimized by the compilers. - memset(&bucket, 0, sizeof(bucket)); - } - }; - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::initializeBucket(ValueType& bucket) - { - HashTableBucketInitializer<Traits::emptyValueIsZero>::template initialize<Traits>(bucket); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template<typename HashTranslator, typename T, typename Extra> - inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::add(const T& key, const Extra& extra) - { - checkKey<HashTranslator>(key); - - invalidateIterators(); - - if (!m_table) - expand(); - - internalCheckTableConsistency(); - - ASSERT(m_table); - - int k = 0; - ValueType* table = m_table; - int sizeMask = m_tableSizeMask; - unsigned h = HashTranslator::hash(key); - int i = h & sizeMask; - -#if DUMP_HASHTABLE_STATS - atomicIncrement(&HashTableStats::numAccesses); - int probeCount = 0; -#endif - - ValueType* deletedEntry = 0; - ValueType* entry; - while (1) { - entry = table + i; - - // we count on the compiler to optimize out this branch - if (HashFunctions::safeToCompareToEmptyOrDeleted) { - if (isEmptyBucket(*entry)) - break; - - if (HashTranslator::equal(Extractor::extract(*entry), key)) - return std::make_pair(makeKnownGoodIterator(entry), false); - - if (isDeletedBucket(*entry)) - deletedEntry = entry; - } else { - if (isEmptyBucket(*entry)) - break; - - if (isDeletedBucket(*entry)) - deletedEntry = entry; - else if (HashTranslator::equal(Extractor::extract(*entry), key)) - return std::make_pair(makeKnownGoodIterator(entry), false); - } -#if DUMP_HASHTABLE_STATS - ++probeCount; - HashTableStats::recordCollisionAtCount(probeCount); -#endif - if (k == 0) - k = 1 | doubleHash(h); - i = (i + k) & sizeMask; - } - - if (deletedEntry) { - initializeBucket(*deletedEntry); - entry = deletedEntry; - --m_deletedCount; - } - - HashTranslator::translate(*entry, key, extra); - - ++m_keyCount; - - if (shouldExpand()) { - // FIXME: This makes an extra copy on expand. Probably not that bad since - // expand is rare, but would be better to have a version of expand that can - // follow a pivot entry and return the new position. - KeyType enteredKey = Extractor::extract(*entry); - expand(); - pair<iterator, bool> p = std::make_pair(find(enteredKey), true); - ASSERT(p.first != end()); - return p; - } - - internalCheckTableConsistency(); - - return std::make_pair(makeKnownGoodIterator(entry), true); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template<typename HashTranslator, typename T, typename Extra> - inline pair<typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator, bool> HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::addPassingHashCode(const T& key, const Extra& extra) - { - checkKey<HashTranslator>(key); - - invalidateIterators(); - - if (!m_table) - expand(); - - internalCheckTableConsistency(); - - FullLookupType lookupResult = fullLookupForWriting<HashTranslator>(key); - - ValueType* entry = lookupResult.first.first; - bool found = lookupResult.first.second; - unsigned h = lookupResult.second; - - if (found) - return std::make_pair(makeKnownGoodIterator(entry), false); - - if (isDeletedBucket(*entry)) { - initializeBucket(*entry); - --m_deletedCount; - } - - HashTranslator::translate(*entry, key, extra, h); - ++m_keyCount; - if (shouldExpand()) { - // FIXME: This makes an extra copy on expand. Probably not that bad since - // expand is rare, but would be better to have a version of expand that can - // follow a pivot entry and return the new position. - KeyType enteredKey = Extractor::extract(*entry); - expand(); - pair<iterator, bool> p = std::make_pair(find(enteredKey), true); - ASSERT(p.first != end()); - return p; - } - - internalCheckTableConsistency(); - - return std::make_pair(makeKnownGoodIterator(entry), true); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::reinsert(ValueType& entry) - { - ASSERT(m_table); - ASSERT(!lookupForWriting(Extractor::extract(entry)).second); - ASSERT(!isDeletedBucket(*(lookupForWriting(Extractor::extract(entry)).first))); -#if DUMP_HASHTABLE_STATS - atomicIncrement(&HashTableStats::numReinserts); -#endif - - Mover<ValueType, Traits::needsDestruction>::move(entry, *lookupForWriting(Extractor::extract(entry)).first); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template <typename HashTranslator, typename T> - typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::find(const T& key) - { - if (!m_table) - return end(); - - ValueType* entry = lookup<HashTranslator>(key); - if (!entry) - return end(); - - return makeKnownGoodIterator(entry); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template <typename HashTranslator, typename T> - typename HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::const_iterator HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::find(const T& key) const - { - if (!m_table) - return end(); - - ValueType* entry = const_cast<HashTable*>(this)->lookup<HashTranslator>(key); - if (!entry) - return end(); - - return makeKnownGoodConstIterator(entry); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - template <typename HashTranslator, typename T> - bool HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::contains(const T& key) const - { - if (!m_table) - return false; - - return const_cast<HashTable*>(this)->lookup<HashTranslator>(key); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeAndInvalidateWithoutEntryConsistencyCheck(ValueType* pos) - { - invalidateIterators(); - remove(pos); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeAndInvalidate(ValueType* pos) - { - invalidateIterators(); - internalCheckTableConsistency(); - remove(pos); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(ValueType* pos) - { -#if DUMP_HASHTABLE_STATS - atomicIncrement(&HashTableStats::numRemoves); -#endif - - deleteBucket(*pos); - ++m_deletedCount; - --m_keyCount; - - if (shouldShrink()) - shrink(); - - internalCheckTableConsistency(); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(iterator it) - { - if (it == end()) - return; - - removeAndInvalidate(const_cast<ValueType*>(it.m_iterator.m_position)); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeWithoutEntryConsistencyCheck(iterator it) - { - if (it == end()) - return; - - removeAndInvalidateWithoutEntryConsistencyCheck(const_cast<ValueType*>(it.m_iterator.m_position)); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::removeWithoutEntryConsistencyCheck(const_iterator it) - { - if (it == end()) - return; - - removeAndInvalidateWithoutEntryConsistencyCheck(const_cast<ValueType*>(it.m_position)); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - inline void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::remove(const KeyType& key) - { - remove(find(key)); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - Value* HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::allocateTable(int size) - { - // would use a template member function with explicit specializations here, but - // gcc doesn't appear to support that - if (Traits::emptyValueIsZero) - return static_cast<ValueType*>(fastZeroedMalloc(size * sizeof(ValueType))); - ValueType* result = static_cast<ValueType*>(fastMalloc(size * sizeof(ValueType))); - for (int i = 0; i < size; i++) - initializeBucket(result[i]); - return result; - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::deallocateTable(ValueType* table, int size) - { - if (Traits::needsDestruction) { - for (int i = 0; i < size; ++i) { - if (!isDeletedBucket(table[i])) - table[i].~ValueType(); - } - } - fastFree(table); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::expand() - { - int newSize; - if (m_tableSize == 0) - newSize = KeyTraits::minimumTableSize; - else if (mustRehashInPlace()) - newSize = m_tableSize; - else - newSize = m_tableSize * 2; - - rehash(newSize); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::rehash(int newTableSize) - { - internalCheckTableConsistencyExceptSize(); - - int oldTableSize = m_tableSize; - ValueType* oldTable = m_table; - -#if DUMP_HASHTABLE_STATS - if (oldTableSize != 0) - atomicIncrement(&HashTableStats::numRehashes); -#endif - - m_tableSize = newTableSize; - m_tableSizeMask = newTableSize - 1; - m_table = allocateTable(newTableSize); - - for (int i = 0; i != oldTableSize; ++i) - if (!isEmptyOrDeletedBucket(oldTable[i])) - reinsert(oldTable[i]); - - m_deletedCount = 0; - - deallocateTable(oldTable, oldTableSize); - - internalCheckTableConsistency(); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::clear() - { - invalidateIterators(); - if (!m_table) - return; - - deallocateTable(m_table, m_tableSize); - m_table = 0; - m_tableSize = 0; - m_tableSizeMask = 0; - m_keyCount = 0; - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::HashTable(const HashTable& other) - : m_table(0) - , m_tableSize(0) - , m_tableSizeMask(0) - , m_keyCount(0) - , m_deletedCount(0) -#if CHECK_HASHTABLE_ITERATORS - , m_iterators(0) -#endif - { - // Copy the hash table the dumb way, by adding each element to the new table. - // It might be more efficient to copy the table slots, but it's not clear that efficiency is needed. - const_iterator end = other.end(); - for (const_iterator it = other.begin(); it != end; ++it) - add(*it); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::swap(HashTable& other) - { - invalidateIterators(); - other.invalidateIterators(); - - ValueType* tmp_table = m_table; - m_table = other.m_table; - other.m_table = tmp_table; - - int tmp_tableSize = m_tableSize; - m_tableSize = other.m_tableSize; - other.m_tableSize = tmp_tableSize; - - int tmp_tableSizeMask = m_tableSizeMask; - m_tableSizeMask = other.m_tableSizeMask; - other.m_tableSizeMask = tmp_tableSizeMask; - - int tmp_keyCount = m_keyCount; - m_keyCount = other.m_keyCount; - other.m_keyCount = tmp_keyCount; - - int tmp_deletedCount = m_deletedCount; - m_deletedCount = other.m_deletedCount; - other.m_deletedCount = tmp_deletedCount; - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>& HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::operator=(const HashTable& other) - { - HashTable tmp(other); - swap(tmp); - return *this; - } - -#if !ASSERT_DISABLED - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistency() const - { - checkTableConsistencyExceptSize(); - ASSERT(!m_table || !shouldExpand()); - ASSERT(!shouldShrink()); - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::checkTableConsistencyExceptSize() const - { - if (!m_table) - return; - - int count = 0; - int deletedCount = 0; - for (int j = 0; j < m_tableSize; ++j) { - ValueType* entry = m_table + j; - if (isEmptyBucket(*entry)) - continue; - - if (isDeletedBucket(*entry)) { - ++deletedCount; - continue; - } - - const_iterator it = find(Extractor::extract(*entry)); - ASSERT(entry == it.m_position); - ++count; - - ValueCheck<Key>::checkConsistency(it->first); - } - - ASSERT(count == m_keyCount); - ASSERT(deletedCount == m_deletedCount); - ASSERT(m_tableSize >= KeyTraits::minimumTableSize); - ASSERT(m_tableSizeMask); - ASSERT(m_tableSize == m_tableSizeMask + 1); - } - -#endif // ASSERT_DISABLED - -#if CHECK_HASHTABLE_ITERATORS - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>::invalidateIterators() - { - MutexLocker lock(m_mutex); - const_iterator* next; - for (const_iterator* p = m_iterators; p; p = next) { - next = p->m_next; - p->m_table = 0; - p->m_next = 0; - p->m_previous = 0; - } - m_iterators = 0; - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void addIterator(const HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* table, - HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* it) - { - it->m_table = table; - it->m_previous = 0; - - // Insert iterator at head of doubly-linked list of iterators. - if (!table) { - it->m_next = 0; - } else { - MutexLocker lock(table->m_mutex); - ASSERT(table->m_iterators != it); - it->m_next = table->m_iterators; - table->m_iterators = it; - if (it->m_next) { - ASSERT(!it->m_next->m_previous); - it->m_next->m_previous = it; - } - } - } - - template<typename Key, typename Value, typename Extractor, typename HashFunctions, typename Traits, typename KeyTraits> - void removeIterator(HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits>* it) - { - typedef HashTable<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> HashTableType; - typedef HashTableConstIterator<Key, Value, Extractor, HashFunctions, Traits, KeyTraits> const_iterator; - - // Delete iterator from doubly-linked list of iterators. - if (!it->m_table) { - ASSERT(!it->m_next); - ASSERT(!it->m_previous); - } else { - MutexLocker lock(it->m_table->m_mutex); - if (it->m_next) { - ASSERT(it->m_next->m_previous == it); - it->m_next->m_previous = it->m_previous; - } - if (it->m_previous) { - ASSERT(it->m_table->m_iterators != it); - ASSERT(it->m_previous->m_next == it); - it->m_previous->m_next = it->m_next; - } else { - ASSERT(it->m_table->m_iterators == it); - it->m_table->m_iterators = it->m_next; - } - } - - it->m_table = 0; - it->m_next = 0; - it->m_previous = 0; - } - -#endif // CHECK_HASHTABLE_ITERATORS - - // iterator adapters - - template<typename HashTableType, typename ValueType> struct HashTableConstIteratorAdapter { - HashTableConstIteratorAdapter() {} - HashTableConstIteratorAdapter(const typename HashTableType::const_iterator& impl) : m_impl(impl) {} - - const ValueType* get() const { return (const ValueType*)m_impl.get(); } - const ValueType& operator*() const { return *get(); } - const ValueType* operator->() const { return get(); } - - HashTableConstIteratorAdapter& operator++() { ++m_impl; return *this; } - // postfix ++ intentionally omitted - - typename HashTableType::const_iterator m_impl; - }; - - template<typename HashTableType, typename ValueType> struct HashTableIteratorAdapter { - HashTableIteratorAdapter() {} - HashTableIteratorAdapter(const typename HashTableType::iterator& impl) : m_impl(impl) {} - - ValueType* get() const { return (ValueType*)m_impl.get(); } - ValueType& operator*() const { return *get(); } - ValueType* operator->() const { return get(); } - - HashTableIteratorAdapter& operator++() { ++m_impl; return *this; } - // postfix ++ intentionally omitted - - operator HashTableConstIteratorAdapter<HashTableType, ValueType>() { - typename HashTableType::const_iterator i = m_impl; - return i; - } - - typename HashTableType::iterator m_impl; - }; - - template<typename T, typename U> - inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b) - { - return a.m_impl == b.m_impl; - } - - template<typename T, typename U> - inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b) - { - return a.m_impl != b.m_impl; - } - - template<typename T, typename U> - inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b) - { - return a.m_impl == b.m_impl; - } - - template<typename T, typename U> - inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b) - { - return a.m_impl != b.m_impl; - } - - // All 4 combinations of ==, != and Const,non const. - template<typename T, typename U> - inline bool operator==(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b) - { - return a.m_impl == b.m_impl; - } - - template<typename T, typename U> - inline bool operator!=(const HashTableConstIteratorAdapter<T, U>& a, const HashTableIteratorAdapter<T, U>& b) - { - return a.m_impl != b.m_impl; - } - - template<typename T, typename U> - inline bool operator==(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b) - { - return a.m_impl == b.m_impl; - } - - template<typename T, typename U> - inline bool operator!=(const HashTableIteratorAdapter<T, U>& a, const HashTableConstIteratorAdapter<T, U>& b) - { - return a.m_impl != b.m_impl; - } - -} // namespace WTF - -#include <wtf/HashIterators.h> - -#endif // WTF_HashTable_h diff --git a/Source/JavaScriptCore/wtf/HashTraits.h b/Source/JavaScriptCore/wtf/HashTraits.h deleted file mode 100644 index 10f14d1af..000000000 --- a/Source/JavaScriptCore/wtf/HashTraits.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_HashTraits_h -#define WTF_HashTraits_h - -#include <wtf/HashFunctions.h> -#include <wtf/StdLibExtras.h> -#include <wtf/TypeTraits.h> -#include <utility> -#include <limits> - -namespace WTF { - - class String; - - template<typename T> class OwnPtr; - template<typename T> class PassOwnPtr; - - using std::pair; - using std::make_pair; - - template<typename T> struct HashTraits; - - template<bool isInteger, typename T> struct GenericHashTraitsBase; - - template<typename T> struct GenericHashTraitsBase<false, T> { - static const bool emptyValueIsZero = false; - static const bool needsDestruction = true; - static const int minimumTableSize = 64; - }; - - // Default integer traits disallow both 0 and -1 as keys (max value instead of -1 for unsigned). - template<typename T> struct GenericHashTraitsBase<true, T> : GenericHashTraitsBase<false, T> { - static const bool emptyValueIsZero = true; - static const bool needsDestruction = false; - static void constructDeletedValue(T& slot) { slot = static_cast<T>(-1); } - static bool isDeletedValue(T value) { return value == static_cast<T>(-1); } - }; - - template<typename T> struct GenericHashTraits : GenericHashTraitsBase<IsInteger<T>::value, T> { - typedef T TraitType; - typedef T EmptyValueType; - - static T emptyValue() { return T(); } - - // Type for functions that take ownership, such as add. - // The store function either not be called or called once to store something passed in. - // The value passed to the store function will be either PassInType or PassInType&. - typedef const T& PassInType; - static void store(const T& value, T& storage) { storage = value; } - - // Type for return value of functions that transfer ownership, such as take. - typedef T PassOutType; - static PassOutType passOut(const T& value) { return value; } - - // Type for return value of functions that do not transfer ownership, such as get. - // FIXME: We could change this type to const T& for better performance if we figured out - // a way to handle the return value from emptyValue, which is a temporary. - typedef T PeekType; - static PeekType peek(const T& value) { return value; } - }; - - template<typename T> struct HashTraits : GenericHashTraits<T> { }; - - template<typename T> struct FloatHashTraits : GenericHashTraits<T> { - static const bool needsDestruction = false; - static T emptyValue() { return std::numeric_limits<T>::infinity(); } - static void constructDeletedValue(T& slot) { slot = -std::numeric_limits<T>::infinity(); } - static bool isDeletedValue(T value) { return value == -std::numeric_limits<T>::infinity(); } - }; - - template<> struct HashTraits<float> : FloatHashTraits<float> { }; - template<> struct HashTraits<double> : FloatHashTraits<double> { }; - - // Default unsigned traits disallow both 0 and max as keys -- use these traits to allow zero and disallow max - 1. - template<typename T> struct UnsignedWithZeroKeyHashTraits : GenericHashTraits<T> { - static const bool emptyValueIsZero = false; - static const bool needsDestruction = false; - static T emptyValue() { return std::numeric_limits<T>::max(); } - static void constructDeletedValue(T& slot) { slot = std::numeric_limits<T>::max() - 1; } - static bool isDeletedValue(T value) { return value == std::numeric_limits<T>::max() - 1; } - }; - - template<typename P> struct HashTraits<P*> : GenericHashTraits<P*> { - static const bool emptyValueIsZero = true; - static const bool needsDestruction = false; - static void constructDeletedValue(P*& slot) { slot = reinterpret_cast<P*>(-1); } - static bool isDeletedValue(P* value) { return value == reinterpret_cast<P*>(-1); } - }; - - template<typename T> struct SimpleClassHashTraits : GenericHashTraits<T> { - static const bool emptyValueIsZero = true; - static void constructDeletedValue(T& slot) { new (NotNull, &slot) T(HashTableDeletedValue); } - static bool isDeletedValue(const T& value) { return value.isHashTableDeletedValue(); } - }; - - template<typename P> struct HashTraits<OwnPtr<P> > : SimpleClassHashTraits<OwnPtr<P> > { - typedef std::nullptr_t EmptyValueType; - - static EmptyValueType emptyValue() { return nullptr; } - - typedef PassOwnPtr<P> PassInType; - static void store(PassOwnPtr<P> value, OwnPtr<P>& storage) { storage = value; } - - typedef PassOwnPtr<P> PassOutType; - static PassOwnPtr<P> passOut(OwnPtr<P>& value) { return value.release(); } - static PassOwnPtr<P> passOut(std::nullptr_t) { return nullptr; } - - typedef typename OwnPtr<P>::PtrType PeekType; - static PeekType peek(const OwnPtr<P>& value) { return value.get(); } - static PeekType peek(std::nullptr_t) { return 0; } - }; - - template<typename P> struct HashTraits<RefPtr<P> > : SimpleClassHashTraits<RefPtr<P> > { - typedef PassRefPtr<P> PassInType; - static void store(PassRefPtr<P> value, RefPtr<P>& storage) { storage = value; } - - // FIXME: We should change PassOutType to PassRefPtr for better performance. - // FIXME: We should consider changing PeekType to a raw pointer for better performance, - // but then callers won't need to call get; doing so will require updating many call sites. - }; - - template<> struct HashTraits<String> : SimpleClassHashTraits<String> { }; - - // special traits for pairs, helpful for their use in HashMap implementation - - template<typename FirstTraitsArg, typename SecondTraitsArg> - struct PairHashTraits : GenericHashTraits<pair<typename FirstTraitsArg::TraitType, typename SecondTraitsArg::TraitType> > { - typedef FirstTraitsArg FirstTraits; - typedef SecondTraitsArg SecondTraits; - typedef pair<typename FirstTraits::TraitType, typename SecondTraits::TraitType> TraitType; - typedef pair<typename FirstTraits::EmptyValueType, typename SecondTraits::EmptyValueType> EmptyValueType; - - static const bool emptyValueIsZero = FirstTraits::emptyValueIsZero && SecondTraits::emptyValueIsZero; - static EmptyValueType emptyValue() { return make_pair(FirstTraits::emptyValue(), SecondTraits::emptyValue()); } - - static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; - - static const int minimumTableSize = FirstTraits::minimumTableSize; - - static void constructDeletedValue(TraitType& slot) { FirstTraits::constructDeletedValue(slot.first); } - static bool isDeletedValue(const TraitType& value) { return FirstTraits::isDeletedValue(value.first); } - }; - - template<typename First, typename Second> - struct HashTraits<pair<First, Second> > : public PairHashTraits<HashTraits<First>, HashTraits<Second> > { }; - -} // namespace WTF - -using WTF::HashTraits; -using WTF::PairHashTraits; - -#endif // WTF_HashTraits_h diff --git a/Source/JavaScriptCore/wtf/HexNumber.h b/Source/JavaScriptCore/wtf/HexNumber.h deleted file mode 100644 index 8fd60323b..000000000 --- a/Source/JavaScriptCore/wtf/HexNumber.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2011 Research In Motion Limited. 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 HexNumber_h -#define HexNumber_h - -#include <wtf/text/StringConcatenate.h> - -namespace WTF { - -enum HexConversionMode { - Lowercase, - Uppercase -}; - -namespace Internal { - -static const char* hexDigitsForMode(HexConversionMode mode) -{ - static const char lowerHexDigits[17] = "0123456789abcdef"; - static const char upperHexDigits[17] = "0123456789ABCDEF"; - return mode == Lowercase ? lowerHexDigits : upperHexDigits; -} - -}; // namespace Internal - -template<typename T> -inline void appendByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase) -{ - const char* hexDigits = Internal::hexDigitsForMode(mode); - destination.append(hexDigits[byte >> 4]); - destination.append(hexDigits[byte & 0xF]); -} - -template<typename T> -inline void placeByteAsHexCompressIfPossible(unsigned char byte, T& destination, unsigned& index, HexConversionMode mode = Uppercase) -{ - const char* hexDigits = Internal::hexDigitsForMode(mode); - if (byte >= 0x10) - destination[index++] = hexDigits[byte >> 4]; - destination[index++] = hexDigits[byte & 0xF]; -} - -template<typename T> -inline void placeByteAsHex(unsigned char byte, T& destination, HexConversionMode mode = Uppercase) -{ - const char* hexDigits = Internal::hexDigitsForMode(mode); - *destination++ = hexDigits[byte >> 4]; - *destination++ = hexDigits[byte & 0xF]; -} - -template<typename T> -inline void appendUnsignedAsHex(unsigned number, T& destination, HexConversionMode mode = Uppercase) -{ - const char* hexDigits = Internal::hexDigitsForMode(mode); - Vector<UChar, 8> result; - do { - result.prepend(hexDigits[number % 16]); - number >>= 4; - } while (number > 0); - - destination.append(result.data(), result.size()); -} - -// Same as appendUnsignedAsHex, but using exactly 'desiredDigits' for the conversion. -template<typename T> -inline void appendUnsignedAsHexFixedSize(unsigned number, T& destination, unsigned desiredDigits, HexConversionMode mode = Uppercase) -{ - ASSERT(desiredDigits); - - const char* hexDigits = Internal::hexDigitsForMode(mode); - Vector<UChar, 8> result; - do { - result.prepend(hexDigits[number % 16]); - number >>= 4; - } while (result.size() < desiredDigits); - - ASSERT(result.size() == desiredDigits); - destination.append(result.data(), result.size()); -} - -} // namespace WTF - -using WTF::appendByteAsHex; -using WTF::appendUnsignedAsHex; -using WTF::appendUnsignedAsHexFixedSize; -using WTF::placeByteAsHex; -using WTF::placeByteAsHexCompressIfPossible; -using WTF::Lowercase; - -#endif // HexNumber_h diff --git a/Source/JavaScriptCore/wtf/InlineASM.h b/Source/JavaScriptCore/wtf/InlineASM.h deleted file mode 100644 index 1c99e65a1..000000000 --- a/Source/JavaScriptCore/wtf/InlineASM.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2011 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 InlineASM_h -#define InlineASM_h - -#include <wtf/Platform.h> - -/* asm directive helpers */ - -#if OS(DARWIN) || (OS(WINDOWS) && CPU(X86)) -#define SYMBOL_STRING(name) "_" #name -#else -#define SYMBOL_STRING(name) #name -#endif - -#if OS(IOS) -#define THUMB_FUNC_PARAM(name) SYMBOL_STRING(name) -#else -#define THUMB_FUNC_PARAM(name) -#endif - -#if (OS(LINUX) || OS(FREEBSD)) && CPU(X86_64) -#define SYMBOL_STRING_RELOCATION(name) #name "@plt" -#elif OS(DARWIN) || (CPU(X86_64) && COMPILER(MINGW) && !GCC_VERSION_AT_LEAST(4, 5, 0)) -#define SYMBOL_STRING_RELOCATION(name) "_" #name -#elif CPU(X86) && COMPILER(MINGW) -#define SYMBOL_STRING_RELOCATION(name) "@" #name "@4" -#else -#define SYMBOL_STRING_RELOCATION(name) SYMBOL_STRING(name) -#endif - -#if OS(DARWIN) - // Mach-O platform -#define HIDE_SYMBOL(name) ".private_extern _" #name -#elif OS(AIX) - // IBM's own file format -#define HIDE_SYMBOL(name) ".lglobl " #name -#elif OS(LINUX) \ - || OS(FREEBSD) \ - || OS(OPENBSD) \ - || OS(SOLARIS) \ - || (OS(HPUX) && CPU(IA64)) \ - || OS(NETBSD) - // ELF platform -#define HIDE_SYMBOL(name) ".hidden " #name -#else -#define HIDE_SYMBOL(name) -#endif - -// FIXME: figure out how this works on all the platforms. I know that -// on Linux, the preferred form is ".Lstuff" as opposed to "Lstuff". -// Don't know about any of the others. -#if PLATFORM(MAC) -#define LOCAL_LABEL_STRING(name) "L" #name -#endif - -#endif // InlineASM_h diff --git a/Source/JavaScriptCore/wtf/Int16Array.h b/Source/JavaScriptCore/wtf/Int16Array.h deleted file mode 100644 index df3dcc265..000000000 --- a/Source/JavaScriptCore/wtf/Int16Array.h +++ /dev/null @@ -1,93 +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 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 Int16Array_h -#define Int16Array_h - -#include <wtf/IntegralTypedArrayBase.h> - -namespace WTF { - -class ArrayBuffer; - -class Int16Array : public IntegralTypedArrayBase<short> { -public: - static inline PassRefPtr<Int16Array> create(unsigned length); - static inline PassRefPtr<Int16Array> create(short* array, unsigned length); - static inline PassRefPtr<Int16Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); - - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<short>* array, unsigned offset) { return TypedArrayBase<short>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<short>::set(index, value); } - - inline PassRefPtr<Int16Array> subarray(int start) const; - inline PassRefPtr<Int16Array> subarray(int start, int end) const; - -private: - inline Int16Array(PassRefPtr<ArrayBuffer>, - unsigned byteOffset, - unsigned length); - // Make constructor visible to superclass. - friend class TypedArrayBase<short>; - - // Overridden from ArrayBufferView. - virtual bool isShortArray() const { return true; } -}; - -PassRefPtr<Int16Array> Int16Array::create(unsigned length) -{ - return TypedArrayBase<short>::create<Int16Array>(length); -} - -PassRefPtr<Int16Array> Int16Array::create(short* array, unsigned length) -{ - return TypedArrayBase<short>::create<Int16Array>(array, length); -} - -PassRefPtr<Int16Array> Int16Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -{ - return TypedArrayBase<short>::create<Int16Array>(buffer, byteOffset, length); -} - -Int16Array::Int16Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) - : IntegralTypedArrayBase<short>(buffer, byteOffset, length) -{ -} - -PassRefPtr<Int16Array> Int16Array::subarray(int start) const -{ - return subarray(start, length()); -} - -PassRefPtr<Int16Array> Int16Array::subarray(int start, int end) const -{ - return subarrayImpl<Int16Array>(start, end); -} - -} // namespace WTF - -using WTF::Int16Array; - -#endif // Int16Array_h diff --git a/Source/JavaScriptCore/wtf/Int32Array.h b/Source/JavaScriptCore/wtf/Int32Array.h deleted file mode 100644 index f3148c7bc..000000000 --- a/Source/JavaScriptCore/wtf/Int32Array.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 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 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 Int32Array_h -#define Int32Array_h - -#include <wtf/IntegralTypedArrayBase.h> - -namespace WTF { - -class Int32Array : public IntegralTypedArrayBase<int> { -public: - static inline PassRefPtr<Int32Array> create(unsigned length); - static inline PassRefPtr<Int32Array> create(int* array, unsigned length); - static inline PassRefPtr<Int32Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); - - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<int>* array, unsigned offset) { return TypedArrayBase<int>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<int>::set(index, value); } - - inline PassRefPtr<Int32Array> subarray(int start) const; - inline PassRefPtr<Int32Array> subarray(int start, int end) const; - -private: - inline Int32Array(PassRefPtr<ArrayBuffer>, - unsigned byteOffset, - unsigned length); - // Make constructor visible to superclass. - friend class TypedArrayBase<int>; - - // Overridden from ArrayBufferView. - virtual bool isIntArray() const { return true; } -}; - -PassRefPtr<Int32Array> Int32Array::create(unsigned length) -{ - return TypedArrayBase<int>::create<Int32Array>(length); -} - -PassRefPtr<Int32Array> Int32Array::create(int* array, unsigned length) -{ - return TypedArrayBase<int>::create<Int32Array>(array, length); -} - -PassRefPtr<Int32Array> Int32Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -{ - return TypedArrayBase<int>::create<Int32Array>(buffer, byteOffset, length); -} - -Int32Array::Int32Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) - : IntegralTypedArrayBase<int>(buffer, byteOffset, length) -{ -} - -PassRefPtr<Int32Array> Int32Array::subarray(int start) const -{ - return subarray(start, length()); -} - -PassRefPtr<Int32Array> Int32Array::subarray(int start, int end) const -{ - return subarrayImpl<Int32Array>(start, end); -} - -} // namespace WTF - -using WTF::Int32Array; - -#endif // Int32Array_h diff --git a/Source/JavaScriptCore/wtf/Int8Array.h b/Source/JavaScriptCore/wtf/Int8Array.h deleted file mode 100644 index cb5d343e4..000000000 --- a/Source/JavaScriptCore/wtf/Int8Array.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 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 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 Int8Array_h -#define Int8Array_h - -#include <wtf/IntegralTypedArrayBase.h> - -namespace WTF { - -class ArrayBuffer; - -class Int8Array : public IntegralTypedArrayBase<signed char> { -public: - static inline PassRefPtr<Int8Array> create(unsigned length); - static inline PassRefPtr<Int8Array> create(signed char* array, unsigned length); - static inline PassRefPtr<Int8Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); - - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<signed char>* array, unsigned offset) { return TypedArrayBase<signed char>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<signed char>::set(index, value); } - - inline PassRefPtr<Int8Array> subarray(int start) const; - inline PassRefPtr<Int8Array> subarray(int start, int end) const; - -private: - inline Int8Array(PassRefPtr<ArrayBuffer>, - unsigned byteOffset, - unsigned length); - // Make constructor visible to superclass. - friend class TypedArrayBase<signed char>; - - // Overridden from ArrayBufferView. - virtual bool isByteArray() const { return true; } -}; - -PassRefPtr<Int8Array> Int8Array::create(unsigned length) -{ - return TypedArrayBase<signed char>::create<Int8Array>(length); -} - -PassRefPtr<Int8Array> Int8Array::create(signed char* array, unsigned length) -{ - return TypedArrayBase<signed char>::create<Int8Array>(array, length); -} - -PassRefPtr<Int8Array> Int8Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -{ - return TypedArrayBase<signed char>::create<Int8Array>(buffer, byteOffset, length); -} - -Int8Array::Int8Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) - : IntegralTypedArrayBase<signed char>(buffer, byteOffset, length) -{ -} - -PassRefPtr<Int8Array> Int8Array::subarray(int start) const -{ - return subarray(start, length()); -} - -PassRefPtr<Int8Array> Int8Array::subarray(int start, int end) const -{ - return subarrayImpl<Int8Array>(start, end); -} - -} // namespace WTF - -using WTF::Int8Array; - -#endif // Int8Array_h diff --git a/Source/JavaScriptCore/wtf/IntegralTypedArrayBase.h b/Source/JavaScriptCore/wtf/IntegralTypedArrayBase.h deleted file mode 100644 index f276400f8..000000000 --- a/Source/JavaScriptCore/wtf/IntegralTypedArrayBase.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * 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. - * - * 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 IntegralTypedArrayBase_h -#define IntegralTypedArrayBase_h - -#include <wtf/TypedArrayBase.h> -#include <limits> -#include <wtf/MathExtras.h> - -// Base class for all WebGL<T>Array types holding integral -// (non-floating-point) values. - -namespace WTF { - -template <typename T> -class IntegralTypedArrayBase : public TypedArrayBase<T> { - public: - void set(unsigned index, double value) - { - if (index >= TypedArrayBase<T>::m_length) - return; - if (isnan(value)) // Clamp NaN to 0 - value = 0; - // The double cast is necessary to get the correct wrapping - // for out-of-range values with Int32Array and Uint32Array. - TypedArrayBase<T>::data()[index] = static_cast<T>(static_cast<int64_t>(value)); - } - - // Invoked by the indexed getter. Does not perform range checks; caller - // is responsible for doing so and returning undefined as necessary. - T item(unsigned index) const - { - ASSERT(index < TypedArrayBase<T>::m_length); - return TypedArrayBase<T>::data()[index]; - } - - protected: - IntegralTypedArrayBase(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) - : TypedArrayBase<T>(buffer, byteOffset, length) - { - } -}; - -} // namespace WTF - -using WTF::IntegralTypedArrayBase; - -#endif // IntegralTypedArrayBase_h diff --git a/Source/JavaScriptCore/wtf/ListHashSet.h b/Source/JavaScriptCore/wtf/ListHashSet.h deleted file mode 100644 index 799466fa9..000000000 --- a/Source/JavaScriptCore/wtf/ListHashSet.h +++ /dev/null @@ -1,853 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved. - * Copyright (C) 2011, Benjamin Poulain <ikipou@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_ListHashSet_h -#define WTF_ListHashSet_h - -#include <wtf/HashSet.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> - -namespace WTF { - - // ListHashSet: Just like HashSet, this class provides a Set - // interface - a collection of unique objects with O(1) insertion, - // removal and test for containership. However, it also has an - // order - iterating it will always give back values in the order - // in which they are added. - - // In theory it would be possible to add prepend, insertAfter - // and an append that moves the element to the end even if already present, - // but unclear yet if these are needed. - - template<typename Value, size_t inlineCapacity, typename HashFunctions> class ListHashSet; - - template<typename Value, size_t inlineCapacity, typename HashFunctions> - void deleteAllValues(const ListHashSet<Value, inlineCapacity, HashFunctions>&); - - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetReverseIterator; - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstReverseIterator; - - template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode; - template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator; - - template<typename HashArg> struct ListHashSetNodeHashFunctions; - template<typename HashArg> struct ListHashSetTranslator; - - template<typename ValueArg, size_t inlineCapacity = 256, typename HashArg = typename DefaultHash<ValueArg>::Hash> class ListHashSet { - WTF_MAKE_FAST_ALLOCATED; - private: - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator; - - typedef HashTraits<Node*> NodeTraits; - typedef ListHashSetNodeHashFunctions<HashArg> NodeHash; - typedef ListHashSetTranslator<HashArg> BaseTranslator; - - typedef HashTable<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplType; - typedef HashTableIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplTypeIterator; - typedef HashTableConstIterator<Node*, Node*, IdentityExtractor, NodeHash, NodeTraits, NodeTraits> ImplTypeConstIterator; - - typedef HashArg HashFunctions; - - public: - typedef ValueArg ValueType; - - typedef ListHashSetIterator<ValueType, inlineCapacity, HashArg> iterator; - typedef ListHashSetConstIterator<ValueType, inlineCapacity, HashArg> const_iterator; - friend class ListHashSetConstIterator<ValueType, inlineCapacity, HashArg>; - - typedef ListHashSetReverseIterator<ValueType, inlineCapacity, HashArg> reverse_iterator; - typedef ListHashSetConstReverseIterator<ValueType, inlineCapacity, HashArg> const_reverse_iterator; - friend class ListHashSetConstReverseIterator<ValueType, inlineCapacity, HashArg>; - - ListHashSet(); - ListHashSet(const ListHashSet&); - ListHashSet& operator=(const ListHashSet&); - ~ListHashSet(); - - void swap(ListHashSet&); - - int size() const; - int capacity() const; - bool isEmpty() const; - - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - - reverse_iterator rbegin(); - reverse_iterator rend(); - const_reverse_iterator rbegin() const; - const_reverse_iterator rend() const; - - ValueType& first(); - const ValueType& first() const; - - ValueType& last(); - const ValueType& last() const; - void removeLast(); - - iterator find(const ValueType&); - const_iterator find(const ValueType&) const; - bool contains(const ValueType&) const; - - // An alternate version of find() that finds the object by hashing and comparing - // with some other type, to avoid the cost of type conversion. - // The HashTranslator interface is defined in HashSet. - // FIXME: We should reverse the order of the template arguments so that callers - // can just pass the translator let the compiler deduce T. - template<typename T, typename HashTranslator> iterator find(const T&); - template<typename T, typename HashTranslator> const_iterator find(const T&) const; - template<typename T, typename HashTranslator> bool contains(const T&) const; - - // The return value of add is a pair of an iterator to the new value's location, - // and a bool that is true if an new entry was added. - pair<iterator, bool> add(const ValueType&); - - pair<iterator, bool> insertBefore(const ValueType& beforeValue, const ValueType& newValue); - pair<iterator, bool> insertBefore(iterator it, const ValueType&); - - void remove(const ValueType&); - void remove(iterator); - void clear(); - - private: - void unlinkAndDelete(Node*); - void appendNode(Node*); - void insertNodeBefore(Node* beforeNode, Node* newNode); - void deleteAllNodes(); - - iterator makeIterator(Node*); - const_iterator makeConstIterator(Node*) const; - reverse_iterator makeReverseIterator(Node*); - const_reverse_iterator makeConstReverseIterator(Node*) const; - - friend void deleteAllValues<>(const ListHashSet&); - - ImplType m_impl; - Node* m_head; - Node* m_tail; - OwnPtr<NodeAllocator> m_allocator; - }; - - template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNodeAllocator { - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator; - - ListHashSetNodeAllocator() - : m_freeList(pool()) - , m_isDoneWithInitialFreeList(false) - { - memset(m_pool.pool, 0, sizeof(m_pool.pool)); - } - - Node* allocate() - { - Node* result = m_freeList; - - if (!result) - return static_cast<Node*>(fastMalloc(sizeof(Node))); - - ASSERT(!result->m_isAllocated); - - Node* next = result->m_next; - ASSERT(!next || !next->m_isAllocated); - if (!next && !m_isDoneWithInitialFreeList) { - next = result + 1; - if (next == pastPool()) { - m_isDoneWithInitialFreeList = true; - next = 0; - } else { - ASSERT(inPool(next)); - ASSERT(!next->m_isAllocated); - } - } - m_freeList = next; - - return result; - } - - void deallocate(Node* node) - { - if (inPool(node)) { -#ifndef NDEBUG - node->m_isAllocated = false; -#endif - node->m_next = m_freeList; - m_freeList = node; - return; - } - - fastFree(node); - } - - private: - Node* pool() { return reinterpret_cast_ptr<Node*>(m_pool.pool); } - Node* pastPool() { return pool() + m_poolSize; } - - bool inPool(Node* node) - { - return node >= pool() && node < pastPool(); - } - - Node* m_freeList; - bool m_isDoneWithInitialFreeList; - static const size_t m_poolSize = inlineCapacity; - union { - char pool[sizeof(Node) * m_poolSize]; - double forAlignment; - } m_pool; - }; - - template<typename ValueArg, size_t inlineCapacity> struct ListHashSetNode { - typedef ListHashSetNodeAllocator<ValueArg, inlineCapacity> NodeAllocator; - - ListHashSetNode(ValueArg value) - : m_value(value) - , m_prev(0) - , m_next(0) -#ifndef NDEBUG - , m_isAllocated(true) -#endif - { - } - - void* operator new(size_t, NodeAllocator* allocator) - { - return allocator->allocate(); - } - void destroy(NodeAllocator* allocator) - { - this->~ListHashSetNode(); - allocator->deallocate(this); - } - - ValueArg m_value; - ListHashSetNode* m_prev; - ListHashSetNode* m_next; - -#ifndef NDEBUG - bool m_isAllocated; -#endif - }; - - template<typename HashArg> struct ListHashSetNodeHashFunctions { - template<typename T> static unsigned hash(const T& key) { return HashArg::hash(key->m_value); } - template<typename T> static bool equal(const T& a, const T& b) { return HashArg::equal(a->m_value, b->m_value); } - static const bool safeToCompareToEmptyOrDeleted = false; - }; - - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetIterator { - private: - typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; - typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator; - typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator; - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ValueArg ValueType; - typedef ValueType& ReferenceType; - typedef ValueType* PointerType; - - friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; - - ListHashSetIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { } - - public: - ListHashSetIterator() { } - - // default copy, assignment and destructor are OK - - PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } - ReferenceType operator*() const { return *get(); } - PointerType operator->() const { return get(); } - - iterator& operator++() { ++m_iterator; return *this; } - - // postfix ++ intentionally omitted - - iterator& operator--() { --m_iterator; return *this; } - - // postfix -- intentionally omitted - - // Comparison. - bool operator==(const iterator& other) const { return m_iterator == other.m_iterator; } - bool operator!=(const iterator& other) const { return m_iterator != other.m_iterator; } - - operator const_iterator() const { return m_iterator; } - - private: - Node* node() { return m_iterator.node(); } - - const_iterator m_iterator; - }; - - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstIterator { - private: - typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; - typedef ListHashSetIterator<ValueArg, inlineCapacity, HashArg> iterator; - typedef ListHashSetConstIterator<ValueArg, inlineCapacity, HashArg> const_iterator; - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ValueArg ValueType; - typedef const ValueType& ReferenceType; - typedef const ValueType* PointerType; - - friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; - friend class ListHashSetIterator<ValueArg, inlineCapacity, HashArg>; - - ListHashSetConstIterator(const ListHashSetType* set, Node* position) - : m_set(set) - , m_position(position) - { - } - - public: - ListHashSetConstIterator() - { - } - - PointerType get() const - { - return &m_position->m_value; - } - ReferenceType operator*() const { return *get(); } - PointerType operator->() const { return get(); } - - const_iterator& operator++() - { - ASSERT(m_position != 0); - m_position = m_position->m_next; - return *this; - } - - // postfix ++ intentionally omitted - - const_iterator& operator--() - { - ASSERT(m_position != m_set->m_head); - if (!m_position) - m_position = m_set->m_tail; - else - m_position = m_position->m_prev; - return *this; - } - - // postfix -- intentionally omitted - - // Comparison. - bool operator==(const const_iterator& other) const - { - return m_position == other.m_position; - } - bool operator!=(const const_iterator& other) const - { - return m_position != other.m_position; - } - - private: - Node* node() { return m_position; } - - const ListHashSetType* m_set; - Node* m_position; - }; - - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetReverseIterator { - private: - typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; - typedef ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg> reverse_iterator; - typedef ListHashSetConstReverseIterator<ValueArg, inlineCapacity, HashArg> const_reverse_iterator; - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ValueArg ValueType; - typedef ValueType& ReferenceType; - typedef ValueType* PointerType; - - friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; - - ListHashSetReverseIterator(const ListHashSetType* set, Node* position) : m_iterator(set, position) { } - - public: - ListHashSetReverseIterator() { } - - // default copy, assignment and destructor are OK - - PointerType get() const { return const_cast<PointerType>(m_iterator.get()); } - ReferenceType operator*() const { return *get(); } - PointerType operator->() const { return get(); } - - reverse_iterator& operator++() { ++m_iterator; return *this; } - - // postfix ++ intentionally omitted - - reverse_iterator& operator--() { --m_iterator; return *this; } - - // postfix -- intentionally omitted - - // Comparison. - bool operator==(const reverse_iterator& other) const { return m_iterator == other.m_iterator; } - bool operator!=(const reverse_iterator& other) const { return m_iterator != other.m_iterator; } - - operator const_reverse_iterator() const { return m_iterator; } - - private: - Node* node() { return m_iterator.node(); } - - const_reverse_iterator m_iterator; - }; - - template<typename ValueArg, size_t inlineCapacity, typename HashArg> class ListHashSetConstReverseIterator { - private: - typedef ListHashSet<ValueArg, inlineCapacity, HashArg> ListHashSetType; - typedef ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg> reverse_iterator; - typedef ListHashSetConstReverseIterator<ValueArg, inlineCapacity, HashArg> const_reverse_iterator; - typedef ListHashSetNode<ValueArg, inlineCapacity> Node; - typedef ValueArg ValueType; - typedef const ValueType& ReferenceType; - typedef const ValueType* PointerType; - - friend class ListHashSet<ValueArg, inlineCapacity, HashArg>; - friend class ListHashSetReverseIterator<ValueArg, inlineCapacity, HashArg>; - - ListHashSetConstReverseIterator(const ListHashSetType* set, Node* position) - : m_set(set) - , m_position(position) - { - } - - public: - ListHashSetConstReverseIterator() - { - } - - PointerType get() const - { - return &m_position->m_value; - } - ReferenceType operator*() const { return *get(); } - PointerType operator->() const { return get(); } - - const_reverse_iterator& operator++() - { - ASSERT(m_position != 0); - m_position = m_position->m_prev; - return *this; - } - - // postfix ++ intentionally omitted - - const_reverse_iterator& operator--() - { - ASSERT(m_position != m_set->m_tail); - if (!m_position) - m_position = m_set->m_head; - else - m_position = m_position->m_next; - return *this; - } - - // postfix -- intentionally omitted - - // Comparison. - bool operator==(const const_reverse_iterator& other) const - { - return m_position == other.m_position; - } - bool operator!=(const const_reverse_iterator& other) const - { - return m_position != other.m_position; - } - - private: - Node* node() { return m_position; } - - const ListHashSetType* m_set; - Node* m_position; - }; - - template<typename HashFunctions> - struct ListHashSetTranslator { - template<typename T> static unsigned hash(const T& key) { return HashFunctions::hash(key); } - template<typename T, typename U> static bool equal(const T& a, const U& b) { return HashFunctions::equal(a->m_value, b); } - template<typename T, typename U, typename V> static void translate(T*& location, const U& key, const V& allocator) - { - location = new (allocator) T(key); - } - }; - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSet<T, inlineCapacity, U>::ListHashSet() - : m_head(0) - , m_tail(0) - , m_allocator(adoptPtr(new NodeAllocator)) - { - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSet<T, inlineCapacity, U>::ListHashSet(const ListHashSet& other) - : m_head(0) - , m_tail(0) - , m_allocator(adoptPtr(new NodeAllocator)) - { - const_iterator end = other.end(); - for (const_iterator it = other.begin(); it != end; ++it) - add(*it); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSet<T, inlineCapacity, U>& ListHashSet<T, inlineCapacity, U>::operator=(const ListHashSet& other) - { - ListHashSet tmp(other); - swap(tmp); - return *this; - } - - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::swap(ListHashSet& other) - { - m_impl.swap(other.m_impl); - std::swap(m_head, other.m_head); - std::swap(m_tail, other.m_tail); - m_allocator.swap(other.m_allocator); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSet<T, inlineCapacity, U>::~ListHashSet() - { - deleteAllNodes(); - } - - template<typename T, size_t inlineCapacity, typename U> - inline int ListHashSet<T, inlineCapacity, U>::size() const - { - return m_impl.size(); - } - - template<typename T, size_t inlineCapacity, typename U> - inline int ListHashSet<T, inlineCapacity, U>::capacity() const - { - return m_impl.capacity(); - } - - template<typename T, size_t inlineCapacity, typename U> - inline bool ListHashSet<T, inlineCapacity, U>::isEmpty() const - { - return m_impl.isEmpty(); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::begin() - { - return makeIterator(m_head); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::end() - { - return makeIterator(0); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::begin() const - { - return makeConstIterator(m_head); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::end() const - { - return makeConstIterator(0); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::reverse_iterator ListHashSet<T, inlineCapacity, U>::rbegin() - { - return makeReverseIterator(m_tail); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::reverse_iterator ListHashSet<T, inlineCapacity, U>::rend() - { - return makeReverseIterator(0); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_reverse_iterator ListHashSet<T, inlineCapacity, U>::rbegin() const - { - return makeConstReverseIterator(m_tail); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_reverse_iterator ListHashSet<T, inlineCapacity, U>::rend() const - { - return makeConstReverseIterator(0); - } - - template<typename T, size_t inlineCapacity, typename U> - inline T& ListHashSet<T, inlineCapacity, U>::first() - { - ASSERT(!isEmpty()); - return m_head->m_value; - } - - template<typename T, size_t inlineCapacity, typename U> - inline const T& ListHashSet<T, inlineCapacity, U>::first() const - { - ASSERT(!isEmpty()); - return m_head->m_value; - } - - template<typename T, size_t inlineCapacity, typename U> - inline T& ListHashSet<T, inlineCapacity, U>::last() - { - ASSERT(!isEmpty()); - return m_tail->m_value; - } - - template<typename T, size_t inlineCapacity, typename U> - inline const T& ListHashSet<T, inlineCapacity, U>::last() const - { - ASSERT(!isEmpty()); - return m_tail->m_value; - } - - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::removeLast() - { - ASSERT(!isEmpty()); - m_impl.remove(m_tail); - unlinkAndDelete(m_tail); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value) - { - ImplTypeIterator it = m_impl.template find<BaseTranslator>(value); - if (it == m_impl.end()) - return end(); - return makeIterator(*it); - } - - template<typename T, size_t inlineCapacity, typename U> - inline typename ListHashSet<T, inlineCapacity, U>::const_iterator ListHashSet<T, inlineCapacity, U>::find(const ValueType& value) const - { - ImplTypeConstIterator it = m_impl.template find<BaseTranslator>(value); - if (it == m_impl.end()) - return end(); - return makeConstIterator(*it); - } - - template<typename Translator> - struct ListHashSetTranslatorAdapter { - template<typename T> static unsigned hash(const T& key) { return Translator::hash(key); } - template<typename T, typename U> static bool equal(const T& a, const U& b) { return Translator::equal(a->m_value, b); } - }; - - template<typename ValueType, size_t inlineCapacity, typename U> - template<typename T, typename HashTranslator> - inline typename ListHashSet<ValueType, inlineCapacity, U>::iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) - { - ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value); - if (it == m_impl.end()) - return end(); - return makeIterator(*it); - } - - template<typename ValueType, size_t inlineCapacity, typename U> - template<typename T, typename HashTranslator> - inline typename ListHashSet<ValueType, inlineCapacity, U>::const_iterator ListHashSet<ValueType, inlineCapacity, U>::find(const T& value) const - { - ImplTypeConstIterator it = m_impl.template find<ListHashSetTranslatorAdapter<HashTranslator> >(value); - if (it == m_impl.end()) - return end(); - return makeConstIterator(*it); - } - - template<typename ValueType, size_t inlineCapacity, typename U> - template<typename T, typename HashTranslator> - inline bool ListHashSet<ValueType, inlineCapacity, U>::contains(const T& value) const - { - return m_impl.template contains<ListHashSetTranslatorAdapter<HashTranslator> >(value); - } - - template<typename T, size_t inlineCapacity, typename U> - inline bool ListHashSet<T, inlineCapacity, U>::contains(const ValueType& value) const - { - return m_impl.template contains<BaseTranslator>(value); - } - - template<typename T, size_t inlineCapacity, typename U> - pair<typename ListHashSet<T, inlineCapacity, U>::iterator, bool> ListHashSet<T, inlineCapacity, U>::add(const ValueType &value) - { - pair<typename ImplType::iterator, bool> result = m_impl.template add<BaseTranslator>(value, m_allocator.get()); - if (result.second) - appendNode(*result.first); - return std::make_pair(makeIterator(*result.first), result.second); - } - - template<typename T, size_t inlineCapacity, typename U> - pair<typename ListHashSet<T, inlineCapacity, U>::iterator, bool> ListHashSet<T, inlineCapacity, U>::insertBefore(iterator it, const ValueType& newValue) - { - pair<typename ImplType::iterator, bool> result = m_impl.template add<BaseTranslator>(newValue, m_allocator.get()); - if (result.second) - insertNodeBefore(it.node(), *result.first); - return std::make_pair(makeIterator(*result.first), result.second); - - } - - template<typename T, size_t inlineCapacity, typename U> - pair<typename ListHashSet<T, inlineCapacity, U>::iterator, bool> ListHashSet<T, inlineCapacity, U>::insertBefore(const ValueType& beforeValue, const ValueType& newValue) - { - return insertBefore(find(beforeValue), newValue); - } - - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::remove(iterator it) - { - if (it == end()) - return; - m_impl.remove(it.node()); - unlinkAndDelete(it.node()); - } - - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::remove(const ValueType& value) - { - remove(find(value)); - } - - template<typename T, size_t inlineCapacity, typename U> - inline void ListHashSet<T, inlineCapacity, U>::clear() - { - deleteAllNodes(); - m_impl.clear(); - m_head = 0; - m_tail = 0; - } - - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::unlinkAndDelete(Node* node) - { - if (!node->m_prev) { - ASSERT(node == m_head); - m_head = node->m_next; - } else { - ASSERT(node != m_head); - node->m_prev->m_next = node->m_next; - } - - if (!node->m_next) { - ASSERT(node == m_tail); - m_tail = node->m_prev; - } else { - ASSERT(node != m_tail); - node->m_next->m_prev = node->m_prev; - } - - node->destroy(m_allocator.get()); - } - - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::appendNode(Node* node) - { - node->m_prev = m_tail; - node->m_next = 0; - - if (m_tail) { - ASSERT(m_head); - m_tail->m_next = node; - } else { - ASSERT(!m_head); - m_head = node; - } - - m_tail = node; - } - - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::insertNodeBefore(Node* beforeNode, Node* newNode) - { - if (!beforeNode) - return appendNode(newNode); - - newNode->m_next = beforeNode; - newNode->m_prev = beforeNode->m_prev; - if (beforeNode->m_prev) - beforeNode->m_prev->m_next = newNode; - beforeNode->m_prev = newNode; - - if (!newNode->m_prev) - m_head = newNode; - } - - template<typename T, size_t inlineCapacity, typename U> - void ListHashSet<T, inlineCapacity, U>::deleteAllNodes() - { - if (!m_head) - return; - - for (Node* node = m_head, *next = m_head->m_next; node; node = next, next = node ? node->m_next : 0) - node->destroy(m_allocator.get()); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSetReverseIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeReverseIterator(Node* position) - { - return ListHashSetReverseIterator<T, inlineCapacity, U>(this, position); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSetConstReverseIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeConstReverseIterator(Node* position) const - { - return ListHashSetConstReverseIterator<T, inlineCapacity, U>(this, position); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSetIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeIterator(Node* position) - { - return ListHashSetIterator<T, inlineCapacity, U>(this, position); - } - - template<typename T, size_t inlineCapacity, typename U> - inline ListHashSetConstIterator<T, inlineCapacity, U> ListHashSet<T, inlineCapacity, U>::makeConstIterator(Node* position) const - { - return ListHashSetConstIterator<T, inlineCapacity, U>(this, position); - } - template<bool, typename ValueType, typename HashTableType> - void deleteAllValues(HashTableType& collection) - { - typedef typename HashTableType::const_iterator iterator; - iterator end = collection.end(); - for (iterator it = collection.begin(); it != end; ++it) - delete (*it)->m_value; - } - - template<typename T, size_t inlineCapacity, typename U> - inline void deleteAllValues(const ListHashSet<T, inlineCapacity, U>& collection) - { - deleteAllValues<true, typename ListHashSet<T, inlineCapacity, U>::ValueType>(collection.m_impl); - } - -} // namespace WTF - -using WTF::ListHashSet; - -#endif /* WTF_ListHashSet_h */ diff --git a/Source/JavaScriptCore/wtf/ListRefPtr.h b/Source/JavaScriptCore/wtf/ListRefPtr.h deleted file mode 100644 index 4ba0632d7..000000000 --- a/Source/JavaScriptCore/wtf/ListRefPtr.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 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 WTF_ListRefPtr_h -#define WTF_ListRefPtr_h - -#include <wtf/RefPtr.h> - -namespace WTF { - - // Specialized version of RefPtr desgined for use in singly-linked lists. - // Derefs the list iteratively to avoid recursive derefing that can overflow the stack. - template <typename T> class ListRefPtr : public RefPtr<T> { - public: - ListRefPtr() : RefPtr<T>() {} - ListRefPtr(T* ptr) : RefPtr<T>(ptr) {} - ListRefPtr(const RefPtr<T>& o) : RefPtr<T>(o) {} - // see comment in PassRefPtr.h for why this takes const reference - template <typename U> ListRefPtr(const PassRefPtr<U>& o) : RefPtr<T>(o) {} - - ~ListRefPtr() - { - RefPtr<T> reaper = this->release(); - while (reaper && reaper->hasOneRef()) - reaper = reaper->releaseNext(); // implicitly protects reaper->next, then derefs reaper - } - - ListRefPtr& operator=(T* optr) { RefPtr<T>::operator=(optr); return *this; } - ListRefPtr& operator=(const RefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; } - ListRefPtr& operator=(const PassRefPtr<T>& o) { RefPtr<T>::operator=(o); return *this; } - template <typename U> ListRefPtr& operator=(const RefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; } - template <typename U> ListRefPtr& operator=(const PassRefPtr<U>& o) { RefPtr<T>::operator=(o); return *this; } - }; - - template <typename T> inline T* getPtr(const ListRefPtr<T>& p) - { - return p.get(); - } - -} // namespace WTF - -using WTF::ListRefPtr; - -#endif // WTF_ListRefPtr_h diff --git a/Source/JavaScriptCore/wtf/Locker.h b/Source/JavaScriptCore/wtf/Locker.h deleted file mode 100644 index c465b99ea..000000000 --- a/Source/JavaScriptCore/wtf/Locker.h +++ /dev/null @@ -1,48 +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. - * 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 Locker_h -#define Locker_h - -#include <wtf/Noncopyable.h> - -namespace WTF { - -template <typename T> class Locker { - WTF_MAKE_NONCOPYABLE(Locker); -public: - Locker(T& lockable) : m_lockable(lockable) { m_lockable.lock(); } - ~Locker() { m_lockable.unlock(); } -private: - T& m_lockable; -}; - -} - -using WTF::Locker; - -#endif diff --git a/Source/JavaScriptCore/wtf/MD5.cpp b/Source/JavaScriptCore/wtf/MD5.cpp deleted file mode 100644 index 07bbadd9f..000000000 --- a/Source/JavaScriptCore/wtf/MD5.cpp +++ /dev/null @@ -1,309 +0,0 @@ -// The original file was copied from sqlite, and was in the public domain. -// Modifications Copyright 2006 Google Inc. All Rights Reserved -/* - * 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -/* - * This code implements the MD5 message-digest algorithm. - * The algorithm is due to Ron Rivest. This code was - * written by Colin Plumb in 1993, no copyright is claimed. - * This code is in the public domain; do with it what you wish. - * - * Equivalent code is available from RSA Data Security, Inc. - * This code has been tested against that, and is equivalent, - * except that you don't need to include two pages of legalese - * with every copy. - * - * To compute the message digest of a chunk of bytes, construct an - * MD5 instance, call addBytes as needed on buffers full of bytes, - * and then call checksum, which will fill a supplied 16-byte array - * with the digest. - */ - -#include "config.h" -#include "MD5.h" - -#include "Assertions.h" -#ifndef NDEBUG -#include "StringExtras.h" -#include "text/CString.h" -#endif -#include <wtf/StdLibExtras.h> - -namespace WTF { - -#ifdef NDEBUG -static inline void testMD5() { } -#else -// MD5 test case. -static bool isTestMD5Done; - -static void expectMD5(CString input, CString expected) -{ - MD5 md5; - md5.addBytes(reinterpret_cast<const uint8_t*>(input.data()), input.length()); - Vector<uint8_t, 16> digest; - md5.checksum(digest); - char* buf = 0; - CString actual = CString::newUninitialized(32, buf); - for (size_t i = 0; i < 16; i++) { - snprintf(buf, 3, "%02x", digest.at(i)); - buf += 2; - } - ASSERT_WITH_MESSAGE(actual == expected, "input:%s[%lu] actual:%s expected:%s", input.data(), static_cast<unsigned long>(input.length()), actual.data(), expected.data()); -} - -static void testMD5() -{ - if (isTestMD5Done) - return; - isTestMD5Done = true; - - // MD5 Test suite from http://www.ietf.org/rfc/rfc1321.txt - expectMD5("", "d41d8cd98f00b204e9800998ecf8427e"); - expectMD5("a", "0cc175b9c0f1b6a831c399e269772661"); - expectMD5("abc", "900150983cd24fb0d6963f7d28e17f72"); - expectMD5("message digest", "f96b697d7cb7938d525a2f31aaf161d0"); - expectMD5("abcdefghijklmnopqrstuvwxyz", "c3fcd3d76192e4007dfb496cca67e13b"); - expectMD5("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "d174ab98d277d9f5a5611c2c9f419d9f"); - expectMD5("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "57edf4a22be3c955ac49da2e2107b67a"); -} -#endif - -// Note: this code is harmless on little-endian machines. - -static void reverseBytes(uint8_t* buf, unsigned longs) -{ - ASSERT(longs > 0); - do { - uint32_t t = static_cast<uint32_t>(buf[3] << 8 | buf[2]) << 16 | buf[1] << 8 | buf[0]; - ASSERT_WITH_MESSAGE(!(reinterpret_cast<uintptr_t>(buf) % sizeof(t)), "alignment error of buf"); - *reinterpret_cast_ptr<uint32_t *>(buf) = t; - buf += 4; - } while (--longs); -} - -// The four core functions. -// F1 is originally defined as (x & y | ~x & z), but optimized somewhat: 4 bit ops -> 3 bit ops. -#define F1(x, y, z) (z ^ (x & (y ^ z))) -#define F2(x, y, z) F1(z, x, y) -#define F3(x, y, z) (x ^ y ^ z) -#define F4(x, y, z) (y ^ (x | ~z)) - -// This is the central step in the MD5 algorithm. -#define MD5STEP(f, w, x, y, z, data, s) \ - (w += f(x, y, z) + data, w = w << s | w >> (32 - s), w += x) - -static void MD5Transform(uint32_t buf[4], const uint32_t in[16]) -{ - uint32_t a = buf[0]; - uint32_t b = buf[1]; - uint32_t c = buf[2]; - uint32_t d = buf[3]; - - MD5STEP(F1, a, b, c, d, in[ 0]+0xd76aa478, 7); - MD5STEP(F1, d, a, b, c, in[ 1]+0xe8c7b756, 12); - MD5STEP(F1, c, d, a, b, in[ 2]+0x242070db, 17); - MD5STEP(F1, b, c, d, a, in[ 3]+0xc1bdceee, 22); - MD5STEP(F1, a, b, c, d, in[ 4]+0xf57c0faf, 7); - MD5STEP(F1, d, a, b, c, in[ 5]+0x4787c62a, 12); - MD5STEP(F1, c, d, a, b, in[ 6]+0xa8304613, 17); - MD5STEP(F1, b, c, d, a, in[ 7]+0xfd469501, 22); - MD5STEP(F1, a, b, c, d, in[ 8]+0x698098d8, 7); - MD5STEP(F1, d, a, b, c, in[ 9]+0x8b44f7af, 12); - MD5STEP(F1, c, d, a, b, in[10]+0xffff5bb1, 17); - MD5STEP(F1, b, c, d, a, in[11]+0x895cd7be, 22); - MD5STEP(F1, a, b, c, d, in[12]+0x6b901122, 7); - MD5STEP(F1, d, a, b, c, in[13]+0xfd987193, 12); - MD5STEP(F1, c, d, a, b, in[14]+0xa679438e, 17); - MD5STEP(F1, b, c, d, a, in[15]+0x49b40821, 22); - - MD5STEP(F2, a, b, c, d, in[ 1]+0xf61e2562, 5); - MD5STEP(F2, d, a, b, c, in[ 6]+0xc040b340, 9); - MD5STEP(F2, c, d, a, b, in[11]+0x265e5a51, 14); - MD5STEP(F2, b, c, d, a, in[ 0]+0xe9b6c7aa, 20); - MD5STEP(F2, a, b, c, d, in[ 5]+0xd62f105d, 5); - MD5STEP(F2, d, a, b, c, in[10]+0x02441453, 9); - MD5STEP(F2, c, d, a, b, in[15]+0xd8a1e681, 14); - MD5STEP(F2, b, c, d, a, in[ 4]+0xe7d3fbc8, 20); - MD5STEP(F2, a, b, c, d, in[ 9]+0x21e1cde6, 5); - MD5STEP(F2, d, a, b, c, in[14]+0xc33707d6, 9); - MD5STEP(F2, c, d, a, b, in[ 3]+0xf4d50d87, 14); - MD5STEP(F2, b, c, d, a, in[ 8]+0x455a14ed, 20); - MD5STEP(F2, a, b, c, d, in[13]+0xa9e3e905, 5); - MD5STEP(F2, d, a, b, c, in[ 2]+0xfcefa3f8, 9); - MD5STEP(F2, c, d, a, b, in[ 7]+0x676f02d9, 14); - MD5STEP(F2, b, c, d, a, in[12]+0x8d2a4c8a, 20); - - MD5STEP(F3, a, b, c, d, in[ 5]+0xfffa3942, 4); - MD5STEP(F3, d, a, b, c, in[ 8]+0x8771f681, 11); - MD5STEP(F3, c, d, a, b, in[11]+0x6d9d6122, 16); - MD5STEP(F3, b, c, d, a, in[14]+0xfde5380c, 23); - MD5STEP(F3, a, b, c, d, in[ 1]+0xa4beea44, 4); - MD5STEP(F3, d, a, b, c, in[ 4]+0x4bdecfa9, 11); - MD5STEP(F3, c, d, a, b, in[ 7]+0xf6bb4b60, 16); - MD5STEP(F3, b, c, d, a, in[10]+0xbebfbc70, 23); - MD5STEP(F3, a, b, c, d, in[13]+0x289b7ec6, 4); - MD5STEP(F3, d, a, b, c, in[ 0]+0xeaa127fa, 11); - MD5STEP(F3, c, d, a, b, in[ 3]+0xd4ef3085, 16); - MD5STEP(F3, b, c, d, a, in[ 6]+0x04881d05, 23); - MD5STEP(F3, a, b, c, d, in[ 9]+0xd9d4d039, 4); - MD5STEP(F3, d, a, b, c, in[12]+0xe6db99e5, 11); - MD5STEP(F3, c, d, a, b, in[15]+0x1fa27cf8, 16); - MD5STEP(F3, b, c, d, a, in[ 2]+0xc4ac5665, 23); - - MD5STEP(F4, a, b, c, d, in[ 0]+0xf4292244, 6); - MD5STEP(F4, d, a, b, c, in[ 7]+0x432aff97, 10); - MD5STEP(F4, c, d, a, b, in[14]+0xab9423a7, 15); - MD5STEP(F4, b, c, d, a, in[ 5]+0xfc93a039, 21); - MD5STEP(F4, a, b, c, d, in[12]+0x655b59c3, 6); - MD5STEP(F4, d, a, b, c, in[ 3]+0x8f0ccc92, 10); - MD5STEP(F4, c, d, a, b, in[10]+0xffeff47d, 15); - MD5STEP(F4, b, c, d, a, in[ 1]+0x85845dd1, 21); - MD5STEP(F4, a, b, c, d, in[ 8]+0x6fa87e4f, 6); - MD5STEP(F4, d, a, b, c, in[15]+0xfe2ce6e0, 10); - MD5STEP(F4, c, d, a, b, in[ 6]+0xa3014314, 15); - MD5STEP(F4, b, c, d, a, in[13]+0x4e0811a1, 21); - MD5STEP(F4, a, b, c, d, in[ 4]+0xf7537e82, 6); - MD5STEP(F4, d, a, b, c, in[11]+0xbd3af235, 10); - MD5STEP(F4, c, d, a, b, in[ 2]+0x2ad7d2bb, 15); - MD5STEP(F4, b, c, d, a, in[ 9]+0xeb86d391, 21); - - buf[0] += a; - buf[1] += b; - buf[2] += c; - buf[3] += d; -} - -MD5::MD5() -{ - // FIXME: Move unit tests somewhere outside the constructor. See bug 55853. - testMD5(); - m_buf[0] = 0x67452301; - m_buf[1] = 0xefcdab89; - m_buf[2] = 0x98badcfe; - m_buf[3] = 0x10325476; - m_bits[0] = 0; - m_bits[1] = 0; - memset(m_in, 0, sizeof(m_in)); - ASSERT_WITH_MESSAGE(!(reinterpret_cast<uintptr_t>(m_in) % sizeof(uint32_t)), "alignment error of m_in"); -} - -void MD5::addBytes(const uint8_t* input, size_t length) -{ - const uint8_t* buf = input; - - // Update bitcount - uint32_t t = m_bits[0]; - m_bits[0] = t + (length << 3); - if (m_bits[0] < t) - m_bits[1]++; // Carry from low to high - m_bits[1] += length >> 29; - - t = (t >> 3) & 0x3f; // Bytes already in shsInfo->data - - // Handle any leading odd-sized chunks - - if (t) { - uint8_t* p = m_in + t; - - t = 64 - t; - if (length < t) { - memcpy(p, buf, length); - return; - } - memcpy(p, buf, t); - reverseBytes(m_in, 16); - MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); // m_in is 4-byte aligned. - buf += t; - length -= t; - } - - // Process data in 64-byte chunks - - while (length >= 64) { - memcpy(m_in, buf, 64); - reverseBytes(m_in, 16); - MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); // m_in is 4-byte aligned. - buf += 64; - length -= 64; - } - - // Handle any remaining bytes of data. - memcpy(m_in, buf, length); -} - -void MD5::checksum(Vector<uint8_t, 16>& digest) -{ - // Compute number of bytes mod 64 - unsigned count = (m_bits[0] >> 3) & 0x3F; - - // Set the first char of padding to 0x80. This is safe since there is - // always at least one byte free - uint8_t* p = m_in + count; - *p++ = 0x80; - - // Bytes of padding needed to make 64 bytes - count = 64 - 1 - count; - - // Pad out to 56 mod 64 - if (count < 8) { - // Two lots of padding: Pad the first block to 64 bytes - memset(p, 0, count); - reverseBytes(m_in, 16); - MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t *>(m_in)); // m_in is 4-byte aligned. - - // Now fill the next block with 56 bytes - memset(m_in, 0, 56); - } else { - // Pad block to 56 bytes - memset(p, 0, count - 8); - } - reverseBytes(m_in, 14); - - // Append length in bits and transform - // m_in is 4-byte aligned. - (reinterpret_cast_ptr<uint32_t*>(m_in))[14] = m_bits[0]; - (reinterpret_cast_ptr<uint32_t*>(m_in))[15] = m_bits[1]; - - MD5Transform(m_buf, reinterpret_cast_ptr<uint32_t*>(m_in)); - reverseBytes(reinterpret_cast<uint8_t*>(m_buf), 4); - - // Now, m_buf contains checksum result. - if (!digest.isEmpty()) - digest.clear(); - digest.append(reinterpret_cast<uint8_t*>(m_buf), 16); - - // In case it's sensitive - memset(m_buf, 0, sizeof(m_buf)); - memset(m_bits, 0, sizeof(m_bits)); - memset(m_in, 0, sizeof(m_in)); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/MD5.h b/Source/JavaScriptCore/wtf/MD5.h deleted file mode 100644 index ef027ccad..000000000 --- a/Source/JavaScriptCore/wtf/MD5.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WTF_MD5_h -#define WTF_MD5_h - -#include <wtf/Vector.h> - -namespace WTF { - -class MD5 { -public: - WTF_EXPORT_PRIVATE MD5(); - - void addBytes(const Vector<uint8_t>& input) - { - addBytes(input.data(), input.size()); - } - WTF_EXPORT_PRIVATE void addBytes(const uint8_t* input, size_t length); - - // checksum has a side effect of resetting the state of the object. - WTF_EXPORT_PRIVATE void checksum(Vector<uint8_t, 16>&); - -private: - uint32_t m_buf[4]; - uint32_t m_bits[2]; - uint8_t m_in[64]; -}; - -} // namespace WTF - -using WTF::MD5; - -#endif // WTF_MD5_h diff --git a/Source/JavaScriptCore/wtf/MainThread.cpp b/Source/JavaScriptCore/wtf/MainThread.cpp deleted file mode 100644 index f8686aa31..000000000 --- a/Source/JavaScriptCore/wtf/MainThread.cpp +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright (C) 2007, 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 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" -#include "MainThread.h" - -#include "CurrentTime.h" -#include "Deque.h" -#include "Functional.h" -#include "StdLibExtras.h" -#include "Threading.h" -#include <wtf/ThreadSpecific.h> - -#if PLATFORM(CHROMIUM) -#error Chromium uses a different main thread implementation -#endif - -namespace WTF { - -struct FunctionWithContext { - MainThreadFunction* function; - void* context; - ThreadCondition* syncFlag; - - FunctionWithContext(MainThreadFunction* function = 0, void* context = 0, ThreadCondition* syncFlag = 0) - : function(function) - , context(context) - , syncFlag(syncFlag) - { - } - bool operator == (const FunctionWithContext& o) - { - return function == o.function - && context == o.context - && syncFlag == o.syncFlag; - } -}; - -class FunctionWithContextFinder { -public: - FunctionWithContextFinder(const FunctionWithContext& m) : m(m) {} - bool operator() (FunctionWithContext& o) { return o == m; } - FunctionWithContext m; -}; - - -typedef Deque<FunctionWithContext> FunctionQueue; - -static bool callbacksPaused; // This global variable is only accessed from main thread. -#if !PLATFORM(MAC) -static ThreadIdentifier mainThreadIdentifier; -#endif - -static Mutex& mainThreadFunctionQueueMutex() -{ - DEFINE_STATIC_LOCAL(Mutex, staticMutex, ()); - return staticMutex; -} - -static FunctionQueue& functionQueue() -{ - DEFINE_STATIC_LOCAL(FunctionQueue, staticFunctionQueue, ()); - return staticFunctionQueue; -} - - -#if !PLATFORM(MAC) - -void initializeMainThread() -{ - static bool initializedMainThread; - if (initializedMainThread) - return; - initializedMainThread = true; - - mainThreadIdentifier = currentThread(); - - mainThreadFunctionQueueMutex(); - initializeMainThreadPlatform(); - initializeGCThreads(); -} - -#else - -static pthread_once_t initializeMainThreadKeyOnce = PTHREAD_ONCE_INIT; - -static void initializeMainThreadOnce() -{ - mainThreadFunctionQueueMutex(); - initializeMainThreadPlatform(); -} - -void initializeMainThread() -{ - pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadOnce); -} - -static void initializeMainThreadToProcessMainThreadOnce() -{ - mainThreadFunctionQueueMutex(); - initializeMainThreadToProcessMainThreadPlatform(); -} - -void initializeMainThreadToProcessMainThread() -{ - pthread_once(&initializeMainThreadKeyOnce, initializeMainThreadToProcessMainThreadOnce); -} -#endif - -// 0.1 sec delays in UI is approximate threshold when they become noticeable. Have a limit that's half of that. -static const double maxRunLoopSuspensionTime = 0.05; - -void dispatchFunctionsFromMainThread() -{ - ASSERT(isMainThread()); - - if (callbacksPaused) - return; - - double startTime = currentTime(); - - FunctionWithContext invocation; - while (true) { - { - MutexLocker locker(mainThreadFunctionQueueMutex()); - if (!functionQueue().size()) - break; - invocation = functionQueue().takeFirst(); - } - - invocation.function(invocation.context); - if (invocation.syncFlag) { - MutexLocker locker(mainThreadFunctionQueueMutex()); - invocation.syncFlag->signal(); - } - - // If we are running accumulated functions for too long so UI may become unresponsive, we need to - // yield so the user input can be processed. Otherwise user may not be able to even close the window. - // This code has effect only in case the scheduleDispatchFunctionsOnMainThread() is implemented in a way that - // allows input events to be processed before we are back here. - if (currentTime() - startTime > maxRunLoopSuspensionTime) { - scheduleDispatchFunctionsOnMainThread(); - break; - } - } -} - -void callOnMainThread(MainThreadFunction* function, void* context) -{ - ASSERT(function); - bool needToSchedule = false; - { - MutexLocker locker(mainThreadFunctionQueueMutex()); - needToSchedule = functionQueue().size() == 0; - functionQueue().append(FunctionWithContext(function, context)); - } - if (needToSchedule) - scheduleDispatchFunctionsOnMainThread(); -} - -void callOnMainThreadAndWait(MainThreadFunction* function, void* context) -{ - ASSERT(function); - - if (isMainThread()) { - function(context); - return; - } - - ThreadCondition syncFlag; - Mutex& functionQueueMutex = mainThreadFunctionQueueMutex(); - MutexLocker locker(functionQueueMutex); - functionQueue().append(FunctionWithContext(function, context, &syncFlag)); - if (functionQueue().size() == 1) - scheduleDispatchFunctionsOnMainThread(); - syncFlag.wait(functionQueueMutex); -} - -void cancelCallOnMainThread(MainThreadFunction* function, void* context) -{ - ASSERT(function); - - MutexLocker locker(mainThreadFunctionQueueMutex()); - - FunctionWithContextFinder pred(FunctionWithContext(function, context)); - - while (true) { - // We must redefine 'i' each pass, because the itererator's operator= - // requires 'this' to be valid, and remove() invalidates all iterators - FunctionQueue::iterator i(functionQueue().findIf(pred)); - if (i == functionQueue().end()) - break; - functionQueue().remove(i); - } -} - -static void callFunctionObject(void* context) -{ - Function<void ()>* function = static_cast<Function<void ()>*>(context); - (*function)(); - delete function; -} - -void callOnMainThread(const Function<void ()>& function) -{ - callOnMainThread(callFunctionObject, new Function<void ()>(function)); -} - -void setMainThreadCallbacksPaused(bool paused) -{ - ASSERT(isMainThread()); - - if (callbacksPaused == paused) - return; - - callbacksPaused = paused; - - if (!callbacksPaused) - scheduleDispatchFunctionsOnMainThread(); -} - -#if !PLATFORM(MAC) -bool isMainThread() -{ - return currentThread() == mainThreadIdentifier; -} -#endif - -#if ENABLE(PARALLEL_GC) -static ThreadSpecific<bool>* isGCThread; -#endif - -void initializeGCThreads() -{ -#if ENABLE(PARALLEL_GC) - isGCThread = new ThreadSpecific<bool>(); -#endif -} - -#if ENABLE(PARALLEL_GC) -void registerGCThread() -{ - if (!isGCThread) { - // This happens if we're running in a process that doesn't care about - // MainThread. - return; - } - - **isGCThread = true; -} - -bool isMainThreadOrGCThread() -{ - if (isGCThread->isSet() && **isGCThread) - return true; - - return isMainThread(); -} -#elif PLATFORM(MAC) -// This is necessary because JavaScriptCore.exp doesn't support preprocessor macros. -bool isMainThreadOrGCThread() -{ - return isMainThread(); -} -#endif - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/MainThread.h b/Source/JavaScriptCore/wtf/MainThread.h deleted file mode 100644 index 24200779a..000000000 --- a/Source/JavaScriptCore/wtf/MainThread.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * 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 MainThread_h -#define MainThread_h - -#include <wtf/Platform.h> - -#include <stdint.h> - -namespace WTF { - -typedef uint32_t ThreadIdentifier; -typedef void MainThreadFunction(void*); - -// Must be called from the main thread. -WTF_EXPORT_PRIVATE void initializeMainThread(); - -WTF_EXPORT_PRIVATE void callOnMainThread(MainThreadFunction*, void* context); -WTF_EXPORT_PRIVATE void callOnMainThreadAndWait(MainThreadFunction*, void* context); -WTF_EXPORT_PRIVATE void cancelCallOnMainThread(MainThreadFunction*, void* context); - -template<typename> class Function; -WTF_EXPORT_PRIVATE void callOnMainThread(const Function<void ()>&); - -WTF_EXPORT_PRIVATE void setMainThreadCallbacksPaused(bool paused); - -WTF_EXPORT_PRIVATE bool isMainThread(); - -void initializeGCThreads(); - -#if ENABLE(PARALLEL_GC) -void registerGCThread(); -WTF_EXPORT_PRIVATE bool isMainThreadOrGCThread(); -#elif PLATFORM(MAC) -WTF_EXPORT_PRIVATE bool isMainThreadOrGCThread(); -#else -inline bool isMainThreadOrGCThread() { return isMainThread(); } -#endif - -// NOTE: these functions are internal to the callOnMainThread implementation. -void initializeMainThreadPlatform(); -void scheduleDispatchFunctionsOnMainThread(); -void dispatchFunctionsFromMainThread(); - -#if PLATFORM(MAC) -// This version of initializeMainThread sets up the main thread as corresponding -// to the process's main thread, and not necessarily the thread that calls this -// function. It should only be used as a legacy aid for Mac WebKit. -WTF_EXPORT_PRIVATE void initializeMainThreadToProcessMainThread(); -void initializeMainThreadToProcessMainThreadPlatform(); -#endif - -} // namespace WTF - -using WTF::callOnMainThread; -using WTF::callOnMainThreadAndWait; -using WTF::cancelCallOnMainThread; -using WTF::setMainThreadCallbacksPaused; -using WTF::isMainThread; -using WTF::isMainThreadOrGCThread; -#endif // MainThread_h diff --git a/Source/JavaScriptCore/wtf/MallocZoneSupport.h b/Source/JavaScriptCore/wtf/MallocZoneSupport.h deleted file mode 100644 index 4332e40b8..000000000 --- a/Source/JavaScriptCore/wtf/MallocZoneSupport.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2007 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 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 MallocZoneSupport_h -#define MallocZoneSupport_h - -#include <malloc/malloc.h> - -namespace WTF { - -class RemoteMemoryReader { - task_t m_task; - memory_reader_t* m_reader; - -public: - RemoteMemoryReader(task_t task, memory_reader_t* reader) - : m_task(task) - , m_reader(reader) - { } - - void* operator()(vm_address_t address, size_t size) const - { - void* output; - kern_return_t err = (*m_reader)(m_task, address, size, static_cast<void**>(&output)); - if (err) - output = 0; - return output; - } - - template <typename T> - T* operator()(T* address, size_t size=sizeof(T)) const - { - return static_cast<T*>((*this)(reinterpret_cast<vm_address_t>(address), size)); - } - - template <typename T> - T* nextEntryInLinkedList(T** address) const - { - T** output = (*this)(address); - if (!output) - return 0; - return *output; - } -}; - -} // namespace WTF - -#endif // MallocZoneSupport_h diff --git a/Source/JavaScriptCore/wtf/MathExtras.h b/Source/JavaScriptCore/wtf/MathExtras.h deleted file mode 100644 index e8ebd6ba1..000000000 --- a/Source/JavaScriptCore/wtf/MathExtras.h +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 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 WTF_MathExtras_h -#define WTF_MathExtras_h - -#include <algorithm> -#include <cmath> -#include <float.h> -#include <limits> -#include <stdint.h> -#include <stdlib.h> -#include <wtf/StdLibExtras.h> - -#if OS(SOLARIS) -#include <ieeefp.h> -#endif - -#if OS(OPENBSD) -#include <sys/types.h> -#include <machine/ieee.h> -#endif - -#if COMPILER(MSVC) -#if OS(WINCE) -#include <stdlib.h> -#endif -#include <limits> -#endif - -#if OS(QNX) -// FIXME: Look into a way to have cmath import its functions into both the standard and global -// namespace. For now, we include math.h since the QNX cmath header only imports its functions -// into the standard namespace. -#include <math.h> -#endif - -#ifndef M_PI -const double piDouble = 3.14159265358979323846; -const float piFloat = 3.14159265358979323846f; -#else -const double piDouble = M_PI; -const float piFloat = static_cast<float>(M_PI); -#endif - -#ifndef M_PI_2 -const double piOverTwoDouble = 1.57079632679489661923; -const float piOverTwoFloat = 1.57079632679489661923f; -#else -const double piOverTwoDouble = M_PI_2; -const float piOverTwoFloat = static_cast<float>(M_PI_2); -#endif - -#ifndef M_PI_4 -const double piOverFourDouble = 0.785398163397448309616; -const float piOverFourFloat = 0.785398163397448309616f; -#else -const double piOverFourDouble = M_PI_4; -const float piOverFourFloat = static_cast<float>(M_PI_4); -#endif - -#if OS(DARWIN) - -// Work around a bug in the Mac OS X libc where ceil(-0.1) return +0. -inline double wtf_ceil(double x) { return copysign(ceil(x), x); } - -#define ceil(x) wtf_ceil(x) - -#endif - -#if OS(SOLARIS) - -#ifndef isfinite -inline bool isfinite(double x) { return finite(x) && !isnand(x); } -#endif -#ifndef isinf -inline bool isinf(double x) { return !finite(x) && !isnand(x); } -#endif -#ifndef signbit -inline bool signbit(double x) { return copysign(1.0, x) < 0; } -#endif - -#endif - -#if OS(OPENBSD) - -#ifndef isfinite -inline bool isfinite(double x) { return finite(x); } -#endif -#ifndef signbit -inline bool signbit(double x) { struct ieee_double *p = (struct ieee_double *)&x; return p->dbl_sign; } -#endif - -#endif - -#if COMPILER(MSVC) || (COMPILER(RVCT) && !(RVCT_VERSION_AT_LEAST(3, 0, 0, 0))) - -// We must not do 'num + 0.5' or 'num - 0.5' because they can cause precision loss. -static double round(double num) -{ - double integer = ceil(num); - if (num > 0) - return integer - num > 0.5 ? integer - 1.0 : integer; - return integer - num >= 0.5 ? integer - 1.0 : integer; -} -static float roundf(float num) -{ - float integer = ceilf(num); - if (num > 0) - return integer - num > 0.5f ? integer - 1.0f : integer; - return integer - num >= 0.5f ? integer - 1.0f : integer; -} -inline long long llround(double num) { return static_cast<long long>(round(num)); } -inline long long llroundf(float num) { return static_cast<long long>(roundf(num)); } -inline long lround(double num) { return static_cast<long>(round(num)); } -inline long lroundf(float num) { return static_cast<long>(roundf(num)); } -inline double trunc(double num) { return num > 0 ? floor(num) : ceil(num); } - -#endif - -#if COMPILER(GCC) && OS(QNX) -// The stdlib on QNX doesn't contain long abs(long). See PR #104666. -inline long long abs(long num) { return labs(num); } -#endif - -#if COMPILER(MSVC) -// The 64bit version of abs() is already defined in stdlib.h which comes with VC10 -#if COMPILER(MSVC9_OR_LOWER) -inline long long abs(long long num) { return _abs64(num); } -#endif - -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; } - -inline double nextafter(double x, double y) { return _nextafter(x, y); } -inline float nextafterf(float x, float y) { return x > y ? x - FLT_EPSILON : x + FLT_EPSILON; } - -inline double copysign(double x, double y) { return _copysign(x, y); } -inline int isfinite(double x) { return _finite(x); } - -// MSVC's math.h does not currently supply log2 or log2f. -inline double log2(double num) -{ - // This constant is roughly M_LN2, which is not provided by default on Windows. - return log(num) / 0.693147180559945309417232121458176568; -} - -inline float log2f(float num) -{ - // This constant is roughly M_LN2, which is not provided by default on Windows. - return logf(num) / 0.693147180559945309417232121458176568f; -} - -// Work around a bug in Win, where atan2(+-infinity, +-infinity) yields NaN instead of specific values. -inline double wtf_atan2(double x, double y) -{ - double posInf = std::numeric_limits<double>::infinity(); - double negInf = -std::numeric_limits<double>::infinity(); - double nan = std::numeric_limits<double>::quiet_NaN(); - - double result = nan; - - if (x == posInf && y == posInf) - result = piOverFourDouble; - else if (x == posInf && y == negInf) - result = 3 * piOverFourDouble; - else if (x == negInf && y == posInf) - result = -piOverFourDouble; - else if (x == negInf && y == negInf) - result = -3 * piOverFourDouble; - else - result = ::atan2(x, y); - - return result; -} - -// Work around a bug in the Microsoft CRT, where fmod(x, +-infinity) yields NaN instead of x. -inline double wtf_fmod(double x, double y) { return (!isinf(x) && isinf(y)) ? x : fmod(x, y); } - -// Work around a bug in the Microsoft CRT, where pow(NaN, 0) yields NaN instead of 1. -inline double wtf_pow(double x, double y) { return y == 0 ? 1 : pow(x, y); } - -#define atan2(x, y) wtf_atan2(x, y) -#define fmod(x, y) wtf_fmod(x, y) -#define pow(x, y) wtf_pow(x, y) - -#endif // COMPILER(MSVC) - -inline double deg2rad(double d) { return d * piDouble / 180.0; } -inline double rad2deg(double r) { return r * 180.0 / piDouble; } -inline double deg2grad(double d) { return d * 400.0 / 360.0; } -inline double grad2deg(double g) { return g * 360.0 / 400.0; } -inline double turn2deg(double t) { return t * 360.0; } -inline double deg2turn(double d) { return d / 360.0; } -inline double rad2grad(double r) { return r * 200.0 / piDouble; } -inline double grad2rad(double g) { return g * piDouble / 200.0; } - -inline float deg2rad(float d) { return d * piFloat / 180.0f; } -inline float rad2deg(float r) { return r * 180.0f / piFloat; } -inline float deg2grad(float d) { return d * 400.0f / 360.0f; } -inline float grad2deg(float g) { return g * 360.0f / 400.0f; } -inline float turn2deg(float t) { return t * 360.0f; } -inline float deg2turn(float d) { return d / 360.0f; } -inline float rad2grad(float r) { return r * 200.0f / piFloat; } -inline float grad2rad(float g) { return g * piFloat / 200.0f; } - -// std::numeric_limits<T>::min() returns the smallest positive value for floating point types -template<typename T> inline T defaultMinimumForClamp() { return std::numeric_limits<T>::min(); } -template<> inline float defaultMinimumForClamp() { return -std::numeric_limits<float>::max(); } -template<> inline double defaultMinimumForClamp() { return -std::numeric_limits<double>::max(); } -template<typename T> inline T defaultMaximumForClamp() { return std::numeric_limits<T>::max(); } - -template<typename T> inline T clampTo(double value, T min = defaultMinimumForClamp<T>(), T max = defaultMaximumForClamp<T>()) -{ - if (value >= static_cast<double>(max)) - return max; - if (value <= static_cast<double>(min)) - return min; - return static_cast<T>(value); -} -template<> inline long long int clampTo(double, long long int, long long int); // clampTo does not support long long ints. - -inline int clampToInteger(double value) -{ - return clampTo<int>(value); -} - -inline float clampToFloat(double value) -{ - return clampTo<float>(value); -} - -inline int clampToPositiveInteger(double value) -{ - return clampTo<int>(value, 0); -} - -inline int clampToInteger(float value) -{ - return clampTo<int>(value); -} - -inline int clampToInteger(unsigned x) -{ - const unsigned intMax = static_cast<unsigned>(std::numeric_limits<int>::max()); - - if (x >= intMax) - return std::numeric_limits<int>::max(); - return static_cast<int>(x); -} - -inline bool isWithinIntRange(float x) -{ - return x > static_cast<float>(std::numeric_limits<int>::min()) && x < static_cast<float>(std::numeric_limits<int>::max()); -} - -#if !COMPILER(MSVC) && !COMPILER(RVCT) && !OS(SOLARIS) -using std::isfinite; -using std::isinf; -using std::isnan; -using std::signbit; -#endif - -// decompose 'number' to its sign, exponent, and mantissa components. -// The result is interpreted as: -// (sign ? -1 : 1) * pow(2, exponent) * (mantissa / (1 << 52)) -inline void decomposeDouble(double number, bool& sign, int32_t& exponent, uint64_t& mantissa) -{ - ASSERT(isfinite(number)); - - sign = signbit(number); - - uint64_t bits = WTF::bitwise_cast<uint64_t>(number); - exponent = (static_cast<int32_t>(bits >> 52) & 0x7ff) - 0x3ff; - mantissa = bits & 0xFFFFFFFFFFFFFull; - - // Check for zero/denormal values; if so, adjust the exponent, - // if not insert the implicit, omitted leading 1 bit. - if (exponent == -0x3ff) - exponent = mantissa ? -0x3fe : 0; - else - mantissa |= 0x10000000000000ull; -} - -// Calculate d % 2^{64}. -inline void doubleToInteger(double d, unsigned long long& value) -{ - if (isnan(d) || isinf(d)) - value = 0; - else { - // -2^{64} < fmodValue < 2^{64}. - double fmodValue = fmod(trunc(d), std::numeric_limits<unsigned long long>::max() + 1.0); - if (fmodValue >= 0) { - // 0 <= fmodValue < 2^{64}. - // 0 <= value < 2^{64}. This cast causes no loss. - value = static_cast<unsigned long long>(fmodValue); - } else { - // -2^{64} < fmodValue < 0. - // 0 < fmodValueInUnsignedLongLong < 2^{64}. This cast causes no loss. - unsigned long long fmodValueInUnsignedLongLong = static_cast<unsigned long long>(-fmodValue); - // -1 < (std::numeric_limits<unsigned long long>::max() - fmodValueInUnsignedLongLong) < 2^{64} - 1. - // 0 < value < 2^{64}. - value = std::numeric_limits<unsigned long long>::max() - fmodValueInUnsignedLongLong + 1; - } - } -} - -#endif // #ifndef WTF_MathExtras_h diff --git a/Source/JavaScriptCore/wtf/MessageQueue.h b/Source/JavaScriptCore/wtf/MessageQueue.h deleted file mode 100644 index dda852fe1..000000000 --- a/Source/JavaScriptCore/wtf/MessageQueue.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2008 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. - * 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 MessageQueue_h -#define MessageQueue_h - -#include <limits> -#include <wtf/Assertions.h> -#include <wtf/Deque.h> -#include <wtf/Noncopyable.h> -#include <wtf/Threading.h> - -namespace WTF { - - enum MessageQueueWaitResult { - MessageQueueTerminated, // Queue was destroyed while waiting for message. - MessageQueueTimeout, // Timeout was specified and it expired. - MessageQueueMessageReceived // A message was successfully received and returned. - }; - - // The queue takes ownership of messages and transfer it to the new owner - // when messages are fetched from the queue. - // Essentially, MessageQueue acts as a queue of OwnPtr<DataType>. - template<typename DataType> - class MessageQueue { - WTF_MAKE_NONCOPYABLE(MessageQueue); - public: - MessageQueue() : m_killed(false) { } - ~MessageQueue(); - - void append(PassOwnPtr<DataType>); - bool appendAndCheckEmpty(PassOwnPtr<DataType>); - void prepend(PassOwnPtr<DataType>); - - PassOwnPtr<DataType> waitForMessage(); - PassOwnPtr<DataType> tryGetMessage(); - PassOwnPtr<DataType> tryGetMessageIgnoringKilled(); - template<typename Predicate> - PassOwnPtr<DataType> waitForMessageFilteredWithTimeout(MessageQueueWaitResult&, Predicate&, double absoluteTime); - - template<typename Predicate> - void removeIf(Predicate&); - - void kill(); - bool killed() const; - - // The result of isEmpty() is only valid if no other thread is manipulating the queue at the same time. - bool isEmpty(); - - static double infiniteTime() { return std::numeric_limits<double>::max(); } - - private: - static bool alwaysTruePredicate(DataType*) { return true; } - - mutable Mutex m_mutex; - ThreadCondition m_condition; - Deque<DataType*> m_queue; - bool m_killed; - }; - - template<typename DataType> - MessageQueue<DataType>::~MessageQueue() - { - deleteAllValues(m_queue); - } - - template<typename DataType> - inline void MessageQueue<DataType>::append(PassOwnPtr<DataType> message) - { - MutexLocker lock(m_mutex); - m_queue.append(message.leakPtr()); - m_condition.signal(); - } - - // Returns true if the queue was empty before the item was added. - template<typename DataType> - inline bool MessageQueue<DataType>::appendAndCheckEmpty(PassOwnPtr<DataType> message) - { - MutexLocker lock(m_mutex); - bool wasEmpty = m_queue.isEmpty(); - m_queue.append(message.leakPtr()); - m_condition.signal(); - return wasEmpty; - } - - template<typename DataType> - inline void MessageQueue<DataType>::prepend(PassOwnPtr<DataType> message) - { - MutexLocker lock(m_mutex); - m_queue.prepend(message.leakPtr()); - m_condition.signal(); - } - - template<typename DataType> - inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessage() - { - MessageQueueWaitResult exitReason; - OwnPtr<DataType> result = waitForMessageFilteredWithTimeout(exitReason, MessageQueue<DataType>::alwaysTruePredicate, infiniteTime()); - ASSERT(exitReason == MessageQueueTerminated || exitReason == MessageQueueMessageReceived); - return result.release(); - } - - template<typename DataType> - template<typename Predicate> - inline PassOwnPtr<DataType> MessageQueue<DataType>::waitForMessageFilteredWithTimeout(MessageQueueWaitResult& result, Predicate& predicate, double absoluteTime) - { - MutexLocker lock(m_mutex); - bool timedOut = false; - - DequeConstIterator<DataType*> found = m_queue.end(); - while (!m_killed && !timedOut && (found = m_queue.findIf(predicate)) == m_queue.end()) - timedOut = !m_condition.timedWait(m_mutex, absoluteTime); - - ASSERT(!timedOut || absoluteTime != infiniteTime()); - - if (m_killed) { - result = MessageQueueTerminated; - return nullptr; - } - - if (timedOut) { - result = MessageQueueTimeout; - return nullptr; - } - - ASSERT(found != m_queue.end()); - OwnPtr<DataType> message = adoptPtr(*found); - m_queue.remove(found); - result = MessageQueueMessageReceived; - return message.release(); - } - - template<typename DataType> - inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessage() - { - MutexLocker lock(m_mutex); - if (m_killed) - return nullptr; - if (m_queue.isEmpty()) - return nullptr; - - return adoptPtr(m_queue.takeFirst()); - } - - template<typename DataType> - inline PassOwnPtr<DataType> MessageQueue<DataType>::tryGetMessageIgnoringKilled() - { - MutexLocker lock(m_mutex); - if (m_queue.isEmpty()) - return nullptr; - - return adoptPtr(m_queue.takeFirst()); - } - - template<typename DataType> - template<typename Predicate> - inline void MessageQueue<DataType>::removeIf(Predicate& predicate) - { - MutexLocker lock(m_mutex); - DequeConstIterator<DataType*> found = m_queue.end(); - while ((found = m_queue.findIf(predicate)) != m_queue.end()) { - DataType* message = *found; - m_queue.remove(found); - delete message; - } - } - - template<typename DataType> - inline bool MessageQueue<DataType>::isEmpty() - { - MutexLocker lock(m_mutex); - if (m_killed) - return true; - return m_queue.isEmpty(); - } - - template<typename DataType> - inline void MessageQueue<DataType>::kill() - { - MutexLocker lock(m_mutex); - m_killed = true; - m_condition.broadcast(); - } - - template<typename DataType> - inline bool MessageQueue<DataType>::killed() const - { - MutexLocker lock(m_mutex); - return m_killed; - } -} // namespace WTF - -using WTF::MessageQueue; -// MessageQueueWaitResult enum and all its values. -using WTF::MessageQueueWaitResult; -using WTF::MessageQueueTerminated; -using WTF::MessageQueueTimeout; -using WTF::MessageQueueMessageReceived; - -#endif // MessageQueue_h diff --git a/Source/JavaScriptCore/wtf/MetaAllocator.cpp b/Source/JavaScriptCore/wtf/MetaAllocator.cpp deleted file mode 100644 index 649fbf2bc..000000000 --- a/Source/JavaScriptCore/wtf/MetaAllocator.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Copyright (C) 2011 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 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" -#include "MetaAllocator.h" - -#include <wtf/FastMalloc.h> - -namespace WTF { - -void MetaAllocatorTracker::notify(MetaAllocatorHandle* handle) -{ - m_allocations.insert(handle); -} - -void MetaAllocatorTracker::release(MetaAllocatorHandle* handle) -{ - m_allocations.remove(handle); -} - -ALWAYS_INLINE void MetaAllocator::release(MetaAllocatorHandle* handle) -{ - SpinLockHolder locker(&m_lock); - if (handle->sizeInBytes()) { - decrementPageOccupancy(handle->start(), handle->sizeInBytes()); - addFreeSpaceFromReleasedHandle(handle->start(), handle->sizeInBytes()); - } - - if (UNLIKELY(!!m_tracker)) - m_tracker->release(handle); -} - -MetaAllocatorHandle::MetaAllocatorHandle(MetaAllocator* allocator, void* start, size_t sizeInBytes, void* ownerUID) - : m_allocator(allocator) - , m_start(start) - , m_sizeInBytes(sizeInBytes) - , m_ownerUID(ownerUID) -{ - ASSERT(allocator); - ASSERT(start); - ASSERT(sizeInBytes); - turnOffVerifier(); -} - -MetaAllocatorHandle::~MetaAllocatorHandle() -{ - ASSERT(m_allocator); - m_allocator->release(this); -} - -void MetaAllocatorHandle::shrink(size_t newSizeInBytes) -{ - ASSERT(newSizeInBytes <= m_sizeInBytes); - - SpinLockHolder locker(&m_allocator->m_lock); - - newSizeInBytes = m_allocator->roundUp(newSizeInBytes); - - ASSERT(newSizeInBytes <= m_sizeInBytes); - - if (newSizeInBytes == m_sizeInBytes) - return; - - uintptr_t freeStart = reinterpret_cast<uintptr_t>(m_start) + newSizeInBytes; - size_t freeSize = m_sizeInBytes - newSizeInBytes; - uintptr_t freeEnd = freeStart + freeSize; - - uintptr_t firstCompletelyFreePage = (freeStart + m_allocator->m_pageSize - 1) & ~(m_allocator->m_pageSize - 1); - if (firstCompletelyFreePage < freeEnd) - m_allocator->decrementPageOccupancy(reinterpret_cast<void*>(firstCompletelyFreePage), freeSize - (firstCompletelyFreePage - freeStart)); - - m_allocator->addFreeSpaceFromReleasedHandle(reinterpret_cast<void*>(freeStart), freeSize); - - m_sizeInBytes = newSizeInBytes; -} - -MetaAllocator::MetaAllocator(size_t allocationGranule) - : m_allocationGranule(allocationGranule) - , m_pageSize(pageSize()) - , m_bytesAllocated(0) - , m_bytesReserved(0) - , m_bytesCommitted(0) - , m_tracker(0) -#ifndef NDEBUG - , m_mallocBalance(0) -#endif -#if ENABLE(META_ALLOCATOR_PROFILE) - , m_numAllocations(0) - , m_numFrees(0) -#endif -{ - m_lock.Init(); - - for (m_logPageSize = 0; m_logPageSize < 32; ++m_logPageSize) { - if (static_cast<size_t>(1) << m_logPageSize == m_pageSize) - break; - } - - ASSERT(static_cast<size_t>(1) << m_logPageSize == m_pageSize); - - for (m_logAllocationGranule = 0; m_logAllocationGranule < 32; ++m_logAllocationGranule) { - if (static_cast<size_t>(1) << m_logAllocationGranule == m_allocationGranule) - break; - } - - ASSERT(static_cast<size_t>(1) << m_logAllocationGranule == m_allocationGranule); -} - -PassRefPtr<MetaAllocatorHandle> MetaAllocator::allocate(size_t sizeInBytes, void* ownerUID) -{ - SpinLockHolder locker(&m_lock); - - if (!sizeInBytes) - return 0; - - sizeInBytes = roundUp(sizeInBytes); - - void* start = findAndRemoveFreeSpace(sizeInBytes); - if (!start) { - size_t requestedNumberOfPages = (sizeInBytes + m_pageSize - 1) >> m_logPageSize; - size_t numberOfPages = requestedNumberOfPages; - - start = allocateNewSpace(numberOfPages); - if (!start) - return 0; - - ASSERT(numberOfPages >= requestedNumberOfPages); - - size_t roundedUpSize = numberOfPages << m_logPageSize; - - ASSERT(roundedUpSize >= sizeInBytes); - - m_bytesReserved += roundedUpSize; - - if (roundedUpSize > sizeInBytes) { - void* freeSpaceStart = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start) + sizeInBytes); - size_t freeSpaceSize = roundedUpSize - sizeInBytes; - addFreeSpace(freeSpaceStart, freeSpaceSize); - } - } - incrementPageOccupancy(start, sizeInBytes); - m_bytesAllocated += sizeInBytes; -#if ENABLE(META_ALLOCATOR_PROFILE) - m_numAllocations++; -#endif - - MetaAllocatorHandle* handle = new MetaAllocatorHandle(this, start, sizeInBytes, ownerUID); - - if (UNLIKELY(!!m_tracker)) - m_tracker->notify(handle); - - return adoptRef(handle); -} - -MetaAllocator::Statistics MetaAllocator::currentStatistics() -{ - SpinLockHolder locker(&m_lock); - Statistics result; - result.bytesAllocated = m_bytesAllocated; - result.bytesReserved = m_bytesReserved; - result.bytesCommitted = m_bytesCommitted; - return result; -} - -void* MetaAllocator::findAndRemoveFreeSpace(size_t sizeInBytes) -{ - FreeSpaceNode* node = m_freeSpaceSizeMap.findLeastGreaterThanOrEqual(sizeInBytes); - - if (!node) - return 0; - - ASSERT(node->m_sizeInBytes >= sizeInBytes); - - m_freeSpaceSizeMap.remove(node); - - void* result; - - if (node->m_sizeInBytes == sizeInBytes) { - // Easy case: perfect fit, so just remove the node entirely. - result = node->m_start; - - m_freeSpaceStartAddressMap.remove(node->m_start); - m_freeSpaceEndAddressMap.remove(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes)); - freeFreeSpaceNode(node); - } else { - // Try to be a good citizen and ensure that the returned chunk of memory - // straddles as few pages as possible, but only insofar as doing so will - // not increase fragmentation. The intuition is that minimizing - // fragmentation is a strictly higher priority than minimizing the number - // of committed pages, since in the long run, smaller fragmentation means - // fewer committed pages and fewer failures in general. - - uintptr_t firstPage = reinterpret_cast<uintptr_t>(node->m_start) >> m_logPageSize; - uintptr_t lastPage = (reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes - 1) >> m_logPageSize; - - uintptr_t lastPageForLeftAllocation = (reinterpret_cast<uintptr_t>(node->m_start) + sizeInBytes - 1) >> m_logPageSize; - uintptr_t firstPageForRightAllocation = (reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes - sizeInBytes) >> m_logPageSize; - - if (lastPageForLeftAllocation - firstPage + 1 <= lastPage - firstPageForRightAllocation + 1) { - // Allocate in the left side of the returned chunk, and slide the node to the right. - result = node->m_start; - - m_freeSpaceStartAddressMap.remove(node->m_start); - - node->m_sizeInBytes -= sizeInBytes; - node->m_start = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_start) + sizeInBytes); - - m_freeSpaceSizeMap.insert(node); - m_freeSpaceStartAddressMap.add(node->m_start, node); - } else { - // Allocate in the right size of the returned chunk, and slide the node to the left; - - result = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes - sizeInBytes); - - m_freeSpaceEndAddressMap.remove(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(node->m_start) + node->m_sizeInBytes)); - - node->m_sizeInBytes -= sizeInBytes; - - m_freeSpaceSizeMap.insert(node); - m_freeSpaceEndAddressMap.add(result, node); - } - } - - return result; -} - -void MetaAllocator::addFreeSpaceFromReleasedHandle(void* start, size_t sizeInBytes) -{ -#if ENABLE(META_ALLOCATOR_PROFILE) - m_numFrees++; -#endif - m_bytesAllocated -= sizeInBytes; - addFreeSpace(start, sizeInBytes); -} - -void MetaAllocator::addFreshFreeSpace(void* start, size_t sizeInBytes) -{ - SpinLockHolder locker(&m_lock); - m_bytesReserved += sizeInBytes; - addFreeSpace(start, sizeInBytes); -} - -size_t MetaAllocator::debugFreeSpaceSize() -{ -#ifndef NDEBUG - SpinLockHolder locker(&m_lock); - size_t result = 0; - for (FreeSpaceNode* node = m_freeSpaceSizeMap.first(); node; node = node->successor()) - result += node->m_sizeInBytes; - return result; -#else - CRASH(); - return 0; -#endif -} - -void MetaAllocator::addFreeSpace(void* start, size_t sizeInBytes) -{ - void* end = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start) + sizeInBytes); - - HashMap<void*, FreeSpaceNode*>::iterator leftNeighbor = m_freeSpaceEndAddressMap.find(start); - HashMap<void*, FreeSpaceNode*>::iterator rightNeighbor = m_freeSpaceStartAddressMap.find(end); - - if (leftNeighbor != m_freeSpaceEndAddressMap.end()) { - // We have something we can coalesce with on the left. Remove it from the tree, and - // remove its end from the end address map. - - ASSERT(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(leftNeighbor->second->m_start) + leftNeighbor->second->m_sizeInBytes) == leftNeighbor->first); - - FreeSpaceNode* leftNode = leftNeighbor->second; - - void* leftStart = leftNode->m_start; - size_t leftSize = leftNode->m_sizeInBytes; - void* leftEnd = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(leftStart) + leftSize); - - ASSERT(leftEnd == start); - - m_freeSpaceSizeMap.remove(leftNode); - m_freeSpaceEndAddressMap.remove(leftEnd); - - // Now check if there is also something to coalesce with on the right. - if (rightNeighbor != m_freeSpaceStartAddressMap.end()) { - // Freeing something in the middle of free blocks. Coalesce both left and - // right, whilst removing the right neighbor from the maps. - - ASSERT(rightNeighbor->second->m_start == rightNeighbor->first); - - FreeSpaceNode* rightNode = rightNeighbor->second; - void* rightStart = rightNeighbor->first; - size_t rightSize = rightNode->m_sizeInBytes; - void* rightEnd = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(rightStart) + rightSize); - - ASSERT(rightStart == end); - ASSERT(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(leftStart) + leftSize + sizeInBytes + rightSize) == rightEnd); - - m_freeSpaceSizeMap.remove(rightNode); - m_freeSpaceStartAddressMap.remove(rightStart); - m_freeSpaceEndAddressMap.remove(rightEnd); - - freeFreeSpaceNode(rightNode); - - leftNode->m_sizeInBytes += sizeInBytes + rightSize; - - m_freeSpaceSizeMap.insert(leftNode); - m_freeSpaceEndAddressMap.add(rightEnd, leftNode); - } else { - leftNode->m_sizeInBytes += sizeInBytes; - - m_freeSpaceSizeMap.insert(leftNode); - m_freeSpaceEndAddressMap.add(end, leftNode); - } - } else { - // Cannot coalesce with left; try to see if we can coalesce with right. - - if (rightNeighbor != m_freeSpaceStartAddressMap.end()) { - FreeSpaceNode* rightNode = rightNeighbor->second; - void* rightStart = rightNeighbor->first; - size_t rightSize = rightNode->m_sizeInBytes; - void* rightEnd = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(rightStart) + rightSize); - - ASSERT(rightStart == end); - ASSERT_UNUSED(rightEnd, reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start) + sizeInBytes + rightSize) == rightEnd); - - m_freeSpaceSizeMap.remove(rightNode); - m_freeSpaceStartAddressMap.remove(rightStart); - - rightNode->m_sizeInBytes += sizeInBytes; - rightNode->m_start = start; - - m_freeSpaceSizeMap.insert(rightNode); - m_freeSpaceStartAddressMap.add(start, rightNode); - } else { - // Nothing to coalesce with, so create a new free space node and add it. - - FreeSpaceNode* node = allocFreeSpaceNode(); - - node->m_sizeInBytes = sizeInBytes; - node->m_start = start; - - m_freeSpaceSizeMap.insert(node); - m_freeSpaceStartAddressMap.add(start, node); - m_freeSpaceEndAddressMap.add(end, node); - } - } -} - -void MetaAllocator::incrementPageOccupancy(void* address, size_t sizeInBytes) -{ - uintptr_t firstPage = reinterpret_cast<uintptr_t>(address) >> m_logPageSize; - uintptr_t lastPage = (reinterpret_cast<uintptr_t>(address) + sizeInBytes - 1) >> m_logPageSize; - - for (uintptr_t page = firstPage; page <= lastPage; ++page) { - HashMap<uintptr_t, size_t>::iterator iter = m_pageOccupancyMap.find(page); - if (iter == m_pageOccupancyMap.end()) { - m_pageOccupancyMap.add(page, 1); - m_bytesCommitted += m_pageSize; - notifyNeedPage(reinterpret_cast<void*>(page << m_logPageSize)); - } else - iter->second++; - } -} - -void MetaAllocator::decrementPageOccupancy(void* address, size_t sizeInBytes) -{ - uintptr_t firstPage = reinterpret_cast<uintptr_t>(address) >> m_logPageSize; - uintptr_t lastPage = (reinterpret_cast<uintptr_t>(address) + sizeInBytes - 1) >> m_logPageSize; - - for (uintptr_t page = firstPage; page <= lastPage; ++page) { - HashMap<uintptr_t, size_t>::iterator iter = m_pageOccupancyMap.find(page); - ASSERT(iter != m_pageOccupancyMap.end()); - if (!--(iter->second)) { - m_pageOccupancyMap.remove(iter); - m_bytesCommitted -= m_pageSize; - notifyPageIsFree(reinterpret_cast<void*>(page << m_logPageSize)); - } - } -} - -size_t MetaAllocator::roundUp(size_t sizeInBytes) -{ - if (std::numeric_limits<size_t>::max() - m_allocationGranule <= sizeInBytes) - CRASH(); - return (sizeInBytes + m_allocationGranule - 1) & ~(m_allocationGranule - 1); -} - -MetaAllocator::FreeSpaceNode* MetaAllocator::allocFreeSpaceNode() -{ -#ifndef NDEBUG - m_mallocBalance++; -#endif - return new (NotNull, fastMalloc(sizeof(FreeSpaceNode))) FreeSpaceNode(0, 0); -} - -void MetaAllocator::freeFreeSpaceNode(FreeSpaceNode* node) -{ -#ifndef NDEBUG - m_mallocBalance--; -#endif - fastFree(node); -} - -#if ENABLE(META_ALLOCATOR_PROFILE) -void MetaAllocator::dumpProfile() -{ - dataLog("num allocations = %u, num frees = %u\n", m_numAllocations, m_numFrees); -} -#endif - -} // namespace WTF - - diff --git a/Source/JavaScriptCore/wtf/MetaAllocator.h b/Source/JavaScriptCore/wtf/MetaAllocator.h deleted file mode 100644 index 8a73a3b03..000000000 --- a/Source/JavaScriptCore/wtf/MetaAllocator.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2011 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 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 WTF_MetaAllocator_h -#define WTF_MetaAllocator_h - -#include <wtf/Assertions.h> -#include <wtf/HashMap.h> -#include <wtf/MetaAllocatorHandle.h> -#include <wtf/Noncopyable.h> -#include <wtf/PageBlock.h> -#include <wtf/RedBlackTree.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> -#include <wtf/TCSpinLock.h> - -namespace WTF { - -#define ENABLE_META_ALLOCATOR_PROFILE 0 - -class MetaAllocatorTracker { -public: - void notify(MetaAllocatorHandle*); - void release(MetaAllocatorHandle*); - - MetaAllocatorHandle* find(void* address) - { - MetaAllocatorHandle* handle = m_allocations.findGreatestLessThanOrEqual(address); - if (handle && address < handle->end()) - return handle; - return 0; - } - - RedBlackTree<MetaAllocatorHandle, void*> m_allocations; -}; - -class MetaAllocator { - WTF_MAKE_NONCOPYABLE(MetaAllocator); - -public: - WTF_EXPORT_PRIVATE MetaAllocator(size_t allocationGranule); - - virtual ~MetaAllocator(); - - WTF_EXPORT_PRIVATE PassRefPtr<MetaAllocatorHandle> allocate(size_t sizeInBytes, void* ownerUID); - - void trackAllocations(MetaAllocatorTracker* tracker) - { - m_tracker = tracker; - } - - // Non-atomic methods for getting allocator statistics. - size_t bytesAllocated() { return m_bytesAllocated; } - size_t bytesReserved() { return m_bytesReserved; } - size_t bytesCommitted() { return m_bytesCommitted; } - - // Atomic method for getting allocator statistics. - struct Statistics { - size_t bytesAllocated; - size_t bytesReserved; - size_t bytesCommitted; - }; - Statistics currentStatistics(); - - // Add more free space to the allocator. Call this directly from - // the constructor if you wish to operate the allocator within a - // fixed pool. - WTF_EXPORT_PRIVATE void addFreshFreeSpace(void* start, size_t sizeInBytes); - - // This is meant only for implementing tests. Never call this in release - // builds. - WTF_EXPORT_PRIVATE size_t debugFreeSpaceSize(); - -#if ENABLE(META_ALLOCATOR_PROFILE) - void dumpProfile(); -#else - void dumpProfile() { } -#endif - -protected: - - // Allocate new virtual space, but don't commit. This may return more - // pages than we asked, in which case numPages is changed. - virtual void* allocateNewSpace(size_t& numPages) = 0; - - // Commit a page. - virtual void notifyNeedPage(void* page) = 0; - - // Uncommit a page. - virtual void notifyPageIsFree(void* page) = 0; - - // NOTE: none of the above methods are called during allocator - // destruction, in part because a MetaAllocator cannot die so long - // as there are Handles that refer to it. - -private: - - friend class MetaAllocatorHandle; - - class FreeSpaceNode : public RedBlackTree<FreeSpaceNode, size_t>::Node { - public: - FreeSpaceNode(void* start, size_t sizeInBytes) - : m_start(start) - , m_sizeInBytes(sizeInBytes) - { - } - - size_t key() - { - return m_sizeInBytes; - } - - void* m_start; - size_t m_sizeInBytes; - }; - typedef RedBlackTree<FreeSpaceNode, size_t> Tree; - - // Release a MetaAllocatorHandle. - void release(MetaAllocatorHandle*); - - // Remove free space from the allocator. This is effectively - // the allocate() function, except that it does not mark the - // returned space as being in-use. - void* findAndRemoveFreeSpace(size_t sizeInBytes); - - // This is called when memory from an allocation is freed. - void addFreeSpaceFromReleasedHandle(void* start, size_t sizeInBytes); - - // This is the low-level implementation of adding free space; it - // is called from both addFreeSpaceFromReleasedHandle and from - // addFreshFreeSpace. - void addFreeSpace(void* start, size_t sizeInBytes); - - // Management of used space. - - void incrementPageOccupancy(void* address, size_t sizeInBytes); - void decrementPageOccupancy(void* address, size_t sizeInBytes); - - // Utilities. - - size_t roundUp(size_t sizeInBytes); - - FreeSpaceNode* allocFreeSpaceNode(); - WTF_EXPORT_PRIVATE void freeFreeSpaceNode(FreeSpaceNode*); - - size_t m_allocationGranule; - unsigned m_logAllocationGranule; - size_t m_pageSize; - unsigned m_logPageSize; - - Tree m_freeSpaceSizeMap; - HashMap<void*, FreeSpaceNode*> m_freeSpaceStartAddressMap; - HashMap<void*, FreeSpaceNode*> m_freeSpaceEndAddressMap; - HashMap<uintptr_t, size_t> m_pageOccupancyMap; - - size_t m_bytesAllocated; - size_t m_bytesReserved; - size_t m_bytesCommitted; - - SpinLock m_lock; - - MetaAllocatorTracker* m_tracker; - -#ifndef NDEBUG - size_t m_mallocBalance; -#endif - -#if ENABLE(META_ALLOCATOR_PROFILE) - unsigned m_numAllocations; - unsigned m_numFrees; -#endif -}; - -inline MetaAllocator::~MetaAllocator() -{ - for (FreeSpaceNode* node = m_freeSpaceSizeMap.first(); node;) { - FreeSpaceNode* next = node->successor(); - m_freeSpaceSizeMap.remove(node); - freeFreeSpaceNode(node); - node = next; - } - m_lock.Finalize(); -#ifndef NDEBUG - ASSERT(!m_mallocBalance); -#endif -} - -} // namespace WTF - -#endif // WTF_MetaAllocator_h - diff --git a/Source/JavaScriptCore/wtf/MetaAllocatorHandle.h b/Source/JavaScriptCore/wtf/MetaAllocatorHandle.h deleted file mode 100644 index c43f491f3..000000000 --- a/Source/JavaScriptCore/wtf/MetaAllocatorHandle.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2011 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 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 WTF_MetaAllocatorHandle_h -#define WTF_MetaAllocatorHandle_h - -#include <wtf/Assertions.h> -#include <wtf/RedBlackTree.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> - -namespace WTF { - -class MetaAllocator; - -class MetaAllocatorHandle : public RefCounted<MetaAllocatorHandle>, public RedBlackTree<MetaAllocatorHandle, void*>::Node { -private: - MetaAllocatorHandle(MetaAllocator*, void* start, size_t sizeInBytes, void* ownerUID); - -public: - WTF_EXPORT_PRIVATE ~MetaAllocatorHandle(); - - void* start() - { - return m_start; - } - - void* end() - { - return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(m_start) + m_sizeInBytes); - } - - size_t sizeInBytes() - { - return m_sizeInBytes; - } - - WTF_EXPORT_PRIVATE void shrink(size_t newSizeInBytes); - - bool isManaged() - { - return !!m_allocator; - } - - MetaAllocator* allocator() - { - ASSERT(m_allocator); - return m_allocator; - } - - void* ownerUID() - { - return m_ownerUID; - } - - void* key() - { - return m_start; - } - -private: - friend class MetaAllocator; - - MetaAllocator* m_allocator; - void* m_start; - size_t m_sizeInBytes; - void* m_ownerUID; -}; - -} - -#endif diff --git a/Source/JavaScriptCore/wtf/NonCopyingSort.h b/Source/JavaScriptCore/wtf/NonCopyingSort.h deleted file mode 100644 index fd611bde7..000000000 --- a/Source/JavaScriptCore/wtf/NonCopyingSort.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 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 WTF_NonCopyingSort_h -#define WTF_NonCopyingSort_h - -namespace WTF { - -using std::swap; - -template<typename RandomAccessIterator, typename Predicate> -inline void siftDown(RandomAccessIterator array, ptrdiff_t start, ptrdiff_t end, Predicate compareLess) -{ - ptrdiff_t root = start; - - while (root * 2 + 1 <= end) { - ptrdiff_t child = root * 2 + 1; - if (child < end && compareLess(array[child], array[child + 1])) - child++; - - if (compareLess(array[root], array[child])) { - swap(array[root], array[child]); - root = child; - } else - return; - } -} - -template<typename RandomAccessIterator, typename Predicate> -inline void heapify(RandomAccessIterator array, ptrdiff_t count, Predicate compareLess) -{ - ptrdiff_t start = (count - 2) / 2; - - while (start >= 0) { - siftDown(array, start, count - 1, compareLess); - start--; - } -} - -template<typename RandomAccessIterator, typename Predicate> -void heapSort(RandomAccessIterator start, RandomAccessIterator end, Predicate compareLess) -{ - ptrdiff_t count = end - start; - heapify(start, count, compareLess); - - ptrdiff_t endIndex = count - 1; - while (endIndex > 0) { - swap(start[endIndex], start[0]); - siftDown(start, 0, endIndex - 1, compareLess); - endIndex--; - } -} - -template<typename RandomAccessIterator, typename Predicate> -inline void nonCopyingSort(RandomAccessIterator start, RandomAccessIterator end, Predicate compareLess) -{ - // heapsort happens to use only swaps, not copies, but the essential thing about - // this function is the fact that it does not copy, not the specific algorithm - heapSort(start, end, compareLess); -} - -} // namespace WTF - -using WTF::nonCopyingSort; - -#endif // WTF_NonCopyingSort_h diff --git a/Source/JavaScriptCore/wtf/Noncopyable.h b/Source/JavaScriptCore/wtf/Noncopyable.h deleted file mode 100644 index 1e95cbb92..000000000 --- a/Source/JavaScriptCore/wtf/Noncopyable.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_Noncopyable_h -#define WTF_Noncopyable_h - -#include <wtf/Compiler.h> - -#if COMPILER_SUPPORTS(CXX_DELETED_FUNCTIONS) - #define WTF_MAKE_NONCOPYABLE(ClassName) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") \ - _Pragma("clang diagnostic ignored \"-Wc++0x-extensions\"") \ - private: \ - ClassName(const ClassName&) = delete; \ - ClassName& operator=(const ClassName&) = delete; \ - _Pragma("clang diagnostic pop") -#else - #define WTF_MAKE_NONCOPYABLE(ClassName) \ - private: \ - ClassName(const ClassName&); \ - ClassName& operator=(const ClassName&) -#endif - -#endif // WTF_Noncopyable_h diff --git a/Source/JavaScriptCore/wtf/NotFound.h b/Source/JavaScriptCore/wtf/NotFound.h deleted file mode 100644 index 4263bceca..000000000 --- a/Source/JavaScriptCore/wtf/NotFound.h +++ /dev/null @@ -1,37 +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 NotFound_h -#define NotFound_h - -namespace WTF { - - const size_t notFound = static_cast<size_t>(-1); - -} // namespace WTF - -using WTF::notFound; - -#endif // NotFound_h diff --git a/Source/JavaScriptCore/wtf/NullPtr.cpp b/Source/JavaScriptCore/wtf/NullPtr.cpp deleted file mode 100644 index d6b0429b1..000000000 --- a/Source/JavaScriptCore/wtf/NullPtr.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - -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 "NullPtr.h" - -#if !(COMPILER_SUPPORTS(CXX_NULLPTR) || defined(_LIBCPP_VERSION)) - -std::nullptr_t nullptr; - -#endif diff --git a/Source/JavaScriptCore/wtf/NullPtr.h b/Source/JavaScriptCore/wtf/NullPtr.h deleted file mode 100644 index 2d0919ca6..000000000 --- a/Source/JavaScriptCore/wtf/NullPtr.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - -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 NullPtr_h -#define NullPtr_h - -// For compilers and standard libraries that do not yet include it, this adds the -// nullptr_t type and nullptr object. They are defined in the same namespaces they -// would be in compiler and library that had the support. - -#include <ciso646> - -#if COMPILER_SUPPORTS(CXX_NULLPTR) || defined(_LIBCPP_VERSION) - -#include <cstddef> - -#else - -namespace std { - class nullptr_t { }; -} - -extern std::nullptr_t nullptr; - -#endif - -#endif diff --git a/Source/JavaScriptCore/wtf/NumberOfCores.cpp b/Source/JavaScriptCore/wtf/NumberOfCores.cpp deleted file mode 100644 index 1e7f45f5c..000000000 --- a/Source/JavaScriptCore/wtf/NumberOfCores.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2012 University of Szeged. 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 "NumberOfCores.h" - -#if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD) || OS(FREEBSD) -#include <sys/sysctl.h> -#include <sys/types.h> -#elif OS(LINUX) || OS(AIX) || OS(SOLARIS) -#include <unistd.h> -#elif OS(WINDOWS) -#include <windows.h> -#include <wtf/UnusedParam.h> -#endif - -namespace WTF { - -int numberOfProcessorCores() -{ - const int defaultIfUnavailable = 1; - static int s_numberOfCores = -1; - - if (s_numberOfCores > 0) - return s_numberOfCores; - -#if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD) || OS(FREEBSD) - unsigned result; - size_t length = sizeof(result); - int name[] = { - CTL_HW, - HW_NCPU - }; - int sysctlResult = sysctl(name, sizeof(name) / sizeof(int), &result, &length, 0, 0); - - s_numberOfCores = sysctlResult < 0 ? defaultIfUnavailable : result; -#elif OS(LINUX) || OS(AIX) || OS(SOLARIS) - long sysconfResult = sysconf(_SC_NPROCESSORS_ONLN); - - s_numberOfCores = sysconfResult < 0 ? defaultIfUnavailable : static_cast<int>(sysconfResult); -#elif OS(WINDOWS) - UNUSED_PARAM(defaultIfUnavailable); - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - - s_numberOfCores = sysInfo.dwNumberOfProcessors; -#else - s_numberOfCores = defaultIfUnavailable; -#endif - return s_numberOfCores; -} - -} diff --git a/Source/JavaScriptCore/wtf/NumberOfCores.h b/Source/JavaScriptCore/wtf/NumberOfCores.h deleted file mode 100644 index 8bc8d9455..000000000 --- a/Source/JavaScriptCore/wtf/NumberOfCores.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2012 University of Szeged. 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 NumberOfCores_h -#define NumberOfCores_h - -namespace WTF { - -int numberOfProcessorCores(); - -} - -#endif diff --git a/Source/JavaScriptCore/wtf/OSAllocator.h b/Source/JavaScriptCore/wtf/OSAllocator.h deleted file mode 100644 index 9ea4f6b51..000000000 --- a/Source/JavaScriptCore/wtf/OSAllocator.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * 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 OSAllocator_h -#define OSAllocator_h - -#include <algorithm> -#include <wtf/UnusedParam.h> -#include <wtf/VMTags.h> -#include <wtf/VMTags.h> - -namespace WTF { - -class OSAllocator { -public: - enum Usage { - UnknownUsage = -1, - FastMallocPages = VM_TAG_FOR_TCMALLOC_MEMORY, - JSGCHeapPages = VM_TAG_FOR_COLLECTOR_MEMORY, - JSVMStackPages = VM_TAG_FOR_REGISTERFILE_MEMORY, - JSJITCodePages = VM_TAG_FOR_EXECUTABLEALLOCATOR_MEMORY, - }; - - // These methods are symmetric; reserveUncommitted allocates VM in an uncommitted state, - // releaseDecommitted should be called on a region of VM allocated by a single reservation, - // the memory must all currently be in a decommitted state. - static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false); - WTF_EXPORT_PRIVATE static void releaseDecommitted(void*, size_t); - - // These methods are symmetric; they commit or decommit a region of VM (uncommitted VM should - // never be accessed, since the OS may not have attached physical memory for these regions). - // Clients should only call commit on uncommitted regions and decommit on committed regions. - static void commit(void*, size_t, bool writable, bool executable); - static void decommit(void*, size_t); - - // These methods are symmetric; reserveAndCommit allocates VM in an committed state, - // decommitAndRelease should be called on a region of VM allocated by a single reservation, - // the memory must all currently be in a committed state. - WTF_EXPORT_PRIVATE static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false); - static void decommitAndRelease(void* base, size_t size); - - // These methods are akin to reserveAndCommit/decommitAndRelease, above - however rather than - // committing/decommitting the entire region additional parameters allow a subregion to be - // specified. - static void* reserveAndCommit(size_t reserveSize, size_t commitSize, Usage = UnknownUsage, bool writable = true, bool executable = false); - static void decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize); - - // Reallocate an existing, committed allocation. - // The prior allocation must be fully comitted, and the new size will also be fully committed. - // This interface is provided since it may be possible to optimize this operation on some platforms. - template<typename T> - static T* reallocateCommitted(T*, size_t oldSize, size_t newSize, Usage = UnknownUsage, bool writable = true, bool executable = false); -}; - -inline void* OSAllocator::reserveAndCommit(size_t reserveSize, size_t commitSize, Usage usage, bool writable, bool executable) -{ - void* base = reserveUncommitted(reserveSize, usage, writable, executable); - commit(base, commitSize, writable, executable); - return base; -} - -inline void OSAllocator::decommitAndRelease(void* releaseBase, size_t releaseSize, void* decommitBase, size_t decommitSize) -{ - ASSERT(decommitBase >= releaseBase && (static_cast<char*>(decommitBase) + decommitSize) <= (static_cast<char*>(releaseBase) + releaseSize)); -#if OS(WINCE) - // On most platforms we can actually skip this final decommit; releasing the VM will - // implicitly decommit any physical memory in the region. This is not true on WINCE. - decommit(decommitBase, decommitSize); -#else - UNUSED_PARAM(decommitBase); - UNUSED_PARAM(decommitSize); -#endif - releaseDecommitted(releaseBase, releaseSize); -} - -inline void OSAllocator::decommitAndRelease(void* base, size_t size) -{ - decommitAndRelease(base, size, base, size); -} - -template<typename T> -inline T* OSAllocator::reallocateCommitted(T* oldBase, size_t oldSize, size_t newSize, Usage usage, bool writable, bool executable) -{ - void* newBase = reserveAndCommit(newSize, usage, writable, executable); - memcpy(newBase, oldBase, std::min(oldSize, newSize)); - decommitAndRelease(oldBase, oldSize); - return static_cast<T*>(newBase); -} - -} // namespace WTF - -using WTF::OSAllocator; - -#endif // OSAllocator_h diff --git a/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp b/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp deleted file mode 100644 index 5dbddc83e..000000000 --- a/Source/JavaScriptCore/wtf/OSAllocatorPosix.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/* - * 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 "OSAllocator.h" - -#include "PageAllocation.h" -#include <errno.h> -#include <sys/mman.h> -#include <wtf/Assertions.h> -#include <wtf/UnusedParam.h> - -namespace WTF { - -void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages) -{ - void* result = reserveAndCommit(bytes, usage, writable, executable, includesGuardPages); -#if OS(QNX) - posix_madvise(result, bytes, POSIX_MADV_DONTNEED); -#elif HAVE(MADV_FREE_REUSE) - // To support the "reserve then commit" model, we have to initially decommit. - while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { } -#endif - return result; -} - -void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages) -{ - // All POSIX reservations start out logically committed. - int protection = PROT_READ; - if (writable) - protection |= PROT_WRITE; - if (executable) - protection |= PROT_EXEC; - - int flags = MAP_PRIVATE | MAP_ANON; -#if PLATFORM(IOS) - if (executable) - flags |= MAP_JIT; -#endif - -#if OS(LINUX) - // Linux distros usually do not allow overcommit by default, so - // JSC's strategy of mmaping a large amount of memory upfront - // won't work very well on some systems. Fortunately there's a - // flag we can pass to mmap to disable the overcommit check for - // this particular call, so we can get away with it as long as the - // overcommit flag value in /proc/sys/vm/overcommit_memory is 0 - // ('heuristic') and not 2 (always check). 0 is the usual default - // value, so this should work well in general. - flags |= MAP_NORESERVE; -#endif - -#if OS(DARWIN) - int fd = usage; -#else - int fd = -1; -#endif - - void* result = 0; -#if (OS(DARWIN) && CPU(X86_64)) - if (executable) { - ASSERT(includesGuardPages); - // Cook up an address to allocate at, using the following recipe: - // 17 bits of zero, stay in userspace kids. - // 26 bits of randomness for ASLR. - // 21 bits of zero, at least stay aligned within one level of the pagetables. - // - // But! - as a temporary workaround for some plugin problems (rdar://problem/6812854), - // for now instead of 2^26 bits of ASLR lets stick with 25 bits of randomization plus - // 2^24, which should put up somewhere in the middle of userspace (in the address range - // 0x200000000000 .. 0x5fffffffffff). - intptr_t randomLocation = 0; - randomLocation = arc4random() & ((1 << 25) - 1); - randomLocation += (1 << 24); - randomLocation <<= 21; - result = reinterpret_cast<void*>(randomLocation); - } -#endif - - result = mmap(result, bytes, protection, flags, fd, 0); - if (result == MAP_FAILED) { - #if ENABLE(CLASSIC_INTERPRETER) - if (executable) - result = 0; - else - #endif - CRASH(); - } - if (result && includesGuardPages) { - // We use mmap to remap the guardpages rather than using mprotect as - // mprotect results in multiple references to the code region. This - // breaks the madvise based mechanism we use to return physical memory - // to the OS. - mmap(result, pageSize(), PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, fd, 0); - mmap(static_cast<char*>(result) + bytes - pageSize(), pageSize(), PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANON, fd, 0); - } - return result; -} - -void OSAllocator::commit(void* address, size_t bytes, bool, bool) -{ -#if OS(QNX) - posix_madvise(address, bytes, POSIX_MADV_WILLNEED); -#elif HAVE(MADV_FREE_REUSE) - while (madvise(address, bytes, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { } -#else - // Non-MADV_FREE_REUSE reservations automatically commit on demand. - UNUSED_PARAM(address); - UNUSED_PARAM(bytes); -#endif -} - -void OSAllocator::decommit(void* address, size_t bytes) -{ -#if OS(QNX) - posix_madvise(address, bytes, POSIX_MADV_DONTNEED); -#elif HAVE(MADV_FREE_REUSE) - while (madvise(address, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { } -#elif HAVE(MADV_FREE) - while (madvise(address, bytes, MADV_FREE) == -1 && errno == EAGAIN) { } -#elif HAVE(MADV_DONTNEED) - while (madvise(address, bytes, MADV_DONTNEED) == -1 && errno == EAGAIN) { } -#else - UNUSED_PARAM(address); - UNUSED_PARAM(bytes); -#endif -} - -void OSAllocator::releaseDecommitted(void* address, size_t bytes) -{ - int result = munmap(address, bytes); - if (result == -1) - CRASH(); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/OSAllocatorWin.cpp b/Source/JavaScriptCore/wtf/OSAllocatorWin.cpp deleted file mode 100644 index 7f5d9b890..000000000 --- a/Source/JavaScriptCore/wtf/OSAllocatorWin.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - * 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 "OSAllocator.h" - -#include "windows.h" -#include <wtf/Assertions.h> - -namespace WTF { - -static inline DWORD protection(bool writable, bool executable) -{ - return executable ? - (writable ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ) : - (writable ? PAGE_READWRITE : PAGE_READONLY); -} - -void* OSAllocator::reserveUncommitted(size_t bytes, Usage, bool writable, bool executable, bool) -{ - void* result = VirtualAlloc(0, bytes, MEM_RESERVE, protection(writable, executable)); - if (!result) - CRASH(); - return result; -} - -void* OSAllocator::reserveAndCommit(size_t bytes, Usage, bool writable, bool executable, bool) -{ - void* result = VirtualAlloc(0, bytes, MEM_RESERVE | MEM_COMMIT, protection(writable, executable)); - if (!result) - CRASH(); - return result; -} - -void OSAllocator::commit(void* address, size_t bytes, bool writable, bool executable) -{ - void* result = VirtualAlloc(address, bytes, MEM_COMMIT, protection(writable, executable)); - if (!result) - CRASH(); -} - -void OSAllocator::decommit(void* address, size_t bytes) -{ - bool result = VirtualFree(address, bytes, MEM_DECOMMIT); - if (!result) - CRASH(); -} - -void OSAllocator::releaseDecommitted(void* address, size_t bytes) -{ - // According to http://msdn.microsoft.com/en-us/library/aa366892(VS.85).aspx, - // dwSize must be 0 if dwFreeType is MEM_RELEASE. - bool result = VirtualFree(address, 0, MEM_RELEASE); - if (!result) - CRASH(); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/OSRandomSource.cpp b/Source/JavaScriptCore/wtf/OSRandomSource.cpp deleted file mode 100644 index 0c1416a2f..000000000 --- a/Source/JavaScriptCore/wtf/OSRandomSource.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2011 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 SOFTWARE IS PROVIDED BY GOOGLE, 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 "OSRandomSource.h" - -#include <stdint.h> -#include <stdlib.h> - -#if OS(UNIX) -#include <fcntl.h> -#include <unistd.h> -#endif - -#if OS(WINDOWS) -#include <windows.h> -#include <wincrypt.h> // windows.h must be included before wincrypt.h. -#endif - -namespace WTF { - -#if USE(OS_RANDOMNESS) -void cryptographicallyRandomValuesFromOS(unsigned char* buffer, size_t length) -{ -#if OS(UNIX) - int fd = open("/dev/urandom", O_RDONLY, 0); - if (fd < 0) - CRASH(); // We need /dev/urandom for this API to work... - - if (read(fd, buffer, length) != static_cast<ssize_t>(length)) - CRASH(); - - close(fd); -#elif OS(WINDOWS) - HCRYPTPROV hCryptProv = 0; - if (!CryptAcquireContext(&hCryptProv, 0, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) - CRASH(); - if (!CryptGenRandom(hCryptProv, length, buffer)) - CRASH(); - CryptReleaseContext(hCryptProv, 0); -#else - #error "This configuration doesn't have a strong source of randomness." - // WARNING: When adding new sources of OS randomness, the randomness must - // be of cryptographic quality! -#endif -} -#endif - -} diff --git a/Source/JavaScriptCore/wtf/OSRandomSource.h b/Source/JavaScriptCore/wtf/OSRandomSource.h deleted file mode 100644 index 214a95472..000000000 --- a/Source/JavaScriptCore/wtf/OSRandomSource.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 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 SOFTWARE IS PROVIDED BY GOOGLE, 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 WTF_OSRandomSource_h -#define WTF_OSRandomSource_h - -namespace WTF { - -#if USE(OS_RANDOMNESS) -// This function attempts to fill buffer with randomness from the operating -// system. If insufficient randomness is available, the buffer will be -// partially filled. Rather than calling this function directly, consider -// calling cryptographicallyRandomNumber or cryptographicallyRandomValues. -void cryptographicallyRandomValuesFromOS(unsigned char* buffer, size_t length); -#endif - -} - -#endif diff --git a/Source/JavaScriptCore/wtf/OwnArrayPtr.h b/Source/JavaScriptCore/wtf/OwnArrayPtr.h deleted file mode 100644 index b3d72dfdb..000000000 --- a/Source/JavaScriptCore/wtf/OwnArrayPtr.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2006, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_OwnArrayPtr_h -#define WTF_OwnArrayPtr_h - -#include <wtf/Assertions.h> -#include <wtf/Noncopyable.h> -#include <wtf/NullPtr.h> -#include <wtf/PassOwnArrayPtr.h> -#include <algorithm> - -namespace WTF { - -template<typename T> class PassOwnArrayPtr; -template<typename T> PassOwnArrayPtr<T> adoptArrayPtr(T*); - -template <typename T> class OwnArrayPtr { -public: - typedef T* PtrType; - - OwnArrayPtr() : m_ptr(0) { } - - // See comment in PassOwnArrayPtr.h for why this takes a const reference. - template<typename U> OwnArrayPtr(const PassOwnArrayPtr<U>& o); - - // This copy constructor is used implicitly by gcc when it generates - // transients for assigning a PassOwnArrayPtr<T> object to a stack-allocated - // OwnArrayPtr<T> object. It should never be called explicitly and gcc - // should optimize away the constructor when generating code. - OwnArrayPtr(const OwnArrayPtr<T>&); - - ~OwnArrayPtr() { deleteOwnedArrayPtr(m_ptr); } - - PtrType get() const { return m_ptr; } - - void clear(); - PassOwnArrayPtr<T> release(); - PtrType leakPtr() WARN_UNUSED_RETURN; - - T& operator*() const { ASSERT(m_ptr); return *m_ptr; } - PtrType operator->() const { ASSERT(m_ptr); return m_ptr; } - - T& operator[](std::ptrdiff_t i) const { ASSERT(m_ptr); ASSERT(i >= 0); return m_ptr[i]; } - - bool operator!() const { return !m_ptr; } - - // This conversion operator allows implicit conversion to bool but not to other integer types. - typedef T* OwnArrayPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &OwnArrayPtr::m_ptr : 0; } - - OwnArrayPtr& operator=(const PassOwnArrayPtr<T>&); - OwnArrayPtr& operator=(std::nullptr_t) { clear(); return *this; } - template<typename U> OwnArrayPtr& operator=(const PassOwnArrayPtr<U>&); - - void swap(OwnArrayPtr& o) { std::swap(m_ptr, o.m_ptr); } - -private: - PtrType m_ptr; -}; - -template<typename T> template<typename U> inline OwnArrayPtr<T>::OwnArrayPtr(const PassOwnArrayPtr<U>& o) - : m_ptr(o.leakPtr()) -{ -} - -template<typename T> inline void OwnArrayPtr<T>::clear() -{ - PtrType ptr = m_ptr; - m_ptr = 0; - deleteOwnedArrayPtr(ptr); -} - -template<typename T> inline PassOwnArrayPtr<T> OwnArrayPtr<T>::release() -{ - PtrType ptr = m_ptr; - m_ptr = 0; - return adoptArrayPtr(ptr); -} - -template<typename T> inline typename OwnArrayPtr<T>::PtrType OwnArrayPtr<T>::leakPtr() -{ - PtrType ptr = m_ptr; - m_ptr = 0; - return ptr; -} - -template<typename T> inline OwnArrayPtr<T>& OwnArrayPtr<T>::operator=(const PassOwnArrayPtr<T>& o) -{ - PtrType ptr = m_ptr; - m_ptr = o.leakPtr(); - ASSERT(!ptr || m_ptr != ptr); - deleteOwnedArrayPtr(ptr); - return *this; -} - -template<typename T> template<typename U> inline OwnArrayPtr<T>& OwnArrayPtr<T>::operator=(const PassOwnArrayPtr<U>& o) -{ - PtrType ptr = m_ptr; - m_ptr = o.leakPtr(); - ASSERT(!ptr || m_ptr != ptr); - deleteOwnedArrayPtr(ptr); - return *this; -} - -template <typename T> inline void swap(OwnArrayPtr<T>& a, OwnArrayPtr<T>& b) -{ - a.swap(b); -} - -template<typename T, typename U> inline bool operator==(const OwnArrayPtr<T>& a, U* b) -{ - return a.get() == b; -} - -template<typename T, typename U> inline bool operator==(T* a, const OwnArrayPtr<U>& b) -{ - return a == b.get(); -} - -template<typename T, typename U> inline bool operator!=(const OwnArrayPtr<T>& a, U* b) -{ - return a.get() != b; -} - -template<typename T, typename U> inline bool operator!=(T* a, const OwnArrayPtr<U>& b) -{ - return a != b.get(); -} - -template <typename T> inline T* getPtr(const OwnArrayPtr<T>& p) -{ - return p.get(); -} - -} // namespace WTF - -using WTF::OwnArrayPtr; - -#endif // WTF_OwnArrayPtr_h diff --git a/Source/JavaScriptCore/wtf/OwnPtr.h b/Source/JavaScriptCore/wtf/OwnPtr.h deleted file mode 100644 index 326e3fd61..000000000 --- a/Source/JavaScriptCore/wtf/OwnPtr.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_OwnPtr_h -#define WTF_OwnPtr_h - -#include <wtf/Assertions.h> -#include <wtf/NullPtr.h> -#include <wtf/OwnPtrCommon.h> -#include <wtf/TypeTraits.h> -#include <algorithm> -#include <memory> - -namespace WTF { - - // Unlike most of our smart pointers, OwnPtr can take either the pointer type or the pointed-to type. - - template<typename T> class PassOwnPtr; - template<typename T> PassOwnPtr<T> adoptPtr(T*); - - template<typename T> class OwnPtr { - public: - typedef typename RemovePointer<T>::Type ValueType; - typedef ValueType* PtrType; - - OwnPtr() : m_ptr(0) { } - OwnPtr(std::nullptr_t) : m_ptr(0) { } - - // See comment in PassOwnPtr.h for why this takes a const reference. - template<typename U> OwnPtr(const PassOwnPtr<U>& o); - - // This copy constructor is used implicitly by gcc when it generates - // transients for assigning a PassOwnPtr<T> object to a stack-allocated - // OwnPtr<T> object. It should never be called explicitly and gcc - // should optimize away the constructor when generating code. - OwnPtr(const OwnPtr<ValueType>&); - - ~OwnPtr() { deleteOwnedPtr(m_ptr); } - - PtrType get() const { return m_ptr; } - - void clear(); - PassOwnPtr<T> release(); - PtrType leakPtr() WARN_UNUSED_RETURN; - - ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; } - PtrType 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 PtrType OwnPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &OwnPtr::m_ptr : 0; } - - OwnPtr& operator=(const PassOwnPtr<T>&); - OwnPtr& operator=(std::nullptr_t) { clear(); return *this; } - template<typename U> OwnPtr& operator=(const PassOwnPtr<U>&); - - void swap(OwnPtr& o) { std::swap(m_ptr, o.m_ptr); } - - private: - OwnPtr& operator=(const OwnPtr<T>&); - - // We should never have two OwnPtrs for the same underlying object (otherwise we'll get - // double-destruction), so these equality operators should never be needed. - template<typename U> bool operator==(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } - template<typename U> bool operator!=(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } - template<typename U> bool operator==(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } - template<typename U> bool operator!=(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } - - PtrType m_ptr; - }; - - template<typename T> template<typename U> inline OwnPtr<T>::OwnPtr(const PassOwnPtr<U>& o) - : m_ptr(o.leakPtr()) - { - } - - template<typename T> inline void OwnPtr<T>::clear() - { - PtrType ptr = m_ptr; - m_ptr = 0; - deleteOwnedPtr(ptr); - } - - template<typename T> inline PassOwnPtr<T> OwnPtr<T>::release() - { - PtrType ptr = m_ptr; - m_ptr = 0; - return adoptPtr(ptr); - } - - template<typename T> inline typename OwnPtr<T>::PtrType OwnPtr<T>::leakPtr() - { - PtrType ptr = m_ptr; - m_ptr = 0; - return ptr; - } - - template<typename T> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<T>& o) - { - PtrType ptr = m_ptr; - m_ptr = o.leakPtr(); - ASSERT(!ptr || m_ptr != ptr); - deleteOwnedPtr(ptr); - return *this; - } - - template<typename T> template<typename U> inline OwnPtr<T>& OwnPtr<T>::operator=(const PassOwnPtr<U>& o) - { - PtrType ptr = m_ptr; - m_ptr = o.leakPtr(); - ASSERT(!ptr || m_ptr != ptr); - deleteOwnedPtr(ptr); - return *this; - } - - template<typename T> inline void swap(OwnPtr<T>& a, OwnPtr<T>& b) - { - a.swap(b); - } - - template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, U* b) - { - return a.get() == b; - } - - template<typename T, typename U> inline bool operator==(T* a, const OwnPtr<U>& b) - { - return a == b.get(); - } - - template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, U* b) - { - return a.get() != b; - } - - template<typename T, typename U> inline bool operator!=(T* a, const OwnPtr<U>& b) - { - return a != b.get(); - } - - template<typename T> inline typename OwnPtr<T>::PtrType getPtr(const OwnPtr<T>& p) - { - return p.get(); - } - -} // namespace WTF - -using WTF::OwnPtr; - -#endif // WTF_OwnPtr_h diff --git a/Source/JavaScriptCore/wtf/OwnPtrCommon.h b/Source/JavaScriptCore/wtf/OwnPtrCommon.h deleted file mode 100644 index 315db8954..000000000 --- a/Source/JavaScriptCore/wtf/OwnPtrCommon.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 - * 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 WTF_OwnPtrCommon_h -#define WTF_OwnPtrCommon_h - -#if OS(WINDOWS) -typedef struct HBITMAP__* HBITMAP; -typedef struct HBRUSH__* HBRUSH; -typedef struct HDC__* HDC; -typedef struct HFONT__* HFONT; -typedef struct HPALETTE__* HPALETTE; -typedef struct HPEN__* HPEN; -typedef struct HRGN__* HRGN; -#endif - -#if PLATFORM(EFL) -typedef struct _Ecore_Evas Ecore_Evas; -typedef struct _Ecore_Pipe Ecore_Pipe; -typedef struct _Eina_Module Eina_Module; -typedef struct _Evas_Object Evas_Object; -#endif - -namespace WTF { - - template <typename T> inline void deleteOwnedPtr(T* ptr) - { - typedef char known[sizeof(T) ? 1 : -1]; - if (sizeof(known)) - delete ptr; - } - -#if OS(WINDOWS) - void deleteOwnedPtr(HBITMAP); - void deleteOwnedPtr(HBRUSH); - void deleteOwnedPtr(HDC); - void deleteOwnedPtr(HFONT); - void deleteOwnedPtr(HPALETTE); - void deleteOwnedPtr(HPEN); - void deleteOwnedPtr(HRGN); -#endif - -#if PLATFORM(EFL) - void deleteOwnedPtr(Ecore_Evas*); - void deleteOwnedPtr(Ecore_Pipe*); - void deleteOwnedPtr(Eina_Module*); - void deleteOwnedPtr(Evas_Object*); -#endif - -} // namespace WTF - -#endif // WTF_OwnPtrCommon_h diff --git a/Source/JavaScriptCore/wtf/PackedIntVector.h b/Source/JavaScriptCore/wtf/PackedIntVector.h deleted file mode 100644 index 9289eb6b3..000000000 --- a/Source/JavaScriptCore/wtf/PackedIntVector.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2011 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 PackedIntVector_h -#define PackedIntVector_h - -#include <wtf/BitVector.h> - -namespace WTF { - -// This class allows you to create an array of integers, where those -// integers have only a handful of bits each. It is not meant to be -// efficient in time, but only in space. (Though making it efficient -// in time for power-of-2 values of bitCount would not be difficult.) -// Note that this does not work as expected for signed types, if you -// are relying on the sign being preserved. - -template<typename T, unsigned bitCount> -class PackedIntVector { -public: - PackedIntVector() - { - ASSERT(bitCount); - ASSERT(bitCount < sizeof(void*) * 8); - } - - PackedIntVector(const PackedIntVector& other) - : m_bits(other.m_bits) - { - } - - PackedIntVector& operator=(const PackedIntVector& other) - { - m_bits = other.m_bits; - return *this; - } - - size_t size() const - { - return m_bits.size() / bitCount; - } - - void ensureSize(size_t numInts) - { - m_bits.ensureSize(numInts * bitCount); - } - - void resize(size_t numInts) - { - m_bits.resize(numInts * bitCount); - } - - void clearAll() - { - m_bits.clearAll(); - } - - T get(size_t index) const - { - uintptr_t result = 0; - for (unsigned subIndex = 0; subIndex < bitCount; ++subIndex) { - result <<= 1; - result |= (m_bits.quickGet(index * bitCount + subIndex) ? 1 : 0); - } - return static_cast<T>(result); - } - - void set(size_t index, T value) - { - // Do arithmetic using uintptr_t, because (1) we know what it is - // (T might be an enum) and (2) it's the largest integer type that - // is likely to perform decently well. - uintptr_t myValue = static_cast<uintptr_t>(value); - - // Preliminary sanity check that the value is not out of range. - ASSERT((myValue & mask()) == myValue); - - for (unsigned subIndex = bitCount; subIndex-- > 0;) { - m_bits.quickSet(index * bitCount + subIndex, !!(myValue & 1)); - myValue >>= 1; - } - - // Final sanity check that we stored what the user thought we - // stored. - ASSERT(get(index) == value); - } -private: - // This returns the mask, and is careful to not step on the wrap-around - // semantics of the shift amount (1 << 32 is 1 since 32 wraps to 0). There - // is the separate question of why you would ever use this to store 32-bit - // or 64-bit values, but it's probably better to have this work as expected - // in such situations regardless. - static uintptr_t mask() { return (static_cast<uintptr_t>(2) << (bitCount - 1)) - 1; } - - // Stores integers bit by bit in big endian. - BitVector m_bits; -}; - -} // namespace WTF - -using WTF::PackedIntVector; - -#endif // PackedIntVector_h - diff --git a/Source/JavaScriptCore/wtf/PageAllocation.h b/Source/JavaScriptCore/wtf/PageAllocation.h deleted file mode 100644 index 18d31880c..000000000 --- a/Source/JavaScriptCore/wtf/PageAllocation.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 PageAllocation_h -#define PageAllocation_h - -#include <wtf/Assertions.h> -#include <wtf/OSAllocator.h> -#include <wtf/PageBlock.h> -#include <wtf/UnusedParam.h> -#include <wtf/VMTags.h> -#include <algorithm> - -#if OS(DARWIN) -#include <mach/mach_init.h> -#include <mach/vm_map.h> -#endif - -#if OS(WINDOWS) -#include <malloc.h> -#include <windows.h> -#endif - -#if HAVE(ERRNO_H) -#include <errno.h> -#endif - -#if HAVE(MMAP) -#include <sys/mman.h> -#include <unistd.h> -#endif - -namespace WTF { - -/* - PageAllocation - - The PageAllocation class provides a cross-platform memory allocation interface - with similar capabilities to posix mmap/munmap. Memory is allocated by calling - PageAllocation::allocate, and deallocated by calling deallocate on the - PageAllocation object. The PageAllocation holds the allocation's base pointer - and size. - - The allocate method is passed the size required (which must be a multiple of - the system page size, which can be accessed using PageAllocation::pageSize). - Callers may also optinally provide a flag indicating the usage (for use by - system memory usage tracking tools, where implemented), and boolean values - specifying the required protection (defaulting to writable, non-executable). -*/ - -class PageAllocation : private PageBlock { -public: - PageAllocation() - { - } - - using PageBlock::size; - using PageBlock::base; - -#ifndef __clang__ - using PageBlock::operator bool; -#else - // FIXME: This is a workaround for <rdar://problem/8876150>, wherein Clang incorrectly emits an access - // control warning when a client tries to use operator bool exposed above via "using PageBlock::operator bool". - operator bool() const { return PageBlock::operator bool(); } -#endif - - static PageAllocation allocate(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false) - { - ASSERT(isPageAligned(size)); - return PageAllocation(OSAllocator::reserveAndCommit(size, usage, writable, executable), size); - } - - void deallocate() - { - // Clear base & size before calling release; if this is *inside* allocation - // then we won't be able to clear then after deallocating the memory. - PageAllocation tmp; - std::swap(tmp, *this); - - ASSERT(tmp); - ASSERT(!*this); - - OSAllocator::decommitAndRelease(tmp.base(), tmp.size()); - } - -private: - PageAllocation(void* base, size_t size) - : PageBlock(base, size, false) - { - } -}; - -} // namespace WTF - -using WTF::PageAllocation; - -#endif // PageAllocation_h diff --git a/Source/JavaScriptCore/wtf/PageAllocationAligned.cpp b/Source/JavaScriptCore/wtf/PageAllocationAligned.cpp deleted file mode 100644 index 6f54710d0..000000000 --- a/Source/JavaScriptCore/wtf/PageAllocationAligned.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 "PageAllocationAligned.h" - -namespace WTF { - -PageAllocationAligned PageAllocationAligned::allocate(size_t size, size_t alignment, OSAllocator::Usage usage, bool writable, bool executable) -{ - ASSERT(isPageAligned(size)); - ASSERT(isPageAligned(alignment)); - ASSERT(isPowerOfTwo(alignment)); - ASSERT(size >= alignment); - size_t alignmentMask = alignment - 1; - -#if OS(DARWIN) - int flags = VM_FLAGS_ANYWHERE; - if (usage != OSAllocator::UnknownUsage) - flags |= usage; - int protection = PROT_READ; - if (writable) - protection |= PROT_WRITE; - if (executable) - protection |= PROT_EXEC; - - vm_address_t address = 0; - vm_map(current_task(), &address, size, alignmentMask, flags, MEMORY_OBJECT_NULL, 0, FALSE, protection, PROT_READ | PROT_WRITE | PROT_EXEC, VM_INHERIT_DEFAULT); - return PageAllocationAligned(reinterpret_cast<void*>(address), size); -#else - size_t alignmentDelta = alignment - pageSize(); - - // Resererve with suffcient additional VM to correctly align. - size_t reservationSize = size + alignmentDelta; - void* reservationBase = OSAllocator::reserveUncommitted(reservationSize, usage, writable, executable); - - // Select an aligned region within the reservation and commit. - void* alignedBase = reinterpret_cast<uintptr_t>(reservationBase) & alignmentMask - ? reinterpret_cast<void*>((reinterpret_cast<uintptr_t>(reservationBase) & ~alignmentMask) + alignment) - : reservationBase; - OSAllocator::commit(alignedBase, size, writable, executable); - - return PageAllocationAligned(alignedBase, size, reservationBase, reservationSize); -#endif -} - -void PageAllocationAligned::deallocate() -{ - // Clear base & size before calling release; if this is *inside* allocation - // then we won't be able to clear then after deallocating the memory. - PageAllocationAligned tmp; - std::swap(tmp, *this); - - ASSERT(tmp); - ASSERT(!*this); - -#if OS(DARWIN) - vm_deallocate(current_task(), reinterpret_cast<vm_address_t>(tmp.base()), tmp.size()); -#else - ASSERT(tmp.m_reservation.contains(tmp.base(), tmp.size())); - OSAllocator::decommitAndRelease(tmp.m_reservation.base(), tmp.m_reservation.size(), tmp.base(), tmp.size()); -#endif -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/PageAllocationAligned.h b/Source/JavaScriptCore/wtf/PageAllocationAligned.h deleted file mode 100644 index c018dabd8..000000000 --- a/Source/JavaScriptCore/wtf/PageAllocationAligned.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * 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 PageAllocationAligned_h -#define PageAllocationAligned_h - -#include <wtf/OSAllocator.h> -#include <wtf/PageReservation.h> - -namespace WTF { - -class PageAllocationAligned : private PageBlock { -public: - PageAllocationAligned() - { - } - - using PageBlock::operator bool; - using PageBlock::size; - using PageBlock::base; - - static PageAllocationAligned allocate(size_t size, size_t alignment, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false); - - void deallocate(); - -private: -#if OS(DARWIN) - PageAllocationAligned(void* base, size_t size) - : PageBlock(base, size, false) - { - } -#else - PageAllocationAligned(void* base, size_t size, void* reservationBase, size_t reservationSize) - : PageBlock(base, size, false) - , m_reservation(reservationBase, reservationSize, false) - { - } - - PageBlock m_reservation; -#endif -}; - - -} // namespace WTF - -using WTF::PageAllocationAligned; - -#endif // PageAllocationAligned_h diff --git a/Source/JavaScriptCore/wtf/PageBlock.h b/Source/JavaScriptCore/wtf/PageBlock.h deleted file mode 100644 index 3c348a0e3..000000000 --- a/Source/JavaScriptCore/wtf/PageBlock.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 PageBlock_h -#define PageBlock_h - -namespace WTF { - -WTF_EXPORT_PRIVATE size_t pageSize(); -inline bool isPageAligned(void* address) { return !(reinterpret_cast<intptr_t>(address) & (pageSize() - 1)); } -inline bool isPageAligned(size_t size) { return !(size & (pageSize() - 1)); } -inline bool isPowerOfTwo(size_t size) { return !(size & (size - 1)); } - -class PageBlock { -public: - PageBlock(); - PageBlock(const PageBlock&); - PageBlock(void*, size_t, bool hasGuardPages); - - void* base() const { return m_base; } - size_t size() const { return m_size; } - - operator bool() const { return !!m_realBase; } - - bool contains(void* containedBase, size_t containedSize) - { - return containedBase >= m_base - && (static_cast<char*>(containedBase) + containedSize) <= (static_cast<char*>(m_base) + m_size); - } - -private: - void* m_realBase; - void* m_base; - size_t m_size; -}; - -inline PageBlock::PageBlock() - : m_realBase(0) - , m_base(0) - , m_size(0) -{ -} - -inline PageBlock::PageBlock(const PageBlock& other) - : m_realBase(other.m_realBase) - , m_base(other.m_base) - , m_size(other.m_size) -{ -} - -inline PageBlock::PageBlock(void* base, size_t size, bool hasGuardPages) - : m_realBase(base) - , m_base(static_cast<char*>(base) + ((base && hasGuardPages) ? pageSize() : 0)) - , m_size(size) -{ -} - -} // namespace WTF - -using WTF::pageSize; -using WTF::isPageAligned; -using WTF::isPageAligned; -using WTF::isPowerOfTwo; - -#endif // PageBlock_h diff --git a/Source/JavaScriptCore/wtf/PageReservation.h b/Source/JavaScriptCore/wtf/PageReservation.h deleted file mode 100644 index 77783ebcc..000000000 --- a/Source/JavaScriptCore/wtf/PageReservation.h +++ /dev/null @@ -1,149 +0,0 @@ -/* - * 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 PageReservation_h -#define PageReservation_h - -#include <wtf/PageAllocation.h> - -namespace WTF { - -/* - PageReservation - - Like PageAllocation, the PageReservation class provides a cross-platform memory - allocation interface, but with a set of capabilities more similar to that of - VirtualAlloc than posix mmap. PageReservation can be used to allocate virtual - memory without committing physical memory pages using PageReservation::reserve. - Following a call to reserve all memory in the region is in a decommited state, - in which the memory should not be used (accessing the memory may cause a fault). - - Before using memory it must be committed by calling commit, which is passed start - and size values (both of which require system page size granularity). One the - committed memory is no longer needed 'decommit' may be called to return the - memory to its devommitted state. Commit should only be called on memory that is - currently decommitted, and decommit should only be called on memory regions that - are currently committed. All memory should be decommited before the reservation - is deallocated. Values in memory may not be retained accross a pair of calls if - the region of memory is decommitted and then committed again. - - Memory protection should not be changed on decommitted memory, and if protection - is changed on memory while it is committed it should be returned to the orignal - protection before decommit is called. -*/ - -class PageReservation : private PageBlock { -public: - PageReservation() - : m_committed(0) - , m_writable(false) - , m_executable(false) - { - } - - using PageBlock::base; - using PageBlock::size; - -#ifndef __clang__ - using PageBlock::operator bool; -#else - // FIXME: This is a workaround for <rdar://problem/8876150>, wherein Clang incorrectly emits an access - // control warning when a client tries to use operator bool exposed above via "using PageBlock::operator bool". - operator bool() const { return PageBlock::operator bool(); } -#endif - - void commit(void* start, size_t size) - { - ASSERT(*this); - ASSERT(isPageAligned(start)); - ASSERT(isPageAligned(size)); - ASSERT(contains(start, size)); - - m_committed += size; - OSAllocator::commit(start, size, m_writable, m_executable); - } - - void decommit(void* start, size_t size) - { - ASSERT(*this); - ASSERT(isPageAligned(start)); - ASSERT(isPageAligned(size)); - ASSERT(contains(start, size)); - - m_committed -= size; - OSAllocator::decommit(start, size); - } - - size_t committed() - { - return m_committed; - } - - static PageReservation reserve(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false) - { - ASSERT(isPageAligned(size)); - return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable, false); - } - - static PageReservation reserveWithGuardPages(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false) - { - ASSERT(isPageAligned(size)); - return PageReservation(OSAllocator::reserveUncommitted(size + pageSize() * 2, usage, writable, executable, true), size, writable, executable, true); - } - - void deallocate() - { - ASSERT(!m_committed); - - // Clear base & size before calling release; if this is *inside* allocation - // then we won't be able to clear then after deallocating the memory. - PageReservation tmp; - std::swap(tmp, *this); - - ASSERT(tmp); - ASSERT(!*this); - - OSAllocator::releaseDecommitted(tmp.base(), tmp.size()); - } - -private: - PageReservation(void* base, size_t size, bool writable, bool executable, bool hasGuardPages) - : PageBlock(base, size, hasGuardPages) - , m_committed(0) - , m_writable(writable) - , m_executable(executable) - { - } - - size_t m_committed; - bool m_writable; - bool m_executable; -}; - -} - -using WTF::PageReservation; - -#endif // PageReservation_h diff --git a/Source/JavaScriptCore/wtf/ParallelJobs.h b/Source/JavaScriptCore/wtf/ParallelJobs.h deleted file mode 100644 index 0923886ad..000000000 --- a/Source/JavaScriptCore/wtf/ParallelJobs.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2011 University of Szeged - * Copyright (C) 2011 Gabor Loki <loki@webkit.org> - * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobs_h -#define ParallelJobs_h - -#include <wtf/Assertions.h> -#include <wtf/Noncopyable.h> -#include <wtf/RefPtr.h> -#include <wtf/Vector.h> - -// Usage: -// -// // Initialize parallel jobs -// ParallelJobs<TypeOfParameter> parallelJobs(&worker [, requestedNumberOfJobs]); -// -// // Fill the parameter array -// for(i = 0; i < parallelJobs.numberOfJobs(); ++i) { -// TypeOfParameter& params = parallelJobs.parameter(i); -// params.attr1 = localVars ... -// ... -// } -// -// // Execute parallel jobs -// parallelJobs.execute(); -// - -#if ENABLE(THREADING_GENERIC) -#include <wtf/ParallelJobsGeneric.h> - -#elif ENABLE(THREADING_OPENMP) -#include <wtf/ParallelJobsOpenMP.h> - -#elif ENABLE(THREADING_LIBDISPATCH) -#include <wtf/ParallelJobsLibdispatch.h> - -#else -#error "No parallel processing API for ParallelJobs" - -#endif - -namespace WTF { - -template<typename Type> -class ParallelJobs { - WTF_MAKE_FAST_ALLOCATED; -public: - typedef void (*WorkerFunction)(Type*); - - ParallelJobs(WorkerFunction func, int requestedJobNumber) : - m_parallelEnvironment(reinterpret_cast<ParallelEnvironment::ThreadFunction>(func), sizeof(Type), requestedJobNumber) - { - m_parameters.grow(m_parallelEnvironment.numberOfJobs()); - ASSERT(numberOfJobs() == m_parameters.size()); - } - - size_t numberOfJobs() - { - return m_parameters.size(); - } - - Type& parameter(size_t i) - { - return m_parameters[i]; - } - - void execute() - { - m_parallelEnvironment.execute(reinterpret_cast<unsigned char*>(m_parameters.data())); - } - -private: - ParallelEnvironment m_parallelEnvironment; - Vector<Type> m_parameters; -}; - -} // namespace WTF - -using WTF::ParallelJobs; - -#endif // ParallelJobs_h diff --git a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp deleted file mode 100644 index 2cc0bc643..000000000 --- a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2011 University of Szeged - * Copyright (C) 2011 Gabor Loki <loki@webkit.org> - * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if ENABLE(THREADING_GENERIC) - -#include "ParallelJobs.h" -#include <wtf/NumberOfCores.h> - -namespace WTF { - -Vector< RefPtr<ParallelEnvironment::ThreadPrivate> >* ParallelEnvironment::s_threadPool = 0; - -ParallelEnvironment::ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, int requestedJobNumber) : - m_threadFunction(threadFunction), - m_sizeOfParameter(sizeOfParameter) -{ - ASSERT_ARG(requestedJobNumber, requestedJobNumber >= 1); - - int maxNumberOfCores = numberOfProcessorCores(); - - if (!requestedJobNumber || requestedJobNumber > maxNumberOfCores) - requestedJobNumber = static_cast<unsigned>(maxNumberOfCores); - - if (!s_threadPool) - s_threadPool = new Vector< RefPtr<ThreadPrivate> >(); - - // The main thread should be also a worker. - int maxNumberOfNewThreads = requestedJobNumber - 1; - - for (int i = 0; i < maxNumberOfCores && m_threads.size() < static_cast<unsigned>(maxNumberOfNewThreads); ++i) { - if (s_threadPool->size() < static_cast<unsigned>(i) + 1U) - s_threadPool->append(ThreadPrivate::create()); - - if ((*s_threadPool)[i]->tryLockFor(this)) - m_threads.append((*s_threadPool)[i]); - } - - m_numberOfJobs = m_threads.size() + 1; -} - -void ParallelEnvironment::execute(void* parameters) -{ - unsigned char* currentParameter = static_cast<unsigned char*>(parameters); - size_t i; - for (i = 0; i < m_threads.size(); ++i) { - m_threads[i]->execute(m_threadFunction, currentParameter); - currentParameter += m_sizeOfParameter; - } - - // The work for the main thread. - (*m_threadFunction)(currentParameter); - - // Wait until all jobs are done. - for (i = 0; i < m_threads.size(); ++i) - m_threads[i]->waitForFinish(); -} - -bool ParallelEnvironment::ThreadPrivate::tryLockFor(ParallelEnvironment* parent) -{ - bool locked = m_mutex.tryLock(); - - if (!locked) - return false; - - if (m_parent) { - m_mutex.unlock(); - return false; - } - - if (!m_threadID) - m_threadID = createThread(&ParallelEnvironment::ThreadPrivate::workerThread, this, "Parallel worker"); - - if (m_threadID) - m_parent = parent; - - m_mutex.unlock(); - return m_threadID; -} - -void ParallelEnvironment::ThreadPrivate::execute(ThreadFunction threadFunction, void* parameters) -{ - MutexLocker lock(m_mutex); - - m_threadFunction = threadFunction; - m_parameters = parameters; - m_running = true; - m_threadCondition.signal(); -} - -void ParallelEnvironment::ThreadPrivate::waitForFinish() -{ - MutexLocker lock(m_mutex); - - while (m_running) - m_threadCondition.wait(m_mutex); -} - -void ParallelEnvironment::ThreadPrivate::workerThread(void* threadData) -{ - ThreadPrivate* sharedThread = reinterpret_cast<ThreadPrivate*>(threadData); - MutexLocker lock(sharedThread->m_mutex); - - while (sharedThread->m_threadID) { - if (sharedThread->m_running) { - (*sharedThread->m_threadFunction)(sharedThread->m_parameters); - sharedThread->m_running = false; - sharedThread->m_parent = 0; - sharedThread->m_threadCondition.signal(); - } - - sharedThread->m_threadCondition.wait(sharedThread->m_mutex); - } -} - -} // namespace WTF -#endif // ENABLE(THREADING_GENERIC) diff --git a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h deleted file mode 100644 index 6de71067f..000000000 --- a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2011 University of Szeged - * Copyright (C) 2011 Gabor Loki <loki@webkit.org> - * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobsGeneric_h -#define ParallelJobsGeneric_h - -#if ENABLE(THREADING_GENERIC) - -#include <wtf/RefCounted.h> -#include <wtf/Threading.h> - -namespace WTF { - -class ParallelEnvironment { - WTF_MAKE_FAST_ALLOCATED; -public: - typedef void (*ThreadFunction)(void*); - - ParallelEnvironment(ThreadFunction, size_t sizeOfParameter, int requestedJobNumber); - - int numberOfJobs() - { - return m_numberOfJobs; - } - - void execute(void* parameters); - - class ThreadPrivate : public RefCounted<ThreadPrivate> { - public: - ThreadPrivate() - : m_threadID(0) - , m_running(false) - , m_parent(0) - { - } - - bool tryLockFor(ParallelEnvironment*); - - void execute(ThreadFunction, void*); - - void waitForFinish(); - - static PassRefPtr<ThreadPrivate> create() - { - return adoptRef(new ThreadPrivate()); - } - - static void workerThread(void*); - - private: - ThreadIdentifier m_threadID; - bool m_running; - ParallelEnvironment* m_parent; - - mutable Mutex m_mutex; - ThreadCondition m_threadCondition; - - ThreadFunction m_threadFunction; - void* m_parameters; - }; - -private: - ThreadFunction m_threadFunction; - size_t m_sizeOfParameter; - int m_numberOfJobs; - - Vector< RefPtr<ThreadPrivate> > m_threads; - static Vector< RefPtr<ThreadPrivate> >* s_threadPool; -}; - -} // namespace WTF - -#endif // ENABLE(THREADING_GENERIC) - - -#endif // ParallelJobsGeneric_h diff --git a/Source/JavaScriptCore/wtf/ParallelJobsLibdispatch.h b/Source/JavaScriptCore/wtf/ParallelJobsLibdispatch.h deleted file mode 100644 index ca7d9a4e8..000000000 --- a/Source/JavaScriptCore/wtf/ParallelJobsLibdispatch.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2011 University of Szeged - * Copyright (C) 2011 Gabor Loki <loki@webkit.org> - * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobsLibdispatch_h -#define ParallelJobsLibdispatch_h - -#if ENABLE(THREADING_LIBDISPATCH) - -#include <dispatch/dispatch.h> - -namespace WTF { - -class ParallelEnvironment { - WTF_MAKE_FAST_ALLOCATED; -public: - typedef void (*ThreadFunction)(void*); - - ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, int requestedJobNumber) - : m_threadFunction(threadFunction) - , m_sizeOfParameter(sizeOfParameter) - , m_numberOfJobs(requestedJobNumber) - { - // We go with the requested number of jobs. libdispatch will distribute the work optimally. - ASSERT_ARG(requestedJobNumber, requestedJobNumber > 0); - } - - int numberOfJobs() - { - return m_numberOfJobs; - } - - void execute(unsigned char* parameters) - { - static dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - - dispatch_apply(m_numberOfJobs, globalQueue, ^(size_t i) { (*m_threadFunction)(parameters + (m_sizeOfParameter * i)); }); - } - -private: - ThreadFunction m_threadFunction; - size_t m_sizeOfParameter; - int m_numberOfJobs; -}; - -} // namespace WTF - -#endif // ENABLE(THREADING_LIBDISPATCH) - -#endif // ParallelJobsLibdispatch_h diff --git a/Source/JavaScriptCore/wtf/ParallelJobsOpenMP.h b/Source/JavaScriptCore/wtf/ParallelJobsOpenMP.h deleted file mode 100644 index 706bd8065..000000000 --- a/Source/JavaScriptCore/wtf/ParallelJobsOpenMP.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2011 University of Szeged - * Copyright (C) 2011 Gabor Loki <loki@webkit.org> - * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 ParallelJobsOpenMP_h -#define ParallelJobsOpenMP_h - -#if ENABLE(THREADING_OPENMP) - -#include <omp.h> - -namespace WTF { - -class ParallelEnvironment { - WTF_MAKE_NONCOPYABLE(ParallelEnvironment); -public: - typedef void (*ThreadFunction)(void*); - - ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, int requestedJobNumber) : - m_threadFunction(threadFunction), - m_sizeOfParameter(sizeOfParameter) - { - int maxNumberOfThreads = omp_get_max_threads(); - - if (!requestedJobNumber || requestedJobNumber > maxNumberOfThreads) - requestedJobNumber = maxNumberOfThreads; - - ASSERT(requestedJobNumber > 0); - - m_numberOfJobs = requestedJobNumber; - - } - - int numberOfJobs() - { - return m_numberOfJobs; - } - - void execute(unsigned char* parameters) - { - omp_set_num_threads(m_numberOfJobs); - -#pragma omp parallel for - for (int i = 0; i < m_numberOfJobs; ++i) - (*m_threadFunction)(parameters + i * m_sizeOfParameter); - } - -private: - ThreadFunction m_threadFunction; - size_t m_sizeOfParameter; - int m_numberOfJobs; -}; - -} // namespace WTF - -#endif // ENABLE(THREADING_OPENMP) - -#endif // ParallelJobsOpenMP_h diff --git a/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h b/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h deleted file mode 100644 index 1db7343de..000000000 --- a/Source/JavaScriptCore/wtf/PassOwnArrayPtr.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * 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 WTF_PassOwnArrayPtr_h -#define WTF_PassOwnArrayPtr_h - -#include <wtf/Assertions.h> -#include <wtf/NullPtr.h> -#include <wtf/TypeTraits.h> - -namespace WTF { - -template<typename T> class OwnArrayPtr; -template<typename T> class PassOwnArrayPtr; -template<typename T> PassOwnArrayPtr<T> adoptArrayPtr(T*); -template<typename T> void deleteOwnedArrayPtr(T* ptr); - -template<typename T> class PassOwnArrayPtr { -public: - typedef T* PtrType; - - PassOwnArrayPtr() : m_ptr(0) { } - PassOwnArrayPtr(std::nullptr_t) : m_ptr(0) { } - - // It somewhat breaks the type system to allow transfer of ownership out of - // a const PassOwnArrayPtr. However, it makes it much easier to work with PassOwnArrayPtr - // temporaries, and we don't have a need to use real const PassOwnArrayPtrs anyway. - PassOwnArrayPtr(const PassOwnArrayPtr& o) : m_ptr(o.leakPtr()) { } - template<typename U> PassOwnArrayPtr(const PassOwnArrayPtr<U>& o) : m_ptr(o.leakPtr()) { } - - ~PassOwnArrayPtr() { deleteOwnedArrayPtr(m_ptr); } - - PtrType get() const { return m_ptr; } - - PtrType leakPtr() const WARN_UNUSED_RETURN; - - T& operator*() const { ASSERT(m_ptr); return *m_ptr; } - PtrType 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 PtrType PassOwnArrayPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnArrayPtr::m_ptr : 0; } - - PassOwnArrayPtr& operator=(const PassOwnArrayPtr&) { COMPILE_ASSERT(!sizeof(T*), PassOwnArrayPtr_should_never_be_assigned_to); return *this; } - - template<typename U> friend PassOwnArrayPtr<U> adoptArrayPtr(U*); - -private: - explicit PassOwnArrayPtr(PtrType ptr) : m_ptr(ptr) { } - - mutable PtrType m_ptr; -}; - -template<typename T> inline typename PassOwnArrayPtr<T>::PtrType PassOwnArrayPtr<T>::leakPtr() const -{ - PtrType ptr = m_ptr; - m_ptr = 0; - return ptr; -} - -template<typename T, typename U> inline bool operator==(const PassOwnArrayPtr<T>& a, const PassOwnArrayPtr<U>& b) -{ - return a.get() == b.get(); -} - -template<typename T, typename U> inline bool operator==(const PassOwnArrayPtr<T>& a, const OwnArrayPtr<U>& b) -{ - return a.get() == b.get(); -} - -template<typename T, typename U> inline bool operator==(const OwnArrayPtr<T>& a, const PassOwnArrayPtr<U>& b) -{ - return a.get() == b.get(); -} - -template<typename T, typename U> inline bool operator==(const PassOwnArrayPtr<T>& a, U* b) -{ - return a.get() == b; -} - -template<typename T, typename U> inline bool operator==(T* a, const PassOwnArrayPtr<U>& b) -{ - return a == b.get(); -} - -template<typename T, typename U> inline bool operator!=(const PassOwnArrayPtr<T>& a, const PassOwnArrayPtr<U>& b) -{ - return a.get() != b.get(); -} - -template<typename T, typename U> inline bool operator!=(const PassOwnArrayPtr<T>& a, const OwnArrayPtr<U>& b) -{ - return a.get() != b.get(); -} - -template<typename T, typename U> inline bool operator!=(const OwnArrayPtr<T>& a, const PassOwnArrayPtr<U>& b) -{ - return a.get() != b.get(); -} - -template<typename T, typename U> inline bool operator!=(const PassOwnArrayPtr<T>& a, U* b) -{ - return a.get() != b; -} - -template<typename T, typename U> inline bool operator!=(T* a, const PassOwnArrayPtr<U>& b) -{ - return a != b.get(); -} - -template<typename T> inline PassOwnArrayPtr<T> adoptArrayPtr(T* ptr) -{ - return PassOwnArrayPtr<T>(ptr); -} - -template<typename T> inline void deleteOwnedArrayPtr(T* ptr) -{ - typedef char known[sizeof(T) ? 1 : -1]; - if (sizeof(known)) - delete [] ptr; -} - -template<typename T, typename U> inline PassOwnArrayPtr<T> static_pointer_cast(const PassOwnArrayPtr<U>& p) -{ - return adoptArrayPtr(static_cast<T*>(p.leakPtr())); -} - -template<typename T, typename U> inline PassOwnArrayPtr<T> const_pointer_cast(const PassOwnArrayPtr<U>& p) -{ - return adoptArrayPtr(const_cast<T*>(p.leakPtr())); -} - -template<typename T> inline T* getPtr(const PassOwnArrayPtr<T>& p) -{ - return p.get(); -} - -} // namespace WTF - -using WTF::PassOwnArrayPtr; -using WTF::adoptArrayPtr; -using WTF::const_pointer_cast; -using WTF::static_pointer_cast; - -#endif // WTF_PassOwnArrayPtr_h diff --git a/Source/JavaScriptCore/wtf/PassOwnPtr.h b/Source/JavaScriptCore/wtf/PassOwnPtr.h deleted file mode 100644 index 5ebf83d65..000000000 --- a/Source/JavaScriptCore/wtf/PassOwnPtr.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 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 WTF_PassOwnPtr_h -#define WTF_PassOwnPtr_h - -#include <wtf/Assertions.h> -#include <wtf/NullPtr.h> -#include <wtf/OwnPtrCommon.h> -#include <wtf/TypeTraits.h> - -namespace WTF { - - // Unlike most of our smart pointers, PassOwnPtr can take either the pointer type or the pointed-to type. - - template<typename T> class OwnPtr; - template<typename T> class PassOwnPtr; - template<typename T> PassOwnPtr<T> adoptPtr(T*); - - template<typename T> class PassOwnPtr { - public: - typedef typename RemovePointer<T>::Type ValueType; - typedef ValueType* PtrType; - - PassOwnPtr() : m_ptr(0) { } - PassOwnPtr(std::nullptr_t) : m_ptr(0) { } - - // It somewhat breaks the type system to allow transfer of ownership out of - // a const PassOwnPtr. However, it makes it much easier to work with PassOwnPtr - // temporaries, and we don't have a need to use real const PassOwnPtrs anyway. - PassOwnPtr(const PassOwnPtr& o) : m_ptr(o.leakPtr()) { } - template<typename U> PassOwnPtr(const PassOwnPtr<U>& o) : m_ptr(o.leakPtr()) { } - - ~PassOwnPtr() { deleteOwnedPtr(m_ptr); } - - PtrType get() const { return m_ptr; } - - PtrType leakPtr() const WARN_UNUSED_RETURN; - - ValueType& operator*() const { ASSERT(m_ptr); return *m_ptr; } - PtrType 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 PtrType PassOwnPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &PassOwnPtr::m_ptr : 0; } - - PassOwnPtr& operator=(const PassOwnPtr&) { COMPILE_ASSERT(!sizeof(T*), PassOwnPtr_should_never_be_assigned_to); return *this; } - - template<typename U> friend PassOwnPtr<U> adoptPtr(U*); - - private: - explicit PassOwnPtr(PtrType ptr) : m_ptr(ptr) { } - - // We should never have two OwnPtrs for the same underlying object (otherwise we'll get - // double-destruction), so these equality operators should never be needed. - template<typename U> bool operator==(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } - template<typename U> bool operator!=(const PassOwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } - template<typename U> bool operator==(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } - template<typename U> bool operator!=(const OwnPtr<U>&) { COMPILE_ASSERT(!sizeof(U*), OwnPtrs_should_never_be_equal); return false; } - - mutable PtrType m_ptr; - }; - - template<typename T> inline typename PassOwnPtr<T>::PtrType PassOwnPtr<T>::leakPtr() const - { - PtrType ptr = m_ptr; - m_ptr = 0; - return ptr; - } - - template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) - { - return a.get() == b.get(); - } - - template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, const OwnPtr<U>& b) - { - return a.get() == b.get(); - } - - template<typename T, typename U> inline bool operator==(const OwnPtr<T>& a, const PassOwnPtr<U>& b) - { - return a.get() == b.get(); - } - - template<typename T, typename U> inline bool operator==(const PassOwnPtr<T>& a, U* b) - { - return a.get() == b; - } - - template<typename T, typename U> inline bool operator==(T* a, const PassOwnPtr<U>& b) - { - return a == b.get(); - } - - template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const PassOwnPtr<U>& b) - { - return a.get() != b.get(); - } - - template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, const OwnPtr<U>& b) - { - return a.get() != b.get(); - } - - template<typename T, typename U> inline bool operator!=(const OwnPtr<T>& a, const PassOwnPtr<U>& b) - { - return a.get() != b.get(); - } - - template<typename T, typename U> inline bool operator!=(const PassOwnPtr<T>& a, U* b) - { - return a.get() != b; - } - - template<typename T, typename U> inline bool operator!=(T* a, const PassOwnPtr<U>& b) - { - return a != b.get(); - } - - template<typename T> inline PassOwnPtr<T> adoptPtr(T* ptr) - { - return PassOwnPtr<T>(ptr); - } - - template<typename T, typename U> inline PassOwnPtr<T> static_pointer_cast(const PassOwnPtr<U>& p) - { - return adoptPtr(static_cast<T*>(p.leakPtr())); - } - - template<typename T, typename U> inline PassOwnPtr<T> const_pointer_cast(const PassOwnPtr<U>& p) - { - return adoptPtr(const_cast<T*>(p.leakPtr())); - } - - template<typename T> inline T* getPtr(const PassOwnPtr<T>& p) - { - return p.get(); - } - -} // namespace WTF - -using WTF::PassOwnPtr; -using WTF::adoptPtr; -using WTF::const_pointer_cast; -using WTF::static_pointer_cast; - -#endif // WTF_PassOwnPtr_h diff --git a/Source/JavaScriptCore/wtf/PassRefPtr.h b/Source/JavaScriptCore/wtf/PassRefPtr.h deleted file mode 100644 index 207721c96..000000000 --- a/Source/JavaScriptCore/wtf/PassRefPtr.h +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_PassRefPtr_h -#define WTF_PassRefPtr_h - -#include <wtf/AlwaysInline.h> -#include <wtf/NullPtr.h> - -namespace WTF { - - template<typename T> class RefPtr; - template<typename T> class PassRefPtr; - template<typename T> PassRefPtr<T> adoptRef(T*); - - inline void adopted(const void*) { } - -#if !PLATFORM(QT) - #define REF_DEREF_INLINE ALWAYS_INLINE -#else - // Using ALWAYS_INLINE broke the Qt build. This may be a GCC bug. - // See https://bugs.webkit.org/show_bug.cgi?id=37253 for details. - #define REF_DEREF_INLINE inline -#endif - - template<typename T> REF_DEREF_INLINE void refIfNotNull(T* ptr) - { - if (LIKELY(ptr != 0)) - ptr->ref(); - } - - template<typename T> REF_DEREF_INLINE void derefIfNotNull(T* ptr) - { - if (LIKELY(ptr != 0)) - ptr->deref(); - } - - #undef REF_DEREF_INLINE - - template<typename T> class PassRefPtr { - public: - PassRefPtr() : m_ptr(0) { } - PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } - // It somewhat breaks the type system to allow transfer of ownership out of - // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr - // temporaries, and we don't have a need to use real const PassRefPtrs anyway. - PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { } - template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.leakRef()) { } - - ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); } - - template<typename U> PassRefPtr(const RefPtr<U>&); - - T* get() const { return m_ptr; } - - T* leakRef() const WARN_UNUSED_RETURN; - - T& operator*() const { return *m_ptr; } - T* operator->() const { 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* (PassRefPtr::*UnspecifiedBoolType); - operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; } - - PassRefPtr& operator=(const PassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), PassRefPtr_should_never_be_assigned_to); return *this; } - - friend PassRefPtr adoptRef<T>(T*); - - private: - // adopting constructor - PassRefPtr(T* ptr, bool) : m_ptr(ptr) { } - - mutable T* m_ptr; - }; - - // NonNullPassRefPtr: Optimized for passing non-null pointers. A NonNullPassRefPtr - // begins life non-null, and can only become null through a call to leakRef() - // or clear(). - - // FIXME: NonNullPassRefPtr could just inherit from PassRefPtr. However, - // if we use inheritance, GCC's optimizer fails to realize that destruction - // of a released NonNullPassRefPtr is a no-op. So, for now, just copy the - // most important code from PassRefPtr. - template<typename T> class NonNullPassRefPtr { - public: - NonNullPassRefPtr(T* ptr) - : m_ptr(ptr) - { - ASSERT(m_ptr); - m_ptr->ref(); - } - - template<typename U> NonNullPassRefPtr(const RefPtr<U>& o) - : m_ptr(o.get()) - { - ASSERT(m_ptr); - m_ptr->ref(); - } - - NonNullPassRefPtr(const NonNullPassRefPtr& o) - : m_ptr(o.leakRef()) - { - ASSERT(m_ptr); - } - - template<typename U> NonNullPassRefPtr(const NonNullPassRefPtr<U>& o) - : m_ptr(o.leakRef()) - { - ASSERT(m_ptr); - } - - template<typename U> NonNullPassRefPtr(const PassRefPtr<U>& o) - : m_ptr(o.leakRef()) - { - ASSERT(m_ptr); - } - - ALWAYS_INLINE ~NonNullPassRefPtr() { derefIfNotNull(m_ptr); } - - T* get() const { return m_ptr; } - - T* leakRef() const WARN_UNUSED_RETURN { T* tmp = m_ptr; m_ptr = 0; return tmp; } - - T& operator*() const { return *m_ptr; } - T* operator->() const { return m_ptr; } - - NonNullPassRefPtr& operator=(const NonNullPassRefPtr&) { COMPILE_ASSERT(!sizeof(T*), NonNullPassRefPtr_should_never_be_assigned_to); return *this; } - - private: - mutable T* m_ptr; - }; - - template<typename T> template<typename U> inline PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o) - : m_ptr(o.get()) - { - T* ptr = m_ptr; - refIfNotNull(ptr); - } - - template<typename T> inline T* PassRefPtr<T>::leakRef() const - { - T* ptr = m_ptr; - m_ptr = 0; - return ptr; - } - - template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) - { - return a.get() == b.get(); - } - - template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) - { - return a.get() == b.get(); - } - - template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b) - { - return a.get() == b.get(); - } - - template<typename T, typename U> inline bool operator==(const PassRefPtr<T>& a, U* b) - { - return a.get() == b; - } - - template<typename T, typename U> inline bool operator==(T* a, const PassRefPtr<U>& b) - { - return a == b.get(); - } - - template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) - { - return a.get() != b.get(); - } - - template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) - { - return a.get() != b.get(); - } - - template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b) - { - return a.get() != b.get(); - } - - template<typename T, typename U> inline bool operator!=(const PassRefPtr<T>& a, U* b) - { - return a.get() != b; - } - - template<typename T, typename U> inline bool operator!=(T* a, const PassRefPtr<U>& b) - { - return a != b.get(); - } - - template<typename T> inline PassRefPtr<T> adoptRef(T* p) - { - adopted(p); - return PassRefPtr<T>(p, true); - } - - template<typename T, typename U> inline PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) - { - return adoptRef(static_cast<T*>(p.leakRef())); - } - - template<typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p) - { - return adoptRef(const_cast<T*>(p.leakRef())); - } - - template<typename T> inline T* getPtr(const PassRefPtr<T>& p) - { - return p.get(); - } - -} // namespace WTF - -using WTF::PassRefPtr; -using WTF::NonNullPassRefPtr; -using WTF::adoptRef; -using WTF::static_pointer_cast; -using WTF::const_pointer_cast; - -#endif // WTF_PassRefPtr_h diff --git a/Source/JavaScriptCore/wtf/PassTraits.h b/Source/JavaScriptCore/wtf/PassTraits.h deleted file mode 100644 index 9564e3ad3..000000000 --- a/Source/JavaScriptCore/wtf/PassTraits.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2011 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 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 WTF_PassTraits_h -#define WTF_PassTraits_h - -#include <wtf/OwnPtr.h> -#include <wtf/RefPtr.h> - -// The PassTraits template exists to help optimize (or make possible) use -// of WTF data structures with WTF smart pointers that have a Pass -// variant for transfer of ownership - -namespace WTF { - -template<typename T> struct PassTraits { - typedef T Type; - typedef T PassType; - static PassType transfer(Type& value) { return value; } -}; - -template<typename T> struct PassTraits<OwnPtr<T> > { - typedef OwnPtr<T> Type; - typedef PassOwnPtr<T> PassType; - static PassType transfer(Type& value) { return value.release(); } -}; - -template<typename T> struct PassTraits<RefPtr<T> > { - typedef RefPtr<T> Type; - typedef PassRefPtr<T> PassType; - static PassType transfer(Type& value) { return value.release(); } -}; - -} // namespace WTF - -using WTF::PassTraits; - -#endif // WTF_PassTraits_h diff --git a/Source/JavaScriptCore/wtf/Platform.h b/Source/JavaScriptCore/wtf/Platform.h deleted file mode 100644 index c374b03c9..000000000 --- a/Source/JavaScriptCore/wtf/Platform.h +++ /dev/null @@ -1,1214 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007-2009 Torch Mobile, Inc. - * Copyright (C) 2010, 2011 Research In Motion Limited. 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 WTF_Platform_h -#define WTF_Platform_h - -/* Include compiler specific macros */ -#include <wtf/Compiler.h> - -/* ==== PLATFORM handles OS, operating environment, graphics API, and - CPU. This macro will be phased out in favor of platform adaptation - macros, policy decision macros, and top-level port definitions. ==== */ -#define PLATFORM(WTF_FEATURE) (defined WTF_PLATFORM_##WTF_FEATURE && WTF_PLATFORM_##WTF_FEATURE) - - -/* ==== Platform adaptation macros: these describe properties of the target environment. ==== */ - -/* CPU() - the target CPU architecture */ -#define CPU(WTF_FEATURE) (defined WTF_CPU_##WTF_FEATURE && WTF_CPU_##WTF_FEATURE) -/* HAVE() - specific system features (headers, functions or similar) that are present or not */ -#define HAVE(WTF_FEATURE) (defined HAVE_##WTF_FEATURE && HAVE_##WTF_FEATURE) -/* OS() - underlying operating system; only to be used for mandated low-level services like - virtual memory, not to choose a GUI toolkit */ -#define OS(WTF_FEATURE) (defined WTF_OS_##WTF_FEATURE && WTF_OS_##WTF_FEATURE) - - -/* ==== Policy decision macros: these define policy choices for a particular port. ==== */ - -/* USE() - use a particular third-party library or optional OS service */ -#define USE(WTF_FEATURE) (defined WTF_USE_##WTF_FEATURE && WTF_USE_##WTF_FEATURE) -/* ENABLE() - turn on a specific feature of WebKit */ -#define ENABLE(WTF_FEATURE) (defined ENABLE_##WTF_FEATURE && ENABLE_##WTF_FEATURE) - - -/* ==== CPU() - the target CPU architecture ==== */ - -/* This also defines CPU(BIG_ENDIAN) or CPU(MIDDLE_ENDIAN) or neither, as appropriate. */ - -/* CPU(ALPHA) - DEC Alpha */ -#if defined(__alpha__) -#define WTF_CPU_ALPHA 1 -#endif - -/* CPU(IA64) - Itanium / IA-64 */ -#if defined(__ia64__) -#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(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) -#define WTF_MIPS_FP64 (defined __mips_fpr && __mips_fpr == 64) -/* MIPS requires allocators to use aligned memory */ -#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1 -#endif /* MIPS */ - -/* CPU(PPC) - PowerPC 32-bit */ -#if defined(__ppc__) \ - || defined(__PPC__) \ - || defined(__powerpc__) \ - || defined(__powerpc) \ - || defined(__POWERPC__) \ - || defined(_M_PPC) \ - || defined(__PPC) -#define WTF_CPU_PPC 1 -#define WTF_CPU_BIG_ENDIAN 1 -#endif - -/* CPU(PPC64) - PowerPC 64-bit */ -#if defined(__ppc64__) \ - || defined(__PPC64__) -#define WTF_CPU_PPC64 1 -#define WTF_CPU_BIG_ENDIAN 1 -#endif - -/* CPU(SH4) - SuperH SH-4 */ -#if defined(__SH4__) -#define WTF_CPU_SH4 1 -#endif - -/* CPU(SPARC32) - SPARC 32-bit */ -#if defined(__sparc) && !defined(__arch64__) || defined(__sparcv8) -#define WTF_CPU_SPARC32 1 -#define WTF_CPU_BIG_ENDIAN 1 -#endif - -/* CPU(SPARC64) - SPARC 64-bit */ -#if defined(__sparc__) && defined(__arch64__) || defined (__sparcv9) -#define WTF_CPU_SPARC64 1 -#define WTF_CPU_BIG_ENDIAN 1 -#endif - -/* CPU(SPARC) - any SPARC, true for CPU(SPARC32) and CPU(SPARC64) */ -#if CPU(SPARC32) || CPU(SPARC64) -#define WTF_CPU_SPARC 1 -#endif - -/* CPU(S390X) - S390 64-bit */ -#if defined(__s390x__) -#define WTF_CPU_S390X 1 -#define WTF_CPU_BIG_ENDIAN 1 -#endif - -/* CPU(S390) - S390 32-bit */ -#if defined(__s390__) -#define WTF_CPU_S390 1 -#define WTF_CPU_BIG_ENDIAN 1 -#endif - -/* CPU(X86) - i386 / x86 32-bit */ -#if defined(__i386__) \ - || defined(i386) \ - || defined(_M_IX86) \ - || defined(_X86_) \ - || defined(__THW_INTEL) -#define WTF_CPU_X86 1 -#endif - -/* CPU(X86_64) - AMD64 / Intel64 / x86_64 64-bit */ -#if defined(__x86_64__) \ - || defined(_M_X64) -#define WTF_CPU_X86_64 1 -#endif - -/* CPU(ARM) - ARM, any version*/ -#if defined(arm) \ - || defined(__arm__) \ - || defined(ARM) \ - || defined(_ARM_) -#define WTF_CPU_ARM 1 - -#if defined(__ARMEB__) || (COMPILER(RVCT) && defined(__BIG_ENDIAN)) -#define WTF_CPU_BIG_ENDIAN 1 - -#elif !defined(__ARM_EABI__) \ - && !defined(__EABI__) \ - && !defined(__VFP_FP__) \ - && !defined(_WIN32_WCE) \ - && !defined(ANDROID) -#define WTF_CPU_MIDDLE_ENDIAN 1 - -#endif - -#define WTF_ARM_ARCH_AT_LEAST(N) (CPU(ARM) && WTF_ARM_ARCH_VERSION >= N) - -/* Set WTF_ARM_ARCH_VERSION */ -#if defined(__ARM_ARCH_4__) \ - || defined(__ARM_ARCH_4T__) \ - || defined(__MARM_ARMV4__) \ - || defined(_ARMV4I_) -#define WTF_ARM_ARCH_VERSION 4 - -#elif defined(__ARM_ARCH_5__) \ - || defined(__ARM_ARCH_5T__) \ - || defined(__MARM_ARMV5__) -#define WTF_ARM_ARCH_VERSION 5 - -#elif defined(__ARM_ARCH_5E__) \ - || defined(__ARM_ARCH_5TE__) \ - || defined(__ARM_ARCH_5TEJ__) -#define WTF_ARM_ARCH_VERSION 5 -/*ARMv5TE requires allocators to use aligned memory*/ -#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1 - -#elif defined(__ARM_ARCH_6__) \ - || defined(__ARM_ARCH_6J__) \ - || defined(__ARM_ARCH_6K__) \ - || defined(__ARM_ARCH_6Z__) \ - || defined(__ARM_ARCH_6ZK__) \ - || defined(__ARM_ARCH_6T2__) \ - || defined(__ARMV6__) -#define WTF_ARM_ARCH_VERSION 6 - -#elif defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) -#define WTF_ARM_ARCH_VERSION 7 - -/* RVCT sets _TARGET_ARCH_ARM */ -#elif defined(__TARGET_ARCH_ARM) -#define WTF_ARM_ARCH_VERSION __TARGET_ARCH_ARM - -#if defined(__TARGET_ARCH_5E) \ - || defined(__TARGET_ARCH_5TE) \ - || defined(__TARGET_ARCH_5TEJ) -/*ARMv5TE requires allocators to use aligned memory*/ -#define WTF_USE_ARENA_ALLOC_ALIGNMENT_INTEGER 1 -#endif - -#else -#define WTF_ARM_ARCH_VERSION 0 - -#endif - -/* Set WTF_THUMB_ARCH_VERSION */ -#if defined(__ARM_ARCH_4T__) -#define WTF_THUMB_ARCH_VERSION 1 - -#elif defined(__ARM_ARCH_5T__) \ - || defined(__ARM_ARCH_5TE__) \ - || defined(__ARM_ARCH_5TEJ__) -#define WTF_THUMB_ARCH_VERSION 2 - -#elif defined(__ARM_ARCH_6J__) \ - || defined(__ARM_ARCH_6K__) \ - || defined(__ARM_ARCH_6Z__) \ - || defined(__ARM_ARCH_6ZK__) \ - || defined(__ARM_ARCH_6M__) -#define WTF_THUMB_ARCH_VERSION 3 - -#elif defined(__ARM_ARCH_6T2__) \ - || defined(__ARM_ARCH_7__) \ - || defined(__ARM_ARCH_7A__) \ - || defined(__ARM_ARCH_7R__) \ - || defined(__ARM_ARCH_7M__) -#define WTF_THUMB_ARCH_VERSION 4 - -/* RVCT sets __TARGET_ARCH_THUMB */ -#elif defined(__TARGET_ARCH_THUMB) -#define WTF_THUMB_ARCH_VERSION __TARGET_ARCH_THUMB - -#else -#define WTF_THUMB_ARCH_VERSION 0 -#endif - - -/* CPU(ARMV5_OR_LOWER) - ARM instruction set v5 or earlier */ -/* On ARMv5 and below the natural alignment is required. - And there are some other differences for v5 or earlier. */ -#if !defined(ARMV5_OR_LOWER) && !WTF_ARM_ARCH_AT_LEAST(6) -#define WTF_CPU_ARMV5_OR_LOWER 1 -#endif - - -/* CPU(ARM_TRADITIONAL) - Thumb2 is not available, only traditional ARM (v4 or greater) */ -/* CPU(ARM_THUMB2) - Thumb2 instruction set is available */ -/* Only one of these will be defined. */ -#if !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2) -# if defined(thumb2) || defined(__thumb2__) \ - || ((defined(__thumb) || defined(__thumb__)) && WTF_THUMB_ARCH_VERSION == 4) -# define WTF_CPU_ARM_TRADITIONAL 0 -# define WTF_CPU_ARM_THUMB2 1 -# elif WTF_ARM_ARCH_AT_LEAST(4) -# define WTF_CPU_ARM_TRADITIONAL 1 -# define WTF_CPU_ARM_THUMB2 0 -# else -# error "Not supported ARM architecture" -# endif -#elif CPU(ARM_TRADITIONAL) && CPU(ARM_THUMB2) /* Sanity Check */ -# error "Cannot use both of WTF_CPU_ARM_TRADITIONAL and WTF_CPU_ARM_THUMB2 platforms" -#endif /* !defined(WTF_CPU_ARM_TRADITIONAL) && !defined(WTF_CPU_ARM_THUMB2) */ - -#if defined(__ARM_NEON__) && !defined(WTF_CPU_ARM_NEON) -#define WTF_CPU_ARM_NEON 1 -#endif - -#endif /* ARM */ - -#if CPU(ARM) || CPU(MIPS) || CPU(SH4) || CPU(SPARC) -#define WTF_CPU_NEEDS_ALIGNED_ACCESS 1 -#endif - -/* ==== OS() - underlying operating system; only to be used for mandated low-level services like - virtual memory, not to choose a GUI toolkit ==== */ - -/* OS(ANDROID) - Android */ -#ifdef ANDROID -#define WTF_OS_ANDROID 1 -#endif - -/* OS(AIX) - AIX */ -#ifdef _AIX -#define WTF_OS_AIX 1 -#endif - -/* OS(DARWIN) - Any Darwin-based OS, including Mac OS X and iPhone OS */ -#ifdef __APPLE__ -#define WTF_OS_DARWIN 1 - -#include <Availability.h> -#include <AvailabilityMacros.h> -#include <TargetConditionals.h> -#endif - -/* OS(IOS) - iOS */ -/* OS(MAC_OS_X) - Mac OS X (not including iOS) */ -#if OS(DARWIN) && ((defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) \ - || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) \ - || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR)) -#define WTF_OS_IOS 1 -#elif OS(DARWIN) && defined(TARGET_OS_MAC) && TARGET_OS_MAC -#define WTF_OS_MAC_OS_X 1 -/* FIXME: BUILDING_ON_.., and TARGETING... macros should be folded into the OS() system */ -#if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 -#define BUILDING_ON_LEOPARD 1 -#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 -#define BUILDING_ON_SNOW_LEOPARD 1 -#elif !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8 -#define BUILDING_ON_LION 1 -#endif -#if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6 -#define TARGETING_LEOPARD 1 -#elif !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 -#define TARGETING_SNOW_LEOPARD 1 -#elif !defined(MAC_OS_X_VERSION_10_8) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 -#define TARGETING_LION 1 -#endif -#endif - -/* OS(FREEBSD) - FreeBSD */ -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) -#define WTF_OS_FREEBSD 1 -#endif - -/* OS(HURD) - GNU/Hurd */ -#ifdef __GNU__ -#define WTF_OS_HURD 1 -#endif - -/* OS(LINUX) - Linux */ -#ifdef __linux__ -#define WTF_OS_LINUX 1 -#endif - -/* OS(NETBSD) - NetBSD */ -#if defined(__NetBSD__) -#define WTF_OS_NETBSD 1 -#endif - -/* OS(OPENBSD) - OpenBSD */ -#ifdef __OpenBSD__ -#define WTF_OS_OPENBSD 1 -#endif - -/* OS(QNX) - QNX */ -#if defined(__QNXNTO__) -#define WTF_OS_QNX 1 -#endif - -/* OS(SOLARIS) - Solaris */ -#if defined(sun) || defined(__sun) -#define WTF_OS_SOLARIS 1 -#endif - -/* OS(WINCE) - Windows CE; note that for this platform OS(WINDOWS) is also defined */ -#if defined(_WIN32_WCE) -#define WTF_OS_WINCE 1 -#endif - -/* OS(WINDOWS) - Any version of Windows */ -#if defined(WIN32) || defined(_WIN32) -#define WTF_OS_WINDOWS 1 -#endif - -#define WTF_OS_WIN ERROR "USE WINDOWS WITH OS NOT WIN" -#define WTF_OS_MAC ERROR "USE MAC_OS_X WITH OS NOT MAC" - -/* OS(UNIX) - Any Unix-like system */ -#if OS(AIX) \ - || OS(ANDROID) \ - || OS(DARWIN) \ - || OS(FREEBSD) \ - || OS(HURD) \ - || OS(LINUX) \ - || OS(NETBSD) \ - || OS(OPENBSD) \ - || OS(QNX) \ - || OS(SOLARIS) \ - || defined(unix) \ - || defined(__unix) \ - || defined(__unix__) -#define WTF_OS_UNIX 1 -#endif - -/* Operating environments */ - -/* FIXME: these are all mixes of OS, operating environment and policy choices. */ -/* PLATFORM(CHROMIUM) */ -/* PLATFORM(QT) */ -/* PLATFORM(WX) */ -/* PLATFORM(GTK) */ -/* PLATFORM(BLACKBERRY) */ -/* PLATFORM(MAC) */ -/* PLATFORM(WIN) */ -#if defined(BUILDING_CHROMIUM__) -#define WTF_PLATFORM_CHROMIUM 1 -#elif defined(BUILDING_QT__) -#define WTF_PLATFORM_QT 1 -#elif defined(BUILDING_WX__) -#define WTF_PLATFORM_WX 1 -#elif defined(BUILDING_GTK__) -#define WTF_PLATFORM_GTK 1 -#elif defined(BUILDING_BLACKBERRY__) -#define WTF_PLATFORM_BLACKBERRY 1 -#elif OS(DARWIN) -#define WTF_PLATFORM_MAC 1 -#elif OS(WINDOWS) -#define WTF_PLATFORM_WIN 1 -#endif - -/* PLATFORM(IOS) */ -/* FIXME: this is sometimes used as an OS switch and sometimes for higher-level things */ -#if (defined(TARGET_OS_EMBEDDED) && TARGET_OS_EMBEDDED) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) -#define WTF_PLATFORM_IOS 1 -#endif - -/* PLATFORM(IOS_SIMULATOR) */ -#if defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR -#define WTF_PLATFORM_IOS 1 -#define WTF_PLATFORM_IOS_SIMULATOR 1 -#else -#define WTF_PLATFORM_IOS_SIMULATOR 0 -#endif - -#if !defined(WTF_PLATFORM_IOS) -#define WTF_PLATFORM_IOS 0 -#endif - -/* Graphics engines */ - -/* USE(CG) and PLATFORM(CI) */ -#if PLATFORM(MAC) || PLATFORM(IOS) -#define WTF_USE_CG 1 -#endif -#if PLATFORM(MAC) || PLATFORM(IOS) || (PLATFORM(WIN) && USE(CG)) -#define WTF_USE_CA 1 -#endif - -/* USE(SKIA) for Win/Linux/Mac/Android */ -#if PLATFORM(CHROMIUM) -#if OS(DARWIN) -#if USE(SKIA_ON_MAC_CHROMIUM) -#define WTF_USE_SKIA 1 -#else -#define WTF_USE_CG 1 -#endif -#define WTF_USE_ATSUI 1 -#define WTF_USE_CORE_TEXT 1 -#define WTF_USE_ICCJPEG 1 -#elif OS(ANDROID) -#define WTF_USE_SKIA 1 -#define WTF_USE_GLES2_RENDERING 0 -#else -#define WTF_USE_SKIA 1 -#define WTF_USE_CHROMIUM_NET 1 -#endif -#endif - -#if PLATFORM(BLACKBERRY) -#define ENABLE_DRAG_SUPPORT 0 -#define USE_SYSTEM_MALLOC 1 -#define WTF_USE_MERSENNE_TWISTER_19937 1 -#define WTF_USE_SKIA 1 -#endif - -#if PLATFORM(GTK) -#define WTF_USE_CAIRO 1 -#endif - - -#if OS(WINCE) -#include <ce_time.h> -#define WTF_USE_MERSENNE_TWISTER_19937 1 -#endif - -/* On Windows, use QueryPerformanceCounter by default */ -#if OS(WINDOWS) -#define WTF_USE_QUERY_PERFORMANCE_COUNTER 1 -#endif - -#if OS(WINCE) && !PLATFORM(QT) -#define NOMINMAX /* Windows min and max conflict with standard macros */ -#define NOSHLWAPI /* shlwapi.h not available on WinCe */ - -/* MSDN documentation says these functions are provided with uspce.lib. But we cannot find this file. */ -#define __usp10__ /* disable "usp10.h" */ - -#define _INC_ASSERT /* disable "assert.h" */ -#define assert(x) - -#endif /* OS(WINCE) && !PLATFORM(QT) */ - -#if PLATFORM(QT) -#ifndef WTF_USE_ICU_UNICODE -#define WTF_USE_QT4_UNICODE 1 -#endif -#elif OS(WINCE) -#define WTF_USE_WINCE_UNICODE 1 -#elif PLATFORM(GTK) -/* The GTK+ Unicode backend is configurable */ -#else -#define WTF_USE_ICU_UNICODE 1 -#endif - -#if PLATFORM(MAC) && !PLATFORM(IOS) -#if !defined(BUILDING_ON_LEOPARD) && CPU(X86_64) -#define WTF_USE_PLUGIN_HOST_PROCESS 1 -#endif -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) -#define ENABLE_GESTURE_EVENTS 1 -#define ENABLE_RUBBER_BANDING 1 -#define WTF_USE_SCROLLBAR_PAINTER 1 -#endif -#if !defined(ENABLE_JAVA_BRIDGE) -#define ENABLE_JAVA_BRIDGE 1 -#endif -#if !defined(ENABLE_DASHBOARD_SUPPORT) -#define ENABLE_DASHBOARD_SUPPORT 1 -#endif -#define WTF_USE_CF 1 -#define WTF_USE_PTHREADS 1 -#define HAVE_PTHREAD_RWLOCK 1 -#define HAVE_READLINE 1 -#define HAVE_RUNLOOP_TIMER 1 -#define ENABLE_FULLSCREEN_API 1 -#define ENABLE_SMOOTH_SCROLLING 1 -#define ENABLE_WEB_ARCHIVE 1 -#define ENABLE_WEB_AUDIO 1 -#if defined(ENABLE_VIDEO) -#define ENABLE_VIDEO_TRACK 1 -#endif -#if !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) -#define HAVE_LAYER_HOSTING_IN_WINDOW_SERVER 1 -#endif -#endif /* PLATFORM(MAC) && !PLATFORM(IOS) */ - -#if PLATFORM(CHROMIUM) && OS(DARWIN) -#define WTF_USE_CF 1 -#define WTF_USE_PTHREADS 1 -#define HAVE_PTHREAD_RWLOCK 1 - -#define WTF_USE_WK_SCROLLBAR_PAINTER 1 -#endif - -#if PLATFORM(IOS) -#define DONT_FINALIZE_ON_MAIN_THREAD 1 -#endif - -#if PLATFORM(QT) && OS(DARWIN) -#define WTF_USE_CF 1 -#define HAVE_DISPATCH_H 1 -#endif - -#if OS(DARWIN) && !PLATFORM(GTK) && !PLATFORM(QT) -#define ENABLE_PURGEABLE_MEMORY 1 -#endif - -#if PLATFORM(IOS) -#define ENABLE_CONTEXT_MENUS 0 -#define ENABLE_DRAG_SUPPORT 0 -#define ENABLE_DATA_TRANSFER_ITEMS 0 -#define ENABLE_FTPDIR 1 -#define ENABLE_GEOLOCATION 1 -#define ENABLE_ICONDATABASE 0 -#define ENABLE_INSPECTOR 1 -#define ENABLE_JAVA_BRIDGE 0 -#define ENABLE_NETSCAPE_PLUGIN_API 0 -#define ENABLE_ORIENTATION_EVENTS 1 -#define ENABLE_REPAINT_THROTTLING 1 -#define ENABLE_WEB_ARCHIVE 1 -#define HAVE_NETWORK_CFDATA_ARRAY_CALLBACK 1 -#define HAVE_PTHREAD_RWLOCK 1 -#define HAVE_READLINE 1 -#define HAVE_RUNLOOP_TIMER 0 -#define WTF_USE_CF 1 -#define WTF_USE_CFNETWORK 1 -#define WTF_USE_PTHREADS 1 - -#if PLATFORM(IOS_SIMULATOR) - #define ENABLE_CLASSIC_INTERPRETER 1 - #define ENABLE_JIT 0 - #define ENABLE_YARR_JIT 0 -#else - #define ENABLE_CLASSIC_INTERPRETER 0 - #define ENABLE_JIT 1 - #define ENABLE_LLINT 1 - #define ENABLE_YARR_JIT 1 -#endif - -#endif - -#if PLATFORM(WIN) && !OS(WINCE) -#define WTF_USE_CF 1 -#define WTF_USE_PTHREADS 0 -#endif - -#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(WIN_CAIRO) -#define WTF_USE_CFNETWORK 1 -#endif - -#if USE(CFNETWORK) || PLATFORM(MAC) || PLATFORM(IOS) -#define WTF_USE_CFURLCACHE 1 -#define WTF_USE_CFURLSTORAGESESSIONS 1 -#endif - -#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(QT) -#define ENABLE_WEB_ARCHIVE 1 -#endif - -#if PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(CHROMIUM) && !PLATFORM(WIN_CAIRO) && !PLATFORM(QT) -#define ENABLE_FULLSCREEN_API 1 -#endif - -#if PLATFORM(WX) -#if !CPU(PPC) -#define ENABLE_ASSEMBLER 1 -#define ENABLE_JIT 1 -#endif -#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 -#define ENABLE_LLINT 0 -#if OS(DARWIN) -#define WTF_USE_CF 1 -#define WTF_USE_CORE_TEXT 1 -#define ENABLE_WEB_ARCHIVE 1 -#endif -#endif - -#if PLATFORM(GTK) -#if HAVE(PTHREAD_H) -#define WTF_USE_PTHREADS 1 -#define HAVE_PTHREAD_RWLOCK 1 -#endif -#elif PLATFORM(QT) && OS(UNIX) -#define WTF_USE_PTHREADS 1 -#define HAVE_PTHREAD_RWLOCK 1 -#endif - -#if !defined(HAVE_ACCESSIBILITY) -#if PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(GTK) || PLATFORM(CHROMIUM) -#define HAVE_ACCESSIBILITY 1 -#endif -#endif /* !defined(HAVE_ACCESSIBILITY) */ - -#if OS(UNIX) -#define HAVE_SIGNAL_H 1 -#endif - -#if !defined(HAVE_VASPRINTF) -#if !COMPILER(MSVC) && !COMPILER(RVCT) && !COMPILER(MINGW) && !(COMPILER(GCC) && OS(QNX)) -#define HAVE_VASPRINTF 1 -#endif -#endif - -#if !defined(HAVE_STRNSTR) -#if OS(DARWIN) || (OS(FREEBSD) && !defined(__GLIBC__)) -#define HAVE_STRNSTR 1 -#endif -#endif - -#if !OS(WINDOWS) && !OS(SOLARIS) \ - && !OS(RVCT) \ - && !OS(ANDROID) -#define HAVE_TM_GMTOFF 1 -#define HAVE_TM_ZONE 1 -#define HAVE_TIMEGM 1 -#endif - -#if OS(DARWIN) - -#define HAVE_ERRNO_H 1 -#define HAVE_LANGINFO_H 1 -#define HAVE_MMAP 1 -#define HAVE_MERGESORT 1 -#define HAVE_SBRK 1 -#define HAVE_STRINGS_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_TIME_H 1 -#define HAVE_SYS_TIMEB_H 1 -#define WTF_USE_ACCELERATE 1 - -#ifndef TARGETING_LEOPARD - -#define HAVE_DISPATCH_H 1 -#define HAVE_HOSTED_CORE_ANIMATION 1 - -#if !PLATFORM(IOS) -#define HAVE_MADV_FREE_REUSE 1 -#define HAVE_MADV_FREE 1 -#define HAVE_PTHREAD_SETNAME_NP 1 -#endif - -#endif - -#if PLATFORM(IOS) -#define HAVE_MADV_FREE 1 -#define HAVE_PTHREAD_SETNAME_NP 1 -#endif - -#elif OS(WINDOWS) - -#if OS(WINCE) -#define HAVE_ERRNO_H 0 -#else -#define HAVE_SYS_TIMEB_H 1 -#define HAVE_ALIGNED_MALLOC 1 -#define HAVE_ISDEBUGGERPRESENT 1 -#endif -#define HAVE_VIRTUALALLOC 1 - -#elif OS(QNX) - -#define HAVE_ERRNO_H 1 -#define HAVE_MMAP 1 -#define HAVE_MADV_FREE_REUSE 1 -#define HAVE_MADV_FREE 1 -#define HAVE_SBRK 1 -#define HAVE_STRINGS_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_TIME_H 1 -#define WTF_USE_PTHREADS 1 - -#elif OS(ANDROID) - -#define HAVE_ERRNO_H 1 -#define HAVE_LANGINFO_H 0 -#define HAVE_NMAP 1 -#define HAVE_SBRK 1 -#define HAVE_STRINGS_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_TIME_H 1 - -#else - -/* FIXME: is this actually used or do other platforms generate their own config.h? */ - -#define HAVE_ERRNO_H 1 -#define HAVE_LANGINFO_H 1 -#define HAVE_MMAP 1 -#define HAVE_SBRK 1 -#define HAVE_STRINGS_H 1 -#define HAVE_SYS_PARAM_H 1 -#define HAVE_SYS_TIME_H 1 - -#endif - -/* ENABLE macro defaults */ - -#if PLATFORM(QT) -/* We must not customize the global operator new and delete for the Qt port. */ -#define ENABLE_GLOBAL_FASTMALLOC_NEW 0 -#if !OS(UNIX) -#define USE_SYSTEM_MALLOC 1 -#endif -#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) -#define ENABLE_FAST_MALLOC_MATCH_VALIDATION 0 -#endif - -#if !defined(ENABLE_ICONDATABASE) -#define ENABLE_ICONDATABASE 1 -#endif - -#if !defined(ENABLE_SQL_DATABASE) -#define ENABLE_SQL_DATABASE 1 -#endif - -#if !defined(ENABLE_JAVASCRIPT_DEBUGGER) -#define ENABLE_JAVASCRIPT_DEBUGGER 1 -#endif - -#if !defined(ENABLE_FTPDIR) -#define ENABLE_FTPDIR 1 -#endif - -#if !defined(ENABLE_CONTEXT_MENUS) -#define ENABLE_CONTEXT_MENUS 1 -#endif - -#if !defined(ENABLE_DRAG_SUPPORT) -#define ENABLE_DRAG_SUPPORT 1 -#endif - -#if !defined(ENABLE_DATA_TRANSFER_ITEMS) -#define ENABLE_DATA_TRANSFER_ITEMS 0 -#endif - -#if !defined(ENABLE_DASHBOARD_SUPPORT) -#define ENABLE_DASHBOARD_SUPPORT 0 -#endif - -#if !defined(ENABLE_INSPECTOR) -#define ENABLE_INSPECTOR 1 -#endif - -#if !defined(ENABLE_JAVA_BRIDGE) -#define ENABLE_JAVA_BRIDGE 0 -#endif - -#if !defined(ENABLE_NETSCAPE_PLUGIN_API) -#define ENABLE_NETSCAPE_PLUGIN_API 1 -#endif - -#if !defined(ENABLE_NETSCAPE_PLUGIN_METADATA_CACHE) -#define ENABLE_NETSCAPE_PLUGIN_METADATA_CACHE 0 -#endif - -#if !defined(ENABLE_PURGEABLE_MEMORY) -#define ENABLE_PURGEABLE_MEMORY 0 -#endif - -#if !defined(WTF_USE_PLUGIN_HOST_PROCESS) -#define WTF_USE_PLUGIN_HOST_PROCESS 0 -#endif - -#if !defined(ENABLE_ORIENTATION_EVENTS) -#define ENABLE_ORIENTATION_EVENTS 0 -#endif - -#if !defined(ENABLE_OPCODE_STATS) -#define ENABLE_OPCODE_STATS 0 -#endif - -#if !defined(ENABLE_GLOBAL_FASTMALLOC_NEW) -#define ENABLE_GLOBAL_FASTMALLOC_NEW 1 -#endif - -#define ENABLE_DEBUG_WITH_BREAKPOINT 0 -#define ENABLE_SAMPLING_COUNTERS 0 -#define ENABLE_SAMPLING_FLAGS 0 -#define ENABLE_SAMPLING_REGIONS 0 -#define ENABLE_OPCODE_SAMPLING 0 -#define ENABLE_CODEBLOCK_SAMPLING 0 -#if ENABLE(CODEBLOCK_SAMPLING) && !ENABLE(OPCODE_SAMPLING) -#error "CODEBLOCK_SAMPLING requires OPCODE_SAMPLING" -#endif -#if ENABLE(OPCODE_SAMPLING) || ENABLE(SAMPLING_FLAGS) || ENABLE(SAMPLING_REGIONS) -#define ENABLE_SAMPLING_THREAD 1 -#endif - -#if !defined(ENABLE_GEOLOCATION) -#define ENABLE_GEOLOCATION 0 -#endif - -#if !defined(ENABLE_VIEWPORT) -#define ENABLE_VIEWPORT 0 -#endif - -#if !defined(ENABLE_NOTIFICATIONS) -#define ENABLE_NOTIFICATIONS 0 -#endif - -#if PLATFORM(IOS) -#define ENABLE_TEXT_CARET 0 -#endif - -#if !defined(ENABLE_TEXT_CARET) -#define ENABLE_TEXT_CARET 1 -#endif - -#if !defined(ENABLE_FULLSCREEN_API) -#define ENABLE_FULLSCREEN_API 0 -#endif - -#if !defined(ENABLE_POINTER_LOCK) -#define ENABLE_POINTER_LOCK 0 -#endif - -#if !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64) -#if (CPU(X86_64) && (OS(UNIX) || OS(WINDOWS))) \ - || (CPU(IA64) && !CPU(IA64_32)) \ - || CPU(ALPHA) \ - || CPU(SPARC64) \ - || CPU(S390X) \ - || CPU(PPC64) -#define WTF_USE_JSVALUE64 1 -#else -#define WTF_USE_JSVALUE32_64 1 -#endif -#endif /* !defined(WTF_USE_JSVALUE64) && !defined(WTF_USE_JSVALUE32_64) */ - -#if !defined(ENABLE_REPAINT_THROTTLING) -#define ENABLE_REPAINT_THROTTLING 0 -#endif - -/* Disable the JIT on versions of GCC prior to 4.1 */ -#if !defined(ENABLE_JIT) && COMPILER(GCC) && !GCC_VERSION_AT_LEAST(4, 1, 0) -#define ENABLE_JIT 0 -#endif - -/* JIT is not implemented for Windows 64-bit */ -#if !defined(ENABLE_JIT) && OS(WINDOWS) && CPU(X86_64) -#define ENABLE_JIT 0 -#endif - -/* The JIT is enabled by default on all x86, x86-64, ARM & MIPS platforms. */ -#if !defined(ENABLE_JIT) \ - && (CPU(X86) || CPU(X86_64) || CPU(ARM) || CPU(MIPS)) \ - && (OS(DARWIN) || !COMPILER(GCC) || GCC_VERSION_AT_LEAST(4, 1, 0)) \ - && !OS(WINCE) \ - && !OS(QNX) -#define ENABLE_JIT 1 -#endif - -/* On some of the platforms where we have a JIT, we want to also have the - low-level interpreter. */ -#if !defined(ENABLE_LLINT) && ENABLE(JIT) && OS(DARWIN) && (CPU(X86) || CPU(X86_64) || CPU(ARM_THUMB2)) -#define ENABLE_LLINT 1 -#endif - -#if !defined(ENABLE_DFG_JIT) && ENABLE(JIT) -/* Enable the DFG JIT on X86 and X86_64. Only tested on Mac and GNU/Linux. */ -#if (CPU(X86) || CPU(X86_64)) && (PLATFORM(MAC) || OS(LINUX)) -#define ENABLE_DFG_JIT 1 -#endif -/* Enable the DFG JIT on ARMv7. Only tested on iOS. */ -#if CPU(ARM_THUMB2) && PLATFORM(IOS) -#define ENABLE_DFG_JIT 1 -#endif -#endif - -/* Profiling of types and values used by JIT code. DFG_JIT depends on it, but you - can enable it manually with DFG turned off if you want to use it as a standalone - profiler. In that case, you probably want to also enable VERBOSE_VALUE_PROFILE - below. */ -#if !defined(ENABLE_VALUE_PROFILER) && ENABLE(DFG_JIT) -#define ENABLE_VALUE_PROFILER 1 -#endif - -#if !defined(ENABLE_VERBOSE_VALUE_PROFILE) && ENABLE(VALUE_PROFILER) -#define ENABLE_VERBOSE_VALUE_PROFILE 0 -#endif - -#if !defined(ENABLE_SIMPLE_HEAP_PROFILING) -#define ENABLE_SIMPLE_HEAP_PROFILING 0 -#endif - -/* Counts uses of write barriers using sampling counters. Be sure to also - set ENABLE_SAMPLING_COUNTERS to 1. */ -#if !defined(ENABLE_WRITE_BARRIER_PROFILING) -#define ENABLE_WRITE_BARRIER_PROFILING 0 -#endif - -/* Ensure that either the JIT or the interpreter has been enabled. */ -#if !defined(ENABLE_CLASSIC_INTERPRETER) && !ENABLE(JIT) -#define ENABLE_CLASSIC_INTERPRETER 1 -#endif -#if !(ENABLE(JIT) || ENABLE(CLASSIC_INTERPRETER)) -#error You have to have at least one execution model enabled to build JSC -#endif - -#if CPU(SH4) && PLATFORM(QT) -#define ENABLE_JIT 1 -#endif - -/* Configure the JIT */ -#if CPU(ARM) -#if !defined(ENABLE_JIT_USE_SOFT_MODULO) && WTF_ARM_ARCH_AT_LEAST(5) -#define ENABLE_JIT_USE_SOFT_MODULO 1 -#endif -#endif - -#if CPU(X86) || CPU(X86_64) || CPU(MIPS) -#if !defined(ENABLE_JIT_USE_SOFT_MODULO) -#define ENABLE_JIT_USE_SOFT_MODULO 1 -#endif -#endif - -#if CPU(X86) && COMPILER(MSVC) -#define JSC_HOST_CALL __fastcall -#elif CPU(X86) && COMPILER(GCC) -#define JSC_HOST_CALL __attribute__ ((fastcall)) -#else -#define JSC_HOST_CALL -#endif - -/* Configure the interpreter */ -#if COMPILER(GCC) || (RVCT_VERSION_AT_LEAST(4, 0, 0, 0) && defined(__GNUC__)) -#define HAVE_COMPUTED_GOTO 1 -#endif -#if HAVE(COMPUTED_GOTO) && ENABLE(CLASSIC_INTERPRETER) -#define ENABLE_COMPUTED_GOTO_CLASSIC_INTERPRETER 1 -#endif - -/* Regular Expression Tracing - Set to 1 to trace RegExp's in jsc. Results dumped at exit */ -#define ENABLE_REGEXP_TRACING 0 - -/* Yet Another Regex Runtime - turned on by default for JIT enabled ports. */ -#if PLATFORM(CHROMIUM) -#define ENABLE_YARR_JIT 0 - -#elif ENABLE(JIT) && !defined(ENABLE_YARR_JIT) -#define ENABLE_YARR_JIT 1 - -/* Setting this flag compares JIT results with interpreter results. */ -#define ENABLE_YARR_JIT_DEBUG 0 -#endif - -#if ENABLE(JIT) || ENABLE(YARR_JIT) -#define ENABLE_ASSEMBLER 1 -#endif - -/* Pick which allocator to use; we only need an executable allocator if the assembler is compiled in. - On x86-64 we use a single fixed mmap, on other platforms we mmap on demand. */ -#if ENABLE(ASSEMBLER) -#if CPU(X86_64) || PLATFORM(IOS) -#define ENABLE_EXECUTABLE_ALLOCATOR_FIXED 1 -#else -#define ENABLE_EXECUTABLE_ALLOCATOR_DEMAND 1 -#endif -#endif - -#if !defined(ENABLE_PAN_SCROLLING) && OS(WINDOWS) -#define ENABLE_PAN_SCROLLING 1 -#endif - -#if !defined(ENABLE_SMOOTH_SCROLLING) -#define ENABLE_SMOOTH_SCROLLING 0 -#endif - -#if !defined(ENABLE_WEB_ARCHIVE) -#define ENABLE_WEB_ARCHIVE 0 -#endif - -/* Use the QXmlStreamReader implementation for XMLDocumentParser */ -/* Use the QXmlQuery implementation for XSLTProcessor */ -#if PLATFORM(QT) -#if !USE(LIBXML2) -#define WTF_USE_QXMLSTREAM 1 -#define WTF_USE_QXMLQUERY 1 -#endif -#endif - -#if PLATFORM(MAC) -/* Complex text framework */ -#ifndef BUILDING_ON_LEOPARD -#define WTF_USE_ATSUI 0 -#define WTF_USE_CORE_TEXT 1 -#else -#define WTF_USE_ATSUI 1 -#define WTF_USE_CORE_TEXT 0 -#endif -#endif - -/* Accelerated compositing */ -#if PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || (PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO)) || PLATFORM(EFL) -#define WTF_USE_ACCELERATED_COMPOSITING 1 -#endif - -/* Compositing on the UI-process in WebKit2 */ -#if PLATFORM(QT) -#define WTF_USE_UI_SIDE_COMPOSITING 1 -#endif - -#if (PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD)) || PLATFORM(IOS) -#define WTF_USE_PROTECTION_SPACE_AUTH_CALLBACK 1 -#endif - -#if !ENABLE(NETSCAPE_PLUGIN_API) || (ENABLE(NETSCAPE_PLUGIN_API) && ((OS(UNIX) && (PLATFORM(QT) || PLATFORM(WX))) || PLATFORM(GTK) || PLATFORM(EFL))) -#define ENABLE_PLUGIN_PACKAGE_SIMPLE_HASH 1 -#endif - -#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) -#define ENABLE_THREADED_SCROLLING 1 -#endif - -/* Set up a define for a common error that is intended to cause a build error -- thus the space after Error. */ -#define WTF_PLATFORM_CFNETWORK Error USE_macro_should_be_used_with_CFNETWORK - -/* FIXME: Eventually we should enable this for all platforms and get rid of the define. */ -#if PLATFORM(IOS) || PLATFORM(MAC) || PLATFORM(WIN) || PLATFORM(QT) -#define WTF_USE_PLATFORM_STRATEGIES 1 -#endif - -#if PLATFORM(WIN) -#define WTF_USE_CROSS_PLATFORM_CONTEXT_MENUS 1 -#endif - -#if PLATFORM(MAC) && HAVE(ACCESSIBILITY) -#define WTF_USE_ACCESSIBILITY_CONTEXT_MENUS 1 -#endif - -/* Geolocation request policy. pre-emptive policy is to acquire user permission before acquiring location. - Client based implementations will have option to choose between pre-emptive and nonpre-emptive permission policy. - pre-emptive permission policy is enabled by default for all client-based implementations. */ -#if ENABLE(CLIENT_BASED_GEOLOCATION) -#define WTF_USE_PREEMPT_GEOLOCATION_PERMISSION 1 -#endif - -#if CPU(ARM_THUMB2) -#define ENABLE_BRANCH_COMPACTION 1 -#endif - -#if !defined(ENABLE_THREADING_LIBDISPATCH) && HAVE(DISPATCH_H) -#define ENABLE_THREADING_LIBDISPATCH 1 -#elif !defined(ENABLE_THREADING_OPENMP) && defined(_OPENMP) -#define ENABLE_THREADING_OPENMP 1 -#elif !defined(THREADING_GENERIC) -#define ENABLE_THREADING_GENERIC 1 -#endif - -#if ENABLE(GLIB_SUPPORT) -#include <wtf/gobject/GTypedefs.h> -#endif - -/* FIXME: This define won't be needed once #27551 is fully landed. However, - since most ports try to support sub-project independence, adding new headers - to WTF causes many ports to break, and so this way we can address the build - breakages one port at a time. */ -#if PLATFORM(MAC) || PLATFORM(QT) -#define WTF_USE_EXPORT_MACROS 1 -#else -#define WTF_USE_EXPORT_MACROS 0 -#endif - -#if (PLATFORM(QT) && !OS(DARWIN)) || PLATFORM(GTK) || PLATFORM(EFL) -#define WTF_USE_UNIX_DOMAIN_SOCKETS 1 -#endif - -#if !defined(ENABLE_COMPARE_AND_SWAP) && COMPILER(GCC) && (CPU(X86) || CPU(X86_64) || CPU(ARM_THUMB2)) -#define ENABLE_COMPARE_AND_SWAP 1 -#endif - -#if !defined(ENABLE_PARALLEL_GC) && (PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT)) && ENABLE(COMPARE_AND_SWAP) -#define ENABLE_PARALLEL_GC 1 -#endif - -#ifndef NDEBUG -#ifndef ENABLE_GC_VALIDATION -#define ENABLE_GC_VALIDATION 1 -#endif -#endif - -#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) -#define WTF_USE_AVFOUNDATION 1 -#endif - -#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) -#define WTF_USE_COREMEDIA 1 -#endif - -#if PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(EFL) || (PLATFORM(WIN) && !OS(WINCE) && !PLATFORM(WIN_CAIRO)) || PLATFORM(QT) || PLATFORM(BLACKBERRY) -#define WTF_USE_REQUEST_ANIMATION_FRAME_TIMER 1 -#endif - -#if PLATFORM(MAC) -#define WTF_USE_REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR 1 -#endif - -#if PLATFORM(MAC) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD) -#define HAVE_INVERTED_WHEEL_EVENTS 1 -#endif - -#if PLATFORM(MAC) -#define WTF_USE_COREAUDIO 1 -#endif - -#if PLATFORM(CHROMIUM) -#if !defined(WTF_USE_V8) -#define WTF_USE_V8 1 -#endif -#endif /* PLATFORM(CHROMIUM) */ - -#if !defined(WTF_USE_V8) -#define WTF_USE_V8 0 -#endif /* !defined(WTF_USE_V8) */ - -/* Using V8 implies not using JSC and vice versa */ -#define WTF_USE_JSC !WTF_USE_V8 - -#if ENABLE(NOTIFICATIONS) && PLATFORM(MAC) -#define ENABLE_TEXT_NOTIFICATIONS_ONLY 1 -#endif - -#if !defined(WTF_USE_WTFURL) -#define WTF_USE_WTFURL 0 -#endif - -#if !PLATFORM(QT) && !PLATFORM(EFL) -#define WTF_USE_ZLIB 1 -#endif - -#endif /* WTF_Platform_h */ diff --git a/Source/JavaScriptCore/wtf/PlatformBlackBerry.cmake b/Source/JavaScriptCore/wtf/PlatformBlackBerry.cmake deleted file mode 100644 index 5f30d0889..000000000 --- a/Source/JavaScriptCore/wtf/PlatformBlackBerry.cmake +++ /dev/null @@ -1,12 +0,0 @@ -LIST(APPEND WTF_SOURCES - OSAllocatorPosix.cpp - TCSystemAlloc.cpp - ThreadIdentifierDataPthreads.cpp - ThreadingPthreads.cpp - blackberry/MainThreadBlackBerry.cpp - unicode/icu/CollatorICU.cpp -) - -LIST(INSERT WTF_INCLUDE_DIRECTORIES 0 - "${BLACKBERRY_THIRD_PARTY_DIR}/icu" -) diff --git a/Source/JavaScriptCore/wtf/PlatformEfl.cmake b/Source/JavaScriptCore/wtf/PlatformEfl.cmake deleted file mode 100644 index 1a13dbba3..000000000 --- a/Source/JavaScriptCore/wtf/PlatformEfl.cmake +++ /dev/null @@ -1,40 +0,0 @@ -LIST(APPEND WTF_SOURCES - efl/MainThreadEfl.cpp - efl/OwnPtrEfl.cpp - gobject/GOwnPtr.cpp - gobject/GRefPtr.cpp - - OSAllocatorPosix.cpp - ThreadIdentifierDataPthreads.cpp - ThreadingPthreads.cpp - - unicode/icu/CollatorICU.cpp -) - -LIST(APPEND WTF_LIBRARIES - pthread - ${Glib_LIBRARIES} - ${ICU_LIBRARIES} - ${ICU_I18N_LIBRARIES} - ${ECORE_LIBRARIES} - ${ECORE_EVAS_LIBRARIES} - ${EINA_LIBRARIES} - ${EVAS_LIBRARIES} - ${CMAKE_DL_LIBS} -) - -LIST(APPEND WTF_LINK_FLAGS - ${ECORE_LDFLAGS} - ${ECORE_EVAS_LDFLAGS} - ${EVAS_LDFLAGS} -) - -LIST(APPEND WTF_INCLUDE_DIRECTORIES - ${ECORE_INCLUDE_DIRS} - ${ECORE_EVAS_INCLUDE_DIRS} - ${EVAS_INCLUDE_DIRS} - ${Glib_INCLUDE_DIRS} - ${ICU_INCLUDE_DIRS} - ${JAVASCRIPTCORE_DIR}/wtf/gobject - ${JAVASCRIPTCORE_DIR}/wtf/unicode/ -) diff --git a/Source/JavaScriptCore/wtf/PlatformWinCE.cmake b/Source/JavaScriptCore/wtf/PlatformWinCE.cmake deleted file mode 100644 index c34c5e5a5..000000000 --- a/Source/JavaScriptCore/wtf/PlatformWinCE.cmake +++ /dev/null @@ -1,26 +0,0 @@ -LIST(APPEND WTF_HEADERS - unicode/wince/UnicodeWinCE.h - - ${3RDPARTY_DIR}/ce-compat/ce_time.h - ${3RDPARTY_DIR}/ce-compat/ce_unicode.h -) - -LIST(APPEND WTF_SOURCES - NullPtr.cpp - OSAllocatorWin.cpp - ThreadingWin.cpp - ThreadSpecificWin.cpp - - unicode/CollatorDefault.cpp - unicode/wince/UnicodeWinCE.cpp - - win/MainThreadWin.cpp - win/OwnPtrWin.cpp - - ${3RDPARTY_DIR}/ce-compat/ce_time.c - ${3RDPARTY_DIR}/ce-compat/ce_unicode.cpp -) - -LIST(APPEND WTF_LIBRARIES - mmtimer -) diff --git a/Source/JavaScriptCore/wtf/PossiblyNull.h b/Source/JavaScriptCore/wtf/PossiblyNull.h deleted file mode 100644 index 46a7d713b..000000000 --- a/Source/JavaScriptCore/wtf/PossiblyNull.h +++ /dev/null @@ -1,59 +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. - */ - -#ifndef PossiblyNull_h -#define PossiblyNull_h - -#include <wtf/Assertions.h> - -namespace WTF { - -template <typename T> struct PossiblyNull { - PossiblyNull(T data) - : m_data(data) - { - } - PossiblyNull(const PossiblyNull<T>& source) - : m_data(source.m_data) - { - source.m_data = 0; - } - ~PossiblyNull() { ASSERT(!m_data); } - bool getValue(T& out) WARN_UNUSED_RETURN; -private: - mutable T m_data; -}; - -template <typename T> bool PossiblyNull<T>::getValue(T& out) -{ - out = m_data; - bool result = !!m_data; - m_data = 0; - return result; -} - -} - -#endif diff --git a/Source/JavaScriptCore/wtf/RandomNumber.cpp b/Source/JavaScriptCore/wtf/RandomNumber.cpp deleted file mode 100644 index 06074ed9f..000000000 --- a/Source/JavaScriptCore/wtf/RandomNumber.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * - * 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 "RandomNumber.h" - -#include "CryptographicallyRandomNumber.h" -#include "RandomNumberSeed.h" - -#include <limits> -#include <limits.h> -#include <stdint.h> -#include <stdlib.h> - -#if USE(MERSENNE_TWISTER_19937) -extern "C" { -#include "mt19937ar.c" -} -#endif - -namespace WTF { - -double randomNumber() -{ -#if USE(OS_RANDOMNESS) - uint32_t bits = cryptographicallyRandomNumber(); - return static_cast<double>(bits) / (static_cast<double>(std::numeric_limits<uint32_t>::max()) + 1.0); -#else - // Without OS_RANDOMNESS, we fall back to other random number generators - // that might not be cryptographically secure. Ideally, most ports would - // define USE(OS_RANDOMNESS). - -#if USE(MERSENNE_TWISTER_19937) - return genrand_res53(); -#else - uint32_t part1 = rand() & (RAND_MAX - 1); - uint32_t part2 = rand() & (RAND_MAX - 1); - // rand only provides 31 bits, and the low order bits of that aren't very random - // so we take the high 26 bits of part 1, and the high 27 bits of part2. - part1 >>= 5; // drop the low 5 bits - part2 >>= 4; // drop the low 4 bits - uint64_t fullRandom = part1; - fullRandom <<= 27; - fullRandom |= part2; - - // Mask off the low 53bits - fullRandom &= (1LL << 53) - 1; - return static_cast<double>(fullRandom)/static_cast<double>(1LL << 53); -#endif -#endif -} - -} diff --git a/Source/JavaScriptCore/wtf/RandomNumber.h b/Source/JavaScriptCore/wtf/RandomNumber.h deleted file mode 100644 index 76b223582..000000000 --- a/Source/JavaScriptCore/wtf/RandomNumber.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * - * 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 WTF_RandomNumber_h -#define WTF_RandomNumber_h - -namespace WTF { - - // Returns a pseudo-random number in the range [0, 1), attempts to be - // cryptographically secure if possible on the target platform - WTF_EXPORT_PRIVATE double randomNumber(); - -} - -using WTF::randomNumber; - -#endif diff --git a/Source/JavaScriptCore/wtf/RandomNumberSeed.h b/Source/JavaScriptCore/wtf/RandomNumberSeed.h deleted file mode 100644 index b5547becb..000000000 --- a/Source/JavaScriptCore/wtf/RandomNumberSeed.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) - * - * 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 WTF_RandomNumberSeed_h -#define WTF_RandomNumberSeed_h - -#include <stdlib.h> -#include <time.h> - -#if HAVE(SYS_TIME_H) -#include <sys/time.h> -#endif - -#if OS(UNIX) -#include <sys/types.h> -#include <unistd.h> -#endif - -#if USE(MERSENNE_TWISTER_19937) -extern "C" { -void init_by_array(unsigned long init_key[],int key_length); -} -#endif - -// Internal JavaScriptCore usage only -namespace WTF { - -inline void initializeRandomNumberGenerator() -{ -#if OS(DARWIN) - // On Darwin we use arc4random which initialises itself. -#elif OS(WINCE) - // initialize rand() - srand(GetTickCount()); -#elif COMPILER(MSVC) && defined(_CRT_RAND_S) - // On Windows we use rand_s which initialises itself -#elif OS(UNIX) - // srandomdev is not guaranteed to exist on linux so we use this poor seed, this should be improved - timeval time; - gettimeofday(&time, 0); - srandom(static_cast<unsigned>(time.tv_usec * getpid())); -#else - srand(static_cast<unsigned>(time(0))); -#endif - -#if USE(MERSENNE_TWISTER_19937) - // use rand() to initialize the Mersenne Twister random number generator. - unsigned long initializationBuffer[4]; - initializationBuffer[0] = (rand() << 16) | rand(); - initializationBuffer[1] = (rand() << 16) | rand(); - initializationBuffer[2] = (rand() << 16) | rand(); - initializationBuffer[3] = (rand() << 16) | rand(); - init_by_array(initializationBuffer, 4); -#endif -} - -} - -#endif diff --git a/Source/JavaScriptCore/wtf/RedBlackTree.h b/Source/JavaScriptCore/wtf/RedBlackTree.h deleted file mode 100644 index 19460c141..000000000 --- a/Source/JavaScriptCore/wtf/RedBlackTree.h +++ /dev/null @@ -1,574 +0,0 @@ -/* - * Copyright (C) 2010, 2011 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 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 RedBlackTree_h -#define RedBlackTree_h - -#include <wtf/Assertions.h> -#include <wtf/Noncopyable.h> - -namespace WTF { - -// This implements a red-black tree with the following properties: -// - The allocation of nodes in the tree is entirely up to the user. -// - If you are in possession of a pointer to a node, you can delete -// it from the tree. The tree will subsequently no longer have a -// reference to this node. -// - The key type must implement operator< and ==. - -template<class NodeType, typename KeyType> -class RedBlackTree { - WTF_MAKE_NONCOPYABLE(RedBlackTree); -private: - enum Color { - Red = 1, - Black - }; - -public: - class Node { - friend class RedBlackTree; - - public: - const NodeType* successor() const - { - const Node* x = this; - if (x->right()) - return treeMinimum(x->right()); - const NodeType* y = x->parent(); - while (y && x == y->right()) { - x = y; - y = y->parent(); - } - return y; - } - - const NodeType* predecessor() const - { - const Node* x = this; - if (x->left()) - return treeMaximum(x->left()); - const NodeType* y = x->parent(); - while (y && x == y->left()) { - x = y; - y = y->parent(); - } - return y; - } - - NodeType* successor() - { - return const_cast<NodeType*>(const_cast<const Node*>(this)->successor()); - } - - NodeType* predecessor() - { - return const_cast<NodeType*>(const_cast<const Node*>(this)->predecessor()); - } - - private: - void reset() - { - m_left = 0; - m_right = 0; - m_parentAndRed = 1; // initialize to red - } - - // NOTE: these methods should pack the parent and red into a single - // word. But doing so appears to reveal a bug in the compiler. - NodeType* parent() const - { - return reinterpret_cast<NodeType*>(m_parentAndRed & ~static_cast<uintptr_t>(1)); - } - - void setParent(NodeType* newParent) - { - m_parentAndRed = reinterpret_cast<uintptr_t>(newParent) | (m_parentAndRed & 1); - } - - NodeType* left() const - { - return m_left; - } - - void setLeft(NodeType* node) - { - m_left = node; - } - - NodeType* right() const - { - return m_right; - } - - void setRight(NodeType* node) - { - m_right = node; - } - - Color color() const - { - if (m_parentAndRed & 1) - return Red; - return Black; - } - - void setColor(Color value) - { - if (value == Red) - m_parentAndRed |= 1; - else - m_parentAndRed &= ~static_cast<uintptr_t>(1); - } - - NodeType* m_left; - NodeType* m_right; - uintptr_t m_parentAndRed; - }; - - RedBlackTree() - : m_root(0) - { - } - - void insert(NodeType* x) - { - x->reset(); - treeInsert(x); - x->setColor(Red); - - while (x != m_root && x->parent()->color() == Red) { - if (x->parent() == x->parent()->parent()->left()) { - NodeType* y = x->parent()->parent()->right(); - if (y && y->color() == Red) { - // Case 1 - x->parent()->setColor(Black); - y->setColor(Black); - x->parent()->parent()->setColor(Red); - x = x->parent()->parent(); - } else { - if (x == x->parent()->right()) { - // Case 2 - x = x->parent(); - leftRotate(x); - } - // Case 3 - x->parent()->setColor(Black); - x->parent()->parent()->setColor(Red); - rightRotate(x->parent()->parent()); - } - } else { - // Same as "then" clause with "right" and "left" exchanged. - NodeType* y = x->parent()->parent()->left(); - if (y && y->color() == Red) { - // Case 1 - x->parent()->setColor(Black); - y->setColor(Black); - x->parent()->parent()->setColor(Red); - x = x->parent()->parent(); - } else { - if (x == x->parent()->left()) { - // Case 2 - x = x->parent(); - rightRotate(x); - } - // Case 3 - x->parent()->setColor(Black); - x->parent()->parent()->setColor(Red); - leftRotate(x->parent()->parent()); - } - } - } - - m_root->setColor(Black); - } - - NodeType* remove(NodeType* z) - { - ASSERT(z); - ASSERT(z->parent() || z == m_root); - - // Y is the node to be unlinked from the tree. - NodeType* y; - if (!z->left() || !z->right()) - y = z; - else - y = z->successor(); - - // Y is guaranteed to be non-null at this point. - NodeType* x; - if (y->left()) - x = y->left(); - else - x = y->right(); - - // X is the child of y which might potentially replace y in - // the tree. X might be null at this point. - NodeType* xParent; - if (x) { - x->setParent(y->parent()); - xParent = x->parent(); - } else - xParent = y->parent(); - if (!y->parent()) - m_root = x; - else { - if (y == y->parent()->left()) - y->parent()->setLeft(x); - else - y->parent()->setRight(x); - } - - if (y != z) { - if (y->color() == Black) - removeFixup(x, xParent); - - y->setParent(z->parent()); - y->setColor(z->color()); - y->setLeft(z->left()); - y->setRight(z->right()); - - if (z->left()) - z->left()->setParent(y); - if (z->right()) - z->right()->setParent(y); - if (z->parent()) { - if (z->parent()->left() == z) - z->parent()->setLeft(y); - else - z->parent()->setRight(y); - } else { - ASSERT(m_root == z); - m_root = y; - } - } else if (y->color() == Black) - removeFixup(x, xParent); - - return z; - } - - NodeType* remove(const KeyType& key) - { - NodeType* result = findExact(key); - if (!result) - return 0; - return remove(result); - } - - NodeType* findExact(const KeyType& key) const - { - for (NodeType* current = m_root; current;) { - if (current->key() == key) - return current; - if (key < current->key()) - current = current->left(); - else - current = current->right(); - } - return 0; - } - - NodeType* findLeastGreaterThanOrEqual(const KeyType& key) const - { - NodeType* best = 0; - for (NodeType* current = m_root; current;) { - if (current->key() == key) - return current; - if (current->key() < key) - current = current->right(); - else { - best = current; - current = current->left(); - } - } - return best; - } - - NodeType* findGreatestLessThanOrEqual(const KeyType& key) const - { - NodeType* best = 0; - for (NodeType* current = m_root; current;) { - if (current->key() == key) - return current; - if (current->key() > key) - current = current->left(); - else { - best = current; - current = current->right(); - } - } - return best; - } - - NodeType* first() const - { - if (!m_root) - return 0; - return treeMinimum(m_root); - } - - NodeType* last() const - { - if (!m_root) - return 0; - return treeMaximum(m_root); - } - - // This is an O(n) operation. - size_t size() - { - size_t result = 0; - for (NodeType* current = first(); current; current = current->successor()) - result++; - return result; - } - - // This is an O(1) operation. - bool isEmpty() - { - return !m_root; - } - -private: - // Finds the minimum element in the sub-tree rooted at the given - // node. - static NodeType* treeMinimum(NodeType* x) - { - while (x->left()) - x = x->left(); - return x; - } - - static NodeType* treeMaximum(NodeType* x) - { - while (x->right()) - x = x->right(); - return x; - } - - static const NodeType* treeMinimum(const NodeType* x) - { - while (x->left()) - x = x->left(); - return x; - } - - static const NodeType* treeMaximum(const NodeType* x) - { - while (x->right()) - x = x->right(); - return x; - } - - void treeInsert(NodeType* z) - { - ASSERT(!z->left()); - ASSERT(!z->right()); - ASSERT(!z->parent()); - ASSERT(z->color() == Red); - - NodeType* y = 0; - NodeType* x = m_root; - while (x) { - y = x; - if (z->key() < x->key()) - x = x->left(); - else - x = x->right(); - } - z->setParent(y); - if (!y) - m_root = z; - else { - if (z->key() < y->key()) - y->setLeft(z); - else - y->setRight(z); - } - } - - //---------------------------------------------------------------------- - // Red-Black tree operations - // - - // Left-rotates the subtree rooted at x. - // Returns the new root of the subtree (x's right child). - NodeType* leftRotate(NodeType* x) - { - // Set y. - NodeType* y = x->right(); - - // Turn y's left subtree into x's right subtree. - x->setRight(y->left()); - if (y->left()) - y->left()->setParent(x); - - // Link x's parent to y. - y->setParent(x->parent()); - if (!x->parent()) - m_root = y; - else { - if (x == x->parent()->left()) - x->parent()->setLeft(y); - else - x->parent()->setRight(y); - } - - // Put x on y's left. - y->setLeft(x); - x->setParent(y); - - return y; - } - - // Right-rotates the subtree rooted at y. - // Returns the new root of the subtree (y's left child). - NodeType* rightRotate(NodeType* y) - { - // Set x. - NodeType* x = y->left(); - - // Turn x's right subtree into y's left subtree. - y->setLeft(x->right()); - if (x->right()) - x->right()->setParent(y); - - // Link y's parent to x. - x->setParent(y->parent()); - if (!y->parent()) - m_root = x; - else { - if (y == y->parent()->left()) - y->parent()->setLeft(x); - else - y->parent()->setRight(x); - } - - // Put y on x's right. - x->setRight(y); - y->setParent(x); - - return x; - } - - // Restores the red-black property to the tree after splicing out - // a node. Note that x may be null, which is why xParent must be - // supplied. - void removeFixup(NodeType* x, NodeType* xParent) - { - while (x != m_root && (!x || x->color() == Black)) { - if (x == xParent->left()) { - // Note: the text points out that w can not be null. - // The reason is not obvious from simply looking at - // the code; it comes about from the properties of the - // red-black tree. - NodeType* w = xParent->right(); - ASSERT(w); // x's sibling should not be null. - if (w->color() == Red) { - // Case 1 - w->setColor(Black); - xParent->setColor(Red); - leftRotate(xParent); - w = xParent->right(); - } - if ((!w->left() || w->left()->color() == Black) - && (!w->right() || w->right()->color() == Black)) { - // Case 2 - w->setColor(Red); - x = xParent; - xParent = x->parent(); - } else { - if (!w->right() || w->right()->color() == Black) { - // Case 3 - w->left()->setColor(Black); - w->setColor(Red); - rightRotate(w); - w = xParent->right(); - } - // Case 4 - w->setColor(xParent->color()); - xParent->setColor(Black); - if (w->right()) - w->right()->setColor(Black); - leftRotate(xParent); - x = m_root; - xParent = x->parent(); - } - } else { - // Same as "then" clause with "right" and "left" - // exchanged. - - // Note: the text points out that w can not be null. - // The reason is not obvious from simply looking at - // the code; it comes about from the properties of the - // red-black tree. - NodeType* w = xParent->left(); - ASSERT(w); // x's sibling should not be null. - if (w->color() == Red) { - // Case 1 - w->setColor(Black); - xParent->setColor(Red); - rightRotate(xParent); - w = xParent->left(); - } - if ((!w->right() || w->right()->color() == Black) - && (!w->left() || w->left()->color() == Black)) { - // Case 2 - w->setColor(Red); - x = xParent; - xParent = x->parent(); - } else { - if (!w->left() || w->left()->color() == Black) { - // Case 3 - w->right()->setColor(Black); - w->setColor(Red); - leftRotate(w); - w = xParent->left(); - } - // Case 4 - w->setColor(xParent->color()); - xParent->setColor(Black); - if (w->left()) - w->left()->setColor(Black); - rightRotate(xParent); - x = m_root; - xParent = x->parent(); - } - } - } - if (x) - x->setColor(Black); - } - - NodeType* m_root; -}; - -} - -#endif - diff --git a/Source/JavaScriptCore/wtf/RefCounted.h b/Source/JavaScriptCore/wtf/RefCounted.h deleted file mode 100644 index cea1434e1..000000000 --- a/Source/JavaScriptCore/wtf/RefCounted.h +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef RefCounted_h -#define RefCounted_h - -#include <wtf/Assertions.h> -#include <wtf/FastAllocBase.h> -#include <wtf/Noncopyable.h> -#include <wtf/OwnPtr.h> -#include <wtf/ThreadRestrictionVerifier.h> -#include <wtf/UnusedParam.h> - -namespace WTF { - -// This base class holds the non-template methods and attributes. -// The RefCounted class inherits from it reducing the template bloat -// generated by the compiler (technique called template hoisting). -class RefCountedBase { -public: - void ref() - { -#ifndef NDEBUG - // Start thread verification as soon as the ref count gets to 2. This - // heuristic reflects the fact that items are often created on one thread - // and then given to another thread to be used. - // FIXME: Make this restriction tigher. Especially as we move to more - // common methods for sharing items across threads like CrossThreadCopier.h - // We should be able to add a "detachFromThread" method to make this explicit. - if (m_refCount == 1) - m_verifier.setShared(true); -#endif - // If this assert fires, it either indicates a thread safety issue or - // that the verification needs to change. See ThreadRestrictionVerifier for - // the different modes. - ASSERT(m_verifier.isSafeToUse()); - ASSERT(!m_deletionHasBegun); - ASSERT(!m_adoptionIsRequired); - ++m_refCount; - } - - bool hasOneRef() const - { - ASSERT(m_verifier.isSafeToUse()); - ASSERT(!m_deletionHasBegun); - return m_refCount == 1; - } - - int refCount() const - { - ASSERT(m_verifier.isSafeToUse()); - return m_refCount; - } - - void setMutexForVerifier(Mutex&); - -#if HAVE(DISPATCH_H) - void setDispatchQueueForVerifier(dispatch_queue_t); -#endif - - // Turns off verification. Use of this method is discouraged (instead extend - // ThreadRestrictionVerifier to verify your case). - // NB. It is necessary to call this in the constructor of many objects in - // JavaScriptCore, because JavaScriptCore objects may be used from multiple - // threads even if the reference counting is done in a racy manner. This is - // because a JSC instance may be used from multiple threads so long as all - // accesses into that instance are protected by a per-instance lock. It would - // be absolutely wrong to prohibit this pattern, and it would be a disastrous - // regression to require that the objects within that instance use a thread- - // safe version of reference counting. - void turnOffVerifier() - { -#ifndef NDEBUG - m_verifier.turnOffVerification(); -#endif - } - - void relaxAdoptionRequirement() - { -#ifndef NDEBUG - ASSERT(!m_deletionHasBegun); - ASSERT(m_adoptionIsRequired); - m_adoptionIsRequired = false; -#endif - } - - // Helper for generating JIT code. Please do not use for non-JIT purposes. - const int* addressOfCount() const - { - return &m_refCount; - } - -protected: - RefCountedBase() - : m_refCount(1) -#ifndef NDEBUG - , m_deletionHasBegun(false) - , m_adoptionIsRequired(true) -#endif - { - } - - ~RefCountedBase() - { - ASSERT(m_deletionHasBegun); - ASSERT(!m_adoptionIsRequired); - } - - // Returns whether the pointer should be freed or not. - bool derefBase() - { - ASSERT(m_verifier.isSafeToUse()); - ASSERT(!m_deletionHasBegun); - ASSERT(!m_adoptionIsRequired); - - ASSERT(m_refCount > 0); - if (m_refCount == 1) { -#ifndef NDEBUG - m_deletionHasBegun = true; -#endif - return true; - } - - --m_refCount; -#ifndef NDEBUG - // Stop thread verification when the ref goes to 1 because it - // is safe to be passed to another thread at this point. - if (m_refCount == 1) - m_verifier.setShared(false); -#endif - return false; - } - -#ifndef NDEBUG - bool deletionHasBegun() const - { - return m_deletionHasBegun; - } -#endif - -private: - -#ifndef NDEBUG - friend void adopted(RefCountedBase*); -#endif - - int m_refCount; -#ifndef NDEBUG - bool m_deletionHasBegun; - bool m_adoptionIsRequired; - ThreadRestrictionVerifier m_verifier; -#endif -}; - -#ifndef NDEBUG - -inline void adopted(RefCountedBase* object) -{ - if (!object) - return; - ASSERT(!object->m_deletionHasBegun); - object->m_adoptionIsRequired = false; -} - -#endif - -template<typename T> class RefCounted : public RefCountedBase { - WTF_MAKE_NONCOPYABLE(RefCounted); WTF_MAKE_FAST_ALLOCATED; -public: - void deref() - { - if (derefBase()) - delete static_cast<T*>(this); - } - -protected: - RefCounted() { } - ~RefCounted() - { - } -}; - -template<typename T> class RefCountedCustomAllocated : public RefCountedBase { - WTF_MAKE_NONCOPYABLE(RefCountedCustomAllocated); - -public: - void deref() - { - if (derefBase()) - delete static_cast<T*>(this); - } - -protected: - ~RefCountedCustomAllocated() - { - } -}; - -#ifdef NDEBUG -inline void RefCountedBase::setMutexForVerifier(Mutex&) { } -#else -inline void RefCountedBase::setMutexForVerifier(Mutex& mutex) -{ - m_verifier.setMutexMode(mutex); -} -#endif - -#if HAVE(DISPATCH_H) -#ifdef NDEBUG -inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t) { } -#else -inline void RefCountedBase::setDispatchQueueForVerifier(dispatch_queue_t queue) -{ - m_verifier.setDispatchQueueMode(queue); -} -#endif // NDEBUG -#endif // HAVE(DISPATCH_H) - -} // namespace WTF - -using WTF::RefCounted; -using WTF::RefCountedCustomAllocated; - -#endif // RefCounted_h diff --git a/Source/JavaScriptCore/wtf/RefCountedArray.h b/Source/JavaScriptCore/wtf/RefCountedArray.h deleted file mode 100644 index 2610a69b8..000000000 --- a/Source/JavaScriptCore/wtf/RefCountedArray.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2011 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 RefCountedArray_h -#define RefCountedArray_h - -#include <wtf/FastMalloc.h> -#include <wtf/StdLibExtras.h> -#include <wtf/Vector.h> - -// This implements a reference counted array for POD** values, which is optimized for: -// - An empty array only uses one word. -// - A copy of the array only uses one word (i.e. assignment means aliasing). -// - The vector can't grow beyond 2^32-1 elements. -// - In all other regards this has similar space usage to a Vector. -// -// ** This could be modified to support non-POD values quite easily. It just -// hasn't been, so far, because there has been no need. Moreover, even now, -// it's used for things that aren't quite POD according to the official -// defintion, such as JSC::Instruction. - -namespace WTF { - -template<typename T> -class RefCountedArray { -public: - RefCountedArray() - : m_data(0) - { - } - - RefCountedArray(const RefCountedArray& other) - : m_data(other.m_data) - { - if (m_data) - Header::fromPayload(m_data)->refCount++; - } - - explicit RefCountedArray(const Vector<T>& other) - { - if (other.isEmpty()) { - m_data = 0; - return; - } - - m_data = (static_cast<Header*>(fastMalloc(Header::size() + sizeof(T) * other.size())))->payload(); - Header::fromPayload(m_data)->refCount = 1; - Header::fromPayload(m_data)->length = other.size(); - ASSERT(Header::fromPayload(m_data)->length == other.size()); - memcpy(m_data, other.begin(), sizeof(T) * other.size()); - } - - RefCountedArray& operator=(const RefCountedArray& other) - { - T* oldData = m_data; - m_data = other.m_data; - if (m_data) - Header::fromPayload(m_data)->refCount++; - - if (!oldData) - return *this; - if (--Header::fromPayload(oldData)->refCount) - return *this; - fastFree(Header::fromPayload(oldData)); - return *this; - } - - ~RefCountedArray() - { - if (!m_data) - return; - if (--Header::fromPayload(m_data)->refCount) - return; - fastFree(Header::fromPayload(m_data)); - } - - size_t size() const - { - if (!m_data) - return 0; - return Header::fromPayload(m_data)->length; - } - - T* data() { return m_data; } - T* begin() { return m_data; } - T* end() - { - if (!m_data) - return 0; - return m_data + Header::fromPayload(m_data)->length; - } - - const T* data() const { return m_data; } - const T* begin() const { return m_data; } - const T* end() const { return const_cast<RefCountedArray*>(this)->end(); } - - T& at(size_t i) - { - ASSERT(i < size()); - return begin()[i]; - } - - const T& at(size_t i) const - { - ASSERT(i < size()); - return begin()[i]; - } - - T& operator[](size_t i) { return at(i); } - const T& operator[](size_t i) const { return at(i); } - -private: - struct Header { - unsigned refCount; - unsigned length; - - static size_t size() - { - return (sizeof(Header) + 7) & ~7; - } - - T* payload() - { - char* result = reinterpret_cast<char*>(this) + size(); - ASSERT(!(bitwise_cast<uintptr_t>(result) & 7)); - return reinterpret_cast<T*>(result); - } - - static Header* fromPayload(T* payload) - { - return reinterpret_cast_ptr<Header*>(reinterpret_cast<char*>(payload) - size()); - } - }; - - T* m_data; -}; - -} // namespace WTF - -using WTF::RefCountedArray; - -#endif // RefCountedArray_h - diff --git a/Source/JavaScriptCore/wtf/RefCountedLeakCounter.cpp b/Source/JavaScriptCore/wtf/RefCountedLeakCounter.cpp deleted file mode 100644 index 670f2a0ce..000000000 --- a/Source/JavaScriptCore/wtf/RefCountedLeakCounter.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 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" -#include "RefCountedLeakCounter.h" - -#include <wtf/HashCountedSet.h> - -namespace WTF { - -#ifdef NDEBUG - -void RefCountedLeakCounter::suppressMessages(const char*) { } -void RefCountedLeakCounter::cancelMessageSuppression(const char*) { } - -RefCountedLeakCounter::RefCountedLeakCounter(const char*) { } -RefCountedLeakCounter::~RefCountedLeakCounter() { } - -void RefCountedLeakCounter::increment() { } -void RefCountedLeakCounter::decrement() { } - -#else - -#define LOG_CHANNEL_PREFIX Log -static WTFLogChannel LogRefCountedLeaks = { 0x00000000, "", WTFLogChannelOn }; - -typedef HashCountedSet<const char*, PtrHash<const char*> > ReasonSet; -static ReasonSet* leakMessageSuppressionReasons; - -void RefCountedLeakCounter::suppressMessages(const char* reason) -{ - if (!leakMessageSuppressionReasons) - leakMessageSuppressionReasons = new ReasonSet; - leakMessageSuppressionReasons->add(reason); -} - -void RefCountedLeakCounter::cancelMessageSuppression(const char* reason) -{ - ASSERT(leakMessageSuppressionReasons); - ASSERT(leakMessageSuppressionReasons->contains(reason)); - leakMessageSuppressionReasons->remove(reason); -} - -RefCountedLeakCounter::RefCountedLeakCounter(const char* description) - : m_description(description) -{ -} - -RefCountedLeakCounter::~RefCountedLeakCounter() -{ - static bool loggedSuppressionReason; - if (m_count) { - if (!leakMessageSuppressionReasons || leakMessageSuppressionReasons->isEmpty()) - LOG(RefCountedLeaks, "LEAK: %u %s", m_count, m_description); - else if (!loggedSuppressionReason) { - // This logs only one reason. Later we could change it so we log all the reasons. - LOG(RefCountedLeaks, "No leak checking done: %s", leakMessageSuppressionReasons->begin()->first); - loggedSuppressionReason = true; - } - } -} - -void RefCountedLeakCounter::increment() -{ - atomicIncrement(&m_count); -} - -void RefCountedLeakCounter::decrement() -{ - atomicDecrement(&m_count); -} - -#endif - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h b/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h deleted file mode 100644 index 8d894dd91..000000000 --- a/Source/JavaScriptCore/wtf/RefCountedLeakCounter.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 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 RefCountedLeakCounter_h -#define RefCountedLeakCounter_h - -#include <wtf/Assertions.h> -#include <wtf/Threading.h> - -namespace WTF { - - struct RefCountedLeakCounter { - WTF_EXPORT_PRIVATE static void suppressMessages(const char*); - WTF_EXPORT_PRIVATE static void cancelMessageSuppression(const char*); - - WTF_EXPORT_PRIVATE explicit RefCountedLeakCounter(const char* description); - WTF_EXPORT_PRIVATE ~RefCountedLeakCounter(); - - WTF_EXPORT_PRIVATE void increment(); - WTF_EXPORT_PRIVATE void decrement(); - -#ifndef NDEBUG - private: -#if COMPILER(MINGW) || COMPILER(MSVC7_OR_LOWER) || OS(WINCE) - int m_count; -#else - volatile int m_count; -#endif - const char* m_description; -#endif - }; - -} // namespace WTF - -#endif diff --git a/Source/JavaScriptCore/wtf/RefPtr.h b/Source/JavaScriptCore/wtf/RefPtr.h deleted file mode 100644 index 70ab60003..000000000 --- a/Source/JavaScriptCore/wtf/RefPtr.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -// RefPtr and PassRefPtr are documented at http://webkit.org/coding/RefPtr.html - -#ifndef WTF_RefPtr_h -#define WTF_RefPtr_h - -#include <algorithm> -#include <wtf/FastAllocBase.h> -#include <wtf/PassRefPtr.h> - -namespace WTF { - - enum PlacementNewAdoptType { PlacementNewAdopt }; - - template<typename T> class PassRefPtr; - template<typename T> class NonNullPassRefPtr; - - enum HashTableDeletedValueType { HashTableDeletedValue }; - - template<typename T> class RefPtr { - WTF_MAKE_FAST_ALLOCATED; - public: - ALWAYS_INLINE RefPtr() : m_ptr(0) { } - ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); } - ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); } - template<typename U> RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); } - - // See comments in PassRefPtr.h for an explanation of why these takes const references. - template<typename U> RefPtr(const PassRefPtr<U>&); - template<typename U> RefPtr(const NonNullPassRefPtr<U>&); - - // Special constructor for cases where we overwrite an object in place. - ALWAYS_INLINE RefPtr(PlacementNewAdoptType) { } - - // Hash table deleted values, which are only constructed and never copied or destroyed. - RefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } - bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } - - ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); } - - T* get() const { return m_ptr; } - - void clear(); - PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; } - - T& operator*() const { return *m_ptr; } - ALWAYS_INLINE T* operator->() const { 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* (RefPtr::*UnspecifiedBoolType); - operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; } - - RefPtr& operator=(const RefPtr&); - RefPtr& operator=(T*); - RefPtr& operator=(const PassRefPtr<T>&); - RefPtr& operator=(const NonNullPassRefPtr<T>&); -#if !COMPILER_SUPPORTS(CXX_NULLPTR) - RefPtr& operator=(std::nullptr_t) { clear(); return *this; } -#endif - template<typename U> RefPtr& operator=(const RefPtr<U>&); - template<typename U> RefPtr& operator=(const PassRefPtr<U>&); - template<typename U> RefPtr& operator=(const NonNullPassRefPtr<U>&); - - void swap(RefPtr&); - - static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } - - private: - T* m_ptr; - }; - - template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o) - : m_ptr(o.leakRef()) - { - } - - template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const NonNullPassRefPtr<U>& o) - : m_ptr(o.leakRef()) - { - } - - template<typename T> inline void RefPtr<T>::clear() - { - T* ptr = m_ptr; - m_ptr = 0; - derefIfNotNull(ptr); - } - - template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o) - { - T* optr = o.get(); - refIfNotNull(optr); - T* ptr = m_ptr; - m_ptr = optr; - derefIfNotNull(ptr); - return *this; - } - - template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o) - { - T* optr = o.get(); - refIfNotNull(optr); - T* ptr = m_ptr; - m_ptr = optr; - derefIfNotNull(ptr); - return *this; - } - - template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr) - { - refIfNotNull(optr); - T* ptr = m_ptr; - m_ptr = optr; - derefIfNotNull(ptr); - return *this; - } - - template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o) - { - T* ptr = m_ptr; - m_ptr = o.leakRef(); - derefIfNotNull(ptr); - return *this; - } - - template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<T>& o) - { - T* ptr = m_ptr; - m_ptr = o.leakRef(); - derefIfNotNull(ptr); - return *this; - } - - template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o) - { - T* ptr = m_ptr; - m_ptr = o.leakRef(); - derefIfNotNull(ptr); - return *this; - } - - template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const NonNullPassRefPtr<U>& o) - { - T* ptr = m_ptr; - m_ptr = o.leakRef(); - derefIfNotNull(ptr); - return *this; - } - - template<class T> inline void RefPtr<T>::swap(RefPtr<T>& o) - { - std::swap(m_ptr, o.m_ptr); - } - - template<class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b) - { - a.swap(b); - } - - template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b) - { - return a.get() == b.get(); - } - - template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b) - { - return a.get() == b; - } - - template<typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b) - { - return a == b.get(); - } - - template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b) - { - return a.get() != b.get(); - } - - template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b) - { - return a.get() != b; - } - - template<typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b) - { - return a != b.get(); - } - - template<typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p) - { - return RefPtr<T>(static_cast<T*>(p.get())); - } - - template<typename T, typename U> inline RefPtr<T> const_pointer_cast(const RefPtr<U>& p) - { - return RefPtr<T>(const_cast<T*>(p.get())); - } - - template<typename T> inline T* getPtr(const RefPtr<T>& p) - { - return p.get(); - } - -} // namespace WTF - -using WTF::RefPtr; -using WTF::static_pointer_cast; -using WTF::const_pointer_cast; - -#endif // WTF_RefPtr_h diff --git a/Source/JavaScriptCore/wtf/RefPtrHashMap.h b/Source/JavaScriptCore/wtf/RefPtrHashMap.h deleted file mode 100644 index f48a59cf6..000000000 --- a/Source/JavaScriptCore/wtf/RefPtrHashMap.h +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2011 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 RefPtrHashMap_h -#define RefPtrHashMap_h - -namespace WTF { - - // This specialization is a copy of HashMap for use with RefPtr keys, with overloaded functions - // to allow for lookup by pointer instead of RefPtr, avoiding ref-count churn. - - // FIXME: Find a way to do this with traits that doesn't require a copy of the HashMap template. - - template<typename T, typename MappedArg, typename HashArg, typename KeyTraitsArg, typename MappedTraitsArg> - class HashMap<RefPtr<T>, MappedArg, HashArg, KeyTraitsArg, MappedTraitsArg> { - WTF_MAKE_FAST_ALLOCATED; - private: - typedef KeyTraitsArg KeyTraits; - typedef MappedTraitsArg MappedTraits; - typedef PairHashTraits<KeyTraits, MappedTraits> ValueTraits; - - public: - typedef typename KeyTraits::TraitType KeyType; - typedef T* RawKeyType; - typedef typename MappedTraits::TraitType MappedType; - typedef typename ValueTraits::TraitType ValueType; - - private: - typedef typename MappedTraits::PassInType MappedPassInType; - typedef typename MappedTraits::PassOutType MappedPassOutType; - typedef typename MappedTraits::PeekType MappedPeekType; - - typedef typename ReferenceTypeMaker<MappedPassInType>::ReferenceType MappedPassInReferenceType; - - typedef HashArg HashFunctions; - - typedef HashTable<KeyType, ValueType, PairFirstExtractor<ValueType>, - HashFunctions, ValueTraits, KeyTraits> HashTableType; - - typedef HashMapTranslator<ValueTraits, HashFunctions> - Translator; - - public: - typedef HashTableIteratorAdapter<HashTableType, ValueType> iterator; - typedef HashTableConstIteratorAdapter<HashTableType, ValueType> const_iterator; - - void swap(HashMap&); - - int size() const; - int capacity() const; - bool isEmpty() const; - - // iterators iterate over pairs of keys and values - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; - - iterator find(const KeyType&); - iterator find(RawKeyType); - const_iterator find(const KeyType&) const; - const_iterator find(RawKeyType) const; - bool contains(const KeyType&) const; - bool contains(RawKeyType) const; - MappedPeekType get(const KeyType&) const; - MappedPeekType get(RawKeyType) const; - MappedPeekType inlineGet(RawKeyType) const; - - // replaces value but not key if key is already present - // return value is a pair of the iterator to the key location, - // and a boolean that's true if a new value was actually added - pair<iterator, bool> set(const KeyType&, MappedPassInType); - pair<iterator, bool> set(RawKeyType, MappedPassInType); - - // does nothing if key is already present - // return value is a pair of the iterator to the key location, - // and a boolean that's true if a new value was actually added - pair<iterator, bool> add(const KeyType&, MappedPassInType); - pair<iterator, bool> add(RawKeyType, MappedPassInType); - - void remove(const KeyType&); - void remove(RawKeyType); - void remove(iterator); - void clear(); - - MappedPassOutType take(const KeyType&); // efficient combination of get with remove - MappedPassOutType take(RawKeyType); // efficient combination of get with remove - - private: - pair<iterator, bool> inlineAdd(const KeyType&, MappedPassInReferenceType); - pair<iterator, bool> inlineAdd(RawKeyType, MappedPassInReferenceType); - - HashTableType m_impl; - }; - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<RefPtr<T>, U, V, W, X>::swap(HashMap& other) - { - m_impl.swap(other.m_impl); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline int HashMap<RefPtr<T>, U, V, W, X>::size() const - { - return m_impl.size(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline int HashMap<RefPtr<T>, U, V, W, X>::capacity() const - { - return m_impl.capacity(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline bool HashMap<RefPtr<T>, U, V, W, X>::isEmpty() const - { - return m_impl.isEmpty(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::begin() - { - return m_impl.begin(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::end() - { - return m_impl.end(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::begin() const - { - return m_impl.begin(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::end() const - { - return m_impl.end(); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key) - { - return m_impl.find(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<RefPtr<T>, U, V, W, X>::iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key) - { - return m_impl.template find<Translator>(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(const KeyType& key) const - { - return m_impl.find(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline typename HashMap<RefPtr<T>, U, V, W, X>::const_iterator HashMap<RefPtr<T>, U, V, W, X>::find(RawKeyType key) const - { - return m_impl.template find<Translator>(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(const KeyType& key) const - { - return m_impl.contains(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline bool HashMap<RefPtr<T>, U, V, W, X>::contains(RawKeyType key) const - { - return m_impl.template contains<Translator>(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool> - HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(const KeyType& key, MappedPassInReferenceType mapped) - { - return m_impl.template add<Translator>(key, mapped); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool> - HashMap<RefPtr<T>, U, V, W, X>::inlineAdd(RawKeyType key, MappedPassInReferenceType mapped) - { - return m_impl.template add<Translator>(key, mapped); - } - - template<typename T, typename U, typename V, typename W, typename X> - pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool> - HashMap<RefPtr<T>, U, V, W, X>::set(const KeyType& key, MappedPassInType mapped) - { - pair<iterator, bool> result = inlineAdd(key, mapped); - if (!result.second) { - // The inlineAdd call above found an existing hash table entry; we need to set the mapped value. - MappedTraits::store(mapped, result.first->second); - } - return result; - } - - template<typename T, typename U, typename V, typename W, typename X> - pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool> - HashMap<RefPtr<T>, U, V, W, X>::set(RawKeyType key, MappedPassInType mapped) - { - pair<iterator, bool> result = inlineAdd(key, mapped); - if (!result.second) { - // The inlineAdd call above found an existing hash table entry; we need to set the mapped value. - MappedTraits::store(mapped, result.first->second); - } - return result; - } - - template<typename T, typename U, typename V, typename W, typename X> - pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool> - HashMap<RefPtr<T>, U, V, W, X>::add(const KeyType& key, MappedPassInType mapped) - { - return inlineAdd(key, mapped); - } - - template<typename T, typename U, typename V, typename W, typename X> - pair<typename HashMap<RefPtr<T>, U, V, W, X>::iterator, bool> - HashMap<RefPtr<T>, U, V, W, X>::add(RawKeyType key, MappedPassInType mapped) - { - return inlineAdd(key, mapped); - } - - template<typename T, typename U, typename V, typename W, typename MappedTraits> - typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedPeekType - HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(const KeyType& key) const - { - ValueType* entry = const_cast<HashTableType&>(m_impl).lookup(key); - if (!entry) - return MappedTraits::peek(MappedTraits::emptyValue()); - return MappedTraits::peek(entry->second); - } - - template<typename T, typename U, typename V, typename W, typename MappedTraits> - typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedPeekType - inline HashMap<RefPtr<T>, U, V, W, MappedTraits>::inlineGet(RawKeyType key) const - { - ValueType* entry = const_cast<HashTableType&>(m_impl).template lookup<Translator>(key); - if (!entry) - return MappedTraits::peek(MappedTraits::emptyValue()); - return MappedTraits::peek(entry->second); - } - - template<typename T, typename U, typename V, typename W, typename MappedTraits> - typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedPeekType - HashMap<RefPtr<T>, U, V, W, MappedTraits>::get(RawKeyType key) const - { - return inlineGet(key); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<RefPtr<T>, U, V, W, X>::remove(iterator it) - { - if (it.m_impl == m_impl.end()) - return; - m_impl.internalCheckTableConsistency(); - m_impl.removeWithoutEntryConsistencyCheck(it.m_impl); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<RefPtr<T>, U, V, W, X>::remove(const KeyType& key) - { - remove(find(key)); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<RefPtr<T>, U, V, W, X>::remove(RawKeyType key) - { - remove(find(key)); - } - - template<typename T, typename U, typename V, typename W, typename X> - inline void HashMap<RefPtr<T>, U, V, W, X>::clear() - { - m_impl.clear(); - } - - template<typename T, typename U, typename V, typename W, typename MappedTraits> - typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedPassOutType - HashMap<RefPtr<T>, U, V, W, MappedTraits>::take(const KeyType& key) - { - iterator it = find(key); - if (it == end()) - return MappedTraits::passOut(MappedTraits::emptyValue()); - MappedPassOutType result = MappedTraits::passOut(it->second); - remove(it); - return result; - } - - template<typename T, typename U, typename V, typename W, typename MappedTraits> - typename HashMap<RefPtr<T>, U, V, W, MappedTraits>::MappedPassOutType - HashMap<RefPtr<T>, U, V, W, MappedTraits>::take(RawKeyType key) - { - iterator it = find(key); - if (it == end()) - return MappedTraits::passOut(MappedTraits::emptyValue()); - MappedPassOutType result = MappedTraits::passOut(it->second); - remove(it); - return result; - } - -} // namespace WTF - -#endif // RefPtrHashMap_h diff --git a/Source/JavaScriptCore/wtf/RetainPtr.h b/Source/JavaScriptCore/wtf/RetainPtr.h deleted file mode 100644 index a3489577a..000000000 --- a/Source/JavaScriptCore/wtf/RetainPtr.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef RetainPtr_h -#define RetainPtr_h - -#include <wtf/HashTraits.h> -#include <wtf/NullPtr.h> -#include <wtf/TypeTraits.h> -#include <algorithm> - -#if USE(CF) -#include <CoreFoundation/CoreFoundation.h> -#endif - -#ifdef __OBJC__ -#import <Foundation/Foundation.h> -#endif - -namespace WTF { - - // Unlike most most of our smart pointers, RetainPtr can take either the pointer type or the pointed-to type, - // so both RetainPtr<NSDictionary> and RetainPtr<CFDictionaryRef> will work. - - enum AdoptCFTag { AdoptCF }; - enum AdoptNSTag { AdoptNS }; - -#ifdef __OBJC__ - inline void adoptNSReference(id ptr) - { - if (ptr) { - CFRetain(ptr); - [ptr release]; - } - } -#endif - - template<typename T> class RetainPtr { - public: - typedef typename RemovePointer<T>::Type ValueType; - typedef ValueType* PtrType; - - RetainPtr() : m_ptr(0) {} - RetainPtr(PtrType ptr) : m_ptr(ptr) { if (ptr) CFRetain(ptr); } - - RetainPtr(AdoptCFTag, PtrType ptr) : m_ptr(ptr) { } - RetainPtr(AdoptNSTag, PtrType ptr) : m_ptr(ptr) { adoptNSReference(ptr); } - - RetainPtr(const RetainPtr& o) : m_ptr(o.m_ptr) { if (PtrType ptr = m_ptr) CFRetain(ptr); } - -#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) - RetainPtr(RetainPtr&& o) : m_ptr(o.leakRef()) { } -#endif - - // Hash table deleted values, which are only constructed and never copied or destroyed. - RetainPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } - bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } - - ~RetainPtr() { if (PtrType ptr = m_ptr) CFRelease(ptr); } - - template<typename U> RetainPtr(const RetainPtr<U>&); - - PtrType get() const { return m_ptr; } - - void clear(); - PtrType leakRef() WARN_UNUSED_RETURN; - - PtrType operator->() const { return m_ptr; } - - bool operator!() const { return !m_ptr; } - - // This conversion operator allows implicit conversion to bool but not to other integer types. - typedef PtrType RetainPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &RetainPtr::m_ptr : 0; } - - RetainPtr& operator=(const RetainPtr&); - template<typename U> RetainPtr& operator=(const RetainPtr<U>&); - RetainPtr& operator=(PtrType); - template<typename U> RetainPtr& operator=(U*); - -#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) - RetainPtr& operator=(RetainPtr&&); - template<typename U> RetainPtr& operator=(RetainPtr<U>&&); -#endif - -#if !COMPILER_SUPPORTS(CXX_NULLPTR) - RetainPtr& operator=(std::nullptr_t) { clear(); return *this; } -#endif - - void adoptCF(PtrType); - void adoptNS(PtrType); - - void swap(RetainPtr&); - - private: - static PtrType hashTableDeletedValue() { return reinterpret_cast<PtrType>(-1); } - - PtrType m_ptr; - }; - - template<typename T> template<typename U> inline RetainPtr<T>::RetainPtr(const RetainPtr<U>& o) - : m_ptr(o.get()) - { - if (PtrType ptr = m_ptr) - CFRetain(ptr); - } - - template<typename T> inline void RetainPtr<T>::clear() - { - if (PtrType ptr = m_ptr) { - m_ptr = 0; - CFRelease(ptr); - } - } - - template<typename T> inline typename RetainPtr<T>::PtrType RetainPtr<T>::leakRef() - { - PtrType ptr = m_ptr; - m_ptr = 0; - return ptr; - } - - template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<T>& o) - { - PtrType optr = o.get(); - if (optr) - CFRetain(optr); - PtrType ptr = m_ptr; - m_ptr = optr; - if (ptr) - CFRelease(ptr); - return *this; - } - - template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(const RetainPtr<U>& o) - { - PtrType optr = o.get(); - if (optr) - CFRetain(optr); - PtrType ptr = m_ptr; - m_ptr = optr; - if (ptr) - CFRelease(ptr); - return *this; - } - - template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(PtrType optr) - { - if (optr) - CFRetain(optr); - PtrType ptr = m_ptr; - m_ptr = optr; - if (ptr) - CFRelease(ptr); - return *this; - } - - template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(U* optr) - { - if (optr) - CFRetain(optr); - PtrType ptr = m_ptr; - m_ptr = optr; - if (ptr) - CFRelease(ptr); - return *this; - } - -#if COMPILER_SUPPORTS(CXX_RVALUE_REFERENCES) - template<typename T> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<T>&& o) - { - adoptCF(o.leakRef()); - return *this; - } - - template<typename T> template<typename U> inline RetainPtr<T>& RetainPtr<T>::operator=(RetainPtr<U>&& o) - { - adoptCF(o.leakRef()); - return *this; - } -#endif - - template<typename T> inline void RetainPtr<T>::adoptCF(PtrType optr) - { - PtrType ptr = m_ptr; - m_ptr = optr; - if (ptr) - CFRelease(ptr); - } - - template<typename T> inline void RetainPtr<T>::adoptNS(PtrType optr) - { - adoptNSReference(optr); - - PtrType ptr = m_ptr; - m_ptr = optr; - if (ptr) - CFRelease(ptr); - } - - template<typename T> inline void RetainPtr<T>::swap(RetainPtr<T>& o) - { - std::swap(m_ptr, o.m_ptr); - } - - template<typename T> inline void swap(RetainPtr<T>& a, RetainPtr<T>& b) - { - a.swap(b); - } - - template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, const RetainPtr<U>& b) - { - return a.get() == b.get(); - } - - template<typename T, typename U> inline bool operator==(const RetainPtr<T>& a, U* b) - { - return a.get() == b; - } - - template<typename T, typename U> inline bool operator==(T* a, const RetainPtr<U>& b) - { - return a == b.get(); - } - - template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, const RetainPtr<U>& b) - { - return a.get() != b.get(); - } - - template<typename T, typename U> inline bool operator!=(const RetainPtr<T>& a, U* b) - { - return a.get() != b; - } - - template<typename T, typename U> inline bool operator!=(T* a, const RetainPtr<U>& b) - { - return a != b.get(); - } - - template<typename T> inline RetainPtr<T> adoptCF(T) WARN_UNUSED_RETURN; - template<typename T> inline RetainPtr<T> adoptCF(T o) - { - return RetainPtr<T>(AdoptCF, o); - } - - template<typename T> inline RetainPtr<T> adoptNS(T) WARN_UNUSED_RETURN; - template<typename T> inline RetainPtr<T> adoptNS(T o) - { - return RetainPtr<T>(AdoptNS, o); - } - - // Helper function for creating a RetainPtr using template argument deduction. - template<typename T> inline RetainPtr<T> retainPtr(T) WARN_UNUSED_RETURN; - template<typename T> inline RetainPtr<T> retainPtr(T o) - { - return RetainPtr<T>(o); - } - - template<typename P> struct HashTraits<RetainPtr<P> > : SimpleClassHashTraits<RetainPtr<P> > { }; - - template<typename P> struct PtrHash<RetainPtr<P> > : PtrHash<typename RetainPtr<P>::PtrType> { - using PtrHash<typename RetainPtr<P>::PtrType>::hash; - static unsigned hash(const RetainPtr<P>& key) { return hash(key.get()); } - using PtrHash<typename RetainPtr<P>::PtrType>::equal; - static bool equal(const RetainPtr<P>& a, const RetainPtr<P>& b) { return a == b; } - static bool equal(typename RetainPtr<P>::PtrType a, const RetainPtr<P>& b) { return a == b; } - static bool equal(const RetainPtr<P>& a, typename RetainPtr<P>::PtrType b) { return a == b; } - }; - - template<typename P> struct DefaultHash<RetainPtr<P> > { typedef PtrHash<RetainPtr<P> > Hash; }; - -} // namespace WTF - -using WTF::AdoptCF; -using WTF::AdoptNS; -using WTF::adoptCF; -using WTF::adoptNS; -using WTF::RetainPtr; -using WTF::retainPtr; - -#endif // WTF_RetainPtr_h diff --git a/Source/JavaScriptCore/wtf/SHA1.cpp b/Source/JavaScriptCore/wtf/SHA1.cpp deleted file mode 100644 index e76f6ac38..000000000 --- a/Source/JavaScriptCore/wtf/SHA1.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -// A straightforward SHA-1 implementation based on RFC 3174. -// http://www.ietf.org/rfc/rfc3174.txt -// The names of functions and variables (such as "a", "b", and "f") follow notations in RFC 3174. - -#include "config.h" -#include "SHA1.h" - -#include "Assertions.h" -#ifndef NDEBUG -#include "StringExtras.h" -#include "text/CString.h" -#endif - -namespace WTF { - -#ifdef NDEBUG -static inline void testSHA1() { } -#else -static bool isTestSHA1Done; - -static void expectSHA1(CString input, int repeat, CString expected) -{ - SHA1 sha1; - for (int i = 0; i < repeat; ++i) - sha1.addBytes(reinterpret_cast<const uint8_t*>(input.data()), input.length()); - Vector<uint8_t, 20> digest; - sha1.computeHash(digest); - char* buffer = 0; - CString actual = CString::newUninitialized(40, buffer); - for (size_t i = 0; i < 20; ++i) { - snprintf(buffer, 3, "%02X", digest.at(i)); - buffer += 2; - } - ASSERT_WITH_MESSAGE(actual == expected, "input: %s, repeat: %d, actual: %s, expected: %s", input.data(), repeat, actual.data(), expected.data()); -} - -static void testSHA1() -{ - if (isTestSHA1Done) - return; - isTestSHA1Done = true; - - // Examples taken from sample code in RFC 3174. - expectSHA1("abc", 1, "A9993E364706816ABA3E25717850C26C9CD0D89D"); - expectSHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 1, "84983E441C3BD26EBAAE4AA1F95129E5E54670F1"); - expectSHA1("a", 1000000, "34AA973CD4C4DAA4F61EEB2BDBAD27316534016F"); - expectSHA1("0123456701234567012345670123456701234567012345670123456701234567", 10, "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452"); -} -#endif - -static inline uint32_t f(int t, uint32_t b, uint32_t c, uint32_t d) -{ - ASSERT(t >= 0 && t < 80); - if (t < 20) - return (b & c) | ((~b) & d); - if (t < 40) - return b ^ c ^ d; - if (t < 60) - return (b & c) | (b & d) | (c & d); - return b ^ c ^ d; -} - -static inline uint32_t k(int t) -{ - ASSERT(t >= 0 && t < 80); - if (t < 20) - return 0x5a827999; - if (t < 40) - return 0x6ed9eba1; - if (t < 60) - return 0x8f1bbcdc; - return 0xca62c1d6; -} - -static inline uint32_t rotateLeft(int n, uint32_t x) -{ - ASSERT(n >= 0 && n < 32); - return (x << n) | (x >> (32 - n)); -} - -SHA1::SHA1() -{ - // FIXME: Move unit tests somewhere outside the constructor. See bug 55853. - testSHA1(); - reset(); -} - -void SHA1::addBytes(const uint8_t* input, size_t length) -{ - while (length--) { - ASSERT(m_cursor < 64); - m_buffer[m_cursor++] = *input++; - ++m_totalBytes; - if (m_cursor == 64) - processBlock(); - } -} - -void SHA1::computeHash(Vector<uint8_t, 20>& digest) -{ - finalize(); - - digest.clear(); - digest.resize(20); - for (size_t i = 0; i < 5; ++i) { - // Treat hashValue as a big-endian value. - uint32_t hashValue = m_hash[i]; - for (int j = 0; j < 4; ++j) { - digest[4 * i + (3 - j)] = hashValue & 0xFF; - hashValue >>= 8; - } - } - - reset(); -} - -void SHA1::finalize() -{ - ASSERT(m_cursor < 64); - m_buffer[m_cursor++] = 0x80; - if (m_cursor > 56) { - // Pad out to next block. - while (m_cursor < 64) - m_buffer[m_cursor++] = 0x00; - processBlock(); - } - - for (size_t i = m_cursor; i < 56; ++i) - m_buffer[i] = 0x00; - - // Write the length as a big-endian 64-bit value. - uint64_t bits = m_totalBytes * 8; - for (int i = 0; i < 8; ++i) { - m_buffer[56 + (7 - i)] = bits & 0xFF; - bits >>= 8; - } - m_cursor = 64; - processBlock(); -} - -void SHA1::processBlock() -{ - ASSERT(m_cursor == 64); - - uint32_t w[80] = { 0 }; - for (int t = 0; t < 16; ++t) - w[t] = (m_buffer[t * 4] << 24) | (m_buffer[t * 4 + 1] << 16) | (m_buffer[t * 4 + 2] << 8) | m_buffer[t * 4 + 3]; - for (int t = 16; t < 80; ++t) - w[t] = rotateLeft(1, w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16]); - - uint32_t a = m_hash[0]; - uint32_t b = m_hash[1]; - uint32_t c = m_hash[2]; - uint32_t d = m_hash[3]; - uint32_t e = m_hash[4]; - - for (int t = 0; t < 80; ++t) { - uint32_t temp = rotateLeft(5, a) + f(t, b, c, d) + e + w[t] + k(t); - e = d; - d = c; - c = rotateLeft(30, b); - b = a; - a = temp; - } - - m_hash[0] += a; - m_hash[1] += b; - m_hash[2] += c; - m_hash[3] += d; - m_hash[4] += e; - - m_cursor = 0; -} - -void SHA1::reset() -{ - m_cursor = 0; - m_totalBytes = 0; - m_hash[0] = 0x67452301; - m_hash[1] = 0xefcdab89; - m_hash[2] = 0x98badcfe; - m_hash[3] = 0x10325476; - m_hash[4] = 0xc3d2e1f0; - - // Clear the buffer after use in case it's sensitive. - memset(m_buffer, 0, sizeof(m_buffer)); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/SHA1.h b/Source/JavaScriptCore/wtf/SHA1.h deleted file mode 100644 index e8cc802e9..000000000 --- a/Source/JavaScriptCore/wtf/SHA1.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef WTF_SHA1_h -#define WTF_SHA1_h - -#include <wtf/Vector.h> - -namespace WTF { - -class SHA1 { -public: - WTF_EXPORT_PRIVATE SHA1(); - - void addBytes(const Vector<uint8_t>& input) - { - addBytes(input.data(), input.size()); - } - WTF_EXPORT_PRIVATE void addBytes(const uint8_t* input, size_t length); - - // computeHash has a side effect of resetting the state of the object. - WTF_EXPORT_PRIVATE void computeHash(Vector<uint8_t, 20>&); - -private: - void finalize(); - void processBlock(); - void reset(); - - uint8_t m_buffer[64]; - size_t m_cursor; // Number of bytes filled in m_buffer (0-64). - uint64_t m_totalBytes; // Number of bytes added so far. - uint32_t m_hash[5]; -}; - -} // namespace WTF - -using WTF::SHA1; - -#endif // WTF_SHA1_h diff --git a/Source/JavaScriptCore/wtf/SegmentedVector.h b/Source/JavaScriptCore/wtf/SegmentedVector.h deleted file mode 100644 index cb9a5f3a8..000000000 --- a/Source/JavaScriptCore/wtf/SegmentedVector.h +++ /dev/null @@ -1,255 +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. - * 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 SegmentedVector_h -#define SegmentedVector_h - -#include <wtf/Vector.h> - -namespace WTF { - - // An iterator for SegmentedVector. It supports only the pre ++ operator - template <typename T, size_t SegmentSize> class SegmentedVector; - template <typename T, size_t SegmentSize> class SegmentedVectorIterator { - private: - friend class SegmentedVector<T, SegmentSize>; - public: - typedef SegmentedVectorIterator<T, SegmentSize> Iterator; - - ~SegmentedVectorIterator() { } - - T& operator*() const { return m_vector.m_segments.at(m_segment)->at(m_index); } - T* operator->() const { return &m_vector.m_segments.at(m_segment)->at(m_index); } - - // Only prefix ++ operator supported - Iterator& operator++() - { - ASSERT(m_index != SegmentSize); - ++m_index; - if (m_index >= m_vector.m_segments.at(m_segment)->size()) { - if (m_segment + 1 < m_vector.m_segments.size()) { - ASSERT(m_vector.m_segments.at(m_segment)->size() > 0); - ++m_segment; - m_index = 0; - } else { - // Points to the "end" symbol - m_segment = 0; - m_index = SegmentSize; - } - } - return *this; - } - - bool operator==(const Iterator& other) const - { - return m_index == other.m_index && m_segment == other.m_segment && &m_vector == &other.m_vector; - } - - bool operator!=(const Iterator& other) const - { - return m_index != other.m_index || m_segment != other.m_segment || &m_vector != &other.m_vector; - } - - SegmentedVectorIterator& operator=(const SegmentedVectorIterator<T, SegmentSize>& other) - { - m_vector = other.m_vector; - m_segment = other.m_segment; - m_index = other.m_index; - return *this; - } - - private: - SegmentedVectorIterator(SegmentedVector<T, SegmentSize>& vector, size_t segment, size_t index) - : m_vector(vector) - , m_segment(segment) - , m_index(index) - { - } - - SegmentedVector<T, SegmentSize>& m_vector; - size_t m_segment; - size_t m_index; - }; - - // SegmentedVector is just like Vector, but it doesn't move the values - // stored in its buffer when it grows. Therefore, it is safe to keep - // pointers into a SegmentedVector. - template <typename T, size_t SegmentSize> class SegmentedVector { - friend class SegmentedVectorIterator<T, SegmentSize>; - public: - typedef SegmentedVectorIterator<T, SegmentSize> Iterator; - - SegmentedVector() - : m_size(0) - { - m_segments.append(&m_inlineSegment); - } - - ~SegmentedVector() - { - deleteAllSegments(); - } - - size_t size() const { return m_size; } - bool isEmpty() const { return !size(); } - - T& at(size_t index) - { - if (index < SegmentSize) - return m_inlineSegment[index]; - return segmentFor(index)->at(subscriptFor(index)); - } - - T& operator[](size_t index) - { - return at(index); - } - - T& last() - { - return at(size() - 1); - } - - template <typename U> void append(const U& value) - { - ++m_size; - - if (m_size <= SegmentSize) { - m_inlineSegment.uncheckedAppend(value); - return; - } - - if (!segmentExistsFor(m_size - 1)) - m_segments.append(new Segment); - segmentFor(m_size - 1)->uncheckedAppend(value); - } - - T& alloc() - { - append<T>(T()); - return last(); - } - - void removeLast() - { - if (m_size <= SegmentSize) - m_inlineSegment.removeLast(); - else - segmentFor(m_size - 1)->removeLast(); - --m_size; - } - - void grow(size_t size) - { - ASSERT(size > m_size); - ensureSegmentsFor(size); - m_size = size; - } - - void clear() - { - deleteAllSegments(); - m_segments.resize(1); - m_inlineSegment.clear(); - m_size = 0; - } - - Iterator begin() - { - return Iterator(*this, 0, m_size ? 0 : SegmentSize); - } - - Iterator end() - { - return Iterator(*this, 0, SegmentSize); - } - - private: - typedef Vector<T, SegmentSize> Segment; - - void deleteAllSegments() - { - // Skip the first segment, because it's our inline segment, which was - // not created by new. - for (size_t i = 1; i < m_segments.size(); i++) - delete m_segments[i]; - } - - bool segmentExistsFor(size_t index) - { - return index / SegmentSize < m_segments.size(); - } - - Segment* segmentFor(size_t index) - { - return m_segments[index / SegmentSize]; - } - - size_t subscriptFor(size_t index) - { - return index % SegmentSize; - } - - void ensureSegmentsFor(size_t size) - { - size_t segmentCount = m_size / SegmentSize; - if (m_size % SegmentSize) - ++segmentCount; - segmentCount = std::max<size_t>(segmentCount, 1); // We always have at least our inline segment. - - size_t neededSegmentCount = size / SegmentSize; - if (size % SegmentSize) - ++neededSegmentCount; - - // Fill up to N - 1 segments. - size_t end = neededSegmentCount - 1; - for (size_t i = segmentCount - 1; i < end; ++i) - ensureSegment(i, SegmentSize); - - // Grow segment N to accomodate the remainder. - ensureSegment(end, subscriptFor(size - 1) + 1); - } - - void ensureSegment(size_t segmentIndex, size_t size) - { - ASSERT(segmentIndex <= m_segments.size()); - if (segmentIndex == m_segments.size()) - m_segments.append(new Segment); - m_segments[segmentIndex]->grow(size); - } - - size_t m_size; - Segment m_inlineSegment; - Vector<Segment*, 32> m_segments; - }; - -} // namespace WTF - -using WTF::SegmentedVector; - -#endif // SegmentedVector_h diff --git a/Source/JavaScriptCore/wtf/SentinelLinkedList.h b/Source/JavaScriptCore/wtf/SentinelLinkedList.h deleted file mode 100644 index 3943aa5de..000000000 --- a/Source/JavaScriptCore/wtf/SentinelLinkedList.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2011 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. - */ - -// A SentinelLinkedList is a linked list with dummy head and tail sentinels, -// which allow for branch-less insertion and removal, and removal without a -// pointer to the list. -// -// Requires: Node is a concrete class with: -// Node(SentinelTag); -// void setPrev(Node*); -// Node* prev(); -// void setNext(Node*); -// Node* next(); - -#ifndef SentinelLinkedList_h -#define SentinelLinkedList_h - -namespace WTF { - -enum SentinelTag { Sentinel }; - -template<typename T> -class BasicRawSentinelNode { -public: - BasicRawSentinelNode(SentinelTag) - : m_next(0) - , m_prev(0) - { - } - - BasicRawSentinelNode() - : m_next(0) - , m_prev(0) - { - } - - void setPrev(BasicRawSentinelNode* prev) { m_prev = prev; } - void setNext(BasicRawSentinelNode* next) { m_next = next; } - - T* prev() { return static_cast<T*>(m_prev); } - T* next() { return static_cast<T*>(m_next); } - - bool isOnList() const - { - ASSERT(!!m_prev == !!m_next); - return !!m_prev; - } - - void remove(); - -private: - BasicRawSentinelNode* m_next; - BasicRawSentinelNode* m_prev; -}; - -template <typename T, typename RawNode = T> class SentinelLinkedList { -public: - typedef T* iterator; - - SentinelLinkedList(); - - void push(T*); - static void remove(T*); - - iterator begin(); - iterator end(); - - bool isEmpty() { return begin() == end(); } - -private: - RawNode m_headSentinel; - RawNode m_tailSentinel; -}; - -template <typename T> void BasicRawSentinelNode<T>::remove() -{ - SentinelLinkedList<T, BasicRawSentinelNode<T> >::remove(static_cast<T*>(this)); -} - -template <typename T, typename RawNode> inline SentinelLinkedList<T, RawNode>::SentinelLinkedList() - : m_headSentinel(Sentinel) - , m_tailSentinel(Sentinel) -{ - m_headSentinel.setNext(&m_tailSentinel); - m_headSentinel.setPrev(0); - - m_tailSentinel.setPrev(&m_headSentinel); - m_tailSentinel.setNext(0); -} - -template <typename T, typename RawNode> inline typename SentinelLinkedList<T, RawNode>::iterator SentinelLinkedList<T, RawNode>::begin() -{ - return static_cast<T*>(m_headSentinel.next()); -} - -template <typename T, typename RawNode> inline typename SentinelLinkedList<T, RawNode>::iterator SentinelLinkedList<T, RawNode>::end() -{ - return static_cast<T*>(&m_tailSentinel); -} - -template <typename T, typename RawNode> inline void SentinelLinkedList<T, RawNode>::push(T* node) -{ - ASSERT(node); - ASSERT(!node->prev()); - ASSERT(!node->next()); - - RawNode* prev = &m_headSentinel; - RawNode* next = m_headSentinel.next(); - - node->setPrev(prev); - node->setNext(next); - - prev->setNext(node); - next->setPrev(node); -} - -template <typename T, typename RawNode> inline void SentinelLinkedList<T, RawNode>::remove(T* node) -{ - ASSERT(node); - ASSERT(!!node->prev()); - ASSERT(!!node->next()); - - RawNode* prev = node->prev(); - RawNode* next = node->next(); - - prev->setNext(next); - next->setPrev(prev); - - node->setPrev(0); - node->setNext(0); -} - -} - -using WTF::BasicRawSentinelNode; -using WTF::SentinelLinkedList; - -#endif - diff --git a/Source/JavaScriptCore/wtf/SimpleStats.h b/Source/JavaScriptCore/wtf/SimpleStats.h deleted file mode 100644 index f1fd7e10a..000000000 --- a/Source/JavaScriptCore/wtf/SimpleStats.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2012 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 SimpleStats_h -#define SimpleStats_h - -#include <wtf/MathExtras.h> -#include <wtf/StdLibExtras.h> - -namespace WTF { - -// Simple and cheap way of tracking statistics if you're not worried about chopping on -// the sum of squares (i.e. the sum of squares is unlikely to exceed 2^52). -class SimpleStats { -public: - SimpleStats() - : m_count(0) - , m_sum(0) - , m_sumOfSquares(0) - { - } - - void add(double value) - { - m_count++; - m_sum += value; - m_sumOfSquares += value * value; - } - - bool operator!() const - { - return !m_count; - } - - double count() const - { - return m_count; - } - - double sum() const - { - return m_sum; - } - - double sumOfSquares() const - { - return m_sumOfSquares; - } - - double mean() const - { - return m_sum / m_count; - } - - // NB. This gives a biased variance as it divides by the number of samples rather - // than the degrees of freedom. This is fine once the count grows large, which in - // our case will happen rather quickly. - double variance() const - { - if (m_count < 2) - return 0; - - // Compute <x^2> - <x>^2 - double secondMoment = m_sumOfSquares / m_count; - double firstMoment = m_sum / m_count; - - return secondMoment - firstMoment * firstMoment; - } - - // NB. This gives a biased standard deviation. See above. - double standardDeviation() const - { - return sqrt(variance()); - } - -private: - double m_count; - double m_sum; - double m_sumOfSquares; -}; - -} // namespace WTF - -#endif // SimpleStats_h - diff --git a/Source/JavaScriptCore/wtf/SizeLimits.cpp b/Source/JavaScriptCore/wtf/SizeLimits.cpp deleted file mode 100644 index 95d9c2b1e..000000000 --- a/Source/JavaScriptCore/wtf/SizeLimits.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#include <wtf/Assertions.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/RefPtr.h> -#include <wtf/ThreadRestrictionVerifier.h> -#include <wtf/Vector.h> - -namespace WTF { - -#ifndef NDEBUG -struct SameSizeAsRefCounted { - int a; - bool b; - bool c; - ThreadRestrictionVerifier d; - // The debug version may get bigger. -}; -#else -struct SameSizeAsRefCounted { - int a; - // Don't add anything here because this should stay small. -}; -#endif - -COMPILE_ASSERT(sizeof(OwnPtr<int>) == sizeof(int*), OwnPtr_should_stay_small); -COMPILE_ASSERT(sizeof(PassRefPtr<RefCounted<int> >) == sizeof(int*), PassRefPtr_should_stay_small); -COMPILE_ASSERT(sizeof(RefCounted<int>) == sizeof(SameSizeAsRefCounted), RefCounted_should_stay_small); -COMPILE_ASSERT(sizeof(RefCountedCustomAllocated<int>) == sizeof(SameSizeAsRefCounted), RefCountedCustomAllocated_should_stay_small); -COMPILE_ASSERT(sizeof(RefPtr<RefCounted<int> >) == sizeof(int*), RefPtr_should_stay_small); -COMPILE_ASSERT(sizeof(Vector<int>) == 3 * sizeof(int*), Vector_should_stay_small); - -} diff --git a/Source/JavaScriptCore/wtf/Spectrum.h b/Source/JavaScriptCore/wtf/Spectrum.h deleted file mode 100644 index 59bc4a29a..000000000 --- a/Source/JavaScriptCore/wtf/Spectrum.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2011 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 Spectrum_h -#define Spectrum_h - -#include <wtf/HashMap.h> -#include <wtf/Vector.h> -#include <algorithm> - -namespace WTF { - -template<typename T> -class Spectrum { -public: - typedef typename HashMap<T, unsigned long>::iterator iterator; - typedef typename HashMap<T, unsigned long>::const_iterator const_iterator; - - Spectrum() { } - - void add(const T& key, unsigned long count = 1) - { - std::pair<iterator, bool> result = m_map.add(key, count); - if (!result.second) - result.first->second += count; - } - - unsigned long get(const T& key) const - { - const_iterator iter = m_map.find(key); - if (iter == m_map.end()) - return 0; - return iter->second; - } - - iterator begin() { return m_map.begin(); } - iterator end() { return m_map.end(); } - const_iterator begin() const { return m_map.begin(); } - const_iterator end() const { return m_map.end(); } - - struct KeyAndCount { - KeyAndCount() { } - - KeyAndCount(const T& key, unsigned long count) - : key(key) - , count(count) - { - } - - bool operator<(const KeyAndCount& other) const - { - if (count != other.count) - return count < other.count; - // This causes lower-ordered keys being returned first; this is really just - // here to make sure that the order is somewhat deterministic rather than being - // determined by hashing. - return key > other.key; - } - - T key; - unsigned long count; - }; - - // Returns a list ordered from lowest-count to highest-count. - Vector<KeyAndCount> buildList() const - { - Vector<KeyAndCount> list; - for (const_iterator iter = begin(); iter != end(); ++iter) - list.append(KeyAndCount(iter->first, iter->second)); - - std::sort(list.begin(), list.end()); - return list; - } - -private: - HashMap<T, unsigned long> m_map; -}; - -} // namespace WTF - -using WTF::Spectrum; - -#endif // Spectrum_h diff --git a/Source/JavaScriptCore/wtf/StackBounds.cpp b/Source/JavaScriptCore/wtf/StackBounds.cpp deleted file mode 100644 index a272ce3de..000000000 --- a/Source/JavaScriptCore/wtf/StackBounds.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU 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 "StackBounds.h" - -#if OS(DARWIN) - -#include <mach/task.h> -#include <mach/thread_act.h> -#include <pthread.h> - -#elif OS(WINDOWS) - -#include <windows.h> - -#elif OS(SOLARIS) - -#include <thread.h> - -#elif OS(QNX) - -#include <errno.h> -#include <fcntl.h> -#include <pthread.h> -#include <stdio.h> -#include <string.h> -#include <sys/procfs.h> - -#elif OS(UNIX) - -#include <pthread.h> -#if HAVE(PTHREAD_NP_H) -#include <pthread_np.h> -#endif - -#endif - -namespace WTF { - -// Bug 26276 - Need a mechanism to determine stack extent -// -// These platforms should now be working correctly: -// DARWIN, QNX, UNIX -// These platforms are not: -// WINDOWS, SOLARIS, OPENBSD, WINCE -// -// FIXME: remove this! - this code unsafely guesses at stack sizes! -#if OS(WINDOWS) || OS(SOLARIS) || OS(OPENBSD) -// Based on the current limit used by the JSC parser, guess the stack size. -static const ptrdiff_t estimatedStackSize = 128 * sizeof(void*) * 1024; -// This method assumes the stack is growing downwards. -static void* estimateStackBound(void* origin) -{ - return static_cast<char*>(origin) - estimatedStackSize; -} -#endif - -#if OS(DARWIN) - -void StackBounds::initialize() -{ - pthread_t thread = pthread_self(); - m_origin = pthread_get_stackaddr_np(thread); - m_bound = static_cast<char*>(m_origin) - pthread_get_stacksize_np(thread); -} - -#elif OS(QNX) - -void StackBounds::initialize() -{ - void* stackBase = 0; - size_t stackSize = 0; - - struct _debug_thread_info threadInfo; - memset(&threadInfo, 0, sizeof(threadInfo)); - threadInfo.tid = pthread_self(); - int fd = open("/proc/self", O_RDONLY); - if (fd == -1) { - LOG_ERROR("Unable to open /proc/self (errno: %d)", errno); - CRASH(); - } - devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0); - close(fd); - stackBase = reinterpret_cast<void*>(threadInfo.stkbase); - stackSize = threadInfo.stksize; - ASSERT(stackBase); - - m_bound = static_cast<char*>(stackBase) + 0x1000; // 4kb guard page - m_origin = static_cast<char*>(stackBase) + stackSize; -} - -#elif OS(SOLARIS) - -void StackBounds::initialize() -{ - stack_t s; - thr_stksegment(&s); - m_origin = s.ss_sp; - m_bound = estimateStackBound(m_origin); -} - -#elif OS(OPENBSD) - -void StackBounds::initialize() -{ - pthread_t thread = pthread_self(); - stack_t stack; - pthread_stackseg_np(thread, &stack); - m_origin = stack.ss_sp; - m_bound = estimateStackBound(m_origin); -} - -#elif OS(UNIX) - -void StackBounds::initialize() -{ - void* stackBase = 0; - size_t stackSize = 0; - - pthread_t thread = pthread_self(); - pthread_attr_t sattr; - pthread_attr_init(&sattr); -#if HAVE(PTHREAD_NP_H) || OS(NETBSD) - // e.g. on FreeBSD 5.4, neundorf@kde.org - pthread_attr_get_np(thread, &sattr); -#else - // FIXME: this function is non-portable; other POSIX systems may have different np alternatives - pthread_getattr_np(thread, &sattr); -#endif - int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize); - (void)rc; // FIXME: Deal with error code somehow? Seems fatal. - ASSERT(stackBase); - pthread_attr_destroy(&sattr); - m_bound = stackBase; - m_origin = static_cast<char*>(stackBase) + stackSize; -} - -#elif OS(WINCE) - -static bool detectGrowingDownward(void* previousFrame) -{ - // Find the address of this stack frame by taking the address of a local variable. - int thisFrame; - return previousFrame > &thisFrame; -} - -static inline bool isPageWritable(void* page) -{ - MEMORY_BASIC_INFORMATION memoryInformation; - DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation)); - - // return false on error, including ptr outside memory - if (result != sizeof(memoryInformation)) - return false; - - DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE); - return protect == PAGE_READWRITE - || protect == PAGE_WRITECOPY - || protect == PAGE_EXECUTE_READWRITE - || protect == PAGE_EXECUTE_WRITECOPY; -} - -static inline void* getLowerStackBound(char* currentPage, DWORD pageSize) -{ - while (currentPage > 0) { - // check for underflow - if (currentPage >= reinterpret_cast<char*>(pageSize)) - currentPage -= pageSize; - else - currentPage = 0; - - if (!isPageWritable(currentPage)) - return currentPage + pageSize; - } - - return 0; -} - -static inline void* getUpperStackBound(char* currentPage, DWORD pageSize) -{ - do { - // guaranteed to complete because isPageWritable returns false at end of memory - currentPage += pageSize; - } while (isPageWritable(currentPage)); - - return currentPage - pageSize; -} - -void StackBounds::initialize() -{ - // find the address of this stack frame by taking the address of a local variable - void* thisFrame = &thisFrame; - bool isGrowingDownward = detectGrowingDownward(thisFrame); - - SYSTEM_INFO systemInfo; - GetSystemInfo(&systemInfo); - DWORD pageSize = systemInfo.dwPageSize; - - // scan all of memory starting from this frame, and return the last writeable page found - char* currentPage = reinterpret_cast<char*>(reinterpret_cast<DWORD>(thisFrame) & ~(pageSize - 1)); - void* lowerStackBound = getLowerStackBound(currentPage, pageSize); - void* upperStackBound = getUpperStackBound(currentPage, pageSize); - - m_origin = isGrowingDownward ? upperStackBound : lowerStackBound; - m_bound = isGrowingDownward ? lowerStackBound : upperStackBound; -} - -#elif OS(WINDOWS) - -void StackBounds::initialize() -{ -#if CPU(X86) && COMPILER(MSVC) - // offset 0x18 from the FS segment register gives a pointer to - // the thread information block for the current thread - NT_TIB* pTib; - __asm { - MOV EAX, FS:[18h] - MOV pTib, EAX - } - m_origin = static_cast<void*>(pTib->StackBase); -#elif CPU(X86) && COMPILER(GCC) - // offset 0x18 from the FS segment register gives a pointer to - // the thread information block for the current thread - NT_TIB* pTib; - asm ( "movl %%fs:0x18, %0\n" - : "=r" (pTib) - ); - m_origin = static_cast<void*>(pTib->StackBase); -#elif CPU(X86_64) - PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb()); - m_origin = reinterpret_cast<void*>(pTib->StackBase); -#else -#error Need a way to get the stack bounds on this platform (Windows) -#endif - // Looks like we should be able to get pTib->StackLimit - m_bound = estimateStackBound(m_origin); -} - -#else -#error Need a way to get the stack bounds on this platform -#endif - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/StackBounds.h b/Source/JavaScriptCore/wtf/StackBounds.h deleted file mode 100644 index afce8606f..000000000 --- a/Source/JavaScriptCore/wtf/StackBounds.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * 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 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 StackBounds_h -#define StackBounds_h - -namespace WTF { - -class StackBounds { - // recursionCheck() / recursionLimit() tests (by default) - // that we are at least this far from the end of the stack. - const static size_t s_defaultAvailabilityDelta = 4096; - -public: - StackBounds() - : m_origin(0) - , m_bound(0) - { - } - - static StackBounds currentThreadStackBounds() - { - StackBounds bounds; - bounds.initialize(); - bounds.checkConsistency(); - return bounds; - } - - void* origin() const - { - ASSERT(m_origin); - return m_origin; - } - - void* current() const - { - checkConsistency(); - void* currentPosition = ¤tPosition; - return currentPosition; - } - - void* recursionLimit(size_t minAvailableDelta = s_defaultAvailabilityDelta) const - { - checkConsistency(); - return isGrowingDownward() - ? static_cast<char*>(m_bound) + minAvailableDelta - : static_cast<char*>(m_bound) - minAvailableDelta; - } - - bool recursionCheck(size_t minAvailableDelta = s_defaultAvailabilityDelta) const - { - checkConsistency(); - return isGrowingDownward() - ? current() >= recursionLimit(minAvailableDelta) - : current() <= recursionLimit(minAvailableDelta); - } - -private: - void initialize(); - - - bool isGrowingDownward() const - { - ASSERT(m_origin && m_bound); -#if OS(WINCE) - return m_origin > m_bound; -#else - return true; -#endif - } - - void checkConsistency() const - { -#if !ASSERT_DISABLED - void* currentPosition = ¤tPosition; - ASSERT(m_origin != m_bound); - ASSERT(isGrowingDownward() - ? (currentPosition < m_origin && currentPosition > m_bound) - : (currentPosition > m_origin && currentPosition < m_bound)); -#endif - } - - void* m_origin; - void* m_bound; -}; - -} // namespace WTF - -using WTF::StackBounds; - -#endif diff --git a/Source/JavaScriptCore/wtf/StaticConstructors.h b/Source/JavaScriptCore/wtf/StaticConstructors.h deleted file mode 100644 index 702c0ca5c..000000000 --- a/Source/JavaScriptCore/wtf/StaticConstructors.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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_OR_LOWER) -#define DEFINE_GLOBAL(type, name) \ - 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_OR_LOWER) -#define DEFINE_GLOBAL(type, name) \ - 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/Source/JavaScriptCore/wtf/StdLibExtras.h b/Source/JavaScriptCore/wtf/StdLibExtras.h deleted file mode 100644 index 0387e5b05..000000000 --- a/Source/JavaScriptCore/wtf/StdLibExtras.h +++ /dev/null @@ -1,305 +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 WTF_StdLibExtras_h -#define WTF_StdLibExtras_h - -#include <wtf/Assertions.h> -#include <wtf/CheckedArithmetic.h> - -// Use these to declare and define a static local variable (static T;) so that -// it is leaked so that its destructors are not called at exit. Using this -// macro also allows workarounds a compiler bug present in Apple's version of GCC 4.0.1. -#ifndef DEFINE_STATIC_LOCAL -#if COMPILER(GCC) && defined(__APPLE_CC__) && __GNUC__ == 4 && __GNUC_MINOR__ == 0 && __GNUC_PATCHLEVEL__ == 1 -#define DEFINE_STATIC_LOCAL(type, name, arguments) \ - static type* name##Ptr = new type arguments; \ - type& name = *name##Ptr -#else -#define DEFINE_STATIC_LOCAL(type, name, arguments) \ - static type& name = *new type arguments -#endif -#endif - -// Use this macro to declare and define a debug-only global variable that may have a -// non-trivial constructor and destructor. When building with clang, this will suppress -// warnings about global constructors and exit-time destructors. -#ifndef NDEBUG -#if COMPILER(CLANG) -#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \ - _Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \ - static type name arguments; \ - _Pragma("clang diagnostic pop") -#else -#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) \ - static type name arguments; -#endif // COMPILER(CLANG) -#else -#define DEFINE_DEBUG_ONLY_GLOBAL(type, name, arguments) -#endif // NDEBUG - -// OBJECT_OFFSETOF: Like the C++ offsetof macro, but you can use it with classes. -// The magic number 0x4000 is insignificant. We use it to avoid using NULL, since -// NULL can cause compiler problems, especially in cases of multiple inheritance. -#define OBJECT_OFFSETOF(class, field) (reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<class*>(0x4000)->field)) - 0x4000) - -// STRINGIZE: Can convert any value to quoted string, even expandable macros -#define STRINGIZE(exp) #exp -#define STRINGIZE_VALUE_OF(exp) STRINGIZE(exp) - -/* - * The reinterpret_cast<Type1*>([pointer to Type2]) expressions - where - * sizeof(Type1) > sizeof(Type2) - cause the following warning on ARM with GCC: - * increases required alignment of target type. - * - * An implicit or an extra static_cast<void*> bypasses the warning. - * For more info see the following bugzilla entries: - * - https://bugs.webkit.org/show_bug.cgi?id=38045 - * - http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43976 - */ -#if (CPU(ARM) || CPU(MIPS)) && COMPILER(GCC) -template<typename Type> -bool isPointerTypeAlignmentOkay(Type* ptr) -{ - return !(reinterpret_cast<intptr_t>(ptr) % __alignof__(Type)); -} - -template<typename TypePtr> -TypePtr reinterpret_cast_ptr(void* ptr) -{ - ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); - return reinterpret_cast<TypePtr>(ptr); -} - -template<typename TypePtr> -TypePtr reinterpret_cast_ptr(const void* ptr) -{ - ASSERT(isPointerTypeAlignmentOkay(reinterpret_cast<TypePtr>(ptr))); - return reinterpret_cast<TypePtr>(ptr); -} -#else -#define reinterpret_cast_ptr reinterpret_cast -#endif - -namespace WTF { - -static const size_t KB = 1024; - -inline bool isPointerAligned(void* p) -{ - return !((intptr_t)(p) & (sizeof(char*) - 1)); -} - -inline bool is8ByteAligned(void* p) -{ - return !((uintptr_t)(p) & (sizeof(double) - 1)); -} - -/* - * C++'s idea of a reinterpret_cast lacks sufficient cojones. - */ -template<typename TO, typename FROM> -inline TO bitwise_cast(FROM from) -{ - COMPILE_ASSERT(sizeof(TO) == sizeof(FROM), WTF_bitwise_cast_sizeof_casted_types_is_equal); - union { - FROM from; - TO to; - } u; - u.from = from; - return u.to; -} - -template<typename To, typename From> -inline To safeCast(From value) -{ - ASSERT(isInBounds<To>(value)); - return static_cast<To>(value); -} - -// Returns a count of the number of bits set in 'bits'. -inline size_t bitCount(unsigned bits) -{ - bits = bits - ((bits >> 1) & 0x55555555); - bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333); - return (((bits + (bits >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24; -} - -// Macro that returns a compile time constant with the length of an array, but gives an error if passed a non-array. -template<typename T, size_t Size> char (&ArrayLengthHelperFunction(T (&)[Size]))[Size]; -#define WTF_ARRAY_LENGTH(array) sizeof(::WTF::ArrayLengthHelperFunction(array)) - -// Efficient implementation that takes advantage of powers of two. -template<size_t divisor> inline size_t roundUpToMultipleOf(size_t x) -{ - COMPILE_ASSERT(divisor && !(divisor & (divisor - 1)), divisor_is_a_power_of_two); - - size_t remainderMask = divisor - 1; - return (x + remainderMask) & ~remainderMask; -} - -enum BinarySearchMode { - KeyMustBePresentInArray, - KeyMustNotBePresentInArray -}; - -// Binary search algorithm, calls extractKey on pre-sorted elements in array, -// compares result with key (KeyTypes should be comparable with '--', '<', '>'). -template<typename ArrayElementType, typename KeyType, KeyType(*extractKey)(ArrayElementType*)> -inline ArrayElementType* binarySearch(ArrayElementType* array, size_t size, KeyType key, BinarySearchMode mode = KeyMustBePresentInArray) -{ - // The array must contain at least one element (pre-condition, array does contain key). - // If the array contains only one element, no need to do the comparison. - while (size > 1) { - // Pick an element to check, half way through the array, and read the value. - int pos = (size - 1) >> 1; - KeyType val = extractKey(&array[pos]); - - // If the key matches, success! - if (val == key) - return &array[pos]; - // The item we are looking for is smaller than the item being check; reduce the value of 'size', - // chopping off the right hand half of the array. - else if (key < val) - size = pos; - // Discard all values in the left hand half of the array, up to and including the item at pos. - else { - size -= (pos + 1); - array += (pos + 1); - } - - // In case of BinarySearchMode = KeyMustBePresentInArray 'size' should never reach zero. - if (mode == KeyMustBePresentInArray) - ASSERT(size); - } - - // In case of BinarySearchMode = KeyMustBePresentInArray if we reach this point - // we've chopped down to one element, no need to check it matches - if (mode == KeyMustBePresentInArray) { - ASSERT(size == 1); - ASSERT(key == extractKey(&array[0])); - } - - return &array[0]; -} - -// Modified binary search algorithm that uses a functor. Note that this is strictly -// more powerful than the above, but results in somewhat less template specialization. -// Hence, depending on inlining heuristics, it might be slower. -template<typename ArrayElementType, typename KeyType, typename ExtractKey> -inline ArrayElementType* binarySearchWithFunctor(ArrayElementType* array, size_t size, KeyType key, BinarySearchMode mode = KeyMustBePresentInArray, const ExtractKey& extractKey = ExtractKey()) -{ - // The array must contain at least one element (pre-condition, array does contain key). - // If the array contains only one element, no need to do the comparison. - while (size > 1) { - // Pick an element to check, half way through the array, and read the value. - int pos = (size - 1) >> 1; - KeyType val = extractKey(&array[pos]); - - // If the key matches, success! - if (val == key) - return &array[pos]; - // The item we are looking for is smaller than the item being check; reduce the value of 'size', - // chopping off the right hand half of the array. - else if (key < val) - size = pos; - // Discard all values in the left hand half of the array, up to and including the item at pos. - else { - size -= (pos + 1); - array += (pos + 1); - } - - // In case of BinarySearchMode = KeyMustBePresentInArray 'size' should never reach zero. - if (mode == KeyMustBePresentInArray) - ASSERT(size); - } - - // In case of BinarySearchMode = KeyMustBePresentInArray if we reach this point - // we've chopped down to one element, no need to check it matches - if (mode == KeyMustBePresentInArray) { - ASSERT(size == 1); - ASSERT(key == extractKey(&array[0])); - } - - return &array[0]; -} - -// Modified binarySearch() algorithm designed for array-like classes that support -// operator[] but not operator+=. One example of a class that qualifies is -// SegmentedVector. -template<typename ArrayElementType, typename KeyType, KeyType(*extractKey)(ArrayElementType*), typename ArrayType> -inline ArrayElementType* genericBinarySearch(ArrayType& array, size_t size, KeyType key) -{ - // The array must contain at least one element (pre-condition, array does conatin key). - // If the array only contains one element, no need to do the comparison. - size_t offset = 0; - while (size > 1) { - // Pick an element to check, half way through the array, and read the value. - int pos = (size - 1) >> 1; - KeyType val = extractKey(&array[offset + pos]); - - // If the key matches, success! - if (val == key) - return &array[offset + pos]; - // The item we are looking for is smaller than the item being check; reduce the value of 'size', - // chopping off the right hand half of the array. - if (key < val) - size = pos; - // Discard all values in the left hand half of the array, up to and including the item at pos. - else { - size -= (pos + 1); - offset += (pos + 1); - } - - // 'size' should never reach zero. - ASSERT(size); - } - - // If we reach this point we've chopped down to one element, no need to check it matches - ASSERT(size == 1); - ASSERT(key == extractKey(&array[offset])); - return &array[offset]; -} - -} // namespace WTF - -// This version of placement new omits a 0 check. -enum NotNullTag { NotNull }; -inline void* operator new(size_t, NotNullTag, void* location) -{ - ASSERT(location); - return location; -} - -using WTF::KB; -using WTF::isPointerAligned; -using WTF::is8ByteAligned; -using WTF::binarySearch; -using WTF::bitwise_cast; -using WTF::safeCast; - -#endif // WTF_StdLibExtras_h diff --git a/Source/JavaScriptCore/wtf/StringExtras.cpp b/Source/JavaScriptCore/wtf/StringExtras.cpp deleted file mode 100644 index 1b96417c8..000000000 --- a/Source/JavaScriptCore/wtf/StringExtras.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2009 Company 100, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if COMPILER(RVCT) && __ARMCC_VERSION < 400000 - -#include "StringExtras.h" - -#include "ASCIICType.h" - -int strcasecmp(const char* s1, const char* s2) -{ - while (toASCIIUpper(*s1) == toASCIIUpper(*s2)) { - if (*s1 == '\0') - return 0; - s1++; - s2++; - } - - return toASCIIUpper(*s1) - toASCIIUpper(*s2); -} - -int strncasecmp(const char* s1, const char* s2, size_t len) -{ - while (len > 0 && toASCIIUpper(*s1) == toASCIIUpper(*s2)) { - if (*s1 == '\0') - return 0; - s1++; - s2++; - len--; - } - - if (!len) - return 0; - - return toASCIIUpper(*s1) - toASCIIUpper(*s2); -} - -#endif diff --git a/Source/JavaScriptCore/wtf/StringExtras.h b/Source/JavaScriptCore/wtf/StringExtras.h deleted file mode 100644 index 371e33bf9..000000000 --- a/Source/JavaScriptCore/wtf/StringExtras.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (C) 2006, 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 WTF_StringExtras_h -#define WTF_StringExtras_h - -#include <stdarg.h> -#include <stdio.h> -#include <string.h> - -#if HAVE(STRINGS_H) -#include <strings.h> -#endif - -#if COMPILER(MSVC) -// FIXME: why a COMPILER check instead of OS? also, these should be HAVE checks - -inline int snprintf(char* buffer, size_t count, const char* format, ...) -{ - int result; - va_list args; - va_start(args, format); - result = _vsnprintf(buffer, count, format, args); - va_end(args); - - // In the case where the string entirely filled the buffer, _vsnprintf will not - // null-terminate it, but snprintf must. - if (count > 0) - buffer[count - 1] = '\0'; - - return result; -} - -inline double wtf_vsnprintf(char* buffer, size_t count, const char* format, va_list args) -{ - int result = _vsnprintf(buffer, count, format, args); - - // In the case where the string entirely filled the buffer, _vsnprintf will not - // null-terminate it, but vsnprintf must. - if (count > 0) - buffer[count - 1] = '\0'; - - return result; -} - -// Work around a difference in Microsoft's implementation of vsnprintf, where -// vsnprintf does not null terminate the buffer. WebKit can rely on the null termination. -#define vsnprintf(buffer, count, format, args) wtf_vsnprintf(buffer, count, format, args) - -#if OS(WINCE) - -inline int strnicmp(const char* string1, const char* string2, size_t count) -{ - return _strnicmp(string1, string2, count); -} - -inline int stricmp(const char* string1, const char* string2) -{ - return _stricmp(string1, string2); -} - -inline char* strdup(const char* strSource) -{ - return _strdup(strSource); -} - -#endif - -inline int strncasecmp(const char* s1, const char* s2, size_t len) -{ - return _strnicmp(s1, s2, len); -} - -inline int strcasecmp(const char* s1, const char* s2) -{ - return _stricmp(s1, s2); -} - -#endif - -#if !HAVE(STRNSTR) - -inline char* strnstr(const char* buffer, const char* target, size_t bufferLength) -{ - size_t targetLength = strlen(target); - if (targetLength == 0) - return const_cast<char*>(buffer); - for (const char* start = buffer; *start && start + targetLength <= buffer + bufferLength; start++) { - if (*start == *target && strncmp(start + 1, target + 1, targetLength - 1) == 0) - return const_cast<char*>(start); - } - return 0; -} - -#endif - -#if COMPILER(RVCT) && __ARMCC_VERSION < 400000 - -int strcasecmp(const char* s1, const char* s2); -int strncasecmp(const char* s1, const char* s2, size_t len); - -#endif - -#endif // WTF_StringExtras_h diff --git a/Source/JavaScriptCore/wtf/StringHasher.h b/Source/JavaScriptCore/wtf/StringHasher.h deleted file mode 100644 index 714525188..000000000 --- a/Source/JavaScriptCore/wtf/StringHasher.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ -#ifndef WTF_StringHasher_h -#define WTF_StringHasher_h - -#include <wtf/unicode/Unicode.h> - -namespace WTF { - -// Golden ratio - arbitrary start value to avoid mapping all 0's to all 0's -static const unsigned stringHashingStartValue = 0x9e3779b9U; - -// Paul Hsieh's SuperFastHash -// http://www.azillionmonkeys.com/qed/hash.html -// char* data is interpreted as latin-encoded (zero extended to 16 bits). - -// NOTE: This class must stay in sync with the create_hash_table script in -// JavaScriptCore and the CodeGeneratorJS.pm script in WebCore. -class StringHasher { -public: - static const unsigned flagCount = 8; // Save 8 bits for StringImpl to use as flags. - - inline StringHasher() - : m_hash(stringHashingStartValue) - , m_hasPendingCharacter(false) - , m_pendingCharacter(0) - { - } - - inline void addCharacters(UChar a, UChar b) - { - ASSERT(!m_hasPendingCharacter); - addCharactersToHash(a, b); - } - - inline void addCharacter(UChar ch) - { - if (m_hasPendingCharacter) { - addCharactersToHash(m_pendingCharacter, ch); - m_hasPendingCharacter = false; - return; - } - - m_pendingCharacter = ch; - m_hasPendingCharacter = true; - } - - inline unsigned hash() const - { - unsigned result = m_hash; - - // Handle end case. - if (m_hasPendingCharacter) { - result += m_pendingCharacter; - result ^= result << 11; - result += result >> 17; - } - - // Force "avalanching" of final 31 bits. - result ^= result << 3; - result += result >> 5; - result ^= result << 2; - result += result >> 15; - result ^= result << 10; - - // Reserving space from the high bits for flags preserves most of the hash's - // value, since hash lookup typically masks out the high bits anyway. - result &= (1u << (sizeof(result) * 8 - flagCount)) - 1; - - // This avoids ever returning a hash code of 0, since that is used to - // signal "hash not computed yet". Setting the high bit maintains - // reasonable fidelity to a hash code of 0 because it is likely to yield - // exactly 0 when hash lookup masks out the high bits. - if (!result) - result = 0x80000000 >> flagCount; - - return result; - } - - template<typename T, UChar Converter(T)> static inline unsigned computeHash(const T* data, unsigned length) - { - StringHasher hasher; - bool rem = length & 1; - length >>= 1; - - while (length--) { - hasher.addCharacters(Converter(data[0]), Converter(data[1])); - data += 2; - } - - if (rem) - hasher.addCharacter(Converter(*data)); - - return hasher.hash(); - } - - template<typename T, UChar Converter(T)> static inline unsigned computeHash(const T* data) - { - StringHasher hasher; - - while (true) { - UChar b0 = Converter(*data++); - if (!b0) - break; - UChar b1 = Converter(*data++); - if (!b1) { - hasher.addCharacter(b0); - break; - } - - hasher.addCharacters(b0, b1); - } - - return hasher.hash(); - } - - template<typename T> static inline unsigned computeHash(const T* data, unsigned length) - { - return computeHash<T, defaultConverter>(data, length); - } - - template<typename T> static inline unsigned computeHash(const T* data) - { - return computeHash<T, defaultConverter>(data); - } - - template<size_t length> static inline unsigned hashMemory(const void* data) - { - COMPILE_ASSERT(!(length % 4), length_must_be_a_multible_of_four); - return computeHash<UChar>(static_cast<const UChar*>(data), length / sizeof(UChar)); - } - - static inline unsigned hashMemory(const void* data, unsigned size) - { - ASSERT(!(size % 2)); - return computeHash<UChar>(static_cast<const UChar*>(data), size / sizeof(UChar)); - } - -private: - static inline UChar defaultConverter(UChar ch) - { - return ch; - } - - static inline UChar defaultConverter(LChar ch) - { - return ch; - } - - inline void addCharactersToHash(UChar a, UChar b) - { - m_hash += a; - unsigned tmp = (b << 11) ^ m_hash; - m_hash = (m_hash << 16) ^ tmp; - m_hash += m_hash >> 11; - } - - unsigned m_hash; - bool m_hasPendingCharacter; - UChar m_pendingCharacter; -}; - -} // namespace WTF - -using WTF::StringHasher; - -#endif // WTF_StringHasher_h diff --git a/Source/JavaScriptCore/wtf/TCPackedCache.h b/Source/JavaScriptCore/wtf/TCPackedCache.h deleted file mode 100644 index 0464f8fdc..000000000 --- a/Source/JavaScriptCore/wtf/TCPackedCache.h +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Geoff Pike -// -// This file provides a minimal cache that can hold a <key, value> pair -// with little if any wasted space. The types of the key and value -// must be unsigned integral types or at least have unsigned semantics -// for >>, casting, and similar operations. -// -// Synchronization is not provided. However, the cache is implemented -// as an array of cache entries whose type is chosen at compile time. -// If a[i] is atomic on your hardware for the chosen array type then -// raciness will not necessarily lead to bugginess. The cache entries -// must be large enough to hold a partial key and a value packed -// together. The partial keys are bit strings of length -// kKeybits - kHashbits, and the values are bit strings of length kValuebits. -// -// In an effort to use minimal space, every cache entry represents -// some <key, value> pair; the class provides no way to mark a cache -// entry as empty or uninitialized. In practice, you may want to have -// reserved keys or values to get around this limitation. For example, in -// tcmalloc's PageID-to-sizeclass cache, a value of 0 is used as -// "unknown sizeclass." -// -// Usage Considerations -// -------------------- -// -// kHashbits controls the size of the cache. The best value for -// kHashbits will of course depend on the application. Perhaps try -// tuning the value of kHashbits by measuring different values on your -// favorite benchmark. Also remember not to be a pig; other -// programs that need resources may suffer if you are. -// -// The main uses for this class will be when performance is -// critical and there's a convenient type to hold the cache's -// entries. As described above, the number of bits required -// for a cache entry is (kKeybits - kHashbits) + kValuebits. Suppose -// kKeybits + kValuebits is 43. Then it probably makes sense to -// chose kHashbits >= 11 so that cache entries fit in a uint32. -// -// On the other hand, suppose kKeybits = kValuebits = 64. Then -// using this class may be less worthwhile. You'll probably -// be using 128 bits for each entry anyway, so maybe just pick -// a hash function, H, and use an array indexed by H(key): -// void Put(K key, V value) { a_[H(key)] = pair<K, V>(key, value); } -// V GetOrDefault(K key, V default) { const pair<K, V> &p = a_[H(key)]; ... } -// etc. -// -// Further Details -// --------------- -// -// For caches used only by one thread, the following is true: -// 1. For a cache c, -// (c.Put(key, value), c.GetOrDefault(key, 0)) == value -// and -// (c.Put(key, value), <...>, c.GetOrDefault(key, 0)) == value -// if the elided code contains no c.Put calls. -// -// 2. Has(key) will return false if no <key, value> pair with that key -// has ever been Put. However, a newly initialized cache will have -// some <key, value> pairs already present. When you create a new -// cache, you must specify an "initial value." The initialization -// procedure is equivalent to Clear(initial_value), which is -// equivalent to Put(k, initial_value) for all keys k from 0 to -// 2^kHashbits - 1. -// -// 3. If key and key' differ then the only way Put(key, value) may -// cause Has(key') to change is that Has(key') may change from true to -// false. Furthermore, a Put() call that doesn't change Has(key') -// doesn't change GetOrDefault(key', ...) either. -// -// Implementation details: -// -// This is a direct-mapped cache with 2^kHashbits entries; -// the hash function simply takes the low bits of the key. -// So, we don't have to store the low bits of the key in the entries. -// Instead, an entry is the high bits of a key and a value, packed -// together. E.g., a 20 bit key and a 7 bit value only require -// a uint16 for each entry if kHashbits >= 11. -// -// Alternatives to this scheme will be added as needed. - -#ifndef TCMALLOC_PACKED_CACHE_INL_H__ -#define TCMALLOC_PACKED_CACHE_INL_H__ - -#ifndef WTF_CHANGES -#include "base/basictypes.h" // for COMPILE_ASSERT -#include "base/logging.h" // for DCHECK -#endif - -#ifndef DCHECK_EQ -#define DCHECK_EQ(val1, val2) ASSERT((val1) == (val2)) -#endif - -// A safe way of doing "(1 << n) - 1" -- without worrying about overflow -// Note this will all be resolved to a constant expression at compile-time -#define N_ONES_(IntType, N) \ - ( (N) == 0 ? 0 : ((static_cast<IntType>(1) << ((N)-1))-1 + \ - (static_cast<IntType>(1) << ((N)-1))) ) - -// The types K and V provide upper bounds on the number of valid keys -// and values, but we explicitly require the keys to be less than -// 2^kKeybits and the values to be less than 2^kValuebits. The size of -// the table is controlled by kHashbits, and the type of each entry in -// the cache is T. See also the big comment at the top of the file. -template <int kKeybits, typename T> -class PackedCache { - public: - typedef uintptr_t K; - typedef size_t V; - static const size_t kHashbits = 12; - static const size_t kValuebits = 8; - - explicit PackedCache(V initial_value) { - COMPILE_ASSERT(kKeybits <= sizeof(K) * 8, key_size); - COMPILE_ASSERT(kValuebits <= sizeof(V) * 8, value_size); - COMPILE_ASSERT(kHashbits <= kKeybits, hash_function); - COMPILE_ASSERT(kKeybits - kHashbits + kValuebits <= kTbits, - entry_size_must_be_big_enough); - Clear(initial_value); - } - - void Put(K key, V value) { - DCHECK_EQ(key, key & kKeyMask); - DCHECK_EQ(value, value & kValueMask); - array_[Hash(key)] = static_cast<T>(KeyToUpper(key) | value); - } - - bool Has(K key) const { - DCHECK_EQ(key, key & kKeyMask); - return KeyMatch(array_[Hash(key)], key); - } - - V GetOrDefault(K key, V default_value) const { - // As with other code in this class, we touch array_ as few times - // as we can. Assuming entries are read atomically (e.g., their - // type is uintptr_t on most hardware) then certain races are - // harmless. - DCHECK_EQ(key, key & kKeyMask); - T entry = array_[Hash(key)]; - return KeyMatch(entry, key) ? EntryToValue(entry) : default_value; - } - - void Clear(V value) { - DCHECK_EQ(value, value & kValueMask); - for (int i = 0; i < 1 << kHashbits; i++) { - array_[i] = static_cast<T>(value); - } - } - - private: - // We are going to pack a value and the upper part of a key into - // an entry of type T. The UPPER type is for the upper part of a key, - // after the key has been masked and shifted for inclusion in an entry. - typedef T UPPER; - - static V EntryToValue(T t) { return t & kValueMask; } - - static UPPER EntryToUpper(T t) { return t & kUpperMask; } - - // If v is a V and u is an UPPER then you can create an entry by - // doing u | v. kHashbits determines where in a K to find the upper - // part of the key, and kValuebits determines where in the entry to put - // it. - static UPPER KeyToUpper(K k) { - const int shift = kHashbits - kValuebits; - // Assume kHashbits >= kValuebits. It would be easy to lift this assumption. - return static_cast<T>(k >> shift) & kUpperMask; - } - - // This is roughly the inverse of KeyToUpper(). Some of the key has been - // thrown away, since KeyToUpper() masks off the low bits of the key. - static K UpperToPartialKey(UPPER u) { - DCHECK_EQ(u, u & kUpperMask); - const int shift = kHashbits - kValuebits; - // Assume kHashbits >= kValuebits. It would be easy to lift this assumption. - return static_cast<K>(u) << shift; - } - - static size_t Hash(K key) { - return static_cast<size_t>(key) & N_ONES_(size_t, kHashbits); - } - - // Does the entry's partial key match the relevant part of the given key? - static bool KeyMatch(T entry, K key) { - return ((KeyToUpper(key) ^ entry) & kUpperMask) == 0; - } - - static const size_t kTbits = 8 * sizeof(T); - static const int kUpperbits = kKeybits - kHashbits; - - // For masking a K. - static const K kKeyMask = N_ONES_(K, kKeybits); - - // For masking a T. - static const T kUpperMask = N_ONES_(T, kUpperbits) << kValuebits; - - // For masking a V or a T. - static const V kValueMask = N_ONES_(V, kValuebits); - - T array_[1 << kHashbits]; -}; - -#undef N_ONES_ - -#endif // TCMALLOC_PACKED_CACHE_INL_H__ diff --git a/Source/JavaScriptCore/wtf/TCPageMap.h b/Source/JavaScriptCore/wtf/TCPageMap.h deleted file mode 100644 index 92fe0b065..000000000 --- a/Source/JavaScriptCore/wtf/TCPageMap.h +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright (c) 2005, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Sanjay Ghemawat <opensource@google.com> -// -// A data structure used by the caching malloc. It maps from page# to -// a pointer that contains info about that page. We use two -// representations: one for 32-bit addresses, and another for 64 bit -// addresses. Both representations provide the same interface. The -// first representation is implemented as a flat array, the seconds as -// a three-level radix tree that strips away approximately 1/3rd of -// the bits every time. -// -// The BITS parameter should be the number of bits required to hold -// a page number. E.g., with 32 bit pointers and 4K pages (i.e., -// page offset fits in lower 12 bits), BITS == 20. - -#ifndef TCMALLOC_PAGEMAP_H__ -#define TCMALLOC_PAGEMAP_H__ - -#if HAVE(STDINT_H) -#include <stdint.h> -#elif HAVE(INTTYPES_H) -#include <inttypes.h> -#else -#include <sys/types.h> -#endif - -#include <string.h> -#include <wtf/Assertions.h> - -// Single-level array -template <int BITS> -class TCMalloc_PageMap1 { - private: - void** array_; - - public: - typedef uintptr_t Number; - - void init(void* (*allocator)(size_t)) { - array_ = reinterpret_cast<void**>((*allocator)(sizeof(void*) << BITS)); - memset(array_, 0, sizeof(void*) << BITS); - } - - // Ensure that the map contains initialized entries "x .. x+n-1". - // Returns true if successful, false if we could not allocate memory. - bool Ensure(Number, size_t) { - // Nothing to do since flat array was allocate at start - return true; - } - - void PreallocateMoreMemory() {} - - // REQUIRES "k" is in range "[0,2^BITS-1]". - // REQUIRES "k" has been ensured before. - // - // Return the current value for KEY. Returns "Value()" if not - // yet set. - void* get(Number k) const { - return array_[k]; - } - - // REQUIRES "k" is in range "[0,2^BITS-1]". - // REQUIRES "k" has been ensured before. - // - // Sets the value for KEY. - void set(Number k, void* v) { - array_[k] = v; - } -}; - -// Two-level radix tree -template <int BITS> -class TCMalloc_PageMap2 { - private: - // Put 32 entries in the root and (2^BITS)/32 entries in each leaf. - static const int ROOT_BITS = 5; - static const int ROOT_LENGTH = 1 << ROOT_BITS; - - static const int LEAF_BITS = BITS - ROOT_BITS; - static const int LEAF_LENGTH = 1 << LEAF_BITS; - - // Leaf node - struct Leaf { - void* values[LEAF_LENGTH]; - }; - - Leaf* root_[ROOT_LENGTH]; // Pointers to 32 child nodes - void* (*allocator_)(size_t); // Memory allocator - - public: - typedef uintptr_t Number; - - void init(void* (*allocator)(size_t)) { - allocator_ = allocator; - memset(root_, 0, sizeof(root_)); - } - - void* get(Number k) const { - ASSERT(k >> BITS == 0); - const Number i1 = k >> LEAF_BITS; - const Number i2 = k & (LEAF_LENGTH-1); - return root_[i1]->values[i2]; - } - - void set(Number k, void* v) { - ASSERT(k >> BITS == 0); - const Number i1 = k >> LEAF_BITS; - const Number i2 = k & (LEAF_LENGTH-1); - root_[i1]->values[i2] = v; - } - - bool Ensure(Number start, size_t n) { - for (Number key = start; key <= start + n - 1; ) { - const Number i1 = key >> LEAF_BITS; - - // Make 2nd level node if necessary - if (root_[i1] == NULL) { - Leaf* leaf = reinterpret_cast<Leaf*>((*allocator_)(sizeof(Leaf))); - if (leaf == NULL) return false; - memset(leaf, 0, sizeof(*leaf)); - root_[i1] = leaf; - } - - // Advance key past whatever is covered by this leaf node - key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; - } - return true; - } - - void PreallocateMoreMemory() { - // Allocate enough to keep track of all possible pages - Ensure(0, 1 << BITS); - } - -#ifdef WTF_CHANGES - template<class Visitor, class MemoryReader> - void visitValues(Visitor& visitor, const MemoryReader& reader) - { - for (int i = 0; i < ROOT_LENGTH; i++) { - if (!root_[i]) - continue; - - Leaf* l = reader(reinterpret_cast<Leaf*>(root_[i])); - for (int j = 0; j < LEAF_LENGTH; j += visitor.visit(l->values[j])) - ; - } - } - - template<class Visitor, class MemoryReader> - void visitAllocations(Visitor& visitor, const MemoryReader&) { - for (int i = 0; i < ROOT_LENGTH; i++) { - if (root_[i]) - visitor.visit(root_[i], sizeof(Leaf)); - } - } -#endif -}; - -// Three-level radix tree -template <int BITS> -class TCMalloc_PageMap3 { - private: - // How many bits should we consume at each interior level - static const int INTERIOR_BITS = (BITS + 2) / 3; // Round-up - static const int INTERIOR_LENGTH = 1 << INTERIOR_BITS; - - // How many bits should we consume at leaf level - static const int LEAF_BITS = BITS - 2*INTERIOR_BITS; - static const int LEAF_LENGTH = 1 << LEAF_BITS; - - // Interior node - struct Node { - Node* ptrs[INTERIOR_LENGTH]; - }; - - // Leaf node - struct Leaf { - void* values[LEAF_LENGTH]; - }; - - Node* root_; // Root of radix tree - void* (*allocator_)(size_t); // Memory allocator - - Node* NewNode() { - Node* result = reinterpret_cast<Node*>((*allocator_)(sizeof(Node))); - if (result != NULL) { - memset(result, 0, sizeof(*result)); - } - return result; - } - - public: - typedef uintptr_t Number; - - void init(void* (*allocator)(size_t)) { - allocator_ = allocator; - root_ = NewNode(); - } - - void* get(Number k) const { - ASSERT(k >> BITS == 0); - const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS); - const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1); - const Number i3 = k & (LEAF_LENGTH-1); - return reinterpret_cast<Leaf*>(root_->ptrs[i1]->ptrs[i2])->values[i3]; - } - - void set(Number k, void* v) { - ASSERT(k >> BITS == 0); - const Number i1 = k >> (LEAF_BITS + INTERIOR_BITS); - const Number i2 = (k >> LEAF_BITS) & (INTERIOR_LENGTH-1); - const Number i3 = k & (LEAF_LENGTH-1); - reinterpret_cast<Leaf*>(root_->ptrs[i1]->ptrs[i2])->values[i3] = v; - } - - bool Ensure(Number start, size_t n) { - for (Number key = start; key <= start + n - 1; ) { - const Number i1 = key >> (LEAF_BITS + INTERIOR_BITS); - const Number i2 = (key >> LEAF_BITS) & (INTERIOR_LENGTH-1); - - // Make 2nd level node if necessary - if (root_->ptrs[i1] == NULL) { - Node* n = NewNode(); - if (n == NULL) return false; - root_->ptrs[i1] = n; - } - - // Make leaf node if necessary - if (root_->ptrs[i1]->ptrs[i2] == NULL) { - Leaf* leaf = reinterpret_cast<Leaf*>((*allocator_)(sizeof(Leaf))); - if (leaf == NULL) return false; - memset(leaf, 0, sizeof(*leaf)); - root_->ptrs[i1]->ptrs[i2] = reinterpret_cast<Node*>(leaf); - } - - // Advance key past whatever is covered by this leaf node - key = ((key >> LEAF_BITS) + 1) << LEAF_BITS; - } - return true; - } - - void PreallocateMoreMemory() { - } - -#ifdef WTF_CHANGES - template<class Visitor, class MemoryReader> - void visitValues(Visitor& visitor, const MemoryReader& reader) { - Node* root = reader(root_); - for (int i = 0; i < INTERIOR_LENGTH; i++) { - if (!root->ptrs[i]) - continue; - - Node* n = reader(root->ptrs[i]); - for (int j = 0; j < INTERIOR_LENGTH; j++) { - if (!n->ptrs[j]) - continue; - - Leaf* l = reader(reinterpret_cast<Leaf*>(n->ptrs[j])); - for (int k = 0; k < LEAF_LENGTH; k += visitor.visit(l->values[k])) - ; - } - } - } - - template<class Visitor, class MemoryReader> - void visitAllocations(Visitor& visitor, const MemoryReader& reader) { - visitor.visit(root_, sizeof(Node)); - - Node* root = reader(root_); - for (int i = 0; i < INTERIOR_LENGTH; i++) { - if (!root->ptrs[i]) - continue; - - visitor.visit(root->ptrs[i], sizeof(Node)); - Node* n = reader(root->ptrs[i]); - for (int j = 0; j < INTERIOR_LENGTH; j++) { - if (!n->ptrs[j]) - continue; - - visitor.visit(n->ptrs[j], sizeof(Leaf)); - } - } - } -#endif -}; - -#endif // TCMALLOC_PAGEMAP_H__ diff --git a/Source/JavaScriptCore/wtf/TCSpinLock.h b/Source/JavaScriptCore/wtf/TCSpinLock.h deleted file mode 100644 index 7f19b6c25..000000000 --- a/Source/JavaScriptCore/wtf/TCSpinLock.h +++ /dev/null @@ -1,286 +0,0 @@ -// Copyright (c) 2005, 2006, Google Inc. -// Copyright (c) 2010, Patrick Gansterer <paroga@paroga.com> -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Sanjay Ghemawat <opensource@google.com> - -#ifndef TCMALLOC_INTERNAL_SPINLOCK_H__ -#define TCMALLOC_INTERNAL_SPINLOCK_H__ - -#if (CPU(X86) || CPU(X86_64) || CPU(PPC)) && (COMPILER(GCC) || COMPILER(MSVC)) - -#include <time.h> /* For nanosleep() */ - -#if HAVE(STDINT_H) -#include <stdint.h> -#elif HAVE(INTTYPES_H) -#include <inttypes.h> -#else -#include <sys/types.h> -#endif - -#if OS(WINDOWS) -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include <windows.h> -#else -#include <sched.h> /* For sched_yield() */ -#endif - -static void TCMalloc_SlowLock(volatile unsigned int* lockword); - -// The following is a struct so that it can be initialized at compile time -struct TCMalloc_SpinLock { - - inline void Lock() { - int r; -#if COMPILER(GCC) -#if CPU(X86) || CPU(X86_64) - __asm__ __volatile__ - ("xchgl %0, %1" - : "=r"(r), "=m"(lockword_) - : "0"(1), "m"(lockword_) - : "memory"); -#else - volatile unsigned int *lockword_ptr = &lockword_; - __asm__ __volatile__ - ("1: lwarx %0, 0, %1\n\t" - "stwcx. %2, 0, %1\n\t" - "bne- 1b\n\t" - "isync" - : "=&r" (r), "=r" (lockword_ptr) - : "r" (1), "1" (lockword_ptr) - : "memory"); -#endif -#elif COMPILER(MSVC) - __asm { - mov eax, this ; store &lockword_ (which is this+0) in eax - mov ebx, 1 ; store 1 in ebx - xchg [eax], ebx ; exchange lockword_ and 1 - mov r, ebx ; store old value of lockword_ in r - } -#endif - if (r) TCMalloc_SlowLock(&lockword_); - } - - inline void Unlock() { -#if COMPILER(GCC) -#if CPU(X86) || CPU(X86_64) - __asm__ __volatile__ - ("movl $0, %0" - : "=m"(lockword_) - : "m" (lockword_) - : "memory"); -#else - __asm__ __volatile__ - ("isync\n\t" - "eieio\n\t" - "stw %1, %0" -#if OS(DARWIN) || CPU(PPC) - : "=o" (lockword_) -#else - : "=m" (lockword_) -#endif - : "r" (0) - : "memory"); -#endif -#elif COMPILER(MSVC) - __asm { - mov eax, this ; store &lockword_ (which is this+0) in eax - mov [eax], 0 ; set lockword_ to 0 - } -#endif - } - // Report if we think the lock can be held by this thread. - // When the lock is truly held by the invoking thread - // we will always return true. - // Indended to be used as CHECK(lock.IsHeld()); - inline bool IsHeld() const { - return lockword_ != 0; - } - - inline void Init() { lockword_ = 0; } - inline void Finalize() { } - - volatile unsigned int lockword_; -}; - -#define SPINLOCK_INITIALIZER { 0 } - -static void TCMalloc_SlowLock(volatile unsigned int* lockword) { -// Yield immediately since fast path failed -#if OS(WINDOWS) - Sleep(0); -#else - sched_yield(); -#endif - while (true) { - int r; -#if COMPILER(GCC) -#if CPU(X86) || CPU(X86_64) - __asm__ __volatile__ - ("xchgl %0, %1" - : "=r"(r), "=m"(*lockword) - : "0"(1), "m"(*lockword) - : "memory"); - -#else - int tmp = 1; - __asm__ __volatile__ - ("1: lwarx %0, 0, %1\n\t" - "stwcx. %2, 0, %1\n\t" - "bne- 1b\n\t" - "isync" - : "=&r" (r), "=r" (lockword) - : "r" (tmp), "1" (lockword) - : "memory"); -#endif -#elif COMPILER(MSVC) - __asm { - mov eax, lockword ; assign lockword into eax - mov ebx, 1 ; assign 1 into ebx - xchg [eax], ebx ; exchange *lockword and 1 - mov r, ebx ; store old value of *lockword in r - } -#endif - if (!r) { - return; - } - - // This code was adapted from the ptmalloc2 implementation of - // spinlocks which would sched_yield() upto 50 times before - // sleeping once for a few milliseconds. Mike Burrows suggested - // just doing one sched_yield() outside the loop and always - // sleeping after that. This change helped a great deal on the - // performance of spinlocks under high contention. A test program - // with 10 threads on a dual Xeon (four virtual processors) went - // from taking 30 seconds to 16 seconds. - - // Sleep for a few milliseconds -#if OS(WINDOWS) - Sleep(2); -#else - struct timespec tm; - tm.tv_sec = 0; - tm.tv_nsec = 2000001; - nanosleep(&tm, NULL); -#endif - } -} - -#elif OS(WINDOWS) - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif -#include <windows.h> - -static void TCMalloc_SlowLock(LPLONG lockword); - -// The following is a struct so that it can be initialized at compile time -struct TCMalloc_SpinLock { - - inline void Lock() { - if (InterlockedExchange(&m_lockword, 1)) - TCMalloc_SlowLock(&m_lockword); - } - - inline void Unlock() { - InterlockedExchange(&m_lockword, 0); - } - - inline bool IsHeld() const { - return m_lockword != 0; - } - - inline void Init() { m_lockword = 0; } - inline void Finalize() { } - - LONG m_lockword; -}; - -#define SPINLOCK_INITIALIZER { 0 } - -static void TCMalloc_SlowLock(LPLONG lockword) { - Sleep(0); // Yield immediately since fast path failed - while (InterlockedExchange(lockword, 1)) - Sleep(2); -} - -#else - -#include <pthread.h> - -// Portable version -struct TCMalloc_SpinLock { - pthread_mutex_t private_lock_; - - inline void Init() { - if (pthread_mutex_init(&private_lock_, NULL) != 0) CRASH(); - } - inline void Finalize() { - if (pthread_mutex_destroy(&private_lock_) != 0) CRASH(); - } - inline void Lock() { - if (pthread_mutex_lock(&private_lock_) != 0) CRASH(); - } - inline void Unlock() { - if (pthread_mutex_unlock(&private_lock_) != 0) CRASH(); - } - bool IsHeld() { - if (pthread_mutex_trylock(&private_lock_)) - return true; - - Unlock(); - return false; - } -}; - -#define SPINLOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER } - -#endif - -// Corresponding locker object that arranges to acquire a spinlock for -// the duration of a C++ scope. -class TCMalloc_SpinLockHolder { - private: - TCMalloc_SpinLock* lock_; - public: - inline explicit TCMalloc_SpinLockHolder(TCMalloc_SpinLock* l) - : lock_(l) { l->Lock(); } - inline ~TCMalloc_SpinLockHolder() { lock_->Unlock(); } -}; - -// Short-hands for convenient use by tcmalloc.cc -typedef TCMalloc_SpinLock SpinLock; -typedef TCMalloc_SpinLockHolder SpinLockHolder; - -#endif // TCMALLOC_INTERNAL_SPINLOCK_H__ diff --git a/Source/JavaScriptCore/wtf/TCSystemAlloc.cpp b/Source/JavaScriptCore/wtf/TCSystemAlloc.cpp deleted file mode 100644 index 1cd89e631..000000000 --- a/Source/JavaScriptCore/wtf/TCSystemAlloc.cpp +++ /dev/null @@ -1,530 +0,0 @@ -// Copyright (c) 2005, 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Sanjay Ghemawat - -#include "config.h" -#if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) -#include "TCSystemAlloc.h" - -#include <algorithm> -#include "Assertions.h" -#include "TCSpinLock.h" -#include "UnusedParam.h" -#include "VMTags.h" - -#if HAVE(STDINT_H) -#include <stdint.h> -#elif HAVE(INTTYPES_H) -#include <inttypes.h> -#else -#include <sys/types.h> -#endif - -#if OS(WINDOWS) -#include "windows.h" -#else -#include <errno.h> -#include <unistd.h> -#include <sys/mman.h> -#endif - -#ifndef MAP_ANONYMOUS -#define MAP_ANONYMOUS MAP_ANON -#endif - -using namespace std; - -// Structure for discovering alignment -union MemoryAligner { - void* p; - double d; - size_t s; -}; - -static SpinLock spinlock = SPINLOCK_INITIALIZER; - -// Page size is initialized on demand -static size_t pagesize = 0; - -// Configuration parameters. -// -// if use_devmem is true, either use_sbrk or use_mmap must also be true. -// For 2.2 kernels, it looks like the sbrk address space (500MBish) and -// the mmap address space (1300MBish) are disjoint, so we need both allocators -// to get as much virtual memory as possible. -#ifndef WTF_CHANGES -static bool use_devmem = false; -#endif - -#if HAVE(SBRK) -static bool use_sbrk = false; -#endif - -#if HAVE(MMAP) -static bool use_mmap = true; -#endif - -#if HAVE(VIRTUALALLOC) -static bool use_VirtualAlloc = true; -#endif - -// Flags to keep us from retrying allocators that failed. -static bool devmem_failure = false; -static bool sbrk_failure = false; -static bool mmap_failure = false; -static bool VirtualAlloc_failure = false; - -#ifndef WTF_CHANGES -DEFINE_int32(malloc_devmem_start, 0, - "Physical memory starting location in MB for /dev/mem allocation." - " Setting this to 0 disables /dev/mem allocation"); -DEFINE_int32(malloc_devmem_limit, 0, - "Physical memory limit location in MB for /dev/mem allocation." - " Setting this to 0 means no limit."); -#else -static const int32_t FLAGS_malloc_devmem_start = 0; -static const int32_t FLAGS_malloc_devmem_limit = 0; -#endif - -#if HAVE(SBRK) - -static void* TrySbrk(size_t size, size_t *actual_size, size_t alignment) { - size = ((size + alignment - 1) / alignment) * alignment; - - // could theoretically return the "extra" bytes here, but this - // is simple and correct. - if (actual_size) - *actual_size = size; - - void* result = sbrk(size); - if (result == reinterpret_cast<void*>(-1)) { - sbrk_failure = true; - return NULL; - } - - // Is it aligned? - uintptr_t ptr = reinterpret_cast<uintptr_t>(result); - if ((ptr & (alignment-1)) == 0) return result; - - // Try to get more memory for alignment - size_t extra = alignment - (ptr & (alignment-1)); - void* r2 = sbrk(extra); - if (reinterpret_cast<uintptr_t>(r2) == (ptr + size)) { - // Contiguous with previous result - return reinterpret_cast<void*>(ptr + extra); - } - - // Give up and ask for "size + alignment - 1" bytes so - // that we can find an aligned region within it. - result = sbrk(size + alignment - 1); - if (result == reinterpret_cast<void*>(-1)) { - sbrk_failure = true; - return NULL; - } - ptr = reinterpret_cast<uintptr_t>(result); - if ((ptr & (alignment-1)) != 0) { - ptr += alignment - (ptr & (alignment-1)); - } - return reinterpret_cast<void*>(ptr); -} - -#endif /* HAVE(SBRK) */ - -#if HAVE(MMAP) - -static void* TryMmap(size_t size, size_t *actual_size, size_t alignment) { - // Enforce page alignment - if (pagesize == 0) pagesize = getpagesize(); - if (alignment < pagesize) alignment = pagesize; - size = ((size + alignment - 1) / alignment) * alignment; - - // could theoretically return the "extra" bytes here, but this - // is simple and correct. - if (actual_size) - *actual_size = size; - - // Ask for extra memory if alignment > pagesize - size_t extra = 0; - if (alignment > pagesize) { - extra = alignment - pagesize; - } - void* result = mmap(NULL, size + extra, - PROT_READ | PROT_WRITE, - MAP_PRIVATE|MAP_ANONYMOUS, - VM_TAG_FOR_TCMALLOC_MEMORY, 0); - if (result == reinterpret_cast<void*>(MAP_FAILED)) { - mmap_failure = true; - return NULL; - } - - // Adjust the return memory so it is aligned - uintptr_t ptr = reinterpret_cast<uintptr_t>(result); - size_t adjust = 0; - if ((ptr & (alignment - 1)) != 0) { - adjust = alignment - (ptr & (alignment - 1)); - } - - // Return the unused memory to the system - if (adjust > 0) { - munmap(reinterpret_cast<void*>(ptr), adjust); - } - if (adjust < extra) { - munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust); - } - - ptr += adjust; - return reinterpret_cast<void*>(ptr); -} - -#endif /* HAVE(MMAP) */ - -#if HAVE(VIRTUALALLOC) - -static void* TryVirtualAlloc(size_t size, size_t *actual_size, size_t alignment) { - // Enforce page alignment - if (pagesize == 0) { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - pagesize = system_info.dwPageSize; - } - - if (alignment < pagesize) alignment = pagesize; - size = ((size + alignment - 1) / alignment) * alignment; - - // could theoretically return the "extra" bytes here, but this - // is simple and correct. - if (actual_size) - *actual_size = size; - - // Ask for extra memory if alignment > pagesize - size_t extra = 0; - if (alignment > pagesize) { - extra = alignment - pagesize; - } - void* result = VirtualAlloc(NULL, size + extra, - MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, - PAGE_READWRITE); - - if (result == NULL) { - VirtualAlloc_failure = true; - return NULL; - } - - // Adjust the return memory so it is aligned - uintptr_t ptr = reinterpret_cast<uintptr_t>(result); - size_t adjust = 0; - if ((ptr & (alignment - 1)) != 0) { - adjust = alignment - (ptr & (alignment - 1)); - } - - // Return the unused memory to the system - we'd like to release but the best we can do - // is decommit, since Windows only lets you free the whole allocation. - if (adjust > 0) { - VirtualFree(reinterpret_cast<void*>(ptr), adjust, MEM_DECOMMIT); - } - if (adjust < extra) { - VirtualFree(reinterpret_cast<void*>(ptr + adjust + size), extra-adjust, MEM_DECOMMIT); - } - - ptr += adjust; - return reinterpret_cast<void*>(ptr); -} - -#endif /* HAVE(MMAP) */ - -#ifndef WTF_CHANGES -static void* TryDevMem(size_t size, size_t *actual_size, size_t alignment) { - static bool initialized = false; - static off_t physmem_base; // next physical memory address to allocate - static off_t physmem_limit; // maximum physical address allowed - static int physmem_fd; // file descriptor for /dev/mem - - // Check if we should use /dev/mem allocation. Note that it may take - // a while to get this flag initialized, so meanwhile we fall back to - // the next allocator. (It looks like 7MB gets allocated before - // this flag gets initialized -khr.) - if (FLAGS_malloc_devmem_start == 0) { - // NOTE: not a devmem_failure - we'd like TCMalloc_SystemAlloc to - // try us again next time. - return NULL; - } - - if (!initialized) { - physmem_fd = open("/dev/mem", O_RDWR); - if (physmem_fd < 0) { - devmem_failure = true; - return NULL; - } - physmem_base = FLAGS_malloc_devmem_start*1024LL*1024LL; - physmem_limit = FLAGS_malloc_devmem_limit*1024LL*1024LL; - initialized = true; - } - - // Enforce page alignment - if (pagesize == 0) pagesize = getpagesize(); - if (alignment < pagesize) alignment = pagesize; - size = ((size + alignment - 1) / alignment) * alignment; - - // could theoretically return the "extra" bytes here, but this - // is simple and correct. - if (actual_size) - *actual_size = size; - - // Ask for extra memory if alignment > pagesize - size_t extra = 0; - if (alignment > pagesize) { - extra = alignment - pagesize; - } - - // check to see if we have any memory left - if (physmem_limit != 0 && physmem_base + size + extra > physmem_limit) { - devmem_failure = true; - return NULL; - } - void *result = mmap(0, size + extra, PROT_READ | PROT_WRITE, - MAP_SHARED, physmem_fd, physmem_base); - if (result == reinterpret_cast<void*>(MAP_FAILED)) { - devmem_failure = true; - return NULL; - } - uintptr_t ptr = reinterpret_cast<uintptr_t>(result); - - // Adjust the return memory so it is aligned - size_t adjust = 0; - if ((ptr & (alignment - 1)) != 0) { - adjust = alignment - (ptr & (alignment - 1)); - } - - // Return the unused virtual memory to the system - if (adjust > 0) { - munmap(reinterpret_cast<void*>(ptr), adjust); - } - if (adjust < extra) { - munmap(reinterpret_cast<void*>(ptr + adjust + size), extra - adjust); - } - - ptr += adjust; - physmem_base += adjust + size; - - return reinterpret_cast<void*>(ptr); -} -#endif - -void* TCMalloc_SystemAlloc(size_t size, size_t *actual_size, size_t alignment) { - // Discard requests that overflow - if (size + alignment < size) return NULL; - - SpinLockHolder lock_holder(&spinlock); - - // Enforce minimum alignment - if (alignment < sizeof(MemoryAligner)) alignment = sizeof(MemoryAligner); - - // Try twice, once avoiding allocators that failed before, and once - // more trying all allocators even if they failed before. - for (int i = 0; i < 2; i++) { - -#ifndef WTF_CHANGES - if (use_devmem && !devmem_failure) { - void* result = TryDevMem(size, actual_size, alignment); - if (result != NULL) return result; - } -#endif - -#if HAVE(SBRK) - if (use_sbrk && !sbrk_failure) { - void* result = TrySbrk(size, actual_size, alignment); - if (result != NULL) return result; - } -#endif - -#if HAVE(MMAP) - if (use_mmap && !mmap_failure) { - void* result = TryMmap(size, actual_size, alignment); - if (result != NULL) return result; - } -#endif - -#if HAVE(VIRTUALALLOC) - if (use_VirtualAlloc && !VirtualAlloc_failure) { - void* result = TryVirtualAlloc(size, actual_size, alignment); - if (result != NULL) return result; - } -#endif - - // nothing worked - reset failure flags and try again - devmem_failure = false; - sbrk_failure = false; - mmap_failure = false; - VirtualAlloc_failure = false; - } - return NULL; -} - -#if HAVE(MADV_FREE_REUSE) - -void TCMalloc_SystemRelease(void* start, size_t length) -{ - int madviseResult; - - while ((madviseResult = madvise(start, length, MADV_FREE_REUSABLE)) == -1 && errno == EAGAIN) { } - - // Although really advisory, if madvise fail, we want to know about it. - ASSERT_UNUSED(madviseResult, madviseResult != -1); -} - -#elif HAVE(MADV_FREE) || HAVE(MADV_DONTNEED) - -void TCMalloc_SystemRelease(void* start, size_t length) -{ - // MADV_FREE clears the modified bit on pages, which allows - // them to be discarded immediately. -#if HAVE(MADV_FREE) - const int advice = MADV_FREE; -#else - const int advice = MADV_DONTNEED; -#endif - if (FLAGS_malloc_devmem_start) { - // It's not safe to use MADV_DONTNEED if we've been mapping - // /dev/mem for heap memory - return; - } - if (pagesize == 0) pagesize = getpagesize(); - const size_t pagemask = pagesize - 1; - - size_t new_start = reinterpret_cast<size_t>(start); - size_t end = new_start + length; - size_t new_end = end; - - // Round up the starting address and round down the ending address - // to be page aligned: - new_start = (new_start + pagesize - 1) & ~pagemask; - new_end = new_end & ~pagemask; - - ASSERT((new_start & pagemask) == 0); - ASSERT((new_end & pagemask) == 0); - ASSERT(new_start >= reinterpret_cast<size_t>(start)); - ASSERT(new_end <= end); - - if (new_end > new_start) { - // Note -- ignoring most return codes, because if this fails it - // doesn't matter... - while (madvise(reinterpret_cast<char*>(new_start), new_end - new_start, - advice) == -1 && - errno == EAGAIN) { - // NOP - } - } -} - -#elif HAVE(MMAP) - -void TCMalloc_SystemRelease(void* start, size_t length) -{ - void* newAddress = mmap(start, length, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); - // If the mmap failed then that's ok, we just won't return the memory to the system. - ASSERT_UNUSED(newAddress, newAddress == start || newAddress == reinterpret_cast<void*>(MAP_FAILED)); -} - -#elif HAVE(VIRTUALALLOC) - -void TCMalloc_SystemRelease(void* start, size_t length) -{ - if (VirtualFree(start, length, MEM_DECOMMIT)) - return; - - // The decommit may fail if the memory region consists of allocations - // from more than one call to VirtualAlloc. In this case, fall back to - // using VirtualQuery to retrieve the allocation boundaries and decommit - // them each individually. - - char* ptr = static_cast<char*>(start); - char* end = ptr + length; - MEMORY_BASIC_INFORMATION info; - while (ptr < end) { - size_t resultSize = VirtualQuery(ptr, &info, sizeof(info)); - ASSERT_UNUSED(resultSize, resultSize == sizeof(info)); - - size_t decommitSize = min<size_t>(info.RegionSize, end - ptr); - BOOL success = VirtualFree(ptr, decommitSize, MEM_DECOMMIT); - ASSERT_UNUSED(success, success); - ptr += decommitSize; - } -} - -#else - -// Platforms that don't support returning memory use an empty inline version of TCMalloc_SystemRelease -// declared in TCSystemAlloc.h - -#endif - -#if HAVE(MADV_FREE_REUSE) - -void TCMalloc_SystemCommit(void* start, size_t length) -{ - while (madvise(start, length, MADV_FREE_REUSE) == -1 && errno == EAGAIN) { } -} - -#elif HAVE(VIRTUALALLOC) - -void TCMalloc_SystemCommit(void* start, size_t length) -{ - if (VirtualAlloc(start, length, MEM_COMMIT, PAGE_READWRITE) == start) - return; - - // The commit may fail if the memory region consists of allocations - // from more than one call to VirtualAlloc. In this case, fall back to - // using VirtualQuery to retrieve the allocation boundaries and commit them - // each individually. - - char* ptr = static_cast<char*>(start); - char* end = ptr + length; - MEMORY_BASIC_INFORMATION info; - while (ptr < end) { - size_t resultSize = VirtualQuery(ptr, &info, sizeof(info)); - ASSERT_UNUSED(resultSize, resultSize == sizeof(info)); - - size_t commitSize = min<size_t>(info.RegionSize, end - ptr); - void* newAddress = VirtualAlloc(ptr, commitSize, MEM_COMMIT, PAGE_READWRITE); - ASSERT_UNUSED(newAddress, newAddress == ptr); - ptr += commitSize; - } -} - -#else - -// Platforms that don't need to explicitly commit memory use an empty inline version of TCMalloc_SystemCommit -// declared in TCSystemAlloc.h - -#endif - -#endif // #if !(defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC) - diff --git a/Source/JavaScriptCore/wtf/TCSystemAlloc.h b/Source/JavaScriptCore/wtf/TCSystemAlloc.h deleted file mode 100644 index 1c677889c..000000000 --- a/Source/JavaScriptCore/wtf/TCSystemAlloc.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) 2005, 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// --- -// Author: Sanjay Ghemawat -// -// Routine that uses sbrk/mmap to allocate memory from the system. -// Useful for implementing malloc. - -#ifndef TCMALLOC_SYSTEM_ALLOC_H__ -#define TCMALLOC_SYSTEM_ALLOC_H__ - -// REQUIRES: "alignment" is a power of two or "0" to indicate default alignment -// -// Allocate and return "N" bytes of zeroed memory. -// -// If actual_bytes is NULL then the returned memory is exactly the -// requested size. If actual bytes is non-NULL then the allocator -// may optionally return more bytes than asked for (i.e. return an -// entire "huge" page if a huge page allocator is in use). -// -// The returned pointer is a multiple of "alignment" if non-zero. -// -// Returns NULL when out of memory. -extern void* TCMalloc_SystemAlloc(size_t bytes, size_t *actual_bytes, - size_t alignment = 0); - -// This call is a hint to the operating system that the pages -// contained in the specified range of memory will not be used for a -// while, and can be released for use by other processes or the OS. -// Pages which are released in this way may be destroyed (zeroed) by -// the OS. The benefit of this function is that it frees memory for -// use by the system, the cost is that the pages are faulted back into -// the address space next time they are touched, which can impact -// performance. (Only pages fully covered by the memory region will -// be released, partial pages will not.) -extern void TCMalloc_SystemRelease(void* start, size_t length); - -extern void TCMalloc_SystemCommit(void* start, size_t length); - -#if !HAVE(MADV_FREE_REUSE) && !HAVE(MADV_DONTNEED) && !HAVE(MMAP) && !HAVE(VIRTUALALLOC) -inline void TCMalloc_SystemRelease(void*, size_t) { } -#endif - -#if !HAVE(VIRTUALALLOC) && !HAVE(MADV_FREE_REUSE) -inline void TCMalloc_SystemCommit(void*, size_t) { } -#endif - -#endif /* TCMALLOC_SYSTEM_ALLOC_H__ */ diff --git a/Source/JavaScriptCore/wtf/TemporaryChange.h b/Source/JavaScriptCore/wtf/TemporaryChange.h deleted file mode 100644 index 95df1728b..000000000 --- a/Source/JavaScriptCore/wtf/TemporaryChange.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2011 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 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 TemporaryChange_h -#define TemporaryChange_h - -#include <wtf/Noncopyable.h> - -namespace WTF { - -// TemporaryChange<> is useful for setting a variable to a new value only within a -// particular scope. An TemporaryChange<> object changes a variable to its original -// value upon destruction, making it an alternative to writing "var = false;" -// or "var = oldVal;" at all of a block's exit points. -// -// This should be obvious, but note that an TemporaryChange<> instance should have a -// shorter lifetime than its scopedVariable, to prevent invalid memory writes -// when the TemporaryChange<> object is destroyed. - -template<typename T> -class TemporaryChange { - WTF_MAKE_NONCOPYABLE(TemporaryChange); -public: - TemporaryChange(T& scopedVariable, T newValue) - : m_scopedVariable(scopedVariable) - , m_originalValue(scopedVariable) - { - m_scopedVariable = newValue; - } - - ~TemporaryChange() - { - m_scopedVariable = m_originalValue; - } - - -private: - T& m_scopedVariable; - T m_originalValue; -}; - -} - -using WTF::TemporaryChange; - -#endif diff --git a/Source/JavaScriptCore/wtf/ThreadFunctionInvocation.h b/Source/JavaScriptCore/wtf/ThreadFunctionInvocation.h deleted file mode 100644 index 2d8599eb9..000000000 --- a/Source/JavaScriptCore/wtf/ThreadFunctionInvocation.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2007, 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 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 ThreadFunctionInvocation_h -#define ThreadFunctionInvocation_h - -namespace WTF { - -typedef void (*ThreadFunction)(void* argument); - -struct ThreadFunctionInvocation { - ThreadFunctionInvocation(ThreadFunction function, void* data) - : function(function) - , data(data) - { - } - - ThreadFunction function; - void* data; -}; - -} // namespace WTF - -#endif // ThreadFunctionInvocation_h diff --git a/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp b/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp deleted file mode 100644 index 0badf939a..000000000 --- a/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2009, 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" - -#if USE(PTHREADS) - -#include "ThreadIdentifierDataPthreads.h" - -#include "Threading.h" - -#if OS(ANDROID) || OS(HURD) -// PTHREAD_KEYS_MAX is not defined in bionic nor in Hurd, so explicitly define it here. -#define PTHREAD_KEYS_MAX 1024 -#else -#include <limits.h> -#endif - -namespace WTF { - -pthread_key_t ThreadIdentifierData::m_key = PTHREAD_KEYS_MAX; - -void clearPthreadHandleForIdentifier(ThreadIdentifier); - -ThreadIdentifierData::~ThreadIdentifierData() -{ - clearPthreadHandleForIdentifier(m_identifier); -} - -void ThreadIdentifierData::initializeOnce() -{ - if (pthread_key_create(&m_key, destruct)) - CRASH(); -} - -ThreadIdentifier ThreadIdentifierData::identifier() -{ - ASSERT(m_key != PTHREAD_KEYS_MAX); - ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(pthread_getspecific(m_key)); - - return threadIdentifierData ? threadIdentifierData->m_identifier : 0; -} - -void ThreadIdentifierData::initialize(ThreadIdentifier id) -{ - ASSERT(!identifier()); - pthread_setspecific(m_key, new ThreadIdentifierData(id)); -} - -void ThreadIdentifierData::destruct(void* data) -{ - ThreadIdentifierData* threadIdentifierData = static_cast<ThreadIdentifierData*>(data); - ASSERT(threadIdentifierData); - - if (threadIdentifierData->m_isDestroyedOnce) { - delete threadIdentifierData; - return; - } - - threadIdentifierData->m_isDestroyedOnce = true; - // Re-setting the value for key causes another destruct() call after all other thread-specific destructors were called. - pthread_setspecific(m_key, threadIdentifierData); -} - -} // namespace WTF - -#endif // USE(PTHREADS) diff --git a/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h b/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h deleted file mode 100644 index 84349a0cd..000000000 --- a/Source/JavaScriptCore/wtf/ThreadIdentifierDataPthreads.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2009 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ThreadIdentifierDataPthreads_h -#define ThreadIdentifierDataPthreads_h - -#include <wtf/Threading.h> - -namespace WTF { - -// Holds ThreadIdentifier in the thread-specific storage and employs pthreads-specific 2-pass destruction to reliably remove -// ThreadIdentifier from threadMap. It assumes regular ThreadSpecific types don't use multiple-pass destruction. -class ThreadIdentifierData { - WTF_MAKE_NONCOPYABLE(ThreadIdentifierData); -public: - ~ThreadIdentifierData(); - - // One time initialization for this class as a whole. - // This method must be called before initialize() and it is not thread-safe. - static void initializeOnce(); - - // Creates and puts an instance of ThreadIdentifierData into thread-specific storage. - static void initialize(ThreadIdentifier identifier); - - // Returns 0 if thread-specific storage was not initialized. - static ThreadIdentifier identifier(); - -private: - ThreadIdentifierData(ThreadIdentifier identifier) - : m_identifier(identifier) - , m_isDestroyedOnce(false) - { - } - - // This thread-specific destructor is called 2 times when thread terminates: - // - first, when all the other thread-specific destructors are called, it simply remembers it was 'destroyed once' - // and re-sets itself into the thread-specific slot to make Pthreads to call it again later. - // - second, after all thread-specific destructors were invoked, it gets called again - this time, we remove the - // ThreadIdentifier from the threadMap, completing the cleanup. - static void destruct(void* data); - - ThreadIdentifier m_identifier; - bool m_isDestroyedOnce; - static pthread_key_t m_key; -}; - -} // namespace WTF - -#endif // ThreadIdentifierDataPthreads_h - - diff --git a/Source/JavaScriptCore/wtf/ThreadRestrictionVerifier.h b/Source/JavaScriptCore/wtf/ThreadRestrictionVerifier.h deleted file mode 100644 index 0eeac8e62..000000000 --- a/Source/JavaScriptCore/wtf/ThreadRestrictionVerifier.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2011 Google Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef ThreadRestrictionVerifier_h -#define ThreadRestrictionVerifier_h - -#include <wtf/Assertions.h> -#include <wtf/Threading.h> -#include <wtf/ThreadingPrimitives.h> - -#if HAVE(DISPATCH_H) -#include <dispatch/dispatch.h> -#endif - -#ifndef NDEBUG - -namespace WTF { - -// Verifies that a class is used in a way that respects its lack of thread-safety. -// The default mode is to verify that the object will only be used on a single thread. The -// thread gets captured when setShared(true) is called. -// The mode may be changed by calling useMutexMode (or turnOffVerification). -class ThreadRestrictionVerifier { -public: - ThreadRestrictionVerifier() - : m_mode(SingleThreadVerificationMode) - , m_shared(false) - , m_owningThread(0) - , m_mutex(0) -#if HAVE(DISPATCH_H) - , m_owningQueue(0) -#endif - { - } - -#if HAVE(DISPATCH_H) - ~ThreadRestrictionVerifier() - { - if (m_owningQueue) - dispatch_release(m_owningQueue); - } -#endif - - void setMutexMode(Mutex& mutex) - { - ASSERT(m_mode == SingleThreadVerificationMode || (m_mode == MutexVerificationMode && &mutex == m_mutex)); - m_mode = MutexVerificationMode; - m_mutex = &mutex; - } - -#if HAVE(DISPATCH_H) - void setDispatchQueueMode(dispatch_queue_t queue) - { - ASSERT(m_mode == SingleThreadVerificationMode); - m_mode = SingleDispatchQueueVerificationMode; - m_owningQueue = queue; - dispatch_retain(m_owningQueue); - } -#endif - - void turnOffVerification() - { - ASSERT(m_mode == SingleThreadVerificationMode); - m_mode = NoVerificationMode; - } - - // Indicates that the object may (or may not) be owned by more than one place. - void setShared(bool shared) - { -#if !ASSERT_DISABLED - bool previouslyShared = m_shared; -#endif - m_shared = shared; - - if (!m_shared) - return; - - switch (m_mode) { - case SingleThreadVerificationMode: - ASSERT(shared != previouslyShared); - // Capture the current thread to verify that subsequent ref/deref happen on this thread. - m_owningThread = currentThread(); - return; - -#if HAVE(DISPATCH_H) - case SingleDispatchQueueVerificationMode: -#endif - case MutexVerificationMode: - case NoVerificationMode: - return; - } - ASSERT_NOT_REACHED(); - } - - // Is it OK to use the object at this moment on the current thread? - bool isSafeToUse() const - { - if (!m_shared) - return true; - - switch (m_mode) { - case SingleThreadVerificationMode: - return m_owningThread == currentThread(); - - case MutexVerificationMode: - if (!m_mutex->tryLock()) - return true; - m_mutex->unlock(); - return false; - -#if HAVE(DISPATCH_H) - case SingleDispatchQueueVerificationMode: - return m_owningQueue == dispatch_get_current_queue(); -#endif - - case NoVerificationMode: - return true; - } - ASSERT_NOT_REACHED(); - return true; - } - -private: - enum VerificationMode { - SingleThreadVerificationMode, - MutexVerificationMode, - NoVerificationMode, -#if HAVE(DISPATCH_H) - SingleDispatchQueueVerificationMode, -#endif - }; - - VerificationMode m_mode; - bool m_shared; - - // Used by SingleThreadVerificationMode - ThreadIdentifier m_owningThread; - - // Used by MutexVerificationMode. - Mutex* m_mutex; - -#if HAVE(DISPATCH_H) - // Used by SingleDispatchQueueVerificationMode. - dispatch_queue_t m_owningQueue; -#endif -}; - -} - -#endif -#endif diff --git a/Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h b/Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h deleted file mode 100644 index 44035e547..000000000 --- a/Source/JavaScriptCore/wtf/ThreadSafeRefCounted.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * 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. - * - * - * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based - * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license - * is virtually identical to the Apple license above but is included here for completeness. - * - * Boost Software License - Version 1.0 - August 17th, 2003 - * - * Permission is hereby granted, free of charge, to any person or organization - * obtaining a copy of the software and accompanying documentation covered by - * this license (the "Software") to use, reproduce, display, distribute, - * execute, and transmit the Software, and to prepare derivative works of the - * Software, and to permit third-parties to whom the Software is furnished to - * do so, all subject to the following: - * - * The copyright notices in the Software and this entire statement, including - * the above license grant, this restriction and the following disclaimer, - * must be included in all copies of the Software, in whole or in part, and - * all derivative works of the Software, unless such copies or derivative - * works are solely in the form of machine-executable object code generated by - * a source language processor. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef ThreadSafeRefCounted_h -#define ThreadSafeRefCounted_h - -#include <wtf/Platform.h> - -#include <wtf/Atomics.h> -#include <wtf/DynamicAnnotations.h> -#include <wtf/ThreadingPrimitives.h> - -namespace WTF { - -class ThreadSafeRefCountedBase { - WTF_MAKE_NONCOPYABLE(ThreadSafeRefCountedBase); - WTF_MAKE_FAST_ALLOCATED; -public: - ThreadSafeRefCountedBase(int initialRefCount = 1) - : m_refCount(initialRefCount) - { - } - - void ref() - { -#if USE(LOCKFREE_THREADSAFEREFCOUNTED) - atomicIncrement(&m_refCount); -#else - MutexLocker locker(m_mutex); - ++m_refCount; -#endif - } - - bool hasOneRef() - { - return refCount() == 1; - } - - int refCount() const - { -#if !USE(LOCKFREE_THREADSAFEREFCOUNTED) - MutexLocker locker(m_mutex); -#endif - return static_cast<int const volatile &>(m_refCount); - } - -protected: - // Returns whether the pointer should be freed or not. - bool derefBase() - { -#if USE(LOCKFREE_THREADSAFEREFCOUNTED) - WTF_ANNOTATE_HAPPENS_BEFORE(&m_refCount); - if (atomicDecrement(&m_refCount) <= 0) { - WTF_ANNOTATE_HAPPENS_AFTER(&m_refCount); - return true; - } -#else - int refCount; - { - MutexLocker locker(m_mutex); - --m_refCount; - refCount = m_refCount; - } - if (refCount <= 0) - return true; -#endif - return false; - } - -private: - int m_refCount; -#if !USE(LOCKFREE_THREADSAFEREFCOUNTED) - mutable Mutex m_mutex; -#endif -}; - -template<class T> class ThreadSafeRefCounted : public ThreadSafeRefCountedBase { -public: - void deref() - { - if (derefBase()) - delete static_cast<T*>(this); - } - -protected: - ThreadSafeRefCounted() - { - } -}; - -} // namespace WTF - -using WTF::ThreadSafeRefCounted; - -#endif // ThreadSafeRefCounted_h diff --git a/Source/JavaScriptCore/wtf/ThreadSpecific.h b/Source/JavaScriptCore/wtf/ThreadSpecific.h deleted file mode 100644 index f20a3f3df..000000000 --- a/Source/JavaScriptCore/wtf/ThreadSpecific.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Jian Li <jianli@chromium.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. - * 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. - */ - -/* Thread local storage is implemented by using either pthread API or Windows - * native API. There is subtle semantic discrepancy for the cleanup function - * implementation as noted below: - * @ In pthread implementation, the destructor function will be called - * repeatedly if there is still non-NULL value associated with the function. - * @ In Windows native implementation, the destructor function will be called - * only once. - * This semantic discrepancy does not impose any problem because nowhere in - * WebKit the repeated call bahavior is utilized. - */ - -#ifndef WTF_ThreadSpecific_h -#define WTF_ThreadSpecific_h - -#include <wtf/Noncopyable.h> -#include <wtf/StdLibExtras.h> - -#if USE(PTHREADS) -#include <pthread.h> -#elif OS(WINDOWS) -#include <windows.h> -#endif - -namespace WTF { - -#if OS(WINDOWS) -// ThreadSpecificThreadExit should be called each time when a thread is detached. -// This is done automatically for threads created with WTF::createThread. -void ThreadSpecificThreadExit(); -#endif - -template<typename T> class ThreadSpecific { - WTF_MAKE_NONCOPYABLE(ThreadSpecific); -public: - ThreadSpecific(); - bool isSet(); // Useful as a fast check to see if this thread has set this value. - T* operator->(); - operator T*(); - T& operator*(); - -private: -#if OS(WINDOWS) - friend void ThreadSpecificThreadExit(); -#endif - - // Not implemented. It's technically possible to destroy a thread specific key, but one would need - // to make sure that all values have been destroyed already (usually, that all threads that used it - // have exited). It's unlikely that any user of this call will be in that situation - and having - // a destructor defined can be confusing, given that it has such strong pre-requisites to work correctly. - ~ThreadSpecific(); - - T* get(); - void set(T*); - void static destroy(void* ptr); - - struct Data { - WTF_MAKE_NONCOPYABLE(Data); - public: - Data(T* value, ThreadSpecific<T>* owner) : value(value), owner(owner) {} - - T* value; - ThreadSpecific<T>* owner; -#if OS(WINDOWS) - void (*destructor)(void*); -#endif - }; - -#if USE(PTHREADS) - pthread_key_t m_key; -#elif OS(WINDOWS) - int m_index; -#endif -}; - -#if USE(PTHREADS) -template<typename T> -inline ThreadSpecific<T>::ThreadSpecific() -{ - int error = pthread_key_create(&m_key, destroy); - if (error) - CRASH(); -} - -template<typename T> -inline T* ThreadSpecific<T>::get() -{ - Data* data = static_cast<Data*>(pthread_getspecific(m_key)); - return data ? data->value : 0; -} - -template<typename T> -inline void ThreadSpecific<T>::set(T* ptr) -{ - ASSERT(!get()); - pthread_setspecific(m_key, new Data(ptr, this)); -} - -#elif OS(WINDOWS) - -// TLS_OUT_OF_INDEXES is not defined on WinCE. -#ifndef TLS_OUT_OF_INDEXES -#define TLS_OUT_OF_INDEXES 0xffffffff -#endif - -// The maximum number of TLS keys that can be created. For simplification, we assume that: -// 1) Once the instance of ThreadSpecific<> is created, it will not be destructed until the program dies. -// 2) We do not need to hold many instances of ThreadSpecific<> data. This fixed number should be far enough. -const int kMaxTlsKeySize = 256; - -long& tlsKeyCount(); -DWORD* tlsKeys(); - -template<typename T> -inline ThreadSpecific<T>::ThreadSpecific() - : m_index(-1) -{ - DWORD tlsKey = TlsAlloc(); - if (tlsKey == TLS_OUT_OF_INDEXES) - CRASH(); - - m_index = InterlockedIncrement(&tlsKeyCount()) - 1; - if (m_index >= kMaxTlsKeySize) - CRASH(); - tlsKeys()[m_index] = tlsKey; -} - -template<typename T> -inline ThreadSpecific<T>::~ThreadSpecific() -{ - // Does not invoke destructor functions. They will be called from ThreadSpecificThreadExit when the thread is detached. - TlsFree(tlsKeys()[m_index]); -} - -template<typename T> -inline T* ThreadSpecific<T>::get() -{ - Data* data = static_cast<Data*>(TlsGetValue(tlsKeys()[m_index])); - return data ? data->value : 0; -} - -template<typename T> -inline void ThreadSpecific<T>::set(T* ptr) -{ - ASSERT(!get()); - Data* data = new Data(ptr, this); - data->destructor = &ThreadSpecific<T>::destroy; - TlsSetValue(tlsKeys()[m_index], data); -} - -#else -#error ThreadSpecific is not implemented for this platform. -#endif - -template<typename T> -inline void ThreadSpecific<T>::destroy(void* ptr) -{ - Data* data = static_cast<Data*>(ptr); - -#if USE(PTHREADS) - // We want get() to keep working while data destructor works, because it can be called indirectly by the destructor. - // Some pthreads implementations zero out the pointer before calling destroy(), so we temporarily reset it. - pthread_setspecific(data->owner->m_key, ptr); -#endif - - data->value->~T(); - fastFree(data->value); - -#if USE(PTHREADS) - pthread_setspecific(data->owner->m_key, 0); -#elif OS(WINDOWS) - TlsSetValue(tlsKeys()[data->owner->m_index], 0); -#else -#error ThreadSpecific is not implemented for this platform. -#endif - - delete data; -} - -template<typename T> -inline bool ThreadSpecific<T>::isSet() -{ - return !!get(); -} - -template<typename T> -inline ThreadSpecific<T>::operator T*() -{ - T* ptr = static_cast<T*>(get()); - if (!ptr) { - // Set up thread-specific value's memory pointer before invoking constructor, in case any function it calls - // needs to access the value, to avoid recursion. - ptr = static_cast<T*>(fastZeroedMalloc(sizeof(T))); - set(ptr); - new (NotNull, ptr) T; - } - return ptr; -} - -template<typename T> -inline T* ThreadSpecific<T>::operator->() -{ - return operator T*(); -} - -template<typename T> -inline T& ThreadSpecific<T>::operator*() -{ - return *operator T*(); -} - -} // namespace WTF - -#endif // WTF_ThreadSpecific_h diff --git a/Source/JavaScriptCore/wtf/ThreadSpecificWin.cpp b/Source/JavaScriptCore/wtf/ThreadSpecificWin.cpp deleted file mode 100644 index d72996a7a..000000000 --- a/Source/JavaScriptCore/wtf/ThreadSpecificWin.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2009 Jian Li <jianli@chromium.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#include "ThreadSpecific.h" - -#if USE(PTHREADS) -#error This file should not be compiled by ports that do not use Windows native ThreadSpecific implementation. -#endif - -namespace WTF { - -long& tlsKeyCount() -{ - static long count; - return count; -} - -DWORD* tlsKeys() -{ - static DWORD keys[kMaxTlsKeySize]; - return keys; -} - -void ThreadSpecificThreadExit() -{ - for (long i = 0; i < tlsKeyCount(); i++) { - // The layout of ThreadSpecific<T>::Data does not depend on T. So we are safe to do the static cast to ThreadSpecific<int> in order to access its data member. - ThreadSpecific<int>::Data* data = static_cast<ThreadSpecific<int>::Data*>(TlsGetValue(tlsKeys()[i])); - if (data) - data->destructor(data); - } -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/Threading.cpp b/Source/JavaScriptCore/wtf/Threading.cpp deleted file mode 100644 index 8d658e934..000000000 --- a/Source/JavaScriptCore/wtf/Threading.cpp +++ /dev/null @@ -1,146 +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 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 "Threading.h" -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> - -#include <string.h> - -namespace WTF { - -struct NewThreadContext { - WTF_MAKE_FAST_ALLOCATED; -public: - NewThreadContext(ThreadFunction entryPoint, void* data, const char* name) - : entryPoint(entryPoint) - , data(data) - , name(name) - { - } - - ThreadFunction entryPoint; - void* data; - const char* name; - - Mutex creationMutex; -}; - -static void threadEntryPoint(void* contextData) -{ - NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData); - - // Block until our creating thread has completed any extra setup work, including - // establishing ThreadIdentifier. - { - MutexLocker locker(context->creationMutex); - } - - initializeCurrentThreadInternal(context->name); - - // Grab the info that we need out of the context, then deallocate it. - ThreadFunction entryPoint = context->entryPoint; - void* data = context->data; - delete context; - - entryPoint(data); -} - -ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name) -{ - // Visual Studio has a 31-character limit on thread names. Longer names will - // be truncated silently, but we'd like callers to know about the limit. -#if !LOG_DISABLED - if (strlen(name) > 31) - LOG_ERROR("Thread name \"%s\" is longer than 31 characters and will be truncated by Visual Studio", name); -#endif - - NewThreadContext* context = new NewThreadContext(entryPoint, data, name); - - // Prevent the thread body from executing until we've established the thread identifier. - MutexLocker locker(context->creationMutex); - - return createThreadInternal(threadEntryPoint, context, name); -} - -#if PLATFORM(MAC) || PLATFORM(WIN) - -// For ABI compatibility with Safari on Mac / Windows: Safari uses the private -// createThread() and waitForThreadCompletion() functions directly and we need -// to keep the old ABI compatibility until it's been rebuilt. - -typedef void* (*ThreadFunctionWithReturnValue)(void* argument); - -WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data, const char* name); - -struct ThreadFunctionWithReturnValueInvocation { - ThreadFunctionWithReturnValueInvocation(ThreadFunctionWithReturnValue function, void* data) - : function(function) - , data(data) - { - } - - ThreadFunctionWithReturnValue function; - void* data; -}; - -static void compatEntryPoint(void* param) -{ - // Balanced by .leakPtr() in createThread. - OwnPtr<ThreadFunctionWithReturnValueInvocation> invocation = adoptPtr(static_cast<ThreadFunctionWithReturnValueInvocation*>(param)); - invocation->function(invocation->data); -} - -ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data, const char* name) -{ - OwnPtr<ThreadFunctionWithReturnValueInvocation> invocation = adoptPtr(new ThreadFunctionWithReturnValueInvocation(entryPoint, data)); - - // Balanced by adoptPtr() in compatEntryPoint. - return createThread(compatEntryPoint, invocation.leakPtr(), name); -} - -WTF_EXPORT_PRIVATE int waitForThreadCompletion(ThreadIdentifier, void**); - -int waitForThreadCompletion(ThreadIdentifier threadID, void**) -{ - return waitForThreadCompletion(threadID); -} - -// This function is deprecated but needs to be kept around for backward -// compatibility. Use the 3-argument version of createThread above. - -WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data); - -ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data) -{ - OwnPtr<ThreadFunctionWithReturnValueInvocation> invocation = adoptPtr(new ThreadFunctionWithReturnValueInvocation(entryPoint, data)); - - // Balanced by adoptPtr() in compatEntryPoint. - return createThread(compatEntryPoint, invocation.leakPtr(), 0); -} -#endif - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/Threading.h b/Source/JavaScriptCore/wtf/Threading.h deleted file mode 100644 index 3e558fc68..000000000 --- a/Source/JavaScriptCore/wtf/Threading.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * 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. - * - * - * Note: The implementations of InterlockedIncrement and InterlockedDecrement are based - * on atomic_increment and atomic_exchange_and_add from the Boost C++ Library. The license - * is virtually identical to the Apple license above but is included here for completeness. - * - * Boost Software License - Version 1.0 - August 17th, 2003 - * - * Permission is hereby granted, free of charge, to any person or organization - * obtaining a copy of the software and accompanying documentation covered by - * this license (the "Software") to use, reproduce, display, distribute, - * execute, and transmit the Software, and to prepare derivative works of the - * Software, and to permit third-parties to whom the Software is furnished to - * do so, all subject to the following: - * - * The copyright notices in the Software and this entire statement, including - * the above license grant, this restriction and the following disclaimer, - * must be included in all copies of the Software, in whole or in part, and - * all derivative works of the Software, unless such copies or derivative - * works are solely in the form of machine-executable object code generated by - * a source language processor. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT - * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE - * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef Threading_h -#define Threading_h - -#include <wtf/Platform.h> - -#include <stdint.h> -#include <wtf/Assertions.h> -#include <wtf/Atomics.h> -#include <wtf/Locker.h> -#include <wtf/Noncopyable.h> -#include <wtf/ThreadSafeRefCounted.h> -#include <wtf/ThreadingPrimitives.h> - -// For portability, we do not use thread-safe statics natively supported by some compilers (e.g. gcc). -#define AtomicallyInitializedStatic(T, name) \ - WTF::lockAtomicallyInitializedStaticMutex(); \ - static T name; \ - WTF::unlockAtomicallyInitializedStaticMutex(); - -namespace WTF { - -typedef uint32_t ThreadIdentifier; -typedef void (*ThreadFunction)(void* argument); - -// This function must be called from the main thread. It is safe to call it repeatedly. -// Darwin is an exception to this rule: it is OK to call it from any thread, the only -// requirement is that the calls are not reentrant. -WTF_EXPORT_PRIVATE void initializeThreading(); - -// Returns 0 if thread creation failed. -// The thread name must be a literal since on some platforms it's passed in to the thread. -WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunction, void*, const char* threadName); - -// Internal platform-specific createThread implementation. -ThreadIdentifier createThreadInternal(ThreadFunction, void*, const char* threadName); - -// Called in the thread during initialization. -// Helpful for platforms where the thread name must be set from within the thread. -void initializeCurrentThreadInternal(const char* threadName); - -WTF_EXPORT_PRIVATE ThreadIdentifier currentThread(); -WTF_EXPORT_PRIVATE int waitForThreadCompletion(ThreadIdentifier); -WTF_EXPORT_PRIVATE void detachThread(ThreadIdentifier); - -WTF_EXPORT_PRIVATE void yield(); - -WTF_EXPORT_PRIVATE void lockAtomicallyInitializedStaticMutex(); -WTF_EXPORT_PRIVATE void unlockAtomicallyInitializedStaticMutex(); - -} // namespace WTF - -using WTF::ThreadIdentifier; -using WTF::createThread; -using WTF::currentThread; -using WTF::detachThread; -using WTF::waitForThreadCompletion; -using WTF::yield; - -#endif // Threading_h diff --git a/Source/JavaScriptCore/wtf/ThreadingNone.cpp b/Source/JavaScriptCore/wtf/ThreadingNone.cpp deleted file mode 100644 index e69de29bb..000000000 --- a/Source/JavaScriptCore/wtf/ThreadingNone.cpp +++ /dev/null diff --git a/Source/JavaScriptCore/wtf/ThreadingPrimitives.h b/Source/JavaScriptCore/wtf/ThreadingPrimitives.h deleted file mode 100644 index 9ed38bc9f..000000000 --- a/Source/JavaScriptCore/wtf/ThreadingPrimitives.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * 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 ThreadingPrimitives_h -#define ThreadingPrimitives_h - -#include <wtf/Platform.h> - -#include <wtf/Assertions.h> -#include <wtf/FastAllocBase.h> -#include <wtf/Locker.h> -#include <wtf/Noncopyable.h> - -#if OS(WINDOWS) -#include <windows.h> -#endif - -#if USE(PTHREADS) -#include <pthread.h> -#endif - -namespace WTF { - -#if USE(PTHREADS) -typedef pthread_mutex_t PlatformMutex; -#if HAVE(PTHREAD_RWLOCK) -typedef pthread_rwlock_t PlatformReadWriteLock; -#else -typedef void* PlatformReadWriteLock; -#endif -typedef pthread_cond_t PlatformCondition; -#elif OS(WINDOWS) -struct PlatformMutex { - CRITICAL_SECTION m_internalMutex; - size_t m_recursionCount; -}; -typedef void* PlatformReadWriteLock; // FIXME: Implement. -struct PlatformCondition { - size_t m_waitersGone; - size_t m_waitersBlocked; - size_t m_waitersToUnblock; - HANDLE m_blockLock; - HANDLE m_blockQueue; - HANDLE m_unblockLock; - - bool timedWait(PlatformMutex&, DWORD durationMilliseconds); - void signal(bool unblockAll); -}; -#else -typedef void* PlatformMutex; -typedef void* PlatformReadWriteLock; -typedef void* PlatformCondition; -#endif - -class Mutex { - WTF_MAKE_NONCOPYABLE(Mutex); WTF_MAKE_FAST_ALLOCATED; -public: - WTF_EXPORT_PRIVATE Mutex(); - WTF_EXPORT_PRIVATE ~Mutex(); - - WTF_EXPORT_PRIVATE void lock(); - WTF_EXPORT_PRIVATE bool tryLock(); - WTF_EXPORT_PRIVATE void unlock(); - -public: - PlatformMutex& impl() { return m_mutex; } -private: - PlatformMutex m_mutex; -}; - -typedef Locker<Mutex> MutexLocker; - -class ReadWriteLock { - WTF_MAKE_NONCOPYABLE(ReadWriteLock); -public: - ReadWriteLock(); - ~ReadWriteLock(); - - void readLock(); - bool tryReadLock(); - - void writeLock(); - bool tryWriteLock(); - - void unlock(); - -private: - PlatformReadWriteLock m_readWriteLock; -}; - -class ThreadCondition { - WTF_MAKE_NONCOPYABLE(ThreadCondition); -public: - WTF_EXPORT_PRIVATE ThreadCondition(); - WTF_EXPORT_PRIVATE ~ThreadCondition(); - - WTF_EXPORT_PRIVATE void wait(Mutex& mutex); - // Returns true if the condition was signaled before absoluteTime, false if the absoluteTime was reached or is in the past. - // The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). - WTF_EXPORT_PRIVATE bool timedWait(Mutex&, double absoluteTime); - WTF_EXPORT_PRIVATE void signal(); - WTF_EXPORT_PRIVATE void broadcast(); - -private: - PlatformCondition m_condition; -}; - -#if OS(WINDOWS) -// The absoluteTime is in seconds, starting on January 1, 1970. The time is assumed to use the same time zone as WTF::currentTime(). -// Returns an interval in milliseconds suitable for passing to one of the Win32 wait functions (e.g., ::WaitForSingleObject). -DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime); -#endif - -} // namespace WTF - -using WTF::Mutex; -using WTF::MutexLocker; -using WTF::ThreadCondition; - -#if OS(WINDOWS) -using WTF::absoluteTimeToWaitTimeoutInterval; -#endif - -#endif // ThreadingPrimitives_h diff --git a/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp b/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp deleted file mode 100644 index abd350dbb..000000000 --- a/Source/JavaScriptCore/wtf/ThreadingPthreads.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* - * Copyright (C) 2007, 2009 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * Copyright (C) 2011 Research In Motion Limited. 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. - */ - -#include "config.h" -#include "Threading.h" - -#if USE(PTHREADS) - -#include "CurrentTime.h" -#include "DateMath.h" -#include "dtoa.h" -#include "dtoa/cached-powers.h" -#include "HashMap.h" -#include "RandomNumberSeed.h" -#include "StdLibExtras.h" -#include "ThreadFunctionInvocation.h" -#include "ThreadIdentifierDataPthreads.h" -#include "ThreadSpecific.h" -#include "UnusedParam.h" -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/WTFThreadData.h> -#include <errno.h> - -#if !COMPILER(MSVC) -#include <limits.h> -#include <sched.h> -#include <sys/time.h> -#endif - -#if OS(MAC_OS_X) && !defined(BUILDING_ON_LEOPARD) -#include <objc/objc-auto.h> -#endif - -#if PLATFORM(BLACKBERRY) -#include <BlackBerryPlatformMisc.h> -#include <BlackBerryPlatformSettings.h> -#endif - -namespace WTF { - -typedef HashMap<ThreadIdentifier, pthread_t> ThreadMap; - -static Mutex* atomicallyInitializedStaticMutex; - -void clearPthreadHandleForIdentifier(ThreadIdentifier); - -static Mutex& threadMapMutex() -{ - DEFINE_STATIC_LOCAL(Mutex, mutex, ()); - return mutex; -} - -void initializeThreading() -{ - if (atomicallyInitializedStaticMutex) - return; - - WTF::double_conversion::initialize(); - // StringImpl::empty() does not construct its static string in a threadsafe fashion, - // so ensure it has been initialized from here. - StringImpl::empty(); - atomicallyInitializedStaticMutex = new Mutex; - threadMapMutex(); - initializeRandomNumberGenerator(); - ThreadIdentifierData::initializeOnce(); - wtfThreadData(); - s_dtoaP5Mutex = new Mutex; - initializeDates(); -} - -void lockAtomicallyInitializedStaticMutex() -{ - ASSERT(atomicallyInitializedStaticMutex); - atomicallyInitializedStaticMutex->lock(); -} - -void unlockAtomicallyInitializedStaticMutex() -{ - atomicallyInitializedStaticMutex->unlock(); -} - -static ThreadMap& threadMap() -{ - DEFINE_STATIC_LOCAL(ThreadMap, map, ()); - return map; -} - -static ThreadIdentifier identifierByPthreadHandle(const pthread_t& pthreadHandle) -{ - MutexLocker locker(threadMapMutex()); - - ThreadMap::iterator i = threadMap().begin(); - for (; i != threadMap().end(); ++i) { - if (pthread_equal(i->second, pthreadHandle)) - return i->first; - } - - return 0; -} - -static ThreadIdentifier establishIdentifierForPthreadHandle(const pthread_t& pthreadHandle) -{ - ASSERT(!identifierByPthreadHandle(pthreadHandle)); - - MutexLocker locker(threadMapMutex()); - - static ThreadIdentifier identifierCount = 1; - - threadMap().add(identifierCount, pthreadHandle); - - return identifierCount++; -} - -static pthread_t pthreadHandleForIdentifier(ThreadIdentifier id) -{ - MutexLocker locker(threadMapMutex()); - - return threadMap().get(id); -} - -void clearPthreadHandleForIdentifier(ThreadIdentifier id) -{ - MutexLocker locker(threadMapMutex()); - - ASSERT(threadMap().contains(id)); - - threadMap().remove(id); -} - -static void* wtfThreadEntryPoint(void* param) -{ - // Balanced by .leakPtr() in createThreadInternal. - OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param)); - invocation->function(invocation->data); - - return 0; -} - -#if PLATFORM(BLACKBERRY) -ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* threadName) -{ - pthread_attr_t attr; - if (pthread_attr_init(&attr)) { - LOG_ERROR("pthread_attr_init() failed: %d", errno); - return 0; - } - - void* stackAddr; - size_t stackSize; - if (pthread_attr_getstack(&attr, &stackAddr, &stackSize)) - LOG_ERROR("pthread_attr_getstack() failed: %d", errno); - else { - stackSize = BlackBerry::Platform::Settings::get()->secondaryThreadStackSize(); - if (pthread_attr_setstack(&attr, stackAddr, stackSize)) - LOG_ERROR("pthread_attr_getstack() failed: %d", errno); - } - - OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data)); - pthread_t threadHandle; - if (pthread_create(&threadHandle, &attr, wtfThreadEntryPoint, invocation.get())) { - LOG_ERROR("pthread_create() failed: %d", errno); - threadHandle = 0; - } - pthread_setname_np(threadHandle, threadName); - - pthread_attr_destroy(&attr); - - if (!threadHandle) - return 0; - - // Balanced by adoptPtr() in wtfThreadEntryPoint. - ThreadFunctionInvocation* leakedInvocation = invocation.leakPtr(); - UNUSED_PARAM(leakedInvocation); - - return establishIdentifierForPthreadHandle(threadHandle); -} -#else -ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char*) -{ - OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data)); - pthread_t threadHandle; - if (pthread_create(&threadHandle, 0, wtfThreadEntryPoint, invocation.get())) { - LOG_ERROR("Failed to create pthread at entry point %p with data %p", wtfThreadEntryPoint, invocation.get()); - return 0; - } - - // Balanced by adoptPtr() in wtfThreadEntryPoint. - ThreadFunctionInvocation* leakedInvocation = invocation.leakPtr(); - UNUSED_PARAM(leakedInvocation); - - return establishIdentifierForPthreadHandle(threadHandle); -} -#endif - -void initializeCurrentThreadInternal(const char* threadName) -{ -#if HAVE(PTHREAD_SETNAME_NP) - pthread_setname_np(threadName); -#else - UNUSED_PARAM(threadName); -#endif - -#if OS(MAC_OS_X) && !defined(BUILDING_ON_LEOPARD) - // All threads that potentially use APIs above the BSD layer must be registered with the Objective-C - // garbage collector in case API implementations use garbage-collected memory. - objc_registerThreadWithCollector(); -#endif - - ThreadIdentifier id = identifierByPthreadHandle(pthread_self()); - ASSERT(id); - ThreadIdentifierData::initialize(id); -} - -int waitForThreadCompletion(ThreadIdentifier threadID) -{ - ASSERT(threadID); - - pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID); - if (!pthreadHandle) - return 0; - - int joinResult = pthread_join(pthreadHandle, 0); - if (joinResult == EDEADLK) - LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID); - - return joinResult; -} - -void detachThread(ThreadIdentifier threadID) -{ - ASSERT(threadID); - - pthread_t pthreadHandle = pthreadHandleForIdentifier(threadID); - if (!pthreadHandle) - return; - - pthread_detach(pthreadHandle); -} - -void yield() -{ - sched_yield(); -} - -ThreadIdentifier currentThread() -{ - ThreadIdentifier id = ThreadIdentifierData::identifier(); - if (id) - return id; - - // Not a WTF-created thread, ThreadIdentifier is not established yet. - id = establishIdentifierForPthreadHandle(pthread_self()); - ThreadIdentifierData::initialize(id); - return id; -} - -Mutex::Mutex() -{ - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); - - pthread_mutex_init(&m_mutex, &attr); - - pthread_mutexattr_destroy(&attr); -} - -Mutex::~Mutex() -{ - pthread_mutex_destroy(&m_mutex); -} - -void Mutex::lock() -{ - int result = pthread_mutex_lock(&m_mutex); - ASSERT_UNUSED(result, !result); -} - -bool Mutex::tryLock() -{ - int result = pthread_mutex_trylock(&m_mutex); - - if (result == 0) - return true; - if (result == EBUSY) - return false; - - ASSERT_NOT_REACHED(); - return false; -} - -void Mutex::unlock() -{ - int result = pthread_mutex_unlock(&m_mutex); - ASSERT_UNUSED(result, !result); -} - -#if HAVE(PTHREAD_RWLOCK) -ReadWriteLock::ReadWriteLock() -{ - pthread_rwlock_init(&m_readWriteLock, NULL); -} - -ReadWriteLock::~ReadWriteLock() -{ - pthread_rwlock_destroy(&m_readWriteLock); -} - -void ReadWriteLock::readLock() -{ - int result = pthread_rwlock_rdlock(&m_readWriteLock); - ASSERT_UNUSED(result, !result); -} - -bool ReadWriteLock::tryReadLock() -{ - int result = pthread_rwlock_tryrdlock(&m_readWriteLock); - - if (result == 0) - return true; - if (result == EBUSY || result == EAGAIN) - return false; - - ASSERT_NOT_REACHED(); - return false; -} - -void ReadWriteLock::writeLock() -{ - int result = pthread_rwlock_wrlock(&m_readWriteLock); - ASSERT_UNUSED(result, !result); -} - -bool ReadWriteLock::tryWriteLock() -{ - int result = pthread_rwlock_trywrlock(&m_readWriteLock); - - if (result == 0) - return true; - if (result == EBUSY || result == EAGAIN) - return false; - - ASSERT_NOT_REACHED(); - return false; -} - -void ReadWriteLock::unlock() -{ - int result = pthread_rwlock_unlock(&m_readWriteLock); - ASSERT_UNUSED(result, !result); -} -#endif // HAVE(PTHREAD_RWLOCK) - -ThreadCondition::ThreadCondition() -{ - pthread_cond_init(&m_condition, NULL); -} - -ThreadCondition::~ThreadCondition() -{ - pthread_cond_destroy(&m_condition); -} - -void ThreadCondition::wait(Mutex& mutex) -{ - int result = pthread_cond_wait(&m_condition, &mutex.impl()); - ASSERT_UNUSED(result, !result); -} - -bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) -{ - if (absoluteTime < currentTime()) - return false; - - if (absoluteTime > INT_MAX) { - wait(mutex); - return true; - } - - int timeSeconds = static_cast<int>(absoluteTime); - int timeNanoseconds = static_cast<int>((absoluteTime - timeSeconds) * 1E9); - - timespec targetTime; - targetTime.tv_sec = timeSeconds; - targetTime.tv_nsec = timeNanoseconds; - - return pthread_cond_timedwait(&m_condition, &mutex.impl(), &targetTime) == 0; -} - -void ThreadCondition::signal() -{ - int result = pthread_cond_signal(&m_condition); - ASSERT_UNUSED(result, !result); -} - -void ThreadCondition::broadcast() -{ - int result = pthread_cond_broadcast(&m_condition); - ASSERT_UNUSED(result, !result); -} - -} // namespace WTF - -#endif // USE(PTHREADS) diff --git a/Source/JavaScriptCore/wtf/ThreadingWin.cpp b/Source/JavaScriptCore/wtf/ThreadingWin.cpp deleted file mode 100644 index bc32262ce..000000000 --- a/Source/JavaScriptCore/wtf/ThreadingWin.cpp +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2009 Torch Mobile, 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. - */ - -/* - * There are numerous academic and practical works on how to implement pthread_cond_wait/pthread_cond_signal/pthread_cond_broadcast - * functions on Win32. Here is one example: http://www.cs.wustl.edu/~schmidt/win32-cv-1.html which is widely credited as a 'starting point' - * of modern attempts. There are several more or less proven implementations, one in Boost C++ library (http://www.boost.org) and another - * in pthreads-win32 (http://sourceware.org/pthreads-win32/). - * - * The number of articles and discussions is the evidence of significant difficulties in implementing these primitives correctly. - * The brief search of revisions, ChangeLog entries, discussions in comp.programming.threads and other places clearly documents - * numerous pitfalls and performance problems the authors had to overcome to arrive to the suitable implementations. - * Optimally, WebKit would use one of those supported/tested libraries directly. To roll out our own implementation is impractical, - * if even for the lack of sufficient testing. However, a faithful reproduction of the code from one of the popular supported - * libraries seems to be a good compromise. - * - * The early Boost implementation (http://www.boxbackup.org/trac/browser/box/nick/win/lib/win32/boost_1_32_0/libs/thread/src/condition.cpp?rev=30) - * is identical to pthreads-win32 (http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32). - * Current Boost uses yet another (although seemingly equivalent) algorithm which came from their 'thread rewrite' effort. - * - * This file includes timedWait/signal/broadcast implementations translated to WebKit coding style from the latest algorithm by - * Alexander Terekhov and Louis Thomas, as captured here: http://sourceware.org/cgi-bin/cvsweb.cgi/pthreads/pthread_cond_wait.c?rev=1.10&content-type=text/x-cvsweb-markup&cvsroot=pthreads-win32 - * It replaces the implementation of their previous algorithm, also documented in the same source above. - * The naming and comments are left very close to original to enable easy cross-check. - * - * The corresponding Pthreads-win32 License is included below, and CONTRIBUTORS file which it refers to is added to - * source directory (as CONTRIBUTORS.pthreads-win32). - */ - -/* - * Pthreads-win32 - POSIX Threads Library for Win32 - * Copyright(C) 1998 John E. Bossom - * Copyright(C) 1999,2005 Pthreads-win32 contributors - * - * Contact Email: rpj@callisto.canberra.edu.au - * - * The current list of contributors is contained - * in the file CONTRIBUTORS included with the source - * code distribution. The list can also be seen at the - * following World Wide Web location: - * http://sources.redhat.com/pthreads-win32/contributors.html - * - * 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 in the file COPYING.LIB; - * if not, write to the Free Software Foundation, Inc., - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -#include "config.h" -#include "Threading.h" -#include "DateMath.h" -#include "dtoa.h" -#include "dtoa/cached-powers.h" - -#include "MainThread.h" -#include "ThreadFunctionInvocation.h" -#include <windows.h> -#include <wtf/CurrentTime.h> -#include <wtf/HashMap.h> -#include <wtf/MathExtras.h> -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/RandomNumberSeed.h> -#include <wtf/WTFThreadData.h> - -#if !USE(PTHREADS) && OS(WINDOWS) -#include "ThreadSpecific.h" -#endif - -#if !OS(WINCE) -#include <process.h> -#endif - -#if HAVE(ERRNO_H) -#include <errno.h> -#endif - -namespace WTF { - -// MS_VC_EXCEPTION, THREADNAME_INFO, and setThreadNameInternal all come from <http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx>. -static const DWORD MS_VC_EXCEPTION = 0x406D1388; - -#pragma pack(push, 8) -typedef struct tagTHREADNAME_INFO { - DWORD dwType; // must be 0x1000 - LPCSTR szName; // pointer to name (in user addr space) - DWORD dwThreadID; // thread ID (-1=caller thread) - DWORD dwFlags; // reserved for future use, must be zero -} THREADNAME_INFO; -#pragma pack(pop) - -void initializeCurrentThreadInternal(const char* szThreadName) -{ -#if COMPILER(MINGW) - // FIXME: Implement thread name setting with MingW. - UNUSED_PARAM(szThreadName); -#else - THREADNAME_INFO info; - info.dwType = 0x1000; - info.szName = szThreadName; - info.dwThreadID = GetCurrentThreadId(); - info.dwFlags = 0; - - __try { - RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), reinterpret_cast<ULONG_PTR*>(&info)); - } __except (EXCEPTION_CONTINUE_EXECUTION) { - } -#endif -} - -static Mutex* atomicallyInitializedStaticMutex; - -void lockAtomicallyInitializedStaticMutex() -{ - ASSERT(atomicallyInitializedStaticMutex); - atomicallyInitializedStaticMutex->lock(); -} - -void unlockAtomicallyInitializedStaticMutex() -{ - atomicallyInitializedStaticMutex->unlock(); -} - -static Mutex& threadMapMutex() -{ - static Mutex mutex; - return mutex; -} - -void initializeThreading() -{ - if (atomicallyInitializedStaticMutex) - return; - - WTF::double_conversion::initialize(); - // StringImpl::empty() does not construct its static string in a threadsafe fashion, - // so ensure it has been initialized from here. - StringImpl::empty(); - atomicallyInitializedStaticMutex = new Mutex; - threadMapMutex(); - initializeRandomNumberGenerator(); - wtfThreadData(); - s_dtoaP5Mutex = new Mutex; - initializeDates(); -} - -static HashMap<DWORD, HANDLE>& threadMap() -{ - static HashMap<DWORD, HANDLE> map; - return map; -} - -static void storeThreadHandleByIdentifier(DWORD threadID, HANDLE threadHandle) -{ - MutexLocker locker(threadMapMutex()); - ASSERT(!threadMap().contains(threadID)); - threadMap().add(threadID, threadHandle); -} - -static HANDLE threadHandleForIdentifier(ThreadIdentifier id) -{ - MutexLocker locker(threadMapMutex()); - return threadMap().get(id); -} - -static void clearThreadHandleForIdentifier(ThreadIdentifier id) -{ - MutexLocker locker(threadMapMutex()); - ASSERT(threadMap().contains(id)); - threadMap().remove(id); -} - -static unsigned __stdcall wtfThreadEntryPoint(void* param) -{ - OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(static_cast<ThreadFunctionInvocation*>(param)); - invocation->function(invocation->data); - -#if !USE(PTHREADS) && OS(WINDOWS) - // Do the TLS cleanup. - ThreadSpecificThreadExit(); -#endif - - return 0; -} - -ThreadIdentifier createThreadInternal(ThreadFunction entryPoint, void* data, const char* threadName) -{ - unsigned threadIdentifier = 0; - ThreadIdentifier threadID = 0; - OwnPtr<ThreadFunctionInvocation> invocation = adoptPtr(new ThreadFunctionInvocation(entryPoint, data)); -#if OS(WINCE) - // This is safe on WINCE, since CRT is in the core and innately multithreaded. - // On desktop Windows, need to use _beginthreadex (not available on WinCE) if using any CRT functions - HANDLE threadHandle = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)wtfThreadEntryPoint, invocation.get(), 0, (LPDWORD)&threadIdentifier); -#else - HANDLE threadHandle = reinterpret_cast<HANDLE>(_beginthreadex(0, 0, wtfThreadEntryPoint, invocation.get(), 0, &threadIdentifier)); -#endif - if (!threadHandle) { -#if OS(WINCE) - LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, ::GetLastError()); -#elif !HAVE(ERRNO_H) - LOG_ERROR("Failed to create thread at entry point %p with data %p.", entryPoint, data); -#else - LOG_ERROR("Failed to create thread at entry point %p with data %p: %ld", entryPoint, data, errno); -#endif - return 0; - } - - // The thread will take ownership of invocation. - invocation.leakPtr(); - - threadID = static_cast<ThreadIdentifier>(threadIdentifier); - storeThreadHandleByIdentifier(threadIdentifier, threadHandle); - - return threadID; -} - -int waitForThreadCompletion(ThreadIdentifier threadID) -{ - ASSERT(threadID); - - HANDLE threadHandle = threadHandleForIdentifier(threadID); - if (!threadHandle) - LOG_ERROR("ThreadIdentifier %u did not correspond to an active thread when trying to quit", threadID); - - DWORD joinResult = WaitForSingleObject(threadHandle, INFINITE); - if (joinResult == WAIT_FAILED) - LOG_ERROR("ThreadIdentifier %u was found to be deadlocked trying to quit", threadID); - - CloseHandle(threadHandle); - clearThreadHandleForIdentifier(threadID); - - return joinResult; -} - -void detachThread(ThreadIdentifier threadID) -{ - ASSERT(threadID); - - HANDLE threadHandle = threadHandleForIdentifier(threadID); - if (threadHandle) - CloseHandle(threadHandle); - clearThreadHandleForIdentifier(threadID); -} - -void yield() -{ - ::Sleep(1); -} - -ThreadIdentifier currentThread() -{ - return static_cast<ThreadIdentifier>(GetCurrentThreadId()); -} - -Mutex::Mutex() -{ - m_mutex.m_recursionCount = 0; - InitializeCriticalSection(&m_mutex.m_internalMutex); -} - -Mutex::~Mutex() -{ - DeleteCriticalSection(&m_mutex.m_internalMutex); -} - -void Mutex::lock() -{ - EnterCriticalSection(&m_mutex.m_internalMutex); - ++m_mutex.m_recursionCount; -} - -bool Mutex::tryLock() -{ - // This method is modeled after the behavior of pthread_mutex_trylock, - // which will return an error if the lock is already owned by the - // current thread. Since the primitive Win32 'TryEnterCriticalSection' - // treats this as a successful case, it changes the behavior of several - // tests in WebKit that check to see if the current thread already - // owned this mutex (see e.g., IconDatabase::getOrCreateIconRecord) - DWORD result = TryEnterCriticalSection(&m_mutex.m_internalMutex); - - if (result != 0) { // We got the lock - // If this thread already had the lock, we must unlock and - // return false so that we mimic the behavior of POSIX's - // pthread_mutex_trylock: - if (m_mutex.m_recursionCount > 0) { - LeaveCriticalSection(&m_mutex.m_internalMutex); - return false; - } - - ++m_mutex.m_recursionCount; - return true; - } - - return false; -} - -void Mutex::unlock() -{ - --m_mutex.m_recursionCount; - LeaveCriticalSection(&m_mutex.m_internalMutex); -} - -bool PlatformCondition::timedWait(PlatformMutex& mutex, DWORD durationMilliseconds) -{ - // Enter the wait state. - DWORD res = WaitForSingleObject(m_blockLock, INFINITE); - ASSERT(res == WAIT_OBJECT_0); - ++m_waitersBlocked; - res = ReleaseSemaphore(m_blockLock, 1, 0); - ASSERT(res); - - --mutex.m_recursionCount; - LeaveCriticalSection(&mutex.m_internalMutex); - - // Main wait - use timeout. - bool timedOut = (WaitForSingleObject(m_blockQueue, durationMilliseconds) == WAIT_TIMEOUT); - - res = WaitForSingleObject(m_unblockLock, INFINITE); - ASSERT(res == WAIT_OBJECT_0); - - int signalsLeft = m_waitersToUnblock; - - if (m_waitersToUnblock) - --m_waitersToUnblock; - else if (++m_waitersGone == (INT_MAX / 2)) { // timeout/canceled or spurious semaphore - // timeout or spurious wakeup occured, normalize the m_waitersGone count - // this may occur if many calls to wait with a timeout are made and - // no call to notify_* is made - res = WaitForSingleObject(m_blockLock, INFINITE); - ASSERT(res == WAIT_OBJECT_0); - m_waitersBlocked -= m_waitersGone; - res = ReleaseSemaphore(m_blockLock, 1, 0); - ASSERT(res); - m_waitersGone = 0; - } - - res = ReleaseMutex(m_unblockLock); - ASSERT(res); - - if (signalsLeft == 1) { - res = ReleaseSemaphore(m_blockLock, 1, 0); // Open the gate. - ASSERT(res); - } - - EnterCriticalSection (&mutex.m_internalMutex); - ++mutex.m_recursionCount; - - return !timedOut; -} - -void PlatformCondition::signal(bool unblockAll) -{ - unsigned signalsToIssue = 0; - - DWORD res = WaitForSingleObject(m_unblockLock, INFINITE); - ASSERT(res == WAIT_OBJECT_0); - - if (m_waitersToUnblock) { // the gate is already closed - if (!m_waitersBlocked) { // no-op - res = ReleaseMutex(m_unblockLock); - ASSERT(res); - return; - } - - if (unblockAll) { - signalsToIssue = m_waitersBlocked; - m_waitersToUnblock += m_waitersBlocked; - m_waitersBlocked = 0; - } else { - signalsToIssue = 1; - ++m_waitersToUnblock; - --m_waitersBlocked; - } - } else if (m_waitersBlocked > m_waitersGone) { - res = WaitForSingleObject(m_blockLock, INFINITE); // Close the gate. - ASSERT(res == WAIT_OBJECT_0); - if (m_waitersGone != 0) { - m_waitersBlocked -= m_waitersGone; - m_waitersGone = 0; - } - if (unblockAll) { - signalsToIssue = m_waitersBlocked; - m_waitersToUnblock = m_waitersBlocked; - m_waitersBlocked = 0; - } else { - signalsToIssue = 1; - m_waitersToUnblock = 1; - --m_waitersBlocked; - } - } else { // No-op. - res = ReleaseMutex(m_unblockLock); - ASSERT(res); - return; - } - - res = ReleaseMutex(m_unblockLock); - ASSERT(res); - - if (signalsToIssue) { - res = ReleaseSemaphore(m_blockQueue, signalsToIssue, 0); - ASSERT(res); - } -} - -static const long MaxSemaphoreCount = static_cast<long>(~0UL >> 1); - -ThreadCondition::ThreadCondition() -{ - m_condition.m_waitersGone = 0; - m_condition.m_waitersBlocked = 0; - m_condition.m_waitersToUnblock = 0; - m_condition.m_blockLock = CreateSemaphore(0, 1, 1, 0); - m_condition.m_blockQueue = CreateSemaphore(0, 0, MaxSemaphoreCount, 0); - m_condition.m_unblockLock = CreateMutex(0, 0, 0); - - if (!m_condition.m_blockLock || !m_condition.m_blockQueue || !m_condition.m_unblockLock) { - if (m_condition.m_blockLock) - CloseHandle(m_condition.m_blockLock); - if (m_condition.m_blockQueue) - CloseHandle(m_condition.m_blockQueue); - if (m_condition.m_unblockLock) - CloseHandle(m_condition.m_unblockLock); - } -} - -ThreadCondition::~ThreadCondition() -{ - CloseHandle(m_condition.m_blockLock); - CloseHandle(m_condition.m_blockQueue); - CloseHandle(m_condition.m_unblockLock); -} - -void ThreadCondition::wait(Mutex& mutex) -{ - m_condition.timedWait(mutex.impl(), INFINITE); -} - -bool ThreadCondition::timedWait(Mutex& mutex, double absoluteTime) -{ - DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime); - - if (!interval) { - // Consider the wait to have timed out, even if our condition has already been signaled, to - // match the pthreads implementation. - return false; - } - - return m_condition.timedWait(mutex.impl(), interval); -} - -void ThreadCondition::signal() -{ - m_condition.signal(false); // Unblock only 1 thread. -} - -void ThreadCondition::broadcast() -{ - m_condition.signal(true); // Unblock all threads. -} - -DWORD absoluteTimeToWaitTimeoutInterval(double absoluteTime) -{ - double currentTime = WTF::currentTime(); - - // Time is in the past - return immediately. - if (absoluteTime < currentTime) - return 0; - - // Time is too far in the future (and would overflow unsigned long) - wait forever. - if (absoluteTime - currentTime > static_cast<double>(INT_MAX) / 1000.0) - return INFINITE; - - return static_cast<DWORD>((absoluteTime - currentTime) * 1000.0); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/TypeTraits.cpp b/Source/JavaScriptCore/wtf/TypeTraits.cpp deleted file mode 100644 index 7cea256b7..000000000 --- a/Source/JavaScriptCore/wtf/TypeTraits.cpp +++ /dev/null @@ -1,155 +0,0 @@ - /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009, 2010 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * 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 "TypeTraits.h" - -#include "Assertions.h" - -namespace WTF { - -COMPILE_ASSERT(IsInteger<bool>::value, WTF_IsInteger_bool_true); -COMPILE_ASSERT(IsInteger<char>::value, WTF_IsInteger_char_true); -COMPILE_ASSERT(IsInteger<signed char>::value, WTF_IsInteger_signed_char_true); -COMPILE_ASSERT(IsInteger<unsigned char>::value, WTF_IsInteger_unsigned_char_true); -COMPILE_ASSERT(IsInteger<short>::value, WTF_IsInteger_short_true); -COMPILE_ASSERT(IsInteger<unsigned short>::value, WTF_IsInteger_unsigned_short_true); -COMPILE_ASSERT(IsInteger<int>::value, WTF_IsInteger_int_true); -COMPILE_ASSERT(IsInteger<unsigned int>::value, WTF_IsInteger_unsigned_int_true); -COMPILE_ASSERT(IsInteger<long>::value, WTF_IsInteger_long_true); -COMPILE_ASSERT(IsInteger<unsigned long>::value, WTF_IsInteger_unsigned_long_true); -COMPILE_ASSERT(IsInteger<long long>::value, WTF_IsInteger_long_long_true); -COMPILE_ASSERT(IsInteger<unsigned long long>::value, WTF_IsInteger_unsigned_long_long_true); -#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) -COMPILE_ASSERT(IsInteger<wchar_t>::value, WTF_IsInteger_wchar_t_true); -#endif -COMPILE_ASSERT(!IsInteger<char*>::value, WTF_IsInteger_char_pointer_false); -COMPILE_ASSERT(!IsInteger<const char*>::value, WTF_IsInteger_const_char_pointer_false); -COMPILE_ASSERT(!IsInteger<volatile char*>::value, WTF_IsInteger_volatile_char_pointer_false); -COMPILE_ASSERT(!IsInteger<double>::value, WTF_IsInteger_double_false); -COMPILE_ASSERT(!IsInteger<float>::value, WTF_IsInteger_float_false); - -COMPILE_ASSERT(IsFloatingPoint<float>::value, WTF_IsFloatingPoint_float_true); -COMPILE_ASSERT(IsFloatingPoint<double>::value, WTF_IsFloatingPoint_double_true); -COMPILE_ASSERT(IsFloatingPoint<long double>::value, WTF_IsFloatingPoint_long_double_true); -COMPILE_ASSERT(!IsFloatingPoint<int>::value, WTF_IsFloatingPoint_int_false); - -COMPILE_ASSERT(IsPod<bool>::value, WTF_IsPod_bool_true); -COMPILE_ASSERT(IsPod<char>::value, WTF_IsPod_char_true); -COMPILE_ASSERT(IsPod<signed char>::value, WTF_IsPod_signed_char_true); -COMPILE_ASSERT(IsPod<unsigned char>::value, WTF_IsPod_unsigned_char_true); -COMPILE_ASSERT(IsPod<short>::value, WTF_IsPod_short_true); -COMPILE_ASSERT(IsPod<unsigned short>::value, WTF_IsPod_unsigned_short_true); -COMPILE_ASSERT(IsPod<int>::value, WTF_IsPod_int_true); -COMPILE_ASSERT(IsPod<unsigned int>::value, WTF_IsPod_unsigned_int_true); -COMPILE_ASSERT(IsPod<long>::value, WTF_IsPod_long_true); -COMPILE_ASSERT(IsPod<unsigned long>::value, WTF_IsPod_unsigned_long_true); -COMPILE_ASSERT(IsPod<long long>::value, WTF_IsPod_long_long_true); -COMPILE_ASSERT(IsPod<unsigned long long>::value, WTF_IsPod_unsigned_long_long_true); -#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) -COMPILE_ASSERT(IsPod<wchar_t>::value, WTF_IsPod_wchar_t_true); -#endif -COMPILE_ASSERT(IsPod<char*>::value, WTF_IsPod_char_pointer_true); -COMPILE_ASSERT(IsPod<const char*>::value, WTF_IsPod_const_char_pointer_true); -COMPILE_ASSERT(IsPod<volatile char*>::value, WTF_IsPod_volatile_char_pointer_true); -COMPILE_ASSERT(IsPod<double>::value, WTF_IsPod_double_true); -COMPILE_ASSERT(IsPod<long double>::value, WTF_IsPod_long_double_true); -COMPILE_ASSERT(IsPod<float>::value, WTF_IsPod_float_true); -COMPILE_ASSERT(!IsPod<IsPod<bool> >::value, WTF_IsPod_struct_false); - -enum IsConvertibleToIntegerCheck { }; -COMPILE_ASSERT(IsConvertibleToInteger<IsConvertibleToIntegerCheck>::value, WTF_IsConvertibleToInteger_enum_true); -COMPILE_ASSERT(IsConvertibleToInteger<bool>::value, WTF_IsConvertibleToInteger_bool_true); -COMPILE_ASSERT(IsConvertibleToInteger<char>::value, WTF_IsConvertibleToInteger_char_true); -COMPILE_ASSERT(IsConvertibleToInteger<signed char>::value, WTF_IsConvertibleToInteger_signed_char_true); -COMPILE_ASSERT(IsConvertibleToInteger<unsigned char>::value, WTF_IsConvertibleToInteger_unsigned_char_true); -COMPILE_ASSERT(IsConvertibleToInteger<short>::value, WTF_IsConvertibleToInteger_short_true); -COMPILE_ASSERT(IsConvertibleToInteger<unsigned short>::value, WTF_IsConvertibleToInteger_unsigned_short_true); -COMPILE_ASSERT(IsConvertibleToInteger<int>::value, WTF_IsConvertibleToInteger_int_true); -COMPILE_ASSERT(IsConvertibleToInteger<unsigned int>::value, WTF_IsConvertibleToInteger_unsigned_int_true); -COMPILE_ASSERT(IsConvertibleToInteger<long>::value, WTF_IsConvertibleToInteger_long_true); -COMPILE_ASSERT(IsConvertibleToInteger<unsigned long>::value, WTF_IsConvertibleToInteger_unsigned_long_true); -COMPILE_ASSERT(IsConvertibleToInteger<long long>::value, WTF_IsConvertibleToInteger_long_long_true); -COMPILE_ASSERT(IsConvertibleToInteger<unsigned long long>::value, WTF_IsConvertibleToInteger_unsigned_long_long_true); -#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) -COMPILE_ASSERT(IsConvertibleToInteger<wchar_t>::value, WTF_IsConvertibleToInteger_wchar_t_true); -#endif -COMPILE_ASSERT(IsConvertibleToInteger<double>::value, WTF_IsConvertibleToInteger_double_true); -COMPILE_ASSERT(IsConvertibleToInteger<long double>::value, WTF_IsConvertibleToInteger_long_double_true); -COMPILE_ASSERT(IsConvertibleToInteger<float>::value, WTF_IsConvertibleToInteger_float_true); -COMPILE_ASSERT(!IsConvertibleToInteger<char*>::value, WTF_IsConvertibleToInteger_char_pointer_false); -COMPILE_ASSERT(!IsConvertibleToInteger<const char*>::value, WTF_IsConvertibleToInteger_const_char_pointer_false); -COMPILE_ASSERT(!IsConvertibleToInteger<volatile char*>::value, WTF_IsConvertibleToInteger_volatile_char_pointer_false); -COMPILE_ASSERT(!IsConvertibleToInteger<IsConvertibleToInteger<bool> >::value, WTF_IsConvertibleToInteger_struct_false); - -COMPILE_ASSERT((IsSameType<bool, bool>::value), WTF_IsSameType_bool_true); -COMPILE_ASSERT((IsSameType<int*, int*>::value), WTF_IsSameType_int_pointer_true); -COMPILE_ASSERT((!IsSameType<int, int*>::value), WTF_IsSameType_int_int_pointer_false); -COMPILE_ASSERT((!IsSameType<bool, const bool>::value), WTF_IsSameType_const_change_false); -COMPILE_ASSERT((!IsSameType<bool, volatile bool>::value), WTF_IsSameType_volatile_change_false); - -template <typename T> -class TestBaseClass { -}; - -class TestDerivedClass : public TestBaseClass<int> { -}; - -COMPILE_ASSERT((IsSubclass<TestDerivedClass, TestBaseClass<int> >::value), WTF_Test_IsSubclass_Derived_From_Base); -COMPILE_ASSERT((!IsSubclass<TestBaseClass<int>, TestDerivedClass>::value), WTF_Test_IsSubclass_Base_From_Derived); -COMPILE_ASSERT((IsSubclassOfTemplate<TestDerivedClass, TestBaseClass>::value), WTF_Test_IsSubclassOfTemplate_Base_From_Derived); -COMPILE_ASSERT((IsSameType<RemoveTemplate<TestBaseClass<int>, TestBaseClass>::Type, int>::value), WTF_Test_RemoveTemplate); -COMPILE_ASSERT((IsSameType<RemoveTemplate<int, TestBaseClass>::Type, int>::value), WTF_Test_RemoveTemplate_WithoutTemplate); - - -COMPILE_ASSERT((IsSameType<bool, RemoveConst<const bool>::Type>::value), WTF_test_RemoveConst_const_bool); -COMPILE_ASSERT((!IsSameType<bool, RemoveConst<volatile bool>::Type>::value), WTF_test_RemoveConst_volatile_bool); - -COMPILE_ASSERT((IsSameType<bool, RemoveVolatile<bool>::Type>::value), WTF_test_RemoveVolatile_bool); -COMPILE_ASSERT((!IsSameType<bool, RemoveVolatile<const bool>::Type>::value), WTF_test_RemoveVolatile_const_bool); -COMPILE_ASSERT((IsSameType<bool, RemoveVolatile<volatile bool>::Type>::value), WTF_test_RemoveVolatile_volatile_bool); - -COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<bool>::Type>::value), WTF_test_RemoveConstVolatile_bool); -COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<const bool>::Type>::value), WTF_test_RemoveConstVolatile_const_bool); -COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<volatile bool>::Type>::value), WTF_test_RemoveConstVolatile_volatile_bool); -COMPILE_ASSERT((IsSameType<bool, RemoveConstVolatile<const volatile bool>::Type>::value), WTF_test_RemoveConstVolatile_const_volatile_bool); - -COMPILE_ASSERT((IsSameType<int, RemovePointer<int>::Type>::value), WTF_Test_RemovePointer_int); -COMPILE_ASSERT((IsSameType<int, RemovePointer<int*>::Type>::value), WTF_Test_RemovePointer_int_pointer); -COMPILE_ASSERT((!IsSameType<int, RemovePointer<int**>::Type>::value), WTF_Test_RemovePointer_int_pointer_pointer); - -COMPILE_ASSERT((IsSameType<int, RemoveReference<int>::Type>::value), WTF_Test_RemoveReference_int); -COMPILE_ASSERT((IsSameType<int, RemoveReference<int&>::Type>::value), WTF_Test_RemoveReference_int_reference); - - -typedef int IntArray[]; -typedef int IntArraySized[4]; - -COMPILE_ASSERT((IsArray<IntArray>::value), WTF_Test_IsArray_int_array); -COMPILE_ASSERT((IsArray<IntArraySized>::value), WTF_Test_IsArray_int_sized_array); - -COMPILE_ASSERT((IsSameType<int, RemoveExtent<IntArray>::Type>::value), WTF_Test_RemoveExtent_int_array); -COMPILE_ASSERT((IsSameType<int, RemoveExtent<IntArraySized>::Type>::value), WTF_Test_RemoveReference_int_sized_array); - -COMPILE_ASSERT((IsSameType<int*, DecayArray<IntArray>::Type>::value), WTF_Test_DecayArray_int_array); -COMPILE_ASSERT((IsSameType<int*, DecayArray<IntArraySized>::Type>::value), WTF_Test_DecayArray_int_sized_array); - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/TypeTraits.h b/Source/JavaScriptCore/wtf/TypeTraits.h deleted file mode 100644 index bfed2aa7b..000000000 --- a/Source/JavaScriptCore/wtf/TypeTraits.h +++ /dev/null @@ -1,435 +0,0 @@ - /* - * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009, 2010 Google Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * 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 TypeTraits_h -#define TypeTraits_h - -#include <wtf/Platform.h> - -#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) -#include <type_traits> -#if defined(__GXX_EXPERIMENTAL_CXX0X__) -#include <tr1/memory> -#endif -#endif - -namespace WTF { - - // The following are provided in this file: - // - // Conditional<Predicate, If, Then>::Type - // - // IsInteger<T>::value - // IsPod<T>::value, see the definition for a note about its limitations - // IsConvertibleToInteger<T>::value - // - // IsArray<T>::value - // - // IsSameType<T, U>::value - // - // RemovePointer<T>::Type - // RemoveReference<T>::Type - // RemoveConst<T>::Type - // RemoveVolatile<T>::Type - // RemoveConstVolatile<T>::Type - // RemoveExtent<T>::Type - // - // DecayArray<T>::Type - // - // COMPILE_ASSERT's in TypeTraits.cpp illustrate their usage and what they do. - - template <bool Predicate, class If, class Then> struct Conditional { typedef If Type; }; - template <class If, class Then> struct Conditional<false, If, Then> { typedef Then Type; }; - - template<typename T> struct IsInteger { static const bool value = false; }; - template<> struct IsInteger<bool> { static const bool value = true; }; - template<> struct IsInteger<char> { static const bool value = true; }; - template<> struct IsInteger<signed char> { static const bool value = true; }; - template<> struct IsInteger<unsigned char> { static const bool value = true; }; - template<> struct IsInteger<short> { static const bool value = true; }; - template<> struct IsInteger<unsigned short> { static const bool value = true; }; - template<> struct IsInteger<int> { static const bool value = true; }; - template<> struct IsInteger<unsigned int> { static const bool value = true; }; - template<> struct IsInteger<long> { static const bool value = true; }; - template<> struct IsInteger<unsigned long> { static const bool value = true; }; - template<> struct IsInteger<long long> { static const bool value = true; }; - template<> struct IsInteger<unsigned long long> { static const bool value = true; }; -#if !COMPILER(MSVC) || defined(_NATIVE_WCHAR_T_DEFINED) - template<> struct IsInteger<wchar_t> { static const bool value = true; }; -#endif - - template<typename T> struct IsFloatingPoint { static const bool value = false; }; - template<> struct IsFloatingPoint<float> { static const bool value = true; }; - template<> struct IsFloatingPoint<double> { static const bool value = true; }; - template<> struct IsFloatingPoint<long double> { static const bool value = true; }; - - template<typename T> struct IsArithmetic { static const bool value = IsInteger<T>::value || IsFloatingPoint<T>::value; }; - - // IsPod is misnamed as it doesn't cover all plain old data (pod) types. - // Specifically, it doesn't allow for enums or for structs. - template <typename T> struct IsPod { static const bool value = IsArithmetic<T>::value; }; - template <typename P> struct IsPod<P*> { static const bool value = true; }; - - template<typename T> class IsConvertibleToInteger { - // Avoid "possible loss of data" warning when using Microsoft's C++ compiler - // by not converting int's to doubles. - template<bool performCheck, typename U> class IsConvertibleToDouble; - template<typename U> class IsConvertibleToDouble<false, U> { - public: - static const bool value = false; - }; - - template<typename U> class IsConvertibleToDouble<true, U> { - typedef char YesType; - struct NoType { - char padding[8]; - }; - - static YesType floatCheck(long double); - static NoType floatCheck(...); - static T& t; - public: - static const bool value = sizeof(floatCheck(t)) == sizeof(YesType); - }; - - public: - static const bool value = IsInteger<T>::value || IsConvertibleToDouble<!IsInteger<T>::value, T>::value; - }; - - - template <class T> struct IsArray { - static const bool value = false; - }; - - template <class T> struct IsArray<T[]> { - static const bool value = true; - }; - - template <class T, size_t N> struct IsArray<T[N]> { - static const bool value = true; - }; - - - template <typename T, typename U> struct IsSameType { - static const bool value = false; - }; - - template <typename T> struct IsSameType<T, T> { - static const bool value = true; - }; - - template <typename T, typename U> class IsSubclass { - typedef char YesType; - struct NoType { - char padding[8]; - }; - - static YesType subclassCheck(U*); - static NoType subclassCheck(...); - static T* t; - public: - static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); - }; - - template <typename T, template<class V> class U> class IsSubclassOfTemplate { - typedef char YesType; - struct NoType { - char padding[8]; - }; - - template<typename W> static YesType subclassCheck(U<W>*); - static NoType subclassCheck(...); - static T* t; - public: - static const bool value = sizeof(subclassCheck(t)) == sizeof(YesType); - }; - - template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate { - typedef T Type; - }; - - template <typename T, template <class V> class OuterTemplate> struct RemoveTemplate<OuterTemplate<T>, OuterTemplate> { - typedef T Type; - }; - - template <typename T> struct RemoveConst { - typedef T Type; - }; - - template <typename T> struct RemoveConst<const T> { - typedef T Type; - }; - - template <typename T> struct RemoveVolatile { - typedef T Type; - }; - - template <typename T> struct RemoveVolatile<volatile T> { - typedef T Type; - }; - - template <typename T> struct RemoveConstVolatile { - typedef typename RemoveVolatile<typename RemoveConst<T>::Type>::Type Type; - }; - - template <typename T> struct RemovePointer { - typedef T Type; - }; - - template <typename T> struct RemovePointer<T*> { - typedef T Type; - }; - - template <typename T> struct RemoveReference { - typedef T Type; - }; - - template <typename T> struct RemoveReference<T&> { - typedef T Type; - }; - - template <typename T> struct RemoveExtent { - typedef T Type; - }; - - template <typename T> struct RemoveExtent<T[]> { - typedef T Type; - }; - - template <typename T, size_t N> struct RemoveExtent<T[N]> { - typedef T Type; - }; - - template <class T> struct DecayArray { - typedef typename RemoveReference<T>::Type U; - public: - typedef typename Conditional< - IsArray<U>::value, - typename RemoveExtent<U>::Type*, - typename RemoveConstVolatile<U>::Type - >::Type Type; - }; - -#if (defined(__GLIBCXX__) && (__GLIBCXX__ >= 20070724) && defined(__GXX_EXPERIMENTAL_CXX0X__)) || (defined(_MSC_VER) && (_MSC_VER >= 1600)) - - // GCC's libstdc++ 20070724 and later supports C++ TR1 type_traits in the std namespace. - // VC10 (VS2010) and later support C++ TR1 type_traits in the std::tr1 namespace. - template<typename T> struct HasTrivialConstructor : public std::tr1::has_trivial_constructor<T> { }; - template<typename T> struct HasTrivialDestructor : public std::tr1::has_trivial_destructor<T> { }; - -#else - - // This compiler doesn't provide type traits, so we provide basic HasTrivialConstructor - // and HasTrivialDestructor definitions. The definitions here include most built-in - // scalar types but do not include POD structs and classes. For the intended purposes of - // type_traits this results correct but potentially less efficient code. - template <typename T, T v> - struct IntegralConstant { - static const T value = v; - typedef T value_type; - typedef IntegralConstant<T, v> type; - }; - - typedef IntegralConstant<bool, true> true_type; - typedef IntegralConstant<bool, false> false_type; - -#if defined(_MSC_VER) && (_MSC_VER >= 1400) && !defined(__INTEL_COMPILER) - // VC8 (VS2005) and later have built-in compiler support for HasTrivialConstructor / HasTrivialDestructor, - // but for some unexplained reason it doesn't work on built-in types. - template <typename T> struct HasTrivialConstructor : public IntegralConstant<bool, __has_trivial_constructor(T)>{ }; - template <typename T> struct HasTrivialDestructor : public IntegralConstant<bool, __has_trivial_destructor(T)>{ }; -#else - template <typename T> struct HasTrivialConstructor : public false_type{ }; - template <typename T> struct HasTrivialDestructor : public false_type{ }; -#endif - - template <typename T> struct HasTrivialConstructor<T*> : public true_type{ }; - template <typename T> struct HasTrivialDestructor<T*> : public true_type{ }; - - template <> struct HasTrivialConstructor<float> : public true_type{ }; - template <> struct HasTrivialConstructor<const float> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile float> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile float> : public true_type{ }; - - template <> struct HasTrivialConstructor<double> : public true_type{ }; - template <> struct HasTrivialConstructor<const double> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile double> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile double> : public true_type{ }; - - template <> struct HasTrivialConstructor<long double> : public true_type{ }; - template <> struct HasTrivialConstructor<const long double> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile long double> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile long double> : public true_type{ }; - - template <> struct HasTrivialConstructor<unsigned char> : public true_type{ }; - template <> struct HasTrivialConstructor<const unsigned char> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile unsigned char> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile unsigned char> : public true_type{ }; - - template <> struct HasTrivialConstructor<unsigned short> : public true_type{ }; - template <> struct HasTrivialConstructor<const unsigned short> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile unsigned short> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile unsigned short> : public true_type{ }; - - template <> struct HasTrivialConstructor<unsigned int> : public true_type{ }; - template <> struct HasTrivialConstructor<const unsigned int> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile unsigned int> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile unsigned int> : public true_type{ }; - - template <> struct HasTrivialConstructor<unsigned long> : public true_type{ }; - template <> struct HasTrivialConstructor<const unsigned long> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile unsigned long> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile unsigned long> : public true_type{ }; - - template <> struct HasTrivialConstructor<unsigned long long> : public true_type{ }; - template <> struct HasTrivialConstructor<const unsigned long long> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile unsigned long long> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile unsigned long long> : public true_type{ }; - - template <> struct HasTrivialConstructor<signed char> : public true_type{ }; - template <> struct HasTrivialConstructor<const signed char> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile signed char> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile signed char> : public true_type{ }; - - template <> struct HasTrivialConstructor<signed short> : public true_type{ }; - template <> struct HasTrivialConstructor<const signed short> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile signed short> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile signed short> : public true_type{ }; - - template <> struct HasTrivialConstructor<signed int> : public true_type{ }; - template <> struct HasTrivialConstructor<const signed int> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile signed int> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile signed int> : public true_type{ }; - - template <> struct HasTrivialConstructor<signed long> : public true_type{ }; - template <> struct HasTrivialConstructor<const signed long> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile signed long> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile signed long> : public true_type{ }; - - template <> struct HasTrivialConstructor<signed long long> : public true_type{ }; - template <> struct HasTrivialConstructor<const signed long long> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile signed long long> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile signed long long> : public true_type{ }; - - template <> struct HasTrivialConstructor<bool> : public true_type{ }; - template <> struct HasTrivialConstructor<const bool> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile bool> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile bool> : public true_type{ }; - - template <> struct HasTrivialConstructor<char> : public true_type{ }; - template <> struct HasTrivialConstructor<const char> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile char> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile char> : public true_type{ }; - - #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) - template <> struct HasTrivialConstructor<wchar_t> : public true_type{ }; - template <> struct HasTrivialConstructor<const wchar_t> : public true_type{ }; - template <> struct HasTrivialConstructor<volatile wchar_t> : public true_type{ }; - template <> struct HasTrivialConstructor<const volatile wchar_t> : public true_type{ }; - #endif - - template <> struct HasTrivialDestructor<float> : public true_type{ }; - template <> struct HasTrivialDestructor<const float> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile float> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile float> : public true_type{ }; - - template <> struct HasTrivialDestructor<double> : public true_type{ }; - template <> struct HasTrivialDestructor<const double> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile double> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile double> : public true_type{ }; - - template <> struct HasTrivialDestructor<long double> : public true_type{ }; - template <> struct HasTrivialDestructor<const long double> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile long double> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile long double> : public true_type{ }; - - template <> struct HasTrivialDestructor<unsigned char> : public true_type{ }; - template <> struct HasTrivialDestructor<const unsigned char> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile unsigned char> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile unsigned char> : public true_type{ }; - - template <> struct HasTrivialDestructor<unsigned short> : public true_type{ }; - template <> struct HasTrivialDestructor<const unsigned short> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile unsigned short> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile unsigned short> : public true_type{ }; - - template <> struct HasTrivialDestructor<unsigned int> : public true_type{ }; - template <> struct HasTrivialDestructor<const unsigned int> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile unsigned int> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile unsigned int> : public true_type{ }; - - template <> struct HasTrivialDestructor<unsigned long> : public true_type{ }; - template <> struct HasTrivialDestructor<const unsigned long> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile unsigned long> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile unsigned long> : public true_type{ }; - - template <> struct HasTrivialDestructor<unsigned long long> : public true_type{ }; - template <> struct HasTrivialDestructor<const unsigned long long> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile unsigned long long> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile unsigned long long> : public true_type{ }; - - template <> struct HasTrivialDestructor<signed char> : public true_type{ }; - template <> struct HasTrivialDestructor<const signed char> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile signed char> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile signed char> : public true_type{ }; - - template <> struct HasTrivialDestructor<signed short> : public true_type{ }; - template <> struct HasTrivialDestructor<const signed short> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile signed short> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile signed short> : public true_type{ }; - - template <> struct HasTrivialDestructor<signed int> : public true_type{ }; - template <> struct HasTrivialDestructor<const signed int> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile signed int> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile signed int> : public true_type{ }; - - template <> struct HasTrivialDestructor<signed long> : public true_type{ }; - template <> struct HasTrivialDestructor<const signed long> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile signed long> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile signed long> : public true_type{ }; - - template <> struct HasTrivialDestructor<signed long long> : public true_type{ }; - template <> struct HasTrivialDestructor<const signed long long> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile signed long long> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile signed long long> : public true_type{ }; - - template <> struct HasTrivialDestructor<bool> : public true_type{ }; - template <> struct HasTrivialDestructor<const bool> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile bool> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile bool> : public true_type{ }; - - template <> struct HasTrivialDestructor<char> : public true_type{ }; - template <> struct HasTrivialDestructor<const char> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile char> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile char> : public true_type{ }; - - #if !defined(_MSC_VER) || defined(_NATIVE_WCHAR_T_DEFINED) - template <> struct HasTrivialDestructor<wchar_t> : public true_type{ }; - template <> struct HasTrivialDestructor<const wchar_t> : public true_type{ }; - template <> struct HasTrivialDestructor<volatile wchar_t> : public true_type{ }; - template <> struct HasTrivialDestructor<const volatile wchar_t> : public true_type{ }; - #endif - -#endif // __GLIBCXX__, etc. - -} // namespace WTF - -#endif // TypeTraits_h diff --git a/Source/JavaScriptCore/wtf/TypedArrayBase.h b/Source/JavaScriptCore/wtf/TypedArrayBase.h deleted file mode 100644 index 7f989198a..000000000 --- a/Source/JavaScriptCore/wtf/TypedArrayBase.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * 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. - * - * 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 TypedArrayBase_h -#define TypedArrayBase_h - -#include <wtf/ArrayBuffer.h> -#include <wtf/ArrayBufferView.h> - -namespace WTF { - -template <typename T> -class TypedArrayBase : public ArrayBufferView { - public: - T* data() const { return static_cast<T*>(baseAddress()); } - - bool set(TypedArrayBase<T>* array, unsigned offset) - { - return setImpl(array, offset * sizeof(T)); - } - - bool setRange(const T* data, size_t dataLength, unsigned offset) - { - return setRangeImpl(reinterpret_cast<const char*>(data), dataLength * sizeof(T), offset * sizeof(T)); - } - - bool zeroRange(unsigned offset, size_t length) - { - return zeroRangeImpl(offset * sizeof(T), length * sizeof(T)); - } - - // Overridden from ArrayBufferView. This must be public because of - // rules about inheritance of members in template classes, and - // because it is accessed via pointers to subclasses. - unsigned length() const - { - return m_length; - } - - virtual unsigned byteLength() const - { - return m_length * sizeof(T); - } - -protected: - TypedArrayBase(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) - : ArrayBufferView(buffer, byteOffset) - , m_length(length) - { - } - - template <class Subclass> - static PassRefPtr<Subclass> create(unsigned length) - { - RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(length, sizeof(T)); - if (!buffer.get()) - return 0; - return create<Subclass>(buffer, 0, length); - } - - template <class Subclass> - static PassRefPtr<Subclass> create(const T* array, unsigned length) - { - RefPtr<Subclass> a = create<Subclass>(length); - if (a) - for (unsigned i = 0; i < length; ++i) - a->set(i, array[i]); - return a; - } - - template <class Subclass> - static PassRefPtr<Subclass> create(PassRefPtr<ArrayBuffer> buffer, - unsigned byteOffset, - unsigned length) - { - RefPtr<ArrayBuffer> buf(buffer); - if (!verifySubRange<T>(buf, byteOffset, length)) - return 0; - - return adoptRef(new Subclass(buf, byteOffset, length)); - } - - template <class Subclass> - PassRefPtr<Subclass> subarrayImpl(int start, int end) const - { - unsigned offset, length; - calculateOffsetAndLength(start, end, m_length, &offset, &length); - clampOffsetAndNumElements<T>(buffer(), m_byteOffset, &offset, &length); - return create<Subclass>(buffer(), offset, length); - } - - virtual void neuter() - { - ArrayBufferView::neuter(); - m_length = 0; - } - - // We do not want to have to access this via a virtual function in subclasses, - // which is why it is protected rather than private. - unsigned m_length; -}; - -} // namespace WTF - -using WTF::TypedArrayBase; - -#endif // TypedArrayBase_h diff --git a/Source/JavaScriptCore/wtf/Uint16Array.h b/Source/JavaScriptCore/wtf/Uint16Array.h deleted file mode 100644 index e73c8ddff..000000000 --- a/Source/JavaScriptCore/wtf/Uint16Array.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 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 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 Uint16Array_h -#define Uint16Array_h - -#include <wtf/IntegralTypedArrayBase.h> - -namespace WTF { - -class ArrayBuffer; - -class Uint16Array : public IntegralTypedArrayBase<unsigned short> { -public: - static inline PassRefPtr<Uint16Array> create(unsigned length); - static inline PassRefPtr<Uint16Array> create(unsigned short* array, unsigned length); - static inline PassRefPtr<Uint16Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); - - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<unsigned short>* array, unsigned offset) { return TypedArrayBase<unsigned short>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<unsigned short>::set(index, value); } - - inline PassRefPtr<Uint16Array> subarray(int start) const; - inline PassRefPtr<Uint16Array> subarray(int start, int end) const; - -private: - inline Uint16Array(PassRefPtr<ArrayBuffer>, - unsigned byteOffset, - unsigned length); - // Make constructor visible to superclass. - friend class TypedArrayBase<unsigned short>; - - // Overridden from ArrayBufferView. - virtual bool isUnsignedShortArray() const { return true; } -}; - -PassRefPtr<Uint16Array> Uint16Array::create(unsigned length) -{ - return TypedArrayBase<unsigned short>::create<Uint16Array>(length); -} - -PassRefPtr<Uint16Array> Uint16Array::create(unsigned short* array, unsigned length) -{ - return TypedArrayBase<unsigned short>::create<Uint16Array>(array, length); -} - -PassRefPtr<Uint16Array> Uint16Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -{ - return TypedArrayBase<unsigned short>::create<Uint16Array>(buffer, byteOffset, length); -} - -Uint16Array::Uint16Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) - : IntegralTypedArrayBase<unsigned short>(buffer, byteOffset, length) -{ -} - -PassRefPtr<Uint16Array> Uint16Array::subarray(int start) const -{ - return subarray(start, length()); -} - -PassRefPtr<Uint16Array> Uint16Array::subarray(int start, int end) const -{ - return subarrayImpl<Uint16Array>(start, end); -} - -} // namespace WTF - -using WTF::Uint16Array; - -#endif // Uint16Array_h diff --git a/Source/JavaScriptCore/wtf/Uint32Array.h b/Source/JavaScriptCore/wtf/Uint32Array.h deleted file mode 100644 index b2a391267..000000000 --- a/Source/JavaScriptCore/wtf/Uint32Array.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 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 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 Uint32Array_h -#define Uint32Array_h - -#include <wtf/IntegralTypedArrayBase.h> - -namespace WTF { - -class ArrayBuffer; - -class Uint32Array : public IntegralTypedArrayBase<unsigned int> { -public: - static inline PassRefPtr<Uint32Array> create(unsigned length); - static inline PassRefPtr<Uint32Array> create(unsigned int* array, unsigned length); - static inline PassRefPtr<Uint32Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); - - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<unsigned int>* array, unsigned offset) { return TypedArrayBase<unsigned int>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<unsigned int>::set(index, value); } - - inline PassRefPtr<Uint32Array> subarray(int start) const; - inline PassRefPtr<Uint32Array> subarray(int start, int end) const; - -private: - inline Uint32Array(PassRefPtr<ArrayBuffer>, - unsigned byteOffset, - unsigned length); - // Make constructor visible to superclass. - friend class TypedArrayBase<unsigned int>; - - // Overridden from ArrayBufferView. - virtual bool isUnsignedIntArray() const { return true; } -}; - -PassRefPtr<Uint32Array> Uint32Array::create(unsigned length) -{ - return TypedArrayBase<unsigned int>::create<Uint32Array>(length); -} - -PassRefPtr<Uint32Array> Uint32Array::create(unsigned int* array, unsigned length) -{ - return TypedArrayBase<unsigned int>::create<Uint32Array>(array, length); -} - -PassRefPtr<Uint32Array> Uint32Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -{ - return TypedArrayBase<unsigned int>::create<Uint32Array>(buffer, byteOffset, length); -} - -Uint32Array::Uint32Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) - : IntegralTypedArrayBase<unsigned int>(buffer, byteOffset, length) -{ -} - -PassRefPtr<Uint32Array> Uint32Array::subarray(int start) const -{ - return subarray(start, length()); -} - -PassRefPtr<Uint32Array> Uint32Array::subarray(int start, int end) const -{ - return subarrayImpl<Uint32Array>(start, end); -} - -} // namespace WTF - -using WTF::Uint32Array; - -#endif // Uint32Array_h diff --git a/Source/JavaScriptCore/wtf/Uint8Array.h b/Source/JavaScriptCore/wtf/Uint8Array.h deleted file mode 100644 index f46ef0fc0..000000000 --- a/Source/JavaScriptCore/wtf/Uint8Array.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 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 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 Uint8Array_h -#define Uint8Array_h - -#include <wtf/IntegralTypedArrayBase.h> - -namespace WTF { - -class ArrayBuffer; - -class Uint8Array : public IntegralTypedArrayBase<unsigned char> { -public: - static inline PassRefPtr<Uint8Array> create(unsigned length); - static inline PassRefPtr<Uint8Array> create(unsigned char* array, unsigned length); - static inline PassRefPtr<Uint8Array> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); - - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<unsigned char>* array, unsigned offset) { return TypedArrayBase<unsigned char>::set(array, offset); } - void set(unsigned index, double value) { IntegralTypedArrayBase<unsigned char>::set(index, value); } - - inline PassRefPtr<Uint8Array> subarray(int start) const; - inline PassRefPtr<Uint8Array> subarray(int start, int end) const; - -protected: - inline Uint8Array(PassRefPtr<ArrayBuffer>, - unsigned byteOffset, - unsigned length); - // Make constructor visible to superclass. - friend class TypedArrayBase<unsigned char>; - - // Overridden from ArrayBufferView. - virtual bool isUnsignedByteArray() const { return true; } -}; - -PassRefPtr<Uint8Array> Uint8Array::create(unsigned length) -{ - return TypedArrayBase<unsigned char>::create<Uint8Array>(length); -} - -PassRefPtr<Uint8Array> Uint8Array::create(unsigned char* array, unsigned length) -{ - return TypedArrayBase<unsigned char>::create<Uint8Array>(array, length); -} - -PassRefPtr<Uint8Array> Uint8Array::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -{ - return TypedArrayBase<unsigned char>::create<Uint8Array>(buffer, byteOffset, length); -} - -Uint8Array::Uint8Array(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -: IntegralTypedArrayBase<unsigned char>(buffer, byteOffset, length) -{ -} - -PassRefPtr<Uint8Array> Uint8Array::subarray(int start) const -{ - return subarray(start, length()); -} - -PassRefPtr<Uint8Array> Uint8Array::subarray(int start, int end) const -{ - return subarrayImpl<Uint8Array>(start, end); -} - -} // namespace WTF - -using WTF::Uint8Array; - -#endif // Uint8Array_h diff --git a/Source/JavaScriptCore/wtf/Uint8ClampedArray.h b/Source/JavaScriptCore/wtf/Uint8ClampedArray.h deleted file mode 100644 index 2b77dacc3..000000000 --- a/Source/JavaScriptCore/wtf/Uint8ClampedArray.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2009 Apple Inc. All rights reserved. - * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2012 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. - * - * 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 Uint8ClampedArray_h -#define Uint8ClampedArray_h - -#include <wtf/Uint8Array.h> - -namespace WTF { - -class Uint8ClampedArray : public Uint8Array { -public: - static inline PassRefPtr<Uint8ClampedArray> create(unsigned length); - static inline PassRefPtr<Uint8ClampedArray> create(unsigned char* array, unsigned length); - static inline PassRefPtr<Uint8ClampedArray> create(PassRefPtr<ArrayBuffer>, unsigned byteOffset, unsigned length); - - // Can’t use "using" here due to a bug in the RVCT compiler. - bool set(TypedArrayBase<unsigned char>* array, unsigned offset) { return TypedArrayBase<unsigned char>::set(array, offset); } - inline void set(unsigned index, double value); - - inline PassRefPtr<Uint8ClampedArray> subarray(int start) const; - inline PassRefPtr<Uint8ClampedArray> subarray(int start, int end) const; - -private: - inline Uint8ClampedArray(PassRefPtr<ArrayBuffer>, - unsigned byteOffset, - unsigned length); - // Make constructor visible to superclass. - friend class TypedArrayBase<unsigned char>; - - // Overridden from ArrayBufferView. - virtual bool isUnsignedByteClampedArray() const { return true; } -}; - -PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::create(unsigned length) -{ - return TypedArrayBase<unsigned char>::create<Uint8ClampedArray>(length); -} - -PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::create(unsigned char* array, unsigned length) -{ - return TypedArrayBase<unsigned char>::create<Uint8ClampedArray>(array, length); -} - -PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::create(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -{ - return TypedArrayBase<unsigned char>::create<Uint8ClampedArray>(buffer, byteOffset, length); -} - -void Uint8ClampedArray::set(unsigned index, double value) -{ - if (index >= m_length) - return; - if (isnan(value) || value < 0) - value = 0; - else if (value > 255) - value = 255; - data()[index] = static_cast<unsigned char>(value + 0.5); -} - -Uint8ClampedArray::Uint8ClampedArray(PassRefPtr<ArrayBuffer> buffer, unsigned byteOffset, unsigned length) -: Uint8Array(buffer, byteOffset, length) -{ -} - -PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::subarray(int start) const -{ - return subarray(start, length()); -} - -PassRefPtr<Uint8ClampedArray> Uint8ClampedArray::subarray(int start, int end) const -{ - return subarrayImpl<Uint8ClampedArray>(start, end); -} - -} // namespace WTF - -using WTF::Uint8ClampedArray; - -#endif // Uint8ClampedArray_h diff --git a/Source/JavaScriptCore/wtf/UnionFind.h b/Source/JavaScriptCore/wtf/UnionFind.h deleted file mode 100644 index fa737116c..000000000 --- a/Source/JavaScriptCore/wtf/UnionFind.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2011 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 UnionFind_h -#define UnionFind_h - -#include <wtf/Assertions.h> - -namespace WTF { - -// A UnionFind class can be used to compute disjoint sets using the -// disjoint-set forest data structure. Each UnionFind instance is a -// node in the forest. Typically you use it by using UnionFind as a -// superclass: -// -// class MemberOfSet : public UnionFind<MemberOfSet> { ... } -// -// Calling x->find() gives you a MemberOfSet* that represents the -// disjoint set that x belongs to. Calling x->unify(y) unifies x's -// set with y's set, and ensures that: -// -// x->find() == y->find() -// -// and that: -// -// a->find() == b->find() -// -// for any a, b if prior to the call to x->unify(y), we would have -// had: -// -// a->find() == x -// b->find() == y -// -// This implementation is almost amortized O(1), but could be worse -// in unlikely pathological cases. It favors having a non-recursive -// single pass implementation of unify() and find() over ensuring the -// theoretical O(InverseAckermann[n]) amortized bound, which is much -// closer to amortized O(1). - -template<typename T> -class UnionFind { -public: - UnionFind() - : m_parent(0) - { - } - - T* find() - { - T* result = static_cast<T*>(this); - T* next = result->m_parent; - while (next) { - result = next; - next = result->m_parent; - } - ASSERT(result); - if (result != this) - m_parent = result; - return result; - } - - void unify(T* other) - { - T* a = static_cast<T*>(this)->find(); - T* b = other->find(); - - ASSERT(!a->m_parent); - ASSERT(!b->m_parent); - - if (a == b) - return; - - a->m_parent = b; - } -private: - T* m_parent; -}; - -} // namespace WTF - -using WTF::UnionFind; - -#endif // UnionFind_h diff --git a/Source/JavaScriptCore/wtf/UnusedParam.h b/Source/JavaScriptCore/wtf/UnusedParam.h deleted file mode 100644 index 4b7234b8d..000000000 --- a/Source/JavaScriptCore/wtf/UnusedParam.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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 WTF_UnusedParam_h -#define WTF_UnusedParam_h - -/* don't use this for C++, it should only be used in plain C files or - ObjC methods, where leaving off the parameter name is not allowed. */ - -#include <wtf/Platform.h> - -#if COMPILER(INTEL) && !OS(WINDOWS) || COMPILER(RVCT) -template<typename T> -inline void unusedParam(T& x) { (void)x; } -#define UNUSED_PARAM(variable) unusedParam(variable) -#else -#define UNUSED_PARAM(variable) (void)variable -#endif - -#endif /* WTF_UnusedParam_h */ diff --git a/Source/JavaScriptCore/wtf/VMTags.h b/Source/JavaScriptCore/wtf/VMTags.h deleted file mode 100644 index 117bc3721..000000000 --- a/Source/JavaScriptCore/wtf/VMTags.h +++ /dev/null @@ -1,75 +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. - */ - -#ifndef VMTags_h -#define VMTags_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) - -#include <mach/vm_statistics.h> - -#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_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_JIT_REGISTER_FILE) - -#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) - -#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) - -#endif // VMTags_h diff --git a/Source/JavaScriptCore/wtf/ValueCheck.h b/Source/JavaScriptCore/wtf/ValueCheck.h deleted file mode 100644 index 2a86eb0f2..000000000 --- a/Source/JavaScriptCore/wtf/ValueCheck.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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 ValueCheck_h -#define ValueCheck_h - -#include <wtf/FastMalloc.h> - -namespace WTF { - -template<typename T> struct ValueCheck { - typedef T TraitType; - static void checkConsistency(const T&) { } -}; - -#if !ASSERT_DISABLED -template<typename P> struct ValueCheck<P*> { - typedef P* TraitType; - static void checkConsistency(const P* p) - { - if (!p) - return; - ASSERT(fastMallocSize(p)); - ValueCheck<P>::checkConsistency(*p); - } -}; -#endif - -} - -#endif // ValueCheck_h diff --git a/Source/JavaScriptCore/wtf/Vector.h b/Source/JavaScriptCore/wtf/Vector.h deleted file mode 100644 index 19e6ffb8c..000000000 --- a/Source/JavaScriptCore/wtf/Vector.h +++ /dev/null @@ -1,1198 +0,0 @@ -/* - * Copyright (C) 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 WTF_Vector_h -#define WTF_Vector_h - -#include <wtf/Alignment.h> -#include <wtf/FastAllocBase.h> -#include <wtf/Noncopyable.h> -#include <wtf/NotFound.h> -#include <wtf/StdLibExtras.h> -#include <wtf/ValueCheck.h> -#include <wtf/VectorTraits.h> -#include <limits> -#include <utility> - -#if PLATFORM(QT) -#include <QDataStream> -#endif - -namespace WTF { - - using std::min; - using std::max; - - template <bool needsDestruction, typename T> - struct VectorDestructor; - - template<typename T> - struct VectorDestructor<false, T> - { - static void destruct(T*, T*) {} - }; - - template<typename T> - struct VectorDestructor<true, T> - { - static void destruct(T* begin, T* end) - { - for (T* cur = begin; cur != end; ++cur) - cur->~T(); - } - }; - - template <bool needsInitialization, bool canInitializeWithMemset, typename T> - struct VectorInitializer; - - template<bool ignore, typename T> - struct VectorInitializer<false, ignore, T> - { - static void initialize(T*, T*) {} - }; - - template<typename T> - struct VectorInitializer<true, false, T> - { - static void initialize(T* begin, T* end) - { - for (T* cur = begin; cur != end; ++cur) - new (NotNull, cur) T; - } - }; - - template<typename T> - struct VectorInitializer<true, true, T> - { - static void initialize(T* begin, T* end) - { - memset(begin, 0, reinterpret_cast<char*>(end) - reinterpret_cast<char*>(begin)); - } - }; - - template <bool canMoveWithMemcpy, typename T> - struct VectorMover; - - template<typename T> - struct VectorMover<false, T> - { - static void move(const T* src, const T* srcEnd, T* dst) - { - while (src != srcEnd) { - new (NotNull, dst) T(*src); -#if COMPILER(SUNCC) && __SUNPRO_CC <= 0x590 - const_cast<T*>(src)->~T(); // Work around obscure SunCC 12 compiler bug. -#else - src->~T(); -#endif - ++dst; - ++src; - } - } - static void moveOverlapping(const T* src, const T* srcEnd, T* dst) - { - if (src > dst) - move(src, srcEnd, dst); - else { - T* dstEnd = dst + (srcEnd - src); - while (src != srcEnd) { - --srcEnd; - --dstEnd; - new (NotNull, dstEnd) T(*srcEnd); - srcEnd->~T(); - } - } - } - }; - - template<typename T> - struct VectorMover<true, T> - { - static void move(const T* src, const T* srcEnd, T* dst) - { - memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src)); - } - static void moveOverlapping(const T* src, const T* srcEnd, T* dst) - { - memmove(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src)); - } - }; - - template <bool canCopyWithMemcpy, typename T> - struct VectorCopier; - - template<typename T> - struct VectorCopier<false, T> - { - static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) - { - while (src != srcEnd) { - new (NotNull, dst) T(*src); - ++dst; - ++src; - } - } - }; - - template<typename T> - struct VectorCopier<true, T> - { - static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) - { - memcpy(dst, src, reinterpret_cast<const char*>(srcEnd) - reinterpret_cast<const char*>(src)); - } - }; - - template <bool canFillWithMemset, typename T> - struct VectorFiller; - - template<typename T> - struct VectorFiller<false, T> - { - static void uninitializedFill(T* dst, T* dstEnd, const T& val) - { - while (dst != dstEnd) { - new (NotNull, dst) T(val); - ++dst; - } - } - }; - - template<typename T> - struct VectorFiller<true, T> - { - static void uninitializedFill(T* dst, T* dstEnd, const T& val) - { - ASSERT(sizeof(T) == sizeof(char)); -#if COMPILER(GCC) && defined(_FORTIFY_SOURCE) - if (!__builtin_constant_p(dstEnd - dst) || (!(dstEnd - dst))) -#endif - memset(dst, val, dstEnd - dst); - } - }; - - template<bool canCompareWithMemcmp, typename T> - struct VectorComparer; - - template<typename T> - struct VectorComparer<false, T> - { - static bool compare(const T* a, const T* b, size_t size) - { - for (size_t i = 0; i < size; ++i) - if (!(a[i] == b[i])) - return false; - return true; - } - }; - - template<typename T> - struct VectorComparer<true, T> - { - static bool compare(const T* a, const T* b, size_t size) - { - return memcmp(a, b, sizeof(T) * size) == 0; - } - }; - - template<typename T> - struct VectorTypeOperations - { - static void destruct(T* begin, T* end) - { - VectorDestructor<VectorTraits<T>::needsDestruction, T>::destruct(begin, end); - } - - static void initialize(T* begin, T* end) - { - VectorInitializer<VectorTraits<T>::needsInitialization, VectorTraits<T>::canInitializeWithMemset, T>::initialize(begin, end); - } - - static void move(const T* src, const T* srcEnd, T* dst) - { - VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::move(src, srcEnd, dst); - } - - static void moveOverlapping(const T* src, const T* srcEnd, T* dst) - { - VectorMover<VectorTraits<T>::canMoveWithMemcpy, T>::moveOverlapping(src, srcEnd, dst); - } - - static void uninitializedCopy(const T* src, const T* srcEnd, T* dst) - { - VectorCopier<VectorTraits<T>::canCopyWithMemcpy, T>::uninitializedCopy(src, srcEnd, dst); - } - - static void uninitializedFill(T* dst, T* dstEnd, const T& val) - { - VectorFiller<VectorTraits<T>::canFillWithMemset, T>::uninitializedFill(dst, dstEnd, val); - } - - static bool compare(const T* a, const T* b, size_t size) - { - return VectorComparer<VectorTraits<T>::canCompareWithMemcmp, T>::compare(a, b, size); - } - }; - - template<typename T> - class VectorBufferBase { - WTF_MAKE_NONCOPYABLE(VectorBufferBase); - public: - void allocateBuffer(size_t newCapacity) - { - ASSERT(newCapacity); - m_capacity = newCapacity; - if (newCapacity > std::numeric_limits<size_t>::max() / sizeof(T)) - CRASH(); - m_buffer = static_cast<T*>(fastMalloc(newCapacity * sizeof(T))); - } - - bool tryAllocateBuffer(size_t newCapacity) - { - ASSERT(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 (!bufferToDeallocate) - return; - - if (m_buffer == bufferToDeallocate) { - m_buffer = 0; - m_capacity = 0; - } - - fastFree(bufferToDeallocate); - } - - T* buffer() { return m_buffer; } - const T* buffer() const { return m_buffer; } - T** bufferSlot() { return &m_buffer; } - size_t capacity() const { return m_capacity; } - - T* releaseBuffer() - { - T* buffer = m_buffer; - m_buffer = 0; - m_capacity = 0; - return buffer; - } - - protected: - VectorBufferBase() - : m_buffer(0) - , m_capacity(0) - { - } - - VectorBufferBase(T* buffer, size_t capacity) - : m_buffer(buffer) - , m_capacity(capacity) - { - } - - ~VectorBufferBase() - { - // FIXME: It would be nice to find a way to ASSERT that m_buffer hasn't leaked here. - } - - T* m_buffer; - size_t m_capacity; - }; - - template<typename T, size_t inlineCapacity> - class VectorBuffer; - - template<typename T> - class VectorBuffer<T, 0> : private VectorBufferBase<T> { - private: - typedef VectorBufferBase<T> Base; - public: - VectorBuffer() - { - } - - VectorBuffer(size_t capacity) - { - // Calling malloc(0) might take a lock and may actually do an - // allocation on some systems. - if (capacity) - allocateBuffer(capacity); - } - - ~VectorBuffer() - { - deallocateBuffer(buffer()); - } - - void swap(VectorBuffer<T, 0>& other) - { - std::swap(m_buffer, other.m_buffer); - std::swap(m_capacity, other.m_capacity); - } - - void restoreInlineBufferIfNeeded() { } - - using Base::allocateBuffer; - using Base::tryAllocateBuffer; - using Base::deallocateBuffer; - - using Base::buffer; - using Base::bufferSlot; - using Base::capacity; - - using Base::releaseBuffer; - private: - using Base::m_buffer; - using Base::m_capacity; - }; - - template<typename T, size_t inlineCapacity> - class VectorBuffer : private VectorBufferBase<T> { - WTF_MAKE_NONCOPYABLE(VectorBuffer); - private: - typedef VectorBufferBase<T> Base; - public: - VectorBuffer() - : Base(inlineBuffer(), inlineCapacity) - { - } - - VectorBuffer(size_t capacity) - : Base(inlineBuffer(), inlineCapacity) - { - if (capacity > inlineCapacity) - Base::allocateBuffer(capacity); - } - - ~VectorBuffer() - { - deallocateBuffer(buffer()); - } - - void allocateBuffer(size_t newCapacity) - { - // FIXME: This should ASSERT(!m_buffer) to catch misuse/leaks. - if (newCapacity > inlineCapacity) - Base::allocateBuffer(newCapacity); - else { - m_buffer = inlineBuffer(); - m_capacity = inlineCapacity; - } - } - - 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()) - return; - Base::deallocateBuffer(bufferToDeallocate); - } - - void swap(VectorBuffer<T, inlineCapacity>& other) - { - if (buffer() == inlineBuffer() && other.buffer() == other.inlineBuffer()) { - WTF::swap(m_inlineBuffer, other.m_inlineBuffer); - std::swap(m_capacity, other.m_capacity); - } else if (buffer() == inlineBuffer()) { - m_buffer = other.m_buffer; - other.m_buffer = other.inlineBuffer(); - WTF::swap(m_inlineBuffer, other.m_inlineBuffer); - std::swap(m_capacity, other.m_capacity); - } else if (other.buffer() == other.inlineBuffer()) { - other.m_buffer = m_buffer; - m_buffer = inlineBuffer(); - WTF::swap(m_inlineBuffer, other.m_inlineBuffer); - std::swap(m_capacity, other.m_capacity); - } else { - std::swap(m_buffer, other.m_buffer); - std::swap(m_capacity, other.m_capacity); - } - } - - void restoreInlineBufferIfNeeded() - { - if (m_buffer) - return; - m_buffer = inlineBuffer(); - m_capacity = inlineCapacity; - } - - using Base::buffer; - using Base::bufferSlot; - using Base::capacity; - - T* releaseBuffer() - { - if (buffer() == inlineBuffer()) - return 0; - return Base::releaseBuffer(); - } - - private: - using Base::m_buffer; - using Base::m_capacity; - - static const size_t m_inlineBufferSize = inlineCapacity * sizeof(T); - T* inlineBuffer() { return reinterpret_cast_ptr<T*>(m_inlineBuffer.buffer); } - - AlignedBuffer<m_inlineBufferSize, WTF_ALIGN_OF(T)> m_inlineBuffer; - }; - - template<typename T, size_t inlineCapacity = 0> - class Vector { - WTF_MAKE_FAST_ALLOCATED; - private: - typedef VectorBuffer<T, inlineCapacity> Buffer; - typedef VectorTypeOperations<T> TypeOperations; - - class VectorReverseProxy; - - public: - typedef T ValueType; - - typedef T* iterator; - typedef const T* const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - - Vector() - : m_size(0) - { - } - - explicit Vector(size_t size) - : m_size(size) - , m_buffer(size) - { - if (begin()) - TypeOperations::initialize(begin(), end()); - } - - ~Vector() - { - if (m_size) - shrink(0); - } - - Vector(const Vector&); - template<size_t otherCapacity> - Vector(const Vector<T, otherCapacity>&); - - Vector& operator=(const Vector&); - template<size_t otherCapacity> - Vector& operator=(const Vector<T, otherCapacity>&); - - size_t size() const { return m_size; } - size_t capacity() const { return m_buffer.capacity(); } - bool isEmpty() const { return !size(); } - - T& at(size_t i) - { - ASSERT(i < size()); - return m_buffer.buffer()[i]; - } - const T& at(size_t i) const - { - ASSERT(i < size()); - return m_buffer.buffer()[i]; - } - - T& operator[](size_t i) { return at(i); } - const T& operator[](size_t i) const { return at(i); } - - T* data() { return m_buffer.buffer(); } - const T* data() const { return m_buffer.buffer(); } - T** dataSlot() { return m_buffer.bufferSlot(); } - - iterator begin() { return data(); } - iterator end() { return begin() + m_size; } - const_iterator begin() const { return data(); } - const_iterator end() const { return begin() + m_size; } - - reverse_iterator rbegin() { return reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } - - VectorReverseProxy& reversed() { return static_cast<VectorReverseProxy&>(*this); } - const VectorReverseProxy& reversed() const { return static_cast<const VectorReverseProxy&>(*this); } - - T& first() { return at(0); } - const T& first() const { return at(0); } - T& last() { return at(size() - 1); } - const T& last() const { return at(size() - 1); } - - template<typename U> bool contains(const U&) const; - template<typename U> size_t find(const U&) const; - template<typename U> size_t reverseFind(const U&) const; - - void shrink(size_t size); - 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()); } - - void clear() { shrinkCapacity(0); } - - template<typename U> void append(const U*, size_t); - 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&); - template<typename U, size_t c> void insert(size_t position, const Vector<U, c>&); - - template<typename U> void prepend(const U*, size_t); - template<typename U> void prepend(const U&); - template<typename U, size_t c> void prepend(const Vector<U, c>&); - - void remove(size_t position); - void remove(size_t position, size_t length); - - void removeLast() - { - ASSERT(!isEmpty()); - shrink(size() - 1); - } - - Vector(size_t size, const T& val) - : m_size(size) - , m_buffer(size) - { - if (begin()) - TypeOperations::uninitializedFill(begin(), end(), val); - } - - void fill(const T&, size_t); - void fill(const T& val) { fill(val, size()); } - - template<typename Iterator> void appendRange(Iterator start, Iterator end); - - T* releaseBuffer(); - - void swap(Vector<T, inlineCapacity>& other) - { - std::swap(m_size, other.m_size); - m_buffer.swap(other.m_buffer); - } - - void reverse(); - - void checkConsistency(); - - 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*); - template<typename U> void appendSlowCase(const U&); - - class VectorReverseProxy : private Vector { - public: - typedef typename Vector::reverse_iterator iterator; - typedef typename Vector::const_reverse_iterator const_iterator; - - iterator begin() { return Vector::rbegin(); } - iterator end() { return Vector::rend(); } - const_iterator begin() const { return Vector::rbegin(); } - const_iterator end() const { return Vector::rend(); } - - private: - friend class Vector; - - // These are intentionally not implemented. - VectorReverseProxy(); - VectorReverseProxy(const VectorReverseProxy&); - VectorReverseProxy& operator=(const VectorReverseProxy&); - ~VectorReverseProxy(); - }; - - size_t m_size; - Buffer m_buffer; - }; - -#if PLATFORM(QT) - template<typename T> - QDataStream& operator<<(QDataStream& stream, const Vector<T>& data) - { - stream << qint64(data.size()); - foreach (const T& i, data) - stream << i; - return stream; - } - - template<typename T> - QDataStream& operator>>(QDataStream& stream, Vector<T>& data) - { - data.clear(); - qint64 count; - T item; - stream >> count; - data.reserveCapacity(count); - for (qint64 i = 0; i < count; ++i) { - stream >> item; - data.append(item); - } - return stream; - } -#endif - - template<typename T, size_t inlineCapacity> - Vector<T, inlineCapacity>::Vector(const Vector& other) - : m_size(other.size()) - , m_buffer(other.capacity()) - { - if (begin()) - TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); - } - - template<typename T, size_t inlineCapacity> - template<size_t otherCapacity> - Vector<T, inlineCapacity>::Vector(const Vector<T, otherCapacity>& other) - : m_size(other.size()) - , m_buffer(other.capacity()) - { - if (begin()) - TypeOperations::uninitializedCopy(other.begin(), other.end(), begin()); - } - - template<typename T, size_t inlineCapacity> - Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, inlineCapacity>& other) - { - if (&other == this) - return *this; - - if (size() > other.size()) - shrink(other.size()); - else if (other.size() > capacity()) { - clear(); - reserveCapacity(other.size()); - if (!begin()) - return *this; - } - -// Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last -#if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL - if (!begin()) - return *this; -#endif - - std::copy(other.begin(), other.begin() + size(), begin()); - TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); - m_size = other.size(); - - return *this; - } - - inline bool typelessPointersAreEqual(const void* a, const void* b) { return a == b; } - - template<typename T, size_t inlineCapacity> - template<size_t otherCapacity> - Vector<T, inlineCapacity>& Vector<T, inlineCapacity>::operator=(const Vector<T, otherCapacity>& other) - { - // If the inline capacities match, we should call the more specific - // template. If the inline capacities don't match, the two objects - // shouldn't be allocated the same address. - ASSERT(!typelessPointersAreEqual(&other, this)); - - if (size() > other.size()) - shrink(other.size()); - else if (other.size() > capacity()) { - clear(); - reserveCapacity(other.size()); - if (!begin()) - return *this; - } - -// Works around an assert in VS2010. See https://connect.microsoft.com/VisualStudio/feedback/details/558044/std-copy-should-not-check-dest-when-first-last -#if COMPILER(MSVC) && defined(_ITERATOR_DEBUG_LEVEL) && _ITERATOR_DEBUG_LEVEL - if (!begin()) - return *this; -#endif - - std::copy(other.begin(), other.begin() + size(), begin()); - TypeOperations::uninitializedCopy(other.begin() + size(), other.end(), end()); - m_size = other.size(); - - return *this; - } - - template<typename T, size_t inlineCapacity> - template<typename U> - bool Vector<T, inlineCapacity>::contains(const U& value) const - { - return find(value) != notFound; - } - - template<typename T, size_t inlineCapacity> - template<typename U> - size_t Vector<T, inlineCapacity>::find(const U& value) const - { - for (size_t i = 0; i < size(); ++i) { - if (at(i) == value) - return i; - } - return notFound; - } - - template<typename T, size_t inlineCapacity> - template<typename U> - size_t Vector<T, inlineCapacity>::reverseFind(const U& value) const - { - for (size_t i = 1; i <= size(); ++i) { - const size_t index = size() - i; - if (at(index) == value) - return index; - } - return notFound; - } - - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::fill(const T& val, size_t newSize) - { - if (size() > newSize) - shrink(newSize); - else if (newSize > capacity()) { - clear(); - reserveCapacity(newSize); - if (!begin()) - return; - } - - std::fill(begin(), end(), val); - TypeOperations::uninitializedFill(end(), begin() + newSize, val); - m_size = newSize; - } - - template<typename T, size_t inlineCapacity> - template<typename Iterator> - void Vector<T, inlineCapacity>::appendRange(Iterator start, Iterator end) - { - for (Iterator it = start; it != end; ++it) - append(*it); - } - - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity) - { - reserveCapacity(max(newMinCapacity, max(static_cast<size_t>(16), capacity() + capacity() / 4 + 1))); - } - - template<typename T, size_t inlineCapacity> - const T* Vector<T, inlineCapacity>::expandCapacity(size_t newMinCapacity, const T* ptr) - { - if (ptr < begin() || ptr >= end()) { - expandCapacity(newMinCapacity); - return ptr; - } - size_t index = ptr - begin(); - expandCapacity(newMinCapacity); - 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) - { - expandCapacity(newMinCapacity); - return ptr; - } - - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::resize(size_t size) - { - if (size <= m_size) - TypeOperations::destruct(begin() + size, end()); - else { - if (size > capacity()) - expandCapacity(size); - if (begin()) - TypeOperations::initialize(end(), begin() + size); - } - - m_size = size; - } - - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::shrink(size_t size) - { - ASSERT(size <= m_size); - TypeOperations::destruct(begin() + size, end()); - m_size = size; - } - - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::grow(size_t size) - { - ASSERT(size >= m_size); - if (size > capacity()) - expandCapacity(size); - if (begin()) - TypeOperations::initialize(end(), begin() + size); - m_size = size; - } - - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::reserveCapacity(size_t newCapacity) - { - if (newCapacity <= capacity()) - return; - T* oldBuffer = begin(); - T* oldEnd = end(); - m_buffer.allocateBuffer(newCapacity); - if (begin()) - TypeOperations::move(oldBuffer, oldEnd, begin()); - m_buffer.deallocateBuffer(oldBuffer); - } - - 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); - ASSERT(capacity() == inlineCapacity); - if (initialCapacity > inlineCapacity) - m_buffer.allocateBuffer(initialCapacity); - } - - template<typename T, size_t inlineCapacity> - void Vector<T, inlineCapacity>::shrinkCapacity(size_t newCapacity) - { - if (newCapacity >= capacity()) - return; - - if (newCapacity < size()) - shrink(newCapacity); - - T* oldBuffer = begin(); - if (newCapacity > 0) { - T* oldEnd = end(); - m_buffer.allocateBuffer(newCapacity); - if (begin() != oldBuffer) - TypeOperations::move(oldBuffer, oldEnd, begin()); - } - - m_buffer.deallocateBuffer(oldBuffer); - m_buffer.restoreInlineBufferIfNeeded(); - } - - // Templatizing these is better than just letting the conversion happen implicitly, - // because for instance it allows a PassRefPtr to be appended to a RefPtr vector - // without refcount thrash. - - template<typename T, size_t inlineCapacity> template<typename U> - void Vector<T, inlineCapacity>::append(const U* data, size_t dataSize) - { - size_t newSize = m_size + dataSize; - if (newSize > capacity()) { - data = expandCapacity(newSize, data); - if (!begin()) - return; - } - if (newSize < m_size) - CRASH(); - T* dest = end(); - for (size_t i = 0; i < dataSize; ++i) - new (NotNull, &dest[i]) T(data[i]); - m_size = newSize; - } - - 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 (NotNull, &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) - { - if (size() != capacity()) { - new (NotNull, end()) T(val); - ++m_size; - return; - } - - appendSlowCase(val); - } - - template<typename T, size_t inlineCapacity> template<typename U> - void Vector<T, inlineCapacity>::appendSlowCase(const U& val) - { - ASSERT(size() == capacity()); - - const U* ptr = &val; - ptr = expandCapacity(size() + 1, ptr); - if (!begin()) - return; - - new (NotNull, end()) T(*ptr); - ++m_size; - } - - // This version of append saves a branch in the case where you know that the - // vector's capacity is large enough for the append to succeed. - - template<typename T, size_t inlineCapacity> template<typename U> - inline void Vector<T, inlineCapacity>::uncheckedAppend(const U& val) - { - ASSERT(size() < capacity()); - const U* ptr = &val; - new (NotNull, end()) T(*ptr); - ++m_size; - } - - // This method should not be called append, a better name would be appendElements. - // It could also be eliminated entirely, and call sites could just use - // appendRange(val.begin(), val.end()). - template<typename T, size_t inlineCapacity> template<size_t otherCapacity> - inline void Vector<T, inlineCapacity>::append(const Vector<T, otherCapacity>& val) - { - append(val.begin(), val.size()); - } - - template<typename T, size_t inlineCapacity> template<typename U> - void Vector<T, inlineCapacity>::insert(size_t position, const U* data, size_t dataSize) - { - ASSERT(position <= size()); - size_t newSize = m_size + dataSize; - if (newSize > capacity()) { - data = expandCapacity(newSize, data); - if (!begin()) - return; - } - if (newSize < m_size) - CRASH(); - T* spot = begin() + position; - TypeOperations::moveOverlapping(spot, end(), spot + dataSize); - for (size_t i = 0; i < dataSize; ++i) - new (NotNull, &spot[i]) T(data[i]); - m_size = newSize; - } - - template<typename T, size_t inlineCapacity> template<typename U> - inline void Vector<T, inlineCapacity>::insert(size_t position, const U& val) - { - ASSERT(position <= size()); - const U* data = &val; - if (size() == capacity()) { - data = expandCapacity(size() + 1, data); - if (!begin()) - return; - } - T* spot = begin() + position; - TypeOperations::moveOverlapping(spot, end(), spot + 1); - new (NotNull, spot) T(*data); - ++m_size; - } - - template<typename T, size_t inlineCapacity> template<typename U, size_t c> - inline void Vector<T, inlineCapacity>::insert(size_t position, const Vector<U, c>& val) - { - insert(position, val.begin(), val.size()); - } - - template<typename T, size_t inlineCapacity> template<typename U> - void Vector<T, inlineCapacity>::prepend(const U* data, size_t dataSize) - { - insert(0, data, dataSize); - } - - template<typename T, size_t inlineCapacity> template<typename U> - inline void Vector<T, inlineCapacity>::prepend(const U& val) - { - insert(0, val); - } - - template<typename T, size_t inlineCapacity> template<typename U, size_t c> - inline void Vector<T, inlineCapacity>::prepend(const Vector<U, c>& val) - { - insert(0, val.begin(), val.size()); - } - - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::remove(size_t position) - { - ASSERT(position < size()); - T* spot = begin() + position; - spot->~T(); - TypeOperations::moveOverlapping(spot + 1, end(), spot); - --m_size; - } - - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::remove(size_t position, size_t length) - { - ASSERT(position < size()); - ASSERT(position + length <= size()); - T* beginSpot = begin() + position; - T* endSpot = beginSpot + length; - TypeOperations::destruct(beginSpot, endSpot); - TypeOperations::moveOverlapping(endSpot, end(), beginSpot); - m_size -= length; - } - - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::reverse() - { - for (size_t i = 0; i < m_size / 2; ++i) - std::swap(at(i), at(m_size - 1 - i)); - } - - template<typename T, size_t inlineCapacity> - inline T* Vector<T, inlineCapacity>::releaseBuffer() - { - T* buffer = m_buffer.releaseBuffer(); - if (inlineCapacity && !buffer && m_size) { - // If the vector had some data, but no buffer to release, - // that means it was using the inline buffer. In that case, - // we create a brand new buffer so the caller always gets one. - size_t bytes = m_size * sizeof(T); - buffer = static_cast<T*>(fastMalloc(bytes)); - memcpy(buffer, data(), bytes); - } - m_size = 0; - return buffer; - } - - template<typename T, size_t inlineCapacity> - inline void Vector<T, inlineCapacity>::checkConsistency() - { -#if !ASSERT_DISABLED - for (size_t i = 0; i < size(); ++i) - ValueCheck<T>::checkConsistency(at(i)); -#endif - } - - template<typename T, size_t inlineCapacity> - void deleteAllValues(const Vector<T, inlineCapacity>& collection) - { - typedef typename Vector<T, inlineCapacity>::const_iterator iterator; - iterator end = collection.end(); - for (iterator it = collection.begin(); it != end; ++it) - delete *it; - } - - template<typename T, size_t inlineCapacity> - inline void swap(Vector<T, inlineCapacity>& a, Vector<T, inlineCapacity>& b) - { - a.swap(b); - } - - template<typename T, size_t inlineCapacity> - bool operator==(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b) - { - if (a.size() != b.size()) - return false; - - return VectorTypeOperations<T>::compare(a.data(), b.data(), a.size()); - } - - template<typename T, size_t inlineCapacity> - inline bool operator!=(const Vector<T, inlineCapacity>& a, const Vector<T, inlineCapacity>& b) - { - return !(a == b); - } - -#if !ASSERT_DISABLED - template<typename T> struct ValueCheck<Vector<T> > { - typedef Vector<T> TraitType; - static void checkConsistency(const Vector<T>& v) - { - v.checkConsistency(); - } - }; -#endif - -} // namespace WTF - -using WTF::Vector; - -#endif // WTF_Vector_h diff --git a/Source/JavaScriptCore/wtf/VectorTraits.h b/Source/JavaScriptCore/wtf/VectorTraits.h deleted file mode 100644 index 4041217ab..000000000 --- a/Source/JavaScriptCore/wtf/VectorTraits.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 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 WTF_VectorTraits_h -#define WTF_VectorTraits_h - -#include <wtf/OwnPtr.h> -#include <wtf/RefPtr.h> -#include <wtf/TypeTraits.h> -#include <utility> -#include <memory> - -using std::pair; - -namespace WTF { - - template<bool isPod, typename T> - struct VectorTraitsBase; - - template<typename T> - struct VectorTraitsBase<false, T> - { - static const bool needsDestruction = true; - static const bool needsInitialization = true; - static const bool canInitializeWithMemset = false; - static const bool canMoveWithMemcpy = false; - static const bool canCopyWithMemcpy = false; - static const bool canFillWithMemset = false; - static const bool canCompareWithMemcmp = false; - }; - - template<typename T> - struct VectorTraitsBase<true, T> - { - static const bool needsDestruction = false; - static const bool needsInitialization = false; - static const bool canInitializeWithMemset = false; - static const bool canMoveWithMemcpy = true; - static const bool canCopyWithMemcpy = true; - static const bool canFillWithMemset = sizeof(T) == sizeof(char); - static const bool canCompareWithMemcmp = true; - }; - - template<typename T> - struct VectorTraits : VectorTraitsBase<IsPod<T>::value, T> { }; - - struct SimpleClassVectorTraits : VectorTraitsBase<false, void> - { - static const bool canInitializeWithMemset = true; - static const bool canMoveWithMemcpy = true; - static const bool canCompareWithMemcmp = true; - }; - - // we know OwnPtr and RefPtr are simple enough that initializing to 0 and moving with memcpy - // (and then not destructing the original) will totally work - template<typename P> - struct VectorTraits<RefPtr<P> > : SimpleClassVectorTraits { }; - - template<typename P> - struct VectorTraits<OwnPtr<P> > : SimpleClassVectorTraits { }; - - template<typename First, typename Second> - struct VectorTraits<pair<First, Second> > - { - typedef VectorTraits<First> FirstTraits; - typedef VectorTraits<Second> SecondTraits; - - static const bool needsDestruction = FirstTraits::needsDestruction || SecondTraits::needsDestruction; - static const bool needsInitialization = FirstTraits::needsInitialization || SecondTraits::needsInitialization; - static const bool canInitializeWithMemset = FirstTraits::canInitializeWithMemset && SecondTraits::canInitializeWithMemset; - static const bool canMoveWithMemcpy = FirstTraits::canMoveWithMemcpy && SecondTraits::canMoveWithMemcpy; - static const bool canCopyWithMemcpy = FirstTraits::canCopyWithMemcpy && SecondTraits::canCopyWithMemcpy; - static const bool canFillWithMemset = false; - static const bool canCompareWithMemcmp = FirstTraits::canCompareWithMemcmp && SecondTraits::canCompareWithMemcmp; - }; - -} // namespace WTF - -using WTF::VectorTraits; -using WTF::SimpleClassVectorTraits; - -#endif // WTF_VectorTraits_h diff --git a/Source/JavaScriptCore/wtf/WTFThreadData.cpp b/Source/JavaScriptCore/wtf/WTFThreadData.cpp deleted file mode 100644 index ec5de7220..000000000 --- a/Source/JavaScriptCore/wtf/WTFThreadData.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 - * 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 "WTFThreadData.h" - -namespace WTF { - -ThreadSpecific<WTFThreadData>* WTFThreadData::staticData; - -WTFThreadData::WTFThreadData() - : m_atomicStringTable(0) - , m_atomicStringTableDestructor(0) -#if USE(JSC) - , m_defaultIdentifierTable(new JSC::IdentifierTable()) - , m_currentIdentifierTable(m_defaultIdentifierTable) - , m_stackBounds(StackBounds::currentThreadStackBounds()) -#endif -{ -} - -WTFThreadData::~WTFThreadData() -{ - if (m_atomicStringTableDestructor) - m_atomicStringTableDestructor(m_atomicStringTable); -#if USE(JSC) - delete m_defaultIdentifierTable; -#endif -} - -} // namespace WTF - -#if USE(JSC) -namespace JSC { - -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; -} - -} // namespace JSC -#endif - diff --git a/Source/JavaScriptCore/wtf/WTFThreadData.h b/Source/JavaScriptCore/wtf/WTFThreadData.h deleted file mode 100644 index b02d10d7c..000000000 --- a/Source/JavaScriptCore/wtf/WTFThreadData.h +++ /dev/null @@ -1,146 +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 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/StackBounds.h> -#include <wtf/text/StringHash.h> -#include <wtf/ThreadSpecific.h> -#include <wtf/Threading.h> - -#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 { - WTF_MAKE_FAST_ALLOCATED; -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); - - bool remove(StringImpl* r) - { - HashSet<StringImpl*>::iterator iter = m_table.find(r); - if (iter == m_table.end()) - return false; - m_table.remove(iter); - return true; - } - - LiteralIdentifierTable& literalTable() { return m_literalTable; } - -private: - HashSet<StringImpl*> m_table; - LiteralIdentifierTable m_literalTable; -}; - -} -#endif - -namespace WTF { - -class AtomicStringTable; - -typedef void (*AtomicStringTableDestructor)(AtomicStringTable*); - -class WTFThreadData { - WTF_MAKE_NONCOPYABLE(WTFThreadData); -public: - WTF_EXPORT_PRIVATE WTFThreadData(); - WTF_EXPORT_PRIVATE ~WTFThreadData(); - - AtomicStringTable* atomicStringTable() - { - return m_atomicStringTable; - } - -#if USE(JSC) - 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; - } - - const StackBounds& stack() const - { - return m_stackBounds; - } -#endif - -private: - AtomicStringTable* m_atomicStringTable; - AtomicStringTableDestructor m_atomicStringTableDestructor; - -#if USE(JSC) - JSC::IdentifierTable* m_defaultIdentifierTable; - JSC::IdentifierTable* m_currentIdentifierTable; - StackBounds m_stackBounds; -#endif - - static WTF_EXPORTDATA ThreadSpecific<WTFThreadData>* staticData; - friend WTFThreadData& wtfThreadData(); - friend class AtomicStringTable; -}; - -inline WTFThreadData& wtfThreadData() -{ - // 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; -} - -} // namespace WTF - -using WTF::WTFThreadData; -using WTF::wtfThreadData; - -#endif // WTFThreadData_h diff --git a/Source/JavaScriptCore/wtf/blackberry/MainThreadBlackBerry.cpp b/Source/JavaScriptCore/wtf/blackberry/MainThreadBlackBerry.cpp deleted file mode 100644 index 7284f4b44..000000000 --- a/Source/JavaScriptCore/wtf/blackberry/MainThreadBlackBerry.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2009, 2010, 2011 Research In Motion Limited. All rights reserved. - * - * 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 "MainThread.h" - -#include <BlackBerryPlatformClient.h> - -namespace WTF { - -void initializeMainThreadPlatform() -{ -} - -void scheduleDispatchFunctionsOnMainThread() -{ - BlackBerry::Platform::Client::get()->scheduleCallOnMainThread(dispatchFunctionsFromMainThread); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/chromium/ChromiumThreading.h b/Source/JavaScriptCore/wtf/chromium/ChromiumThreading.h deleted file mode 100644 index 39386219d..000000000 --- a/Source/JavaScriptCore/wtf/chromium/ChromiumThreading.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -* Copyright (C) 2009 Google Inc. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following disclaimer -* in the documentation and/or other materials provided with the -* distribution. -* * Neither the name of Google Inc. nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#ifndef ChromiumThreading_h -#define ChromiumThreading_h - -namespace WTF { - -// An interface to the embedding layer, which provides threading support. -class ChromiumThreading { -public: - static void callOnMainThread(void (*func)(void*), void* context); -}; - -} // namespace WTF - -#endif // ChromiumThreading_h diff --git a/Source/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp b/Source/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp deleted file mode 100644 index 9e6592b57..000000000 --- a/Source/JavaScriptCore/wtf/chromium/MainThreadChromium.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* -* Copyright (C) 2009 Google Inc. All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions are -* met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* * Redistributions in binary form must reproduce the above -* copyright notice, this list of conditions and the following disclaimer -* in the documentation and/or other materials provided with the -* distribution. -* * Neither the name of Google Inc. nor the names of its -* contributors may be used to endorse or promote products derived from -* this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "config.h" -#include "MainThread.h" - -#include "Assertions.h" -#include "ChromiumThreading.h" -#include "Threading.h" - -namespace WTF { - -static ThreadIdentifier mainThreadIdentifier; - -void initializeMainThread() -{ - static bool initializedMainThread; - if (initializedMainThread) - return; - initializedMainThread = true; - - mainThreadIdentifier = currentThread(); -} - -void callOnMainThread(MainThreadFunction* function, void* context) -{ - ChromiumThreading::callOnMainThread(function, context); -} - -void callOnMainThreadAndWait(MainThreadFunction*, void*) -{ - ASSERT_NOT_REACHED(); -} - -void setMainThreadCallbacksPaused(bool) -{ - ASSERT_NOT_REACHED(); -} - -bool isMainThread() -{ - return currentThread() == mainThreadIdentifier; -} - -} // namespace WTF - diff --git a/Source/JavaScriptCore/wtf/dtoa.cpp b/Source/JavaScriptCore/wtf/dtoa.cpp deleted file mode 100644 index 4c4041e1c..000000000 --- a/Source/JavaScriptCore/wtf/dtoa.cpp +++ /dev/null @@ -1,1363 +0,0 @@ -/**************************************************************** - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. - * Copyright (C) 2002, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - ***************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -/* On a machine with IEEE extended-precision registers, it is - * necessary to specify double-precision (53-bit) rounding precision - * before invoking strtod or dtoa. If the machine uses (the equivalent - * of) Intel 80x87 arithmetic, the call - * _control87(PC_53, MCW_PC); - * does this with many compilers. Whether this or another call is - * appropriate depends on the compiler; for this to work, it may be - * necessary to #include "float.h" or another system-dependent header - * file. - */ - -/* strtod for IEEE-arithmetic machines. - * - * This strtod returns a nearest machine number to the input decimal - * string (or sets errno to ERANGE). With IEEE arithmetic, ties are - * broken by the IEEE round-even rule. Otherwise ties are broken by - * biased rounding (add half and chop). - * - * Inspired loosely by William D. Clinger's paper "How to Read Floating - * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. - * - * Modifications: - * - * 1. We only require IEEE double-precision arithmetic (not IEEE double-extended). - * 2. We get by with floating-point arithmetic in a case that - * Clinger missed -- when we're computing d * 10^n - * for a small integer d and the integer n is not too - * much larger than 22 (the maximum integer k for which - * we can represent 10^k exactly), we may be able to - * compute (d*10^k) * 10^(e-k) with just one roundoff. - * 3. Rather than a bit-at-a-time adjustment of the binary - * result in the hard case, we use floating-point - * arithmetic to determine the adjustment to within - * one bit; only in really hard cases do we need to - * compute a second residual. - * 4. Because of 3., we don't need a large table of powers of 10 - * for ten-to-e (just some small tables, e.g. of 10^k - * for 0 <= k <= 22). - */ - -#include "config.h" -#include "dtoa.h" - -#if HAVE(ERRNO_H) -#include <errno.h> -#endif -#include <float.h> -#include <math.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <wtf/AlwaysInline.h> -#include <wtf/Assertions.h> -#include <wtf/FastMalloc.h> -#include <wtf/MathExtras.h> -#include <wtf/Threading.h> -#include <wtf/UnusedParam.h> -#include <wtf/Vector.h> -#include <wtf/dtoa/double-conversion.h> - -#if COMPILER(MSVC) -#pragma warning(disable: 4244) -#pragma warning(disable: 4245) -#pragma warning(disable: 4554) -#endif - -namespace WTF { - -Mutex* s_dtoaP5Mutex; - -typedef union { - double d; - uint32_t L[2]; -} U; - -#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) -#define word0(x) (x)->L[0] -#define word1(x) (x)->L[1] -#else -#define word0(x) (x)->L[1] -#define word1(x) (x)->L[0] -#endif -#define dval(x) (x)->d - -/* The following definition of Storeinc is appropriate for MIPS processors. - * An alternative that might be better on some machines is - * *p++ = high << 16 | low & 0xffff; - */ -static ALWAYS_INLINE uint32_t* storeInc(uint32_t* p, uint16_t high, uint16_t low) -{ - uint16_t* p16 = reinterpret_cast<uint16_t*>(p); -#if CPU(BIG_ENDIAN) - p16[0] = high; - p16[1] = low; -#else - p16[1] = high; - p16[0] = low; -#endif - return p + 1; -} - -#define Exp_shift 20 -#define Exp_shift1 20 -#define Exp_msk1 0x100000 -#define Exp_msk11 0x100000 -#define Exp_mask 0x7ff00000 -#define P 53 -#define Bias 1023 -#define Emin (-1022) -#define Exp_1 0x3ff00000 -#define Exp_11 0x3ff00000 -#define Ebits 11 -#define Frac_mask 0xfffff -#define Frac_mask1 0xfffff -#define Ten_pmax 22 -#define Bletch 0x10 -#define Bndry_mask 0xfffff -#define Bndry_mask1 0xfffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 1 -#define Tiny0 0 -#define Tiny1 1 -#define Quick_max 14 -#define Int_max 14 - -#define rounded_product(a, b) a *= b -#define rounded_quotient(a, b) a /= b - -#define Big0 (Frac_mask1 | Exp_msk1 * (DBL_MAX_EXP + Bias - 1)) -#define Big1 0xffffffff - -#if CPU(PPC64) || CPU(X86_64) -// FIXME: should we enable this on all 64-bit CPUs? -// 64-bit emulation provided by the compiler is likely to be slower than dtoa own code on 32-bit hardware. -#define USE_LONG_LONG -#endif - -struct BigInt { - BigInt() : sign(0) { } - int sign; - - void clear() - { - sign = 0; - m_words.clear(); - } - - size_t size() const - { - return m_words.size(); - } - - void resize(size_t s) - { - m_words.resize(s); - } - - uint32_t* words() - { - return m_words.data(); - } - - const uint32_t* words() const - { - return m_words.data(); - } - - void append(uint32_t w) - { - m_words.append(w); - } - - Vector<uint32_t, 16> m_words; -}; - -static void multadd(BigInt& b, int m, int a) /* multiply by m and add a */ -{ -#ifdef USE_LONG_LONG - unsigned long long carry; -#else - uint32_t carry; -#endif - - int wds = b.size(); - uint32_t* x = b.words(); - int i = 0; - carry = a; - do { -#ifdef USE_LONG_LONG - unsigned long long y = *x * (unsigned long long)m + carry; - carry = y >> 32; - *x++ = (uint32_t)y & 0xffffffffUL; -#else - uint32_t xi = *x; - uint32_t y = (xi & 0xffff) * m + carry; - uint32_t z = (xi >> 16) * m + (y >> 16); - carry = z >> 16; - *x++ = (z << 16) + (y & 0xffff); -#endif - } while (++i < wds); - - if (carry) - b.append((uint32_t)carry); -} - -static int hi0bits(uint32_t x) -{ - int k = 0; - - if (!(x & 0xffff0000)) { - k = 16; - x <<= 16; - } - if (!(x & 0xff000000)) { - k += 8; - x <<= 8; - } - if (!(x & 0xf0000000)) { - k += 4; - x <<= 4; - } - if (!(x & 0xc0000000)) { - k += 2; - x <<= 2; - } - if (!(x & 0x80000000)) { - k++; - if (!(x & 0x40000000)) - return 32; - } - return k; -} - -static int lo0bits(uint32_t* y) -{ - int k; - uint32_t x = *y; - - if (x & 7) { - if (x & 1) - return 0; - if (x & 2) { - *y = x >> 1; - return 1; - } - *y = x >> 2; - return 2; - } - k = 0; - if (!(x & 0xffff)) { - k = 16; - x >>= 16; - } - if (!(x & 0xff)) { - k += 8; - x >>= 8; - } - if (!(x & 0xf)) { - k += 4; - x >>= 4; - } - if (!(x & 0x3)) { - k += 2; - x >>= 2; - } - if (!(x & 1)) { - k++; - x >>= 1; - if (!x) - return 32; - } - *y = x; - return k; -} - -static void i2b(BigInt& b, int i) -{ - b.sign = 0; - b.resize(1); - b.words()[0] = i; -} - -static void mult(BigInt& aRef, const BigInt& bRef) -{ - const BigInt* a = &aRef; - const BigInt* b = &bRef; - BigInt c; - int wa, wb, wc; - const uint32_t* x = 0; - const uint32_t* xa; - const uint32_t* xb; - const uint32_t* xae; - const uint32_t* xbe; - uint32_t* xc; - uint32_t* xc0; - uint32_t y; -#ifdef USE_LONG_LONG - unsigned long long carry, z; -#else - uint32_t carry, z; -#endif - - if (a->size() < b->size()) { - const BigInt* tmp = a; - a = b; - b = tmp; - } - - wa = a->size(); - wb = b->size(); - wc = wa + wb; - c.resize(wc); - - for (xc = c.words(), xa = xc + wc; xc < xa; xc++) - *xc = 0; - xa = a->words(); - xae = xa + wa; - xb = b->words(); - xbe = xb + wb; - xc0 = c.words(); -#ifdef USE_LONG_LONG - for (; xb < xbe; xc0++) { - if ((y = *xb++)) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * (unsigned long long)y + *xc + carry; - carry = z >> 32; - *xc++ = (uint32_t)z & 0xffffffffUL; - } while (x < xae); - *xc = (uint32_t)carry; - } - } -#else - for (; xb < xbe; xb++, xc0++) { - if ((y = *xb & 0xffff)) { - x = xa; - xc = xc0; - carry = 0; - do { - z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; - carry = z >> 16; - uint32_t z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; - carry = z2 >> 16; - xc = storeInc(xc, z2, z); - } while (x < xae); - *xc = carry; - } - if ((y = *xb >> 16)) { - x = xa; - xc = xc0; - carry = 0; - uint32_t z2 = *xc; - do { - z = (*x & 0xffff) * y + (*xc >> 16) + carry; - carry = z >> 16; - xc = storeInc(xc, z, z2); - z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; - carry = z2 >> 16; - } while (x < xae); - *xc = z2; - } - } -#endif - for (xc0 = c.words(), xc = xc0 + wc; wc > 0 && !*--xc; --wc) { } - c.resize(wc); - aRef = c; -} - -struct P5Node { - WTF_MAKE_NONCOPYABLE(P5Node); WTF_MAKE_FAST_ALLOCATED; -public: - P5Node() { } - BigInt val; - P5Node* next; -}; - -static P5Node* p5s; -static int p5sCount; - -static ALWAYS_INLINE void pow5mult(BigInt& b, int k) -{ - static int p05[3] = { 5, 25, 125 }; - - if (int i = k & 3) - multadd(b, p05[i - 1], 0); - - if (!(k >>= 2)) - return; - - s_dtoaP5Mutex->lock(); - P5Node* p5 = p5s; - - if (!p5) { - /* first time */ - p5 = new P5Node; - i2b(p5->val, 625); - p5->next = 0; - p5s = p5; - p5sCount = 1; - } - - int p5sCountLocal = p5sCount; - s_dtoaP5Mutex->unlock(); - int p5sUsed = 0; - - for (;;) { - if (k & 1) - mult(b, p5->val); - - if (!(k >>= 1)) - break; - - if (++p5sUsed == p5sCountLocal) { - s_dtoaP5Mutex->lock(); - if (p5sUsed == p5sCount) { - ASSERT(!p5->next); - p5->next = new P5Node; - p5->next->next = 0; - p5->next->val = p5->val; - mult(p5->next->val, p5->next->val); - ++p5sCount; - } - - p5sCountLocal = p5sCount; - s_dtoaP5Mutex->unlock(); - } - p5 = p5->next; - } -} - -static ALWAYS_INLINE void lshift(BigInt& b, int k) -{ - int n = k >> 5; - - int origSize = b.size(); - int n1 = n + origSize + 1; - - if (k &= 0x1f) - b.resize(b.size() + n + 1); - else - b.resize(b.size() + n); - - const uint32_t* srcStart = b.words(); - uint32_t* dstStart = b.words(); - const uint32_t* src = srcStart + origSize - 1; - uint32_t* dst = dstStart + n1 - 1; - if (k) { - uint32_t hiSubword = 0; - int s = 32 - k; - for (; src >= srcStart; --src) { - *dst-- = hiSubword | *src >> s; - hiSubword = *src << k; - } - *dst = hiSubword; - ASSERT(dst == dstStart + n); - - b.resize(origSize + n + !!b.words()[n1 - 1]); - } - else { - do { - *--dst = *src--; - } while (src >= srcStart); - } - for (dst = dstStart + n; dst != dstStart; ) - *--dst = 0; - - ASSERT(b.size() <= 1 || b.words()[b.size() - 1]); -} - -static int cmp(const BigInt& a, const BigInt& b) -{ - const uint32_t *xa, *xa0, *xb, *xb0; - int i, j; - - i = a.size(); - j = b.size(); - ASSERT(i <= 1 || a.words()[i - 1]); - ASSERT(j <= 1 || b.words()[j - 1]); - if (i -= j) - return i; - xa0 = a.words(); - xa = xa0 + j; - xb0 = b.words(); - xb = xb0 + j; - for (;;) { - if (*--xa != *--xb) - return *xa < *xb ? -1 : 1; - if (xa <= xa0) - break; - } - return 0; -} - -static ALWAYS_INLINE void diff(BigInt& c, const BigInt& aRef, const BigInt& bRef) -{ - const BigInt* a = &aRef; - const BigInt* b = &bRef; - int i, wa, wb; - uint32_t* xc; - - i = cmp(*a, *b); - if (!i) { - c.sign = 0; - c.resize(1); - c.words()[0] = 0; - return; - } - if (i < 0) { - const BigInt* tmp = a; - a = b; - b = tmp; - i = 1; - } else - i = 0; - - wa = a->size(); - const uint32_t* xa = a->words(); - const uint32_t* xae = xa + wa; - wb = b->size(); - const uint32_t* xb = b->words(); - const uint32_t* xbe = xb + wb; - - c.resize(wa); - c.sign = i; - xc = c.words(); -#ifdef USE_LONG_LONG - unsigned long long borrow = 0; - do { - unsigned long long y = (unsigned long long)*xa++ - *xb++ - borrow; - borrow = y >> 32 & (uint32_t)1; - *xc++ = (uint32_t)y & 0xffffffffUL; - } while (xb < xbe); - while (xa < xae) { - unsigned long long y = *xa++ - borrow; - borrow = y >> 32 & (uint32_t)1; - *xc++ = (uint32_t)y & 0xffffffffUL; - } -#else - uint32_t borrow = 0; - do { - uint32_t y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - uint32_t z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - xc = storeInc(xc, z, y); - } while (xb < xbe); - while (xa < xae) { - uint32_t y = (*xa & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - uint32_t z = (*xa++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - xc = storeInc(xc, z, y); - } -#endif - while (!*--xc) - wa--; - c.resize(wa); -} - -static ALWAYS_INLINE void d2b(BigInt& b, U* d, int* e, int* bits) -{ - int de, k; - uint32_t* x; - uint32_t y, z; - int i; -#define d0 word0(d) -#define d1 word1(d) - - b.sign = 0; - b.resize(1); - x = b.words(); - - z = d0 & Frac_mask; - d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ - if ((de = (int)(d0 >> Exp_shift))) - z |= Exp_msk1; - if ((y = d1)) { - if ((k = lo0bits(&y))) { - x[0] = y | (z << (32 - k)); - z >>= k; - } else - x[0] = y; - if (z) { - b.resize(2); - x[1] = z; - } - - i = b.size(); - } else { - k = lo0bits(&z); - x[0] = z; - i = 1; - b.resize(1); - k += 32; - } - if (de) { - *e = de - Bias - (P - 1) + k; - *bits = P - k; - } else { - *e = 0 - Bias - (P - 1) + 1 + k; - *bits = (32 * i) - hi0bits(x[i - 1]); - } -} -#undef d0 -#undef d1 - -static const double tens[] = { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22 -}; - -static const double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; -static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, - 9007199254740992. * 9007199254740992.e-256 - /* = 2^106 * 1e-256 */ -}; - -/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ -/* flag unnecessarily. It leads to a song and dance at the end of strtod. */ -#define Scale_Bit 0x10 -#define n_bigtens 5 - -template<AllowTrailingJunkTag allowTrailingJunk> -double strtod(const char* s00, char** se) -{ - int length = strlen(s00); - double_conversion::StringToDoubleConverter converter( - (allowTrailingJunk ? double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK : 0) | - double_conversion::StringToDoubleConverter::ALLOW_LEADING_SPACES, - 0.0, - (allowTrailingJunk ? std::numeric_limits<double>::quiet_NaN() : 0.0), - "Infinity", "NaN"); - int processedCharacterCount = 0; - double result = converter.StringToDouble(s00, length, &processedCharacterCount); - if (se) - *se = const_cast<char*>(s00 + processedCharacterCount); - return result; -} - -template double strtod<AllowTrailingJunk>(const char*, char**); -template double strtod<DisallowTrailingJunk>(const char*, char**); - -static ALWAYS_INLINE int quorem(BigInt& b, BigInt& S) -{ - size_t n; - uint32_t* bx; - uint32_t* bxe; - uint32_t q; - uint32_t* sx; - uint32_t* sxe; -#ifdef USE_LONG_LONG - unsigned long long borrow, carry, y, ys; -#else - uint32_t borrow, carry, y, ys; - uint32_t si, z, zs; -#endif - ASSERT(b.size() <= 1 || b.words()[b.size() - 1]); - ASSERT(S.size() <= 1 || S.words()[S.size() - 1]); - - n = S.size(); - ASSERT_WITH_MESSAGE(b.size() <= n, "oversize b in quorem"); - if (b.size() < n) - return 0; - sx = S.words(); - sxe = sx + --n; - bx = b.words(); - bxe = bx + n; - q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ - ASSERT_WITH_MESSAGE(q <= 9, "oversized quotient in quorem"); - if (q) { - borrow = 0; - carry = 0; - do { -#ifdef USE_LONG_LONG - ys = *sx++ * (unsigned long long)q + carry; - carry = ys >> 32; - y = *bx - (ys & 0xffffffffUL) - borrow; - borrow = y >> 32 & (uint32_t)1; - *bx++ = (uint32_t)y & 0xffffffffUL; -#else - si = *sx++; - ys = (si & 0xffff) * q + carry; - zs = (si >> 16) * q + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - bx = storeInc(bx, z, y); -#endif - } while (sx <= sxe); - if (!*bxe) { - bx = b.words(); - while (--bxe > bx && !*bxe) - --n; - b.resize(n); - } - } - if (cmp(b, S) >= 0) { - q++; - borrow = 0; - carry = 0; - bx = b.words(); - sx = S.words(); - do { -#ifdef USE_LONG_LONG - ys = *sx++ + carry; - carry = ys >> 32; - y = *bx - (ys & 0xffffffffUL) - borrow; - borrow = y >> 32 & (uint32_t)1; - *bx++ = (uint32_t)y & 0xffffffffUL; -#else - si = *sx++; - ys = (si & 0xffff) + carry; - zs = (si >> 16) + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - bx = storeInc(bx, z, y); -#endif - } while (sx <= sxe); - bx = b.words(); - bxe = bx + n; - if (!*bxe) { - while (--bxe > bx && !*bxe) - --n; - b.resize(n); - } - } - return q; -} - -/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. - * - * Inspired by "How to Print Floating-Point Numbers Accurately" by - * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. - * - * Modifications: - * 1. Rather than iterating, we use a simple numeric overestimate - * to determine k = floor(log10(d)). We scale relevant - * quantities using O(log2(k)) rather than O(k) multiplications. - * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't - * try to generate digits strictly left to right. Instead, we - * compute with fewer bits and propagate the carry if necessary - * when rounding the final digit up. This is often faster. - * 3. Under the assumption that input will be rounded nearest, - * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. - * That is, we allow equality in stopping tests when the - * round-nearest rule will give the same floating-point value - * as would satisfaction of the stopping test with strict - * inequality. - * 4. We remove common factors of powers of 2 from relevant - * quantities. - * 5. When converting floating-point integers less than 1e16, - * we use floating-point arithmetic rather than resorting - * to multiple-precision integers. - * 6. When asked to produce fewer than 15 digits, we first try - * to get by with floating-point arithmetic; we resort to - * multiple-precision integer arithmetic only if we cannot - * guarantee that the floating-point calculation has given - * the correctly rounded result. For k requested digits and - * "uniformly" distributed input, the probability is - * something like 10^(k-15) that we must resort to the int32_t - * calculation. - * - * Note: 'leftright' translates to 'generate shortest possible string'. - */ -template<bool roundingNone, bool roundingSignificantFigures, bool roundingDecimalPlaces, bool leftright> -void dtoa(DtoaBuffer result, double dd, int ndigits, bool& signOut, int& exponentOut, unsigned& precisionOut) -{ - // Exactly one rounding mode must be specified. - ASSERT(roundingNone + roundingSignificantFigures + roundingDecimalPlaces == 1); - // roundingNone only allowed (only sensible?) with leftright set. - ASSERT(!roundingNone || leftright); - - ASSERT(isfinite(dd)); - - int bbits, b2, b5, be, dig, i, ieps, ilim = 0, ilim0, ilim1 = 0, - j, j1, k, k0, k_check, m2, m5, s2, s5, - spec_case; - int32_t L; - int denorm; - uint32_t x; - BigInt b, delta, mlo, mhi, S; - U d2, eps, u; - double ds; - char* s; - char* s0; - - u.d = dd; - - /* Infinity or NaN */ - ASSERT((word0(&u) & Exp_mask) != Exp_mask); - - // JavaScript toString conversion treats -0 as 0. - if (!dval(&u)) { - signOut = false; - exponentOut = 0; - precisionOut = 1; - result[0] = '0'; - result[1] = '\0'; - return; - } - - if (word0(&u) & Sign_bit) { - signOut = true; - word0(&u) &= ~Sign_bit; // clear sign bit - } else - signOut = false; - - d2b(b, &u, &be, &bbits); - if ((i = (int)(word0(&u) >> Exp_shift1 & (Exp_mask >> Exp_shift1)))) { - dval(&d2) = dval(&u); - word0(&d2) &= Frac_mask1; - word0(&d2) |= Exp_11; - - /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 - * log10(x) = log(x) / log(10) - * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) - * - * This suggests computing an approximation k to log10(d) by - * - * k = (i - Bias)*0.301029995663981 - * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); - * - * We want k to be too large rather than too small. - * The error in the first-order Taylor series approximation - * is in our favor, so we just round up the constant enough - * to compensate for any error in the multiplication of - * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, - * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, - * adding 1e-13 to the constant term more than suffices. - * Hence we adjust the constant term to 0.1760912590558. - * (We could get a more accurate k by invoking log10, - * but this is probably not worthwhile.) - */ - - i -= Bias; - denorm = 0; - } else { - /* d is denormalized */ - - i = bbits + be + (Bias + (P - 1) - 1); - x = (i > 32) ? (word0(&u) << (64 - i)) | (word1(&u) >> (i - 32)) - : word1(&u) << (32 - i); - dval(&d2) = x; - word0(&d2) -= 31 * Exp_msk1; /* adjust exponent */ - i -= (Bias + (P - 1) - 1) + 1; - denorm = 1; - } - ds = (dval(&d2) - 1.5) * 0.289529654602168 + 0.1760912590558 + (i * 0.301029995663981); - k = (int)ds; - if (ds < 0. && ds != k) - k--; /* want k = floor(ds) */ - k_check = 1; - if (k >= 0 && k <= Ten_pmax) { - if (dval(&u) < tens[k]) - k--; - k_check = 0; - } - j = bbits - i - 1; - if (j >= 0) { - b2 = 0; - s2 = j; - } else { - b2 = -j; - s2 = 0; - } - if (k >= 0) { - b5 = 0; - s5 = k; - s2 += k; - } else { - b2 -= k; - b5 = -k; - s5 = 0; - } - - if (roundingNone) { - ilim = ilim1 = -1; - i = 18; - ndigits = 0; - } - if (roundingSignificantFigures) { - if (ndigits <= 0) - ndigits = 1; - ilim = ilim1 = i = ndigits; - } - if (roundingDecimalPlaces) { - i = ndigits + k + 1; - ilim = i; - ilim1 = i - 1; - if (i <= 0) - i = 1; - } - - s = s0 = result; - - if (ilim >= 0 && ilim <= Quick_max) { - /* Try to get by with floating-point arithmetic. */ - - i = 0; - dval(&d2) = dval(&u); - k0 = k; - ilim0 = ilim; - ieps = 2; /* conservative */ - if (k > 0) { - ds = tens[k & 0xf]; - j = k >> 4; - if (j & Bletch) { - /* prevent overflows */ - j &= Bletch - 1; - dval(&u) /= bigtens[n_bigtens - 1]; - ieps++; - } - for (; j; j >>= 1, i++) { - if (j & 1) { - ieps++; - ds *= bigtens[i]; - } - } - dval(&u) /= ds; - } else if ((j1 = -k)) { - dval(&u) *= tens[j1 & 0xf]; - for (j = j1 >> 4; j; j >>= 1, i++) { - if (j & 1) { - ieps++; - dval(&u) *= bigtens[i]; - } - } - } - if (k_check && dval(&u) < 1. && ilim > 0) { - if (ilim1 <= 0) - goto fastFailed; - ilim = ilim1; - k--; - dval(&u) *= 10.; - ieps++; - } - dval(&eps) = (ieps * dval(&u)) + 7.; - word0(&eps) -= (P - 1) * Exp_msk1; - if (!ilim) { - S.clear(); - mhi.clear(); - dval(&u) -= 5.; - if (dval(&u) > dval(&eps)) - goto oneDigit; - if (dval(&u) < -dval(&eps)) - goto noDigits; - goto fastFailed; - } - if (leftright) { - /* Use Steele & White method of only - * generating digits needed. - */ - dval(&eps) = (0.5 / tens[ilim - 1]) - dval(&eps); - for (i = 0;;) { - L = (long int)dval(&u); - dval(&u) -= L; - *s++ = '0' + (int)L; - if (dval(&u) < dval(&eps)) - goto ret; - if (1. - dval(&u) < dval(&eps)) - goto bumpUp; - if (++i >= ilim) - break; - dval(&eps) *= 10.; - dval(&u) *= 10.; - } - } else { - /* Generate ilim digits, then fix them up. */ - dval(&eps) *= tens[ilim - 1]; - for (i = 1;; i++, dval(&u) *= 10.) { - L = (int32_t)(dval(&u)); - if (!(dval(&u) -= L)) - ilim = i; - *s++ = '0' + (int)L; - if (i == ilim) { - if (dval(&u) > 0.5 + dval(&eps)) - goto bumpUp; - if (dval(&u) < 0.5 - dval(&eps)) { - while (*--s == '0') { } - s++; - goto ret; - } - break; - } - } - } -fastFailed: - s = s0; - dval(&u) = dval(&d2); - k = k0; - ilim = ilim0; - } - - /* Do we have a "small" integer? */ - - if (be >= 0 && k <= Int_max) { - /* Yes. */ - ds = tens[k]; - if (ndigits < 0 && ilim <= 0) { - S.clear(); - mhi.clear(); - if (ilim < 0 || dval(&u) <= 5 * ds) - goto noDigits; - goto oneDigit; - } - for (i = 1;; i++, dval(&u) *= 10.) { - L = (int32_t)(dval(&u) / ds); - dval(&u) -= L * ds; - *s++ = '0' + (int)L; - if (!dval(&u)) { - break; - } - if (i == ilim) { - dval(&u) += dval(&u); - if (dval(&u) > ds || (dval(&u) == ds && (L & 1))) { -bumpUp: - while (*--s == '9') - if (s == s0) { - k++; - *s = '0'; - break; - } - ++*s++; - } - break; - } - } - goto ret; - } - - m2 = b2; - m5 = b5; - mhi.clear(); - mlo.clear(); - if (leftright) { - i = denorm ? be + (Bias + (P - 1) - 1 + 1) : 1 + P - bbits; - b2 += i; - s2 += i; - i2b(mhi, 1); - } - if (m2 > 0 && s2 > 0) { - i = m2 < s2 ? m2 : s2; - b2 -= i; - m2 -= i; - s2 -= i; - } - if (b5 > 0) { - if (leftright) { - if (m5 > 0) { - pow5mult(mhi, m5); - mult(b, mhi); - } - if ((j = b5 - m5)) - pow5mult(b, j); - } else - pow5mult(b, b5); - } - i2b(S, 1); - if (s5 > 0) - pow5mult(S, s5); - - /* Check for special case that d is a normalized power of 2. */ - - spec_case = 0; - if ((roundingNone || leftright) && (!word1(&u) && !(word0(&u) & Bndry_mask) && word0(&u) & (Exp_mask & ~Exp_msk1))) { - /* The special case */ - b2 += Log2P; - s2 += Log2P; - spec_case = 1; - } - - /* Arrange for convenient computation of quotients: - * shift left if necessary so divisor has 4 leading 0 bits. - * - * Perhaps we should just compute leading 28 bits of S once - * and for all and pass them and a shift to quorem, so it - * can do shifts and ors to compute the numerator for q. - */ - if ((i = ((s5 ? 32 - hi0bits(S.words()[S.size() - 1]) : 1) + s2) & 0x1f)) - i = 32 - i; - if (i > 4) { - i -= 4; - b2 += i; - m2 += i; - s2 += i; - } else if (i < 4) { - i += 28; - b2 += i; - m2 += i; - s2 += i; - } - if (b2 > 0) - lshift(b, b2); - if (s2 > 0) - lshift(S, s2); - if (k_check) { - if (cmp(b, S) < 0) { - k--; - multadd(b, 10, 0); /* we botched the k estimate */ - if (leftright) - multadd(mhi, 10, 0); - ilim = ilim1; - } - } - if (ilim <= 0 && roundingDecimalPlaces) { - if (ilim < 0) - goto noDigits; - multadd(S, 5, 0); - // For IEEE-754 unbiased rounding this check should be <=, such that 0.5 would flush to zero. - if (cmp(b, S) < 0) - goto noDigits; - goto oneDigit; - } - if (leftright) { - if (m2 > 0) - lshift(mhi, m2); - - /* Compute mlo -- check for special case - * that d is a normalized power of 2. - */ - - mlo = mhi; - if (spec_case) - lshift(mhi, Log2P); - - for (i = 1;;i++) { - dig = quorem(b, S) + '0'; - /* Do we yet have the shortest decimal string - * that will round to d? - */ - j = cmp(b, mlo); - diff(delta, S, mhi); - j1 = delta.sign ? 1 : cmp(b, delta); -#ifdef DTOA_ROUND_BIASED - if (j < 0 || !j) { -#else - // FIXME: ECMA-262 specifies that equidistant results round away from - // zero, which probably means we shouldn't be on the unbiased code path - // (the (word1(&u) & 1) clause is looking highly suspicious). I haven't - // yet understood this code well enough to make the call, but we should - // probably be enabling DTOA_ROUND_BIASED. I think the interesting corner - // case to understand is probably "Math.pow(0.5, 24).toString()". - // I believe this value is interesting because I think it is precisely - // representable in binary floating point, and its decimal representation - // has a single digit that Steele & White reduction can remove, with the - // value 5 (thus equidistant from the next numbers above and below). - // We produce the correct answer using either codepath, and I don't as - // yet understand why. :-) - if (!j1 && !(word1(&u) & 1)) { - if (dig == '9') - goto round9up; - if (j > 0) - dig++; - *s++ = dig; - goto ret; - } - if (j < 0 || (!j && !(word1(&u) & 1))) { -#endif - if ((b.words()[0] || b.size() > 1) && (j1 > 0)) { - lshift(b, 1); - j1 = cmp(b, S); - // For IEEE-754 round-to-even, this check should be (j1 > 0 || (!j1 && (dig & 1))), - // but ECMA-262 specifies that equidistant values (e.g. (.5).toFixed()) should - // be rounded away from zero. - if (j1 >= 0) { - if (dig == '9') - goto round9up; - dig++; - } - } - *s++ = dig; - goto ret; - } - if (j1 > 0) { - if (dig == '9') { /* possible if i == 1 */ -round9up: - *s++ = '9'; - goto roundoff; - } - *s++ = dig + 1; - goto ret; - } - *s++ = dig; - if (i == ilim) - break; - multadd(b, 10, 0); - multadd(mlo, 10, 0); - multadd(mhi, 10, 0); - } - } else { - for (i = 1;; i++) { - *s++ = dig = quorem(b, S) + '0'; - if (!b.words()[0] && b.size() <= 1) - goto ret; - if (i >= ilim) - break; - multadd(b, 10, 0); - } - } - - /* Round off last digit */ - - lshift(b, 1); - j = cmp(b, S); - // For IEEE-754 round-to-even, this check should be (j > 0 || (!j && (dig & 1))), - // but ECMA-262 specifies that equidistant values (e.g. (.5).toFixed()) should - // be rounded away from zero. - if (j >= 0) { -roundoff: - while (*--s == '9') - if (s == s0) { - k++; - *s++ = '1'; - goto ret; - } - ++*s++; - } else { - while (*--s == '0') { } - s++; - } - goto ret; -noDigits: - exponentOut = 0; - precisionOut = 1; - result[0] = '0'; - result[1] = '\0'; - return; -oneDigit: - *s++ = '1'; - k++; - goto ret; -ret: - ASSERT(s > result); - *s = 0; - exponentOut = k; - precisionOut = s - result; -} - -void dtoa(DtoaBuffer result, double dd, bool& sign, int& exponent, unsigned& precision) -{ - // flags are roundingNone, leftright. - dtoa<true, false, false, true>(result, dd, 0, sign, exponent, precision); -} - -void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision) -{ - // flag is roundingSignificantFigures. - dtoa<false, true, false, false>(result, dd, ndigits, sign, exponent, precision); -} - -void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision) -{ - // flag is roundingDecimalPlaces. - dtoa<false, false, true, false>(result, dd, ndigits, sign, exponent, precision); -} - -const char* numberToString(double d, NumberToStringBuffer buffer) -{ - double_conversion::StringBuilder builder(buffer, NumberToStringBufferLength); - const double_conversion::DoubleToStringConverter& converter = double_conversion::DoubleToStringConverter::EcmaScriptConverter(); - converter.ToShortest(d, &builder); - return builder.Finalize(); -} - -static inline const char* formatStringTruncatingTrailingZerosIfNeeded(NumberToStringBuffer buffer, double_conversion::StringBuilder& builder) -{ - size_t length = builder.position(); - size_t decimalPointPosition = 0; - for (; decimalPointPosition < length; ++decimalPointPosition) { - if (buffer[decimalPointPosition] == '.') - break; - } - - // No decimal seperator found, early exit. - if (decimalPointPosition == length) - return builder.Finalize(); - - size_t truncatedLength = length - 1; - for (; truncatedLength > decimalPointPosition; --truncatedLength) { - if (buffer[truncatedLength] != '0') - break; - } - - // No trailing zeros found to strip. - if (truncatedLength == length - 1) - return builder.Finalize(); - - // If we removed all trailing zeros, remove the decimal point as well. - if (truncatedLength == decimalPointPosition) { - ASSERT(truncatedLength > 0); - --truncatedLength; - } - - // Truncate the StringBuilder, and return the final result. - builder.SetPosition(truncatedLength + 1); - return builder.Finalize(); -} - -const char* numberToFixedPrecisionString(double d, unsigned significantFigures, NumberToStringBuffer buffer, bool truncateTrailingZeros) -{ - // Mimic String::format("%.[precision]g", ...), but use dtoas rounding facilities. - // "g": Signed value printed in f or e format, whichever is more compact for the given value and precision. - // The e format is used only when the exponent of the value is less than –4 or greater than or equal to the - // precision argument. Trailing zeros are truncated, and the decimal point appears only if one or more digits follow it. - // "precision": The precision specifies the maximum number of significant digits printed. - double_conversion::StringBuilder builder(buffer, NumberToStringBufferLength); - const double_conversion::DoubleToStringConverter& converter = double_conversion::DoubleToStringConverter::EcmaScriptConverter(); - converter.ToPrecision(d, significantFigures, &builder); - if (!truncateTrailingZeros) - return builder.Finalize(); - return formatStringTruncatingTrailingZerosIfNeeded(buffer, builder); -} - -const char* numberToFixedWidthString(double d, unsigned decimalPlaces, NumberToStringBuffer buffer) -{ - // Mimic String::format("%.[precision]f", ...), but use dtoas rounding facilities. - // "f": Signed value having the form [ – ]dddd.dddd, where dddd is one or more decimal digits. - // The number of digits before the decimal point depends on the magnitude of the number, and - // the number of digits after the decimal point depends on the requested precision. - // "precision": The precision value specifies the number of digits after the decimal point. - // If a decimal point appears, at least one digit appears before it. - // The value is rounded to the appropriate number of digits. - double_conversion::StringBuilder builder(buffer, NumberToStringBufferLength); - const double_conversion::DoubleToStringConverter& converter = double_conversion::DoubleToStringConverter::EcmaScriptConverter(); - converter.ToFixed(d, decimalPlaces, &builder); - return builder.Finalize(); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/dtoa.h b/Source/JavaScriptCore/wtf/dtoa.h deleted file mode 100644 index a4672c07a..000000000 --- a/Source/JavaScriptCore/wtf/dtoa.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2003, 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 WTF_dtoa_h -#define WTF_dtoa_h - -#include <wtf/dtoa/double-conversion.h> -#include <wtf/unicode/Unicode.h> - -namespace WTF { -class Mutex; - -extern WTF::Mutex* s_dtoaP5Mutex; - -typedef char DtoaBuffer[80]; - -WTF_EXPORT_PRIVATE void dtoa(DtoaBuffer result, double dd, bool& sign, int& exponent, unsigned& precision); -WTF_EXPORT_PRIVATE void dtoaRoundSF(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision); -WTF_EXPORT_PRIVATE void dtoaRoundDP(DtoaBuffer result, double dd, int ndigits, bool& sign, int& exponent, unsigned& precision); - -enum AllowTrailingJunkTag { DisallowTrailingJunk = 0, AllowTrailingJunk }; - -// s00: input string. Must not be 0 and must be terminated by 0. -// se: *se will have the last consumed character position + 1. -template<AllowTrailingJunkTag allowTrailingJunk> -double strtod(const char* s00, char** se); - -// Size = 80 for sizeof(DtoaBuffer) + some sign bits, decimal point, 'e', exponent digits. -const unsigned NumberToStringBufferLength = 96; -typedef char NumberToStringBuffer[NumberToStringBufferLength]; -typedef UChar NumberToUStringBuffer[NumberToStringBufferLength]; -WTF_EXPORT_PRIVATE const char* numberToString(double, NumberToStringBuffer); -const char* numberToFixedPrecisionString(double, unsigned significantFigures, NumberToStringBuffer, bool truncateTrailingZeros = false); -const char* numberToFixedWidthString(double, unsigned decimalPlaces, NumberToStringBuffer); - -} // namespace WTF - -using WTF::NumberToStringBuffer; -using WTF::NumberToUStringBuffer; -using WTF::numberToString; -using WTF::numberToFixedPrecisionString; -using WTF::numberToFixedWidthString; - -#endif // WTF_dtoa_h diff --git a/Source/JavaScriptCore/wtf/dtoa/COPYING b/Source/JavaScriptCore/wtf/dtoa/COPYING deleted file mode 100644 index 933718a9e..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/COPYING +++ /dev/null @@ -1,26 +0,0 @@ -Copyright 2006-2011, the V8 project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Source/JavaScriptCore/wtf/dtoa/LICENSE b/Source/JavaScriptCore/wtf/dtoa/LICENSE deleted file mode 100644 index 933718a9e..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/LICENSE +++ /dev/null @@ -1,26 +0,0 @@ -Copyright 2006-2011, the V8 project authors. All rights reserved. -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Source/JavaScriptCore/wtf/dtoa/README b/Source/JavaScriptCore/wtf/dtoa/README deleted file mode 100644 index f186b420f..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/README +++ /dev/null @@ -1,11 +0,0 @@ -http://code.google.com/p/double-conversion - -This project (double-conversion) provides binary-decimal and decimal-binary -routines for IEEE doubles. - -The library consists of efficient conversion routines that have been extracted -from the V8 JavaScript engine. The code has been refactored and improved so that -it can be used more easily in other projects. - -There is extensive documentation in src/double-conversion.h. Other examples can -be found in test/cctest/test-conversions.cc. diff --git a/Source/JavaScriptCore/wtf/dtoa/bignum-dtoa.cc b/Source/JavaScriptCore/wtf/dtoa/bignum-dtoa.cc deleted file mode 100644 index 38be56c73..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/bignum-dtoa.cc +++ /dev/null @@ -1,659 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#include <math.h> - -#include "bignum-dtoa.h" - -#include "bignum.h" -#include "double.h" - -namespace WTF { - -namespace double_conversion { - - static int NormalizedExponent(uint64_t significand, int exponent) { - ASSERT(significand != 0); - while ((significand & Double::kHiddenBit) == 0) { - significand = significand << 1; - exponent = exponent - 1; - } - return exponent; - } - - - // Forward declarations: - // Returns an estimation of k such that 10^(k-1) <= v < 10^k. - static int EstimatePower(int exponent); - // Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator - // and denominator. - static void InitialScaledStartValues(double v, - int estimated_power, - bool need_boundary_deltas, - Bignum* numerator, - Bignum* denominator, - Bignum* delta_minus, - Bignum* delta_plus); - // Multiplies numerator/denominator so that its values lies in the range 1-10. - // Returns decimal_point s.t. - // v = numerator'/denominator' * 10^(decimal_point-1) - // where numerator' and denominator' are the values of numerator and - // denominator after the call to this function. - static void FixupMultiply10(int estimated_power, bool is_even, - int* decimal_point, - Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus); - // Generates digits from the left to the right and stops when the generated - // digits yield the shortest decimal representation of v. - static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus, - bool is_even, - Vector<char> buffer, int* length); - // Generates 'requested_digits' after the decimal point. - static void BignumToFixed(int requested_digits, int* decimal_point, - Bignum* numerator, Bignum* denominator, - Vector<char>(buffer), int* length); - // Generates 'count' digits of numerator/denominator. - // Once 'count' digits have been produced rounds the result depending on the - // remainder (remainders of exactly .5 round upwards). Might update the - // decimal_point when rounding up (for example for 0.9999). - static void GenerateCountedDigits(int count, int* decimal_point, - Bignum* numerator, Bignum* denominator, - Vector<char>(buffer), int* length); - - - void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, - Vector<char> buffer, int* length, int* decimal_point) { - ASSERT(v > 0); - ASSERT(!Double(v).IsSpecial()); - uint64_t significand = Double(v).Significand(); - bool is_even = (significand & 1) == 0; - int exponent = Double(v).Exponent(); - int normalized_exponent = NormalizedExponent(significand, exponent); - // estimated_power might be too low by 1. - int estimated_power = EstimatePower(normalized_exponent); - - // Shortcut for Fixed. - // The requested digits correspond to the digits after the point. If the - // number is much too small, then there is no need in trying to get any - // digits. - if (mode == BIGNUM_DTOA_FIXED && -estimated_power - 1 > requested_digits) { - buffer[0] = '\0'; - *length = 0; - // Set decimal-point to -requested_digits. This is what Gay does. - // Note that it should not have any effect anyways since the string is - // empty. - *decimal_point = -requested_digits; - return; - } - - Bignum numerator; - Bignum denominator; - Bignum delta_minus; - Bignum delta_plus; - // Make sure the bignum can grow large enough. The smallest double equals - // 4e-324. In this case the denominator needs fewer than 324*4 binary digits. - // The maximum double is 1.7976931348623157e308 which needs fewer than - // 308*4 binary digits. - ASSERT(Bignum::kMaxSignificantBits >= 324*4); - bool need_boundary_deltas = (mode == BIGNUM_DTOA_SHORTEST); - InitialScaledStartValues(v, estimated_power, need_boundary_deltas, - &numerator, &denominator, - &delta_minus, &delta_plus); - // We now have v = (numerator / denominator) * 10^estimated_power. - FixupMultiply10(estimated_power, is_even, decimal_point, - &numerator, &denominator, - &delta_minus, &delta_plus); - // We now have v = (numerator / denominator) * 10^(decimal_point-1), and - // 1 <= (numerator + delta_plus) / denominator < 10 - switch (mode) { - case BIGNUM_DTOA_SHORTEST: - GenerateShortestDigits(&numerator, &denominator, - &delta_minus, &delta_plus, - is_even, buffer, length); - break; - case BIGNUM_DTOA_FIXED: - BignumToFixed(requested_digits, decimal_point, - &numerator, &denominator, - buffer, length); - break; - case BIGNUM_DTOA_PRECISION: - GenerateCountedDigits(requested_digits, decimal_point, - &numerator, &denominator, - buffer, length); - break; - default: - UNREACHABLE(); - } - buffer[*length] = '\0'; - } - - - // The procedure starts generating digits from the left to the right and stops - // when the generated digits yield the shortest decimal representation of v. A - // decimal representation of v is a number lying closer to v than to any other - // double, so it converts to v when read. - // - // This is true if d, the decimal representation, is between m- and m+, the - // upper and lower boundaries. d must be strictly between them if !is_even. - // m- := (numerator - delta_minus) / denominator - // m+ := (numerator + delta_plus) / denominator - // - // Precondition: 0 <= (numerator+delta_plus) / denominator < 10. - // If 1 <= (numerator+delta_plus) / denominator < 10 then no leading 0 digit - // will be produced. This should be the standard precondition. - static void GenerateShortestDigits(Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus, - bool is_even, - Vector<char> buffer, int* length) { - // Small optimization: if delta_minus and delta_plus are the same just reuse - // one of the two bignums. - if (Bignum::Equal(*delta_minus, *delta_plus)) { - delta_plus = delta_minus; - } - *length = 0; - while (true) { - uint16_t digit; - digit = numerator->DivideModuloIntBignum(*denominator); - ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. - // digit = numerator / denominator (integer division). - // numerator = numerator % denominator. - buffer[(*length)++] = digit + '0'; - - // Can we stop already? - // If the remainder of the division is less than the distance to the lower - // boundary we can stop. In this case we simply round down (discarding the - // remainder). - // Similarly we test if we can round up (using the upper boundary). - bool in_delta_room_minus; - bool in_delta_room_plus; - if (is_even) { - in_delta_room_minus = Bignum::LessEqual(*numerator, *delta_minus); - } else { - in_delta_room_minus = Bignum::Less(*numerator, *delta_minus); - } - if (is_even) { - in_delta_room_plus = - Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0; - } else { - in_delta_room_plus = - Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0; - } - if (!in_delta_room_minus && !in_delta_room_plus) { - // Prepare for next iteration. - numerator->Times10(); - delta_minus->Times10(); - // We optimized delta_plus to be equal to delta_minus (if they share the - // same value). So don't multiply delta_plus if they point to the same - // object. - if (delta_minus != delta_plus) { - delta_plus->Times10(); - } - } else if (in_delta_room_minus && in_delta_room_plus) { - // Let's see if 2*numerator < denominator. - // If yes, then the next digit would be < 5 and we can round down. - int compare = Bignum::PlusCompare(*numerator, *numerator, *denominator); - if (compare < 0) { - // Remaining digits are less than .5. -> Round down (== do nothing). - } else if (compare > 0) { - // Remaining digits are more than .5 of denominator. -> Round up. - // Note that the last digit could not be a '9' as otherwise the whole - // loop would have stopped earlier. - // We still have an assert here in case the preconditions were not - // satisfied. - ASSERT(buffer[(*length) - 1] != '9'); - buffer[(*length) - 1]++; - } else { - // Halfway case. - // TODO(floitsch): need a way to solve half-way cases. - // For now let's round towards even (since this is what Gay seems to - // do). - - if ((buffer[(*length) - 1] - '0') % 2 == 0) { - // Round down => Do nothing. - } else { - ASSERT(buffer[(*length) - 1] != '9'); - buffer[(*length) - 1]++; - } - } - return; - } else if (in_delta_room_minus) { - // Round down (== do nothing). - return; - } else { // in_delta_room_plus - // Round up. - // Note again that the last digit could not be '9' since this would have - // stopped the loop earlier. - // We still have an ASSERT here, in case the preconditions were not - // satisfied. - ASSERT(buffer[(*length) -1] != '9'); - buffer[(*length) - 1]++; - return; - } - } - } - - - // Let v = numerator / denominator < 10. - // Then we generate 'count' digits of d = x.xxxxx... (without the decimal point) - // from left to right. Once 'count' digits have been produced we decide wether - // to round up or down. Remainders of exactly .5 round upwards. Numbers such - // as 9.999999 propagate a carry all the way, and change the - // exponent (decimal_point), when rounding upwards. - static void GenerateCountedDigits(int count, int* decimal_point, - Bignum* numerator, Bignum* denominator, - Vector<char>(buffer), int* length) { - ASSERT(count >= 0); - for (int i = 0; i < count - 1; ++i) { - uint16_t digit; - digit = numerator->DivideModuloIntBignum(*denominator); - ASSERT(digit <= 9); // digit is a uint16_t and therefore always positive. - // digit = numerator / denominator (integer division). - // numerator = numerator % denominator. - buffer[i] = digit + '0'; - // Prepare for next iteration. - numerator->Times10(); - } - // Generate the last digit. - uint16_t digit; - digit = numerator->DivideModuloIntBignum(*denominator); - if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) { - digit++; - } - buffer[count - 1] = digit + '0'; - // Correct bad digits (in case we had a sequence of '9's). Propagate the - // carry until we hat a non-'9' or til we reach the first digit. - for (int i = count - 1; i > 0; --i) { - if (buffer[i] != '0' + 10) break; - buffer[i] = '0'; - buffer[i - 1]++; - } - if (buffer[0] == '0' + 10) { - // Propagate a carry past the top place. - buffer[0] = '1'; - (*decimal_point)++; - } - *length = count; - } - - - // Generates 'requested_digits' after the decimal point. It might omit - // trailing '0's. If the input number is too small then no digits at all are - // generated (ex.: 2 fixed digits for 0.00001). - // - // Input verifies: 1 <= (numerator + delta) / denominator < 10. - static void BignumToFixed(int requested_digits, int* decimal_point, - Bignum* numerator, Bignum* denominator, - Vector<char>(buffer), int* length) { - // Note that we have to look at more than just the requested_digits, since - // a number could be rounded up. Example: v=0.5 with requested_digits=0. - // Even though the power of v equals 0 we can't just stop here. - if (-(*decimal_point) > requested_digits) { - // The number is definitively too small. - // Ex: 0.001 with requested_digits == 1. - // Set decimal-point to -requested_digits. This is what Gay does. - // Note that it should not have any effect anyways since the string is - // empty. - *decimal_point = -requested_digits; - *length = 0; - return; - } else if (-(*decimal_point) == requested_digits) { - // We only need to verify if the number rounds down or up. - // Ex: 0.04 and 0.06 with requested_digits == 1. - ASSERT(*decimal_point == -requested_digits); - // Initially the fraction lies in range (1, 10]. Multiply the denominator - // by 10 so that we can compare more easily. - denominator->Times10(); - if (Bignum::PlusCompare(*numerator, *numerator, *denominator) >= 0) { - // If the fraction is >= 0.5 then we have to include the rounded - // digit. - buffer[0] = '1'; - *length = 1; - (*decimal_point)++; - } else { - // Note that we caught most of similar cases earlier. - *length = 0; - } - return; - } else { - // The requested digits correspond to the digits after the point. - // The variable 'needed_digits' includes the digits before the point. - int needed_digits = (*decimal_point) + requested_digits; - GenerateCountedDigits(needed_digits, decimal_point, - numerator, denominator, - buffer, length); - } - } - - - // Returns an estimation of k such that 10^(k-1) <= v < 10^k where - // v = f * 2^exponent and 2^52 <= f < 2^53. - // v is hence a normalized double with the given exponent. The output is an - // approximation for the exponent of the decimal approimation .digits * 10^k. - // - // The result might undershoot by 1 in which case 10^k <= v < 10^k+1. - // Note: this property holds for v's upper boundary m+ too. - // 10^k <= m+ < 10^k+1. - // (see explanation below). - // - // Examples: - // EstimatePower(0) => 16 - // EstimatePower(-52) => 0 - // - // Note: e >= 0 => EstimatedPower(e) > 0. No similar claim can be made for e<0. - static int EstimatePower(int exponent) { - // This function estimates log10 of v where v = f*2^e (with e == exponent). - // Note that 10^floor(log10(v)) <= v, but v <= 10^ceil(log10(v)). - // Note that f is bounded by its container size. Let p = 53 (the double's - // significand size). Then 2^(p-1) <= f < 2^p. - // - // Given that log10(v) == log2(v)/log2(10) and e+(len(f)-1) is quite close - // to log2(v) the function is simplified to (e+(len(f)-1)/log2(10)). - // The computed number undershoots by less than 0.631 (when we compute log3 - // and not log10). - // - // Optimization: since we only need an approximated result this computation - // can be performed on 64 bit integers. On x86/x64 architecture the speedup is - // not really measurable, though. - // - // Since we want to avoid overshooting we decrement by 1e10 so that - // floating-point imprecisions don't affect us. - // - // Explanation for v's boundary m+: the computation takes advantage of - // the fact that 2^(p-1) <= f < 2^p. Boundaries still satisfy this requirement - // (even for denormals where the delta can be much more important). - - const double k1Log10 = 0.30102999566398114; // 1/lg(10) - - // For doubles len(f) == 53 (don't forget the hidden bit). - const int kSignificandSize = 53; - double estimate = ceil((exponent + kSignificandSize - 1) * k1Log10 - 1e-10); - return static_cast<int>(estimate); - } - - - // See comments for InitialScaledStartValues. - static void InitialScaledStartValuesPositiveExponent( - double v, int estimated_power, bool need_boundary_deltas, - Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus) { - // A positive exponent implies a positive power. - ASSERT(estimated_power >= 0); - // Since the estimated_power is positive we simply multiply the denominator - // by 10^estimated_power. - - // numerator = v. - numerator->AssignUInt64(Double(v).Significand()); - numerator->ShiftLeft(Double(v).Exponent()); - // denominator = 10^estimated_power. - denominator->AssignPowerUInt16(10, estimated_power); - - if (need_boundary_deltas) { - // Introduce a common denominator so that the deltas to the boundaries are - // integers. - denominator->ShiftLeft(1); - numerator->ShiftLeft(1); - // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common - // denominator (of 2) delta_plus equals 2^e. - delta_plus->AssignUInt16(1); - delta_plus->ShiftLeft(Double(v).Exponent()); - // Same for delta_minus (with adjustments below if f == 2^p-1). - delta_minus->AssignUInt16(1); - delta_minus->ShiftLeft(Double(v).Exponent()); - - // If the significand (without the hidden bit) is 0, then the lower - // boundary is closer than just half a ulp (unit in the last place). - // There is only one exception: if the next lower number is a denormal then - // the distance is 1 ulp. This cannot be the case for exponent >= 0 (but we - // have to test it in the other function where exponent < 0). - uint64_t v_bits = Double(v).AsUint64(); - if ((v_bits & Double::kSignificandMask) == 0) { - // The lower boundary is closer at half the distance of "normal" numbers. - // Increase the common denominator and adapt all but the delta_minus. - denominator->ShiftLeft(1); // *2 - numerator->ShiftLeft(1); // *2 - delta_plus->ShiftLeft(1); // *2 - } - } - } - - - // See comments for InitialScaledStartValues - static void InitialScaledStartValuesNegativeExponentPositivePower( - double v, int estimated_power, bool need_boundary_deltas, - Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus) { - uint64_t significand = Double(v).Significand(); - int exponent = Double(v).Exponent(); - // v = f * 2^e with e < 0, and with estimated_power >= 0. - // This means that e is close to 0 (have a look at how estimated_power is - // computed). - - // numerator = significand - // since v = significand * 2^exponent this is equivalent to - // numerator = v * / 2^-exponent - numerator->AssignUInt64(significand); - // denominator = 10^estimated_power * 2^-exponent (with exponent < 0) - denominator->AssignPowerUInt16(10, estimated_power); - denominator->ShiftLeft(-exponent); - - if (need_boundary_deltas) { - // Introduce a common denominator so that the deltas to the boundaries are - // integers. - denominator->ShiftLeft(1); - numerator->ShiftLeft(1); - // Let v = f * 2^e, then m+ - v = 1/2 * 2^e; With the common - // denominator (of 2) delta_plus equals 2^e. - // Given that the denominator already includes v's exponent the distance - // to the boundaries is simply 1. - delta_plus->AssignUInt16(1); - // Same for delta_minus (with adjustments below if f == 2^p-1). - delta_minus->AssignUInt16(1); - - // If the significand (without the hidden bit) is 0, then the lower - // boundary is closer than just one ulp (unit in the last place). - // There is only one exception: if the next lower number is a denormal - // then the distance is 1 ulp. Since the exponent is close to zero - // (otherwise estimated_power would have been negative) this cannot happen - // here either. - uint64_t v_bits = Double(v).AsUint64(); - if ((v_bits & Double::kSignificandMask) == 0) { - // The lower boundary is closer at half the distance of "normal" numbers. - // Increase the denominator and adapt all but the delta_minus. - denominator->ShiftLeft(1); // *2 - numerator->ShiftLeft(1); // *2 - delta_plus->ShiftLeft(1); // *2 - } - } - } - - - // See comments for InitialScaledStartValues - static void InitialScaledStartValuesNegativeExponentNegativePower( - double v, int estimated_power, bool need_boundary_deltas, - Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus) { - const uint64_t kMinimalNormalizedExponent = - UINT64_2PART_C(0x00100000, 00000000); - uint64_t significand = Double(v).Significand(); - int exponent = Double(v).Exponent(); - // Instead of multiplying the denominator with 10^estimated_power we - // multiply all values (numerator and deltas) by 10^-estimated_power. - - // Use numerator as temporary container for power_ten. - Bignum* power_ten = numerator; - power_ten->AssignPowerUInt16(10, -estimated_power); - - if (need_boundary_deltas) { - // Since power_ten == numerator we must make a copy of 10^estimated_power - // before we complete the computation of the numerator. - // delta_plus = delta_minus = 10^estimated_power - delta_plus->AssignBignum(*power_ten); - delta_minus->AssignBignum(*power_ten); - } - - // numerator = significand * 2 * 10^-estimated_power - // since v = significand * 2^exponent this is equivalent to - // numerator = v * 10^-estimated_power * 2 * 2^-exponent. - // Remember: numerator has been abused as power_ten. So no need to assign it - // to itself. - ASSERT(numerator == power_ten); - numerator->MultiplyByUInt64(significand); - - // denominator = 2 * 2^-exponent with exponent < 0. - denominator->AssignUInt16(1); - denominator->ShiftLeft(-exponent); - - if (need_boundary_deltas) { - // Introduce a common denominator so that the deltas to the boundaries are - // integers. - numerator->ShiftLeft(1); - denominator->ShiftLeft(1); - // With this shift the boundaries have their correct value, since - // delta_plus = 10^-estimated_power, and - // delta_minus = 10^-estimated_power. - // These assignments have been done earlier. - - // The special case where the lower boundary is twice as close. - // This time we have to look out for the exception too. - uint64_t v_bits = Double(v).AsUint64(); - if ((v_bits & Double::kSignificandMask) == 0 && - // The only exception where a significand == 0 has its boundaries at - // "normal" distances: - (v_bits & Double::kExponentMask) != kMinimalNormalizedExponent) { - numerator->ShiftLeft(1); // *2 - denominator->ShiftLeft(1); // *2 - delta_plus->ShiftLeft(1); // *2 - } - } - } - - - // Let v = significand * 2^exponent. - // Computes v / 10^estimated_power exactly, as a ratio of two bignums, numerator - // and denominator. The functions GenerateShortestDigits and - // GenerateCountedDigits will then convert this ratio to its decimal - // representation d, with the required accuracy. - // Then d * 10^estimated_power is the representation of v. - // (Note: the fraction and the estimated_power might get adjusted before - // generating the decimal representation.) - // - // The initial start values consist of: - // - a scaled numerator: s.t. numerator/denominator == v / 10^estimated_power. - // - a scaled (common) denominator. - // optionally (used by GenerateShortestDigits to decide if it has the shortest - // decimal converting back to v): - // - v - m-: the distance to the lower boundary. - // - m+ - v: the distance to the upper boundary. - // - // v, m+, m-, and therefore v - m- and m+ - v all share the same denominator. - // - // Let ep == estimated_power, then the returned values will satisfy: - // v / 10^ep = numerator / denominator. - // v's boundarys m- and m+: - // m- / 10^ep == v / 10^ep - delta_minus / denominator - // m+ / 10^ep == v / 10^ep + delta_plus / denominator - // Or in other words: - // m- == v - delta_minus * 10^ep / denominator; - // m+ == v + delta_plus * 10^ep / denominator; - // - // Since 10^(k-1) <= v < 10^k (with k == estimated_power) - // or 10^k <= v < 10^(k+1) - // we then have 0.1 <= numerator/denominator < 1 - // or 1 <= numerator/denominator < 10 - // - // It is then easy to kickstart the digit-generation routine. - // - // The boundary-deltas are only filled if need_boundary_deltas is set. - static void InitialScaledStartValues(double v, - int estimated_power, - bool need_boundary_deltas, - Bignum* numerator, - Bignum* denominator, - Bignum* delta_minus, - Bignum* delta_plus) { - if (Double(v).Exponent() >= 0) { - InitialScaledStartValuesPositiveExponent( - v, estimated_power, need_boundary_deltas, - numerator, denominator, delta_minus, delta_plus); - } else if (estimated_power >= 0) { - InitialScaledStartValuesNegativeExponentPositivePower( - v, estimated_power, need_boundary_deltas, - numerator, denominator, delta_minus, delta_plus); - } else { - InitialScaledStartValuesNegativeExponentNegativePower( - v, estimated_power, need_boundary_deltas, - numerator, denominator, delta_minus, delta_plus); - } - } - - - // This routine multiplies numerator/denominator so that its values lies in the - // range 1-10. That is after a call to this function we have: - // 1 <= (numerator + delta_plus) /denominator < 10. - // Let numerator the input before modification and numerator' the argument - // after modification, then the output-parameter decimal_point is such that - // numerator / denominator * 10^estimated_power == - // numerator' / denominator' * 10^(decimal_point - 1) - // In some cases estimated_power was too low, and this is already the case. We - // then simply adjust the power so that 10^(k-1) <= v < 10^k (with k == - // estimated_power) but do not touch the numerator or denominator. - // Otherwise the routine multiplies the numerator and the deltas by 10. - static void FixupMultiply10(int estimated_power, bool is_even, - int* decimal_point, - Bignum* numerator, Bignum* denominator, - Bignum* delta_minus, Bignum* delta_plus) { - bool in_range; - if (is_even) { - // For IEEE doubles half-way cases (in decimal system numbers ending with 5) - // are rounded to the closest floating-point number with even significand. - in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) >= 0; - } else { - in_range = Bignum::PlusCompare(*numerator, *delta_plus, *denominator) > 0; - } - if (in_range) { - // Since numerator + delta_plus >= denominator we already have - // 1 <= numerator/denominator < 10. Simply update the estimated_power. - *decimal_point = estimated_power + 1; - } else { - *decimal_point = estimated_power; - numerator->Times10(); - if (Bignum::Equal(*delta_minus, *delta_plus)) { - delta_minus->Times10(); - delta_plus->AssignBignum(*delta_minus); - } else { - delta_minus->Times10(); - delta_plus->Times10(); - } - } - } - -} // namespace double_conversion - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/dtoa/bignum-dtoa.h b/Source/JavaScriptCore/wtf/dtoa/bignum-dtoa.h deleted file mode 100644 index 076168709..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/bignum-dtoa.h +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_BIGNUM_DTOA_H_ -#define DOUBLE_CONVERSION_BIGNUM_DTOA_H_ - -#include "utils.h" - -namespace WTF { - -namespace double_conversion { - - enum BignumDtoaMode { - // Return the shortest correct representation. - // For example the output of 0.299999999999999988897 is (the less accurate but - // correct) 0.3. - BIGNUM_DTOA_SHORTEST, - // Return a fixed number of digits after the decimal point. - // For instance fixed(0.1, 4) becomes 0.1000 - // If the input number is big, the output will be big. - BIGNUM_DTOA_FIXED, - // Return a fixed number of digits, no matter what the exponent is. - BIGNUM_DTOA_PRECISION - }; - - // Converts the given double 'v' to ascii. - // The result should be interpreted as buffer * 10^(point-length). - // The buffer will be null-terminated. - // - // The input v must be > 0 and different from NaN, and Infinity. - // - // The output depends on the given mode: - // - SHORTEST: produce the least amount of digits for which the internal - // identity requirement is still satisfied. If the digits are printed - // (together with the correct exponent) then reading this number will give - // 'v' again. The buffer will choose the representation that is closest to - // 'v'. If there are two at the same distance, than the number is round up. - // In this mode the 'requested_digits' parameter is ignored. - // - FIXED: produces digits necessary to print a given number with - // 'requested_digits' digits after the decimal point. The produced digits - // might be too short in which case the caller has to fill the gaps with '0's. - // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2. - // Halfway cases are rounded up. The call toFixed(0.15, 2) thus returns - // buffer="2", point=0. - // Note: the length of the returned buffer has no meaning wrt the significance - // of its digits. That is, just because it contains '0's does not mean that - // any other digit would not satisfy the internal identity requirement. - // - PRECISION: produces 'requested_digits' where the first digit is not '0'. - // Even though the length of produced digits usually equals - // 'requested_digits', the function is allowed to return fewer digits, in - // which case the caller has to fill the missing digits with '0's. - // Halfway cases are again rounded up. - // 'BignumDtoa' expects the given buffer to be big enough to hold all digits - // and a terminating null-character. - void BignumDtoa(double v, BignumDtoaMode mode, int requested_digits, - Vector<char> buffer, int* length, int* point); - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_BIGNUM_DTOA_H_ diff --git a/Source/JavaScriptCore/wtf/dtoa/bignum.cc b/Source/JavaScriptCore/wtf/dtoa/bignum.cc deleted file mode 100644 index 46a900a85..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/bignum.cc +++ /dev/null @@ -1,770 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#include "bignum.h" -#include "utils.h" - -namespace WTF { - -namespace double_conversion { - - Bignum::Bignum() - : bigits_(bigits_buffer_, kBigitCapacity), used_digits_(0), exponent_(0) { - for (int i = 0; i < kBigitCapacity; ++i) { - bigits_[i] = 0; - } - } - - - template<typename S> - static int BitSize(S value) { - return 8 * sizeof(value); - } - - // Guaranteed to lie in one Bigit. - void Bignum::AssignUInt16(uint16_t value) { - ASSERT(kBigitSize >= BitSize(value)); - Zero(); - if (value == 0) return; - - EnsureCapacity(1); - bigits_[0] = value; - used_digits_ = 1; - } - - - void Bignum::AssignUInt64(uint64_t value) { - const int kUInt64Size = 64; - - Zero(); - if (value == 0) return; - - int needed_bigits = kUInt64Size / kBigitSize + 1; - EnsureCapacity(needed_bigits); - for (int i = 0; i < needed_bigits; ++i) { - bigits_[i] = (uint32_t)value & kBigitMask; - value = value >> kBigitSize; - } - used_digits_ = needed_bigits; - Clamp(); - } - - - void Bignum::AssignBignum(const Bignum& other) { - exponent_ = other.exponent_; - for (int i = 0; i < other.used_digits_; ++i) { - bigits_[i] = other.bigits_[i]; - } - // Clear the excess digits (if there were any). - for (int i = other.used_digits_; i < used_digits_; ++i) { - bigits_[i] = 0; - } - used_digits_ = other.used_digits_; - } - - - static uint64_t ReadUInt64(Vector<const char> buffer, - int from, - int digits_to_read) { - uint64_t result = 0; - for (int i = from; i < from + digits_to_read; ++i) { - int digit = buffer[i] - '0'; - ASSERT(0 <= digit && digit <= 9); - result = result * 10 + digit; - } - return result; - } - - - void Bignum::AssignDecimalString(Vector<const char> value) { - // 2^64 = 18446744073709551616 > 10^19 - const int kMaxUint64DecimalDigits = 19; - Zero(); - int length = value.length(); - int pos = 0; - // Let's just say that each digit needs 4 bits. - while (length >= kMaxUint64DecimalDigits) { - uint64_t digits = ReadUInt64(value, pos, kMaxUint64DecimalDigits); - pos += kMaxUint64DecimalDigits; - length -= kMaxUint64DecimalDigits; - MultiplyByPowerOfTen(kMaxUint64DecimalDigits); - AddUInt64(digits); - } - uint64_t digits = ReadUInt64(value, pos, length); - MultiplyByPowerOfTen(length); - AddUInt64(digits); - Clamp(); - } - - - static int HexCharValue(char c) { - if ('0' <= c && c <= '9') return c - '0'; - if ('a' <= c && c <= 'f') return 10 + c - 'a'; - if ('A' <= c && c <= 'F') return 10 + c - 'A'; - UNREACHABLE(); - return 0; // To make compiler happy. - } - - - void Bignum::AssignHexString(Vector<const char> value) { - Zero(); - int length = value.length(); - - int needed_bigits = length * 4 / kBigitSize + 1; - EnsureCapacity(needed_bigits); - int string_index = length - 1; - for (int i = 0; i < needed_bigits - 1; ++i) { - // These bigits are guaranteed to be "full". - Chunk current_bigit = 0; - for (int j = 0; j < kBigitSize / 4; j++) { - current_bigit += HexCharValue(value[string_index--]) << (j * 4); - } - bigits_[i] = current_bigit; - } - used_digits_ = needed_bigits - 1; - - Chunk most_significant_bigit = 0; // Could be = 0; - for (int j = 0; j <= string_index; ++j) { - most_significant_bigit <<= 4; - most_significant_bigit += HexCharValue(value[j]); - } - if (most_significant_bigit != 0) { - bigits_[used_digits_] = most_significant_bigit; - used_digits_++; - } - Clamp(); - } - - - void Bignum::AddUInt64(uint64_t operand) { - if (operand == 0) return; - Bignum other; - other.AssignUInt64(operand); - AddBignum(other); - } - - - void Bignum::AddBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); - - // If this has a greater exponent than other append zero-bigits to this. - // After this call exponent_ <= other.exponent_. - Align(other); - - // There are two possibilities: - // aaaaaaaaaaa 0000 (where the 0s represent a's exponent) - // bbbbb 00000000 - // ---------------- - // ccccccccccc 0000 - // or - // aaaaaaaaaa 0000 - // bbbbbbbbb 0000000 - // ----------------- - // cccccccccccc 0000 - // In both cases we might need a carry bigit. - - EnsureCapacity(1 + Max(BigitLength(), other.BigitLength()) - exponent_); - Chunk carry = 0; - int bigit_pos = other.exponent_ - exponent_; - ASSERT(bigit_pos >= 0); - for (int i = 0; i < other.used_digits_; ++i) { - Chunk sum = bigits_[bigit_pos] + other.bigits_[i] + carry; - bigits_[bigit_pos] = sum & kBigitMask; - carry = sum >> kBigitSize; - bigit_pos++; - } - - while (carry != 0) { - Chunk sum = bigits_[bigit_pos] + carry; - bigits_[bigit_pos] = sum & kBigitMask; - carry = sum >> kBigitSize; - bigit_pos++; - } - used_digits_ = Max(bigit_pos, used_digits_); - ASSERT(IsClamped()); - } - - - void Bignum::SubtractBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); - // We require this to be bigger than other. - ASSERT(LessEqual(other, *this)); - - Align(other); - - int offset = other.exponent_ - exponent_; - Chunk borrow = 0; - int i; - for (i = 0; i < other.used_digits_; ++i) { - ASSERT((borrow == 0) || (borrow == 1)); - Chunk difference = bigits_[i + offset] - other.bigits_[i] - borrow; - bigits_[i + offset] = difference & kBigitMask; - borrow = difference >> (kChunkSize - 1); - } - while (borrow != 0) { - Chunk difference = bigits_[i + offset] - borrow; - bigits_[i + offset] = difference & kBigitMask; - borrow = difference >> (kChunkSize - 1); - ++i; - } - Clamp(); - } - - - void Bignum::ShiftLeft(int shift_amount) { - if (used_digits_ == 0) return; - exponent_ += shift_amount / kBigitSize; - int local_shift = shift_amount % kBigitSize; - EnsureCapacity(used_digits_ + 1); - BigitsShiftLeft(local_shift); - } - - - void Bignum::MultiplyByUInt32(uint32_t factor) { - if (factor == 1) return; - if (factor == 0) { - Zero(); - return; - } - if (used_digits_ == 0) return; - - // The product of a bigit with the factor is of size kBigitSize + 32. - // Assert that this number + 1 (for the carry) fits into double chunk. - ASSERT(kDoubleChunkSize >= kBigitSize + 32 + 1); - DoubleChunk carry = 0; - for (int i = 0; i < used_digits_; ++i) { - DoubleChunk product = static_cast<DoubleChunk>(factor) * bigits_[i] + carry; - bigits_[i] = static_cast<Chunk>(product & kBigitMask); - carry = (product >> kBigitSize); - } - while (carry != 0) { - EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = (uint32_t)carry & kBigitMask; - used_digits_++; - carry >>= kBigitSize; - } - } - - - void Bignum::MultiplyByUInt64(uint64_t factor) { - if (factor == 1) return; - if (factor == 0) { - Zero(); - return; - } - ASSERT(kBigitSize < 32); - uint64_t carry = 0; - uint64_t low = factor & 0xFFFFFFFF; - uint64_t high = factor >> 32; - for (int i = 0; i < used_digits_; ++i) { - uint64_t product_low = low * bigits_[i]; - uint64_t product_high = high * bigits_[i]; - uint64_t tmp = (carry & kBigitMask) + product_low; - bigits_[i] = (uint32_t)tmp & kBigitMask; - carry = (carry >> kBigitSize) + (tmp >> kBigitSize) + - (product_high << (32 - kBigitSize)); - } - while (carry != 0) { - EnsureCapacity(used_digits_ + 1); - bigits_[used_digits_] = (uint32_t)carry & kBigitMask; - used_digits_++; - carry >>= kBigitSize; - } - } - - - void Bignum::MultiplyByPowerOfTen(int exponent) { - const uint64_t kFive27 = UINT64_2PART_C(0x6765c793, fa10079d); - const uint16_t kFive1 = 5; - const uint16_t kFive2 = kFive1 * 5; - const uint16_t kFive3 = kFive2 * 5; - const uint16_t kFive4 = kFive3 * 5; - const uint16_t kFive5 = kFive4 * 5; - const uint16_t kFive6 = kFive5 * 5; - const uint32_t kFive7 = kFive6 * 5; - const uint32_t kFive8 = kFive7 * 5; - const uint32_t kFive9 = kFive8 * 5; - const uint32_t kFive10 = kFive9 * 5; - const uint32_t kFive11 = kFive10 * 5; - const uint32_t kFive12 = kFive11 * 5; - const uint32_t kFive13 = kFive12 * 5; - const uint32_t kFive1_to_12[] = - { kFive1, kFive2, kFive3, kFive4, kFive5, kFive6, - kFive7, kFive8, kFive9, kFive10, kFive11, kFive12 }; - - ASSERT(exponent >= 0); - if (exponent == 0) return; - if (used_digits_ == 0) return; - - // We shift by exponent at the end just before returning. - int remaining_exponent = exponent; - while (remaining_exponent >= 27) { - MultiplyByUInt64(kFive27); - remaining_exponent -= 27; - } - while (remaining_exponent >= 13) { - MultiplyByUInt32(kFive13); - remaining_exponent -= 13; - } - if (remaining_exponent > 0) { - MultiplyByUInt32(kFive1_to_12[remaining_exponent - 1]); - } - ShiftLeft(exponent); - } - - - void Bignum::Square() { - ASSERT(IsClamped()); - int product_length = 2 * used_digits_; - EnsureCapacity(product_length); - - // Comba multiplication: compute each column separately. - // Example: r = a2a1a0 * b2b1b0. - // r = 1 * a0b0 + - // 10 * (a1b0 + a0b1) + - // 100 * (a2b0 + a1b1 + a0b2) + - // 1000 * (a2b1 + a1b2) + - // 10000 * a2b2 - // - // In the worst case we have to accumulate nb-digits products of digit*digit. - // - // Assert that the additional number of bits in a DoubleChunk are enough to - // sum up used_digits of Bigit*Bigit. - if ((1 << (2 * (kChunkSize - kBigitSize))) <= used_digits_) { - UNIMPLEMENTED(); - } - DoubleChunk accumulator = 0; - // First shift the digits so we don't overwrite them. - int copy_offset = used_digits_; - for (int i = 0; i < used_digits_; ++i) { - bigits_[copy_offset + i] = bigits_[i]; - } - // We have two loops to avoid some 'if's in the loop. - for (int i = 0; i < used_digits_; ++i) { - // Process temporary digit i with power i. - // The sum of the two indices must be equal to i. - int bigit_index1 = i; - int bigit_index2 = 0; - // Sum all of the sub-products. - while (bigit_index1 >= 0) { - Chunk chunk1 = bigits_[copy_offset + bigit_index1]; - Chunk chunk2 = bigits_[copy_offset + bigit_index2]; - accumulator += static_cast<DoubleChunk>(chunk1) * chunk2; - bigit_index1--; - bigit_index2++; - } - bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask; - accumulator >>= kBigitSize; - } - for (int i = used_digits_; i < product_length; ++i) { - int bigit_index1 = used_digits_ - 1; - int bigit_index2 = i - bigit_index1; - // Invariant: sum of both indices is again equal to i. - // Inner loop runs 0 times on last iteration, emptying accumulator. - while (bigit_index2 < used_digits_) { - Chunk chunk1 = bigits_[copy_offset + bigit_index1]; - Chunk chunk2 = bigits_[copy_offset + bigit_index2]; - accumulator += static_cast<DoubleChunk>(chunk1) * chunk2; - bigit_index1--; - bigit_index2++; - } - // The overwritten bigits_[i] will never be read in further loop iterations, - // because bigit_index1 and bigit_index2 are always greater - // than i - used_digits_. - bigits_[i] = static_cast<Chunk>(accumulator) & kBigitMask; - accumulator >>= kBigitSize; - } - // Since the result was guaranteed to lie inside the number the - // accumulator must be 0 now. - ASSERT(accumulator == 0); - - // Don't forget to update the used_digits and the exponent. - used_digits_ = product_length; - exponent_ *= 2; - Clamp(); - } - - - void Bignum::AssignPowerUInt16(uint16_t base, int power_exponent) { - ASSERT(base != 0); - ASSERT(power_exponent >= 0); - if (power_exponent == 0) { - AssignUInt16(1); - return; - } - Zero(); - int shifts = 0; - // We expect base to be in range 2-32, and most often to be 10. - // It does not make much sense to implement different algorithms for counting - // the bits. - while ((base & 1) == 0) { - base >>= 1; - shifts++; - } - int bit_size = 0; - int tmp_base = base; - while (tmp_base != 0) { - tmp_base >>= 1; - bit_size++; - } - int final_size = bit_size * power_exponent; - // 1 extra bigit for the shifting, and one for rounded final_size. - EnsureCapacity(final_size / kBigitSize + 2); - - // Left to Right exponentiation. - int mask = 1; - while (power_exponent >= mask) mask <<= 1; - - // The mask is now pointing to the bit above the most significant 1-bit of - // power_exponent. - // Get rid of first 1-bit; - mask >>= 2; - uint64_t this_value = base; - - bool delayed_multipliciation = false; - const uint64_t max_32bits = 0xFFFFFFFF; - while (mask != 0 && this_value <= max_32bits) { - this_value = this_value * this_value; - // Verify that there is enough space in this_value to perform the - // multiplication. The first bit_size bits must be 0. - if ((power_exponent & mask) != 0) { - uint64_t base_bits_mask = - ~((static_cast<uint64_t>(1) << (64 - bit_size)) - 1); - bool high_bits_zero = (this_value & base_bits_mask) == 0; - if (high_bits_zero) { - this_value *= base; - } else { - delayed_multipliciation = true; - } - } - mask >>= 1; - } - AssignUInt64(this_value); - if (delayed_multipliciation) { - MultiplyByUInt32(base); - } - - // Now do the same thing as a bignum. - while (mask != 0) { - Square(); - if ((power_exponent & mask) != 0) { - MultiplyByUInt32(base); - } - mask >>= 1; - } - - // And finally add the saved shifts. - ShiftLeft(shifts * power_exponent); - } - - - // Precondition: this/other < 16bit. - uint16_t Bignum::DivideModuloIntBignum(const Bignum& other) { - ASSERT(IsClamped()); - ASSERT(other.IsClamped()); - ASSERT(other.used_digits_ > 0); - - // Easy case: if we have less digits than the divisor than the result is 0. - // Note: this handles the case where this == 0, too. - if (BigitLength() < other.BigitLength()) { - return 0; - } - - Align(other); - - uint16_t result = 0; - - // Start by removing multiples of 'other' until both numbers have the same - // number of digits. - while (BigitLength() > other.BigitLength()) { - // This naive approach is extremely inefficient if the this divided other - // might be big. This function is implemented for doubleToString where - // the result should be small (less than 10). - ASSERT(other.bigits_[other.used_digits_ - 1] >= ((1 << kBigitSize) / 16)); - // Remove the multiples of the first digit. - // Example this = 23 and other equals 9. -> Remove 2 multiples. - result += bigits_[used_digits_ - 1]; - SubtractTimes(other, bigits_[used_digits_ - 1]); - } - - ASSERT(BigitLength() == other.BigitLength()); - - // Both bignums are at the same length now. - // Since other has more than 0 digits we know that the access to - // bigits_[used_digits_ - 1] is safe. - Chunk this_bigit = bigits_[used_digits_ - 1]; - Chunk other_bigit = other.bigits_[other.used_digits_ - 1]; - - if (other.used_digits_ == 1) { - // Shortcut for easy (and common) case. - int quotient = this_bigit / other_bigit; - bigits_[used_digits_ - 1] = this_bigit - other_bigit * quotient; - result += quotient; - Clamp(); - return result; - } - - int division_estimate = this_bigit / (other_bigit + 1); - result += division_estimate; - SubtractTimes(other, division_estimate); - - if (other_bigit * (division_estimate + 1) > this_bigit) { - // No need to even try to subtract. Even if other's remaining digits were 0 - // another subtraction would be too much. - return result; - } - - while (LessEqual(other, *this)) { - SubtractBignum(other); - result++; - } - return result; - } - - - template<typename S> - static int SizeInHexChars(S number) { - ASSERT(number > 0); - int result = 0; - while (number != 0) { - number >>= 4; - result++; - } - return result; - } - - - static char HexCharOfValue(int value) { - ASSERT(0 <= value && value <= 16); - if (value < 10) return value + '0'; - return value - 10 + 'A'; - } - - - bool Bignum::ToHexString(char* buffer, int buffer_size) const { - ASSERT(IsClamped()); - // Each bigit must be printable as separate hex-character. - ASSERT(kBigitSize % 4 == 0); - const int kHexCharsPerBigit = kBigitSize / 4; - - if (used_digits_ == 0) { - if (buffer_size < 2) return false; - buffer[0] = '0'; - buffer[1] = '\0'; - return true; - } - // We add 1 for the terminating '\0' character. - int needed_chars = (BigitLength() - 1) * kHexCharsPerBigit + - SizeInHexChars(bigits_[used_digits_ - 1]) + 1; - if (needed_chars > buffer_size) return false; - int string_index = needed_chars - 1; - buffer[string_index--] = '\0'; - for (int i = 0; i < exponent_; ++i) { - for (int j = 0; j < kHexCharsPerBigit; ++j) { - buffer[string_index--] = '0'; - } - } - for (int i = 0; i < used_digits_ - 1; ++i) { - Chunk current_bigit = bigits_[i]; - for (int j = 0; j < kHexCharsPerBigit; ++j) { - buffer[string_index--] = HexCharOfValue(current_bigit & 0xF); - current_bigit >>= 4; - } - } - // And finally the last bigit. - Chunk most_significant_bigit = bigits_[used_digits_ - 1]; - while (most_significant_bigit != 0) { - buffer[string_index--] = HexCharOfValue(most_significant_bigit & 0xF); - most_significant_bigit >>= 4; - } - return true; - } - - - Bignum::Chunk Bignum::BigitAt(int index) const { - if (index >= BigitLength()) return 0; - if (index < exponent_) return 0; - return bigits_[index - exponent_]; - } - - - int Bignum::Compare(const Bignum& a, const Bignum& b) { - ASSERT(a.IsClamped()); - ASSERT(b.IsClamped()); - int bigit_length_a = a.BigitLength(); - int bigit_length_b = b.BigitLength(); - if (bigit_length_a < bigit_length_b) return -1; - if (bigit_length_a > bigit_length_b) return +1; - for (int i = bigit_length_a - 1; i >= Min(a.exponent_, b.exponent_); --i) { - Chunk bigit_a = a.BigitAt(i); - Chunk bigit_b = b.BigitAt(i); - if (bigit_a < bigit_b) return -1; - if (bigit_a > bigit_b) return +1; - // Otherwise they are equal up to this digit. Try the next digit. - } - return 0; - } - - - int Bignum::PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c) { - ASSERT(a.IsClamped()); - ASSERT(b.IsClamped()); - ASSERT(c.IsClamped()); - if (a.BigitLength() < b.BigitLength()) { - return PlusCompare(b, a, c); - } - if (a.BigitLength() + 1 < c.BigitLength()) return -1; - if (a.BigitLength() > c.BigitLength()) return +1; - // The exponent encodes 0-bigits. So if there are more 0-digits in 'a' than - // 'b' has digits, then the bigit-length of 'a'+'b' must be equal to the one - // of 'a'. - if (a.exponent_ >= b.BigitLength() && a.BigitLength() < c.BigitLength()) { - return -1; - } - - Chunk borrow = 0; - // Starting at min_exponent all digits are == 0. So no need to compare them. - int min_exponent = Min(Min(a.exponent_, b.exponent_), c.exponent_); - for (int i = c.BigitLength() - 1; i >= min_exponent; --i) { - Chunk chunk_a = a.BigitAt(i); - Chunk chunk_b = b.BigitAt(i); - Chunk chunk_c = c.BigitAt(i); - Chunk sum = chunk_a + chunk_b; - if (sum > chunk_c + borrow) { - return +1; - } else { - borrow = chunk_c + borrow - sum; - if (borrow > 1) return -1; - borrow <<= kBigitSize; - } - } - if (borrow == 0) return 0; - return -1; - } - - - void Bignum::Clamp() { - while (used_digits_ > 0 && bigits_[used_digits_ - 1] == 0) { - used_digits_--; - } - if (used_digits_ == 0) { - // Zero. - exponent_ = 0; - } - } - - - bool Bignum::IsClamped() const { - return used_digits_ == 0 || bigits_[used_digits_ - 1] != 0; - } - - - void Bignum::Zero() { - for (int i = 0; i < used_digits_; ++i) { - bigits_[i] = 0; - } - used_digits_ = 0; - exponent_ = 0; - } - - - void Bignum::Align(const Bignum& other) { - if (exponent_ > other.exponent_) { - // If "X" represents a "hidden" digit (by the exponent) then we are in the - // following case (a == this, b == other): - // a: aaaaaaXXXX or a: aaaaaXXX - // b: bbbbbbX b: bbbbbbbbXX - // We replace some of the hidden digits (X) of a with 0 digits. - // a: aaaaaa000X or a: aaaaa0XX - int zero_digits = exponent_ - other.exponent_; - EnsureCapacity(used_digits_ + zero_digits); - for (int i = used_digits_ - 1; i >= 0; --i) { - bigits_[i + zero_digits] = bigits_[i]; - } - for (int i = 0; i < zero_digits; ++i) { - bigits_[i] = 0; - } - used_digits_ += zero_digits; - exponent_ -= zero_digits; - ASSERT(used_digits_ >= 0); - ASSERT(exponent_ >= 0); - } - } - - - void Bignum::BigitsShiftLeft(int shift_amount) { - ASSERT(shift_amount < kBigitSize); - ASSERT(shift_amount >= 0); - Chunk carry = 0; - for (int i = 0; i < used_digits_; ++i) { - Chunk new_carry = bigits_[i] >> (kBigitSize - shift_amount); - bigits_[i] = ((bigits_[i] << shift_amount) + carry) & kBigitMask; - carry = new_carry; - } - if (carry != 0) { - bigits_[used_digits_] = carry; - used_digits_++; - } - } - - - void Bignum::SubtractTimes(const Bignum& other, int factor) { - ASSERT(exponent_ <= other.exponent_); - if (factor < 3) { - for (int i = 0; i < factor; ++i) { - SubtractBignum(other); - } - return; - } - Chunk borrow = 0; - int exponent_diff = other.exponent_ - exponent_; - for (int i = 0; i < other.used_digits_; ++i) { - DoubleChunk product = static_cast<DoubleChunk>(factor) * other.bigits_[i]; - DoubleChunk remove = borrow + product; - Chunk difference = bigits_[i + exponent_diff] - ((uint32_t)remove & kBigitMask); - bigits_[i + exponent_diff] = difference & kBigitMask; - borrow = static_cast<Chunk>((difference >> (kChunkSize - 1)) + - (remove >> kBigitSize)); - } - for (int i = other.used_digits_ + exponent_diff; i < used_digits_; ++i) { - if (borrow == 0) return; - Chunk difference = bigits_[i] - borrow; - bigits_[i] = difference & kBigitMask; - borrow = difference >> (kChunkSize - 1); - ++i; - } - Clamp(); - } - - -} // namespace double_conversion - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/dtoa/bignum.h b/Source/JavaScriptCore/wtf/dtoa/bignum.h deleted file mode 100644 index 1a750581a..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/bignum.h +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_BIGNUM_H_ -#define DOUBLE_CONVERSION_BIGNUM_H_ - -#include "utils.h" - -namespace WTF { - -namespace double_conversion { - - class Bignum { - public: - // 3584 = 128 * 28. We can represent 2^3584 > 10^1000 accurately. - // This bignum can encode much bigger numbers, since it contains an - // exponent. - static const int kMaxSignificantBits = 3584; - - Bignum(); - void AssignUInt16(uint16_t value); - void AssignUInt64(uint64_t value); - void AssignBignum(const Bignum& other); - - void AssignDecimalString(Vector<const char> value); - void AssignHexString(Vector<const char> value); - - void AssignPowerUInt16(uint16_t base, int exponent); - - void AddUInt16(uint16_t operand); - void AddUInt64(uint64_t operand); - void AddBignum(const Bignum& other); - // Precondition: this >= other. - void SubtractBignum(const Bignum& other); - - void Square(); - void ShiftLeft(int shift_amount); - void MultiplyByUInt32(uint32_t factor); - void MultiplyByUInt64(uint64_t factor); - void MultiplyByPowerOfTen(int exponent); - void Times10() { return MultiplyByUInt32(10); } - // Pseudocode: - // int result = this / other; - // this = this % other; - // In the worst case this function is in O(this/other). - uint16_t DivideModuloIntBignum(const Bignum& other); - - bool ToHexString(char* buffer, int buffer_size) const; - - static int Compare(const Bignum& a, const Bignum& b); - static bool Equal(const Bignum& a, const Bignum& b) { - return Compare(a, b) == 0; - } - static bool LessEqual(const Bignum& a, const Bignum& b) { - return Compare(a, b) <= 0; - } - static bool Less(const Bignum& a, const Bignum& b) { - return Compare(a, b) < 0; - } - // Returns Compare(a + b, c); - static int PlusCompare(const Bignum& a, const Bignum& b, const Bignum& c); - // Returns a + b == c - static bool PlusEqual(const Bignum& a, const Bignum& b, const Bignum& c) { - return PlusCompare(a, b, c) == 0; - } - // Returns a + b <= c - static bool PlusLessEqual(const Bignum& a, const Bignum& b, const Bignum& c) { - return PlusCompare(a, b, c) <= 0; - } - // Returns a + b < c - static bool PlusLess(const Bignum& a, const Bignum& b, const Bignum& c) { - return PlusCompare(a, b, c) < 0; - } - private: - typedef uint32_t Chunk; - typedef uint64_t DoubleChunk; - - static const int kChunkSize = sizeof(Chunk) * 8; - static const int kDoubleChunkSize = sizeof(DoubleChunk) * 8; - // With bigit size of 28 we loose some bits, but a double still fits easily - // into two chunks, and more importantly we can use the Comba multiplication. - static const int kBigitSize = 28; - static const Chunk kBigitMask = (1 << kBigitSize) - 1; - // Every instance allocates kBigitLength chunks on the stack. Bignums cannot - // grow. There are no checks if the stack-allocated space is sufficient. - static const int kBigitCapacity = kMaxSignificantBits / kBigitSize; - - void EnsureCapacity(int size) { - if (size > kBigitCapacity) { - UNREACHABLE(); - } - } - void Align(const Bignum& other); - void Clamp(); - bool IsClamped() const; - void Zero(); - // Requires this to have enough capacity (no tests done). - // Updates used_digits_ if necessary. - // shift_amount must be < kBigitSize. - void BigitsShiftLeft(int shift_amount); - // BigitLength includes the "hidden" digits encoded in the exponent. - int BigitLength() const { return used_digits_ + exponent_; } - Chunk BigitAt(int index) const; - void SubtractTimes(const Bignum& other, int factor); - - Chunk bigits_buffer_[kBigitCapacity]; - // A vector backed by bigits_buffer_. This way accesses to the array are - // checked for out-of-bounds errors. - Vector<Chunk> bigits_; - int used_digits_; - // The Bignum's value equals value(bigits_) * 2^(exponent_ * kBigitSize). - int exponent_; - - DISALLOW_COPY_AND_ASSIGN(Bignum); - }; - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_BIGNUM_H_ diff --git a/Source/JavaScriptCore/wtf/dtoa/cached-powers.cc b/Source/JavaScriptCore/wtf/dtoa/cached-powers.cc deleted file mode 100644 index 54cb7cadd..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/cached-powers.cc +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2006-2008 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#include <stdarg.h> -#include <limits.h> -#include <math.h> - -#include "UnusedParam.h" -#include "utils.h" -#include "cached-powers.h" - -namespace WTF { - -namespace double_conversion { - - struct CachedPower { - uint64_t significand; - int16_t binary_exponent; - int16_t decimal_exponent; - }; - - static int kCachedPowersLength = 1; - static int kCachedPowersOffset = 1; - static const double kD_1_LOG2_10 = 0.30102999566398114; // 1 / lg(10) - static CachedPower* kCachedPowers = 0; - - int PowersOfTenCache::kDecimalExponentDistance = 1; - int PowersOfTenCache::kMinDecimalExponent = 1; - int PowersOfTenCache::kMaxDecimalExponent = 1; - - void initialize() { - if (kCachedPowers) - return; - static CachedPower cachedPowers[] = { - {UINT64_2PART_C(0xfa8fd5a0, 081c0288), -1220, -348}, - {UINT64_2PART_C(0xbaaee17f, a23ebf76), -1193, -340}, - {UINT64_2PART_C(0x8b16fb20, 3055ac76), -1166, -332}, - {UINT64_2PART_C(0xcf42894a, 5dce35ea), -1140, -324}, - {UINT64_2PART_C(0x9a6bb0aa, 55653b2d), -1113, -316}, - {UINT64_2PART_C(0xe61acf03, 3d1a45df), -1087, -308}, - {UINT64_2PART_C(0xab70fe17, c79ac6ca), -1060, -300}, - {UINT64_2PART_C(0xff77b1fc, bebcdc4f), -1034, -292}, - {UINT64_2PART_C(0xbe5691ef, 416bd60c), -1007, -284}, - {UINT64_2PART_C(0x8dd01fad, 907ffc3c), -980, -276}, - {UINT64_2PART_C(0xd3515c28, 31559a83), -954, -268}, - {UINT64_2PART_C(0x9d71ac8f, ada6c9b5), -927, -260}, - {UINT64_2PART_C(0xea9c2277, 23ee8bcb), -901, -252}, - {UINT64_2PART_C(0xaecc4991, 4078536d), -874, -244}, - {UINT64_2PART_C(0x823c1279, 5db6ce57), -847, -236}, - {UINT64_2PART_C(0xc2109436, 4dfb5637), -821, -228}, - {UINT64_2PART_C(0x9096ea6f, 3848984f), -794, -220}, - {UINT64_2PART_C(0xd77485cb, 25823ac7), -768, -212}, - {UINT64_2PART_C(0xa086cfcd, 97bf97f4), -741, -204}, - {UINT64_2PART_C(0xef340a98, 172aace5), -715, -196}, - {UINT64_2PART_C(0xb23867fb, 2a35b28e), -688, -188}, - {UINT64_2PART_C(0x84c8d4df, d2c63f3b), -661, -180}, - {UINT64_2PART_C(0xc5dd4427, 1ad3cdba), -635, -172}, - {UINT64_2PART_C(0x936b9fce, bb25c996), -608, -164}, - {UINT64_2PART_C(0xdbac6c24, 7d62a584), -582, -156}, - {UINT64_2PART_C(0xa3ab6658, 0d5fdaf6), -555, -148}, - {UINT64_2PART_C(0xf3e2f893, dec3f126), -529, -140}, - {UINT64_2PART_C(0xb5b5ada8, aaff80b8), -502, -132}, - {UINT64_2PART_C(0x87625f05, 6c7c4a8b), -475, -124}, - {UINT64_2PART_C(0xc9bcff60, 34c13053), -449, -116}, - {UINT64_2PART_C(0x964e858c, 91ba2655), -422, -108}, - {UINT64_2PART_C(0xdff97724, 70297ebd), -396, -100}, - {UINT64_2PART_C(0xa6dfbd9f, b8e5b88f), -369, -92}, - {UINT64_2PART_C(0xf8a95fcf, 88747d94), -343, -84}, - {UINT64_2PART_C(0xb9447093, 8fa89bcf), -316, -76}, - {UINT64_2PART_C(0x8a08f0f8, bf0f156b), -289, -68}, - {UINT64_2PART_C(0xcdb02555, 653131b6), -263, -60}, - {UINT64_2PART_C(0x993fe2c6, d07b7fac), -236, -52}, - {UINT64_2PART_C(0xe45c10c4, 2a2b3b06), -210, -44}, - {UINT64_2PART_C(0xaa242499, 697392d3), -183, -36}, - {UINT64_2PART_C(0xfd87b5f2, 8300ca0e), -157, -28}, - {UINT64_2PART_C(0xbce50864, 92111aeb), -130, -20}, - {UINT64_2PART_C(0x8cbccc09, 6f5088cc), -103, -12}, - {UINT64_2PART_C(0xd1b71758, e219652c), -77, -4}, - {UINT64_2PART_C(0x9c400000, 00000000), -50, 4}, - {UINT64_2PART_C(0xe8d4a510, 00000000), -24, 12}, - {UINT64_2PART_C(0xad78ebc5, ac620000), 3, 20}, - {UINT64_2PART_C(0x813f3978, f8940984), 30, 28}, - {UINT64_2PART_C(0xc097ce7b, c90715b3), 56, 36}, - {UINT64_2PART_C(0x8f7e32ce, 7bea5c70), 83, 44}, - {UINT64_2PART_C(0xd5d238a4, abe98068), 109, 52}, - {UINT64_2PART_C(0x9f4f2726, 179a2245), 136, 60}, - {UINT64_2PART_C(0xed63a231, d4c4fb27), 162, 68}, - {UINT64_2PART_C(0xb0de6538, 8cc8ada8), 189, 76}, - {UINT64_2PART_C(0x83c7088e, 1aab65db), 216, 84}, - {UINT64_2PART_C(0xc45d1df9, 42711d9a), 242, 92}, - {UINT64_2PART_C(0x924d692c, a61be758), 269, 100}, - {UINT64_2PART_C(0xda01ee64, 1a708dea), 295, 108}, - {UINT64_2PART_C(0xa26da399, 9aef774a), 322, 116}, - {UINT64_2PART_C(0xf209787b, b47d6b85), 348, 124}, - {UINT64_2PART_C(0xb454e4a1, 79dd1877), 375, 132}, - {UINT64_2PART_C(0x865b8692, 5b9bc5c2), 402, 140}, - {UINT64_2PART_C(0xc83553c5, c8965d3d), 428, 148}, - {UINT64_2PART_C(0x952ab45c, fa97a0b3), 455, 156}, - {UINT64_2PART_C(0xde469fbd, 99a05fe3), 481, 164}, - {UINT64_2PART_C(0xa59bc234, db398c25), 508, 172}, - {UINT64_2PART_C(0xf6c69a72, a3989f5c), 534, 180}, - {UINT64_2PART_C(0xb7dcbf53, 54e9bece), 561, 188}, - {UINT64_2PART_C(0x88fcf317, f22241e2), 588, 196}, - {UINT64_2PART_C(0xcc20ce9b, d35c78a5), 614, 204}, - {UINT64_2PART_C(0x98165af3, 7b2153df), 641, 212}, - {UINT64_2PART_C(0xe2a0b5dc, 971f303a), 667, 220}, - {UINT64_2PART_C(0xa8d9d153, 5ce3b396), 694, 228}, - {UINT64_2PART_C(0xfb9b7cd9, a4a7443c), 720, 236}, - {UINT64_2PART_C(0xbb764c4c, a7a44410), 747, 244}, - {UINT64_2PART_C(0x8bab8eef, b6409c1a), 774, 252}, - {UINT64_2PART_C(0xd01fef10, a657842c), 800, 260}, - {UINT64_2PART_C(0x9b10a4e5, e9913129), 827, 268}, - {UINT64_2PART_C(0xe7109bfb, a19c0c9d), 853, 276}, - {UINT64_2PART_C(0xac2820d9, 623bf429), 880, 284}, - {UINT64_2PART_C(0x80444b5e, 7aa7cf85), 907, 292}, - {UINT64_2PART_C(0xbf21e440, 03acdd2d), 933, 300}, - {UINT64_2PART_C(0x8e679c2f, 5e44ff8f), 960, 308}, - {UINT64_2PART_C(0xd433179d, 9c8cb841), 986, 316}, - {UINT64_2PART_C(0x9e19db92, b4e31ba9), 1013, 324}, - {UINT64_2PART_C(0xeb96bf6e, badf77d9), 1039, 332}, - {UINT64_2PART_C(0xaf87023b, 9bf0ee6b), 1066, 340}, - }; - kCachedPowers = cachedPowers; - kCachedPowersLength = ARRAY_SIZE(cachedPowers); - kCachedPowersOffset = -cachedPowers[0].decimal_exponent; - PowersOfTenCache::kDecimalExponentDistance = kCachedPowers[1].decimal_exponent - kCachedPowers[0].decimal_exponent; - PowersOfTenCache::kMinDecimalExponent = kCachedPowers[0].decimal_exponent; - PowersOfTenCache::kMaxDecimalExponent = kCachedPowers[kCachedPowersLength - 1].decimal_exponent; - } - - void PowersOfTenCache::GetCachedPowerForBinaryExponentRange( - int min_exponent, - int max_exponent, - DiyFp* power, - int* decimal_exponent) { - UNUSED_PARAM(max_exponent); - int kQ = DiyFp::kSignificandSize; - double k = ceil((min_exponent + kQ - 1) * kD_1_LOG2_10); - int foo = kCachedPowersOffset; - int index = - (foo + static_cast<int>(k) - 1) / kDecimalExponentDistance + 1; - ASSERT(0 <= index && index < kCachedPowersLength); - CachedPower cached_power = kCachedPowers[index]; - ASSERT(min_exponent <= cached_power.binary_exponent); - ASSERT(cached_power.binary_exponent <= max_exponent); - *decimal_exponent = cached_power.decimal_exponent; - *power = DiyFp(cached_power.significand, cached_power.binary_exponent); - } - - - void PowersOfTenCache::GetCachedPowerForDecimalExponent(int requested_exponent, - DiyFp* power, - int* found_exponent) { - ASSERT(kMinDecimalExponent <= requested_exponent); - ASSERT(requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance); - int index = - (requested_exponent + kCachedPowersOffset) / kDecimalExponentDistance; - CachedPower cached_power = kCachedPowers[index]; - *power = DiyFp(cached_power.significand, cached_power.binary_exponent); - *found_exponent = cached_power.decimal_exponent; - ASSERT(*found_exponent <= requested_exponent); - ASSERT(requested_exponent < *found_exponent + kDecimalExponentDistance); - } - -} // namespace double_conversion - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/dtoa/cached-powers.h b/Source/JavaScriptCore/wtf/dtoa/cached-powers.h deleted file mode 100644 index cbc04d43d..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/cached-powers.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_CACHED_POWERS_H_ -#define DOUBLE_CONVERSION_CACHED_POWERS_H_ - -#include "diy-fp.h" - -namespace WTF { - -namespace double_conversion { - - class PowersOfTenCache { - public: - - // Not all powers of ten are cached. The decimal exponent of two neighboring - // cached numbers will differ by kDecimalExponentDistance. - static int kDecimalExponentDistance; - - static int kMinDecimalExponent; - static int kMaxDecimalExponent; - - // Returns a cached power-of-ten with a binary exponent in the range - // [min_exponent; max_exponent] (boundaries included). - static void GetCachedPowerForBinaryExponentRange(int min_exponent, - int max_exponent, - DiyFp* power, - int* decimal_exponent); - - // Returns a cached power of ten x ~= 10^k such that - // k <= decimal_exponent < k + kCachedPowersDecimalDistance. - // The given decimal_exponent must satisfy - // kMinDecimalExponent <= requested_exponent, and - // requested_exponent < kMaxDecimalExponent + kDecimalExponentDistance. - static void GetCachedPowerForDecimalExponent(int requested_exponent, - DiyFp* power, - int* found_exponent); - }; - - // Initializes the table of cached powers used by the dtoa algorithm. - // This needs to be called when JSC is being initialized. - void initialize(); - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_CACHED_POWERS_H_ diff --git a/Source/JavaScriptCore/wtf/dtoa/diy-fp.cc b/Source/JavaScriptCore/wtf/dtoa/diy-fp.cc deleted file mode 100644 index c0233595f..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/diy-fp.cc +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#include "diy-fp.h" -#include "utils.h" - -namespace WTF { - -namespace double_conversion { - - void DiyFp::Multiply(const DiyFp& other) { - // Simply "emulates" a 128 bit multiplication. - // However: the resulting number only contains 64 bits. The least - // significant 64 bits are only used for rounding the most significant 64 - // bits. - const uint64_t kM32 = 0xFFFFFFFFU; - uint64_t a = f_ >> 32; - uint64_t b = f_ & kM32; - uint64_t c = other.f_ >> 32; - uint64_t d = other.f_ & kM32; - uint64_t ac = a * c; - uint64_t bc = b * c; - uint64_t ad = a * d; - uint64_t bd = b * d; - uint64_t tmp = (bd >> 32) + (ad & kM32) + (bc & kM32); - // By adding 1U << 31 to tmp we round the final result. - // Halfway cases will be round up. - tmp += 1U << 31; - uint64_t result_f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32); - e_ += other.e_ + 64; - f_ = result_f; - } - -} // namespace double_conversion - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/dtoa/diy-fp.h b/Source/JavaScriptCore/wtf/dtoa/diy-fp.h deleted file mode 100644 index e843100a8..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/diy-fp.h +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_DIY_FP_H_ -#define DOUBLE_CONVERSION_DIY_FP_H_ - -#include "utils.h" - -namespace WTF { - -namespace double_conversion { - - // This "Do It Yourself Floating Point" class implements a floating-point number - // with a uint64 significand and an int exponent. Normalized DiyFp numbers will - // have the most significant bit of the significand set. - // Multiplication and Subtraction do not normalize their results. - // DiyFp are not designed to contain special doubles (NaN and Infinity). - class DiyFp { - public: - static const int kSignificandSize = 64; - - DiyFp() : f_(0), e_(0) {} - DiyFp(uint64_t f, int e) : f_(f), e_(e) {} - - // this = this - other. - // The exponents of both numbers must be the same and the significand of this - // must be bigger than the significand of other. - // The result will not be normalized. - void Subtract(const DiyFp& other) { - ASSERT(e_ == other.e_); - ASSERT(f_ >= other.f_); - f_ -= other.f_; - } - - // Returns a - b. - // The exponents of both numbers must be the same and this must be bigger - // than other. The result will not be normalized. - static DiyFp Minus(const DiyFp& a, const DiyFp& b) { - DiyFp result = a; - result.Subtract(b); - return result; - } - - - // this = this * other. - void Multiply(const DiyFp& other); - - // returns a * b; - static DiyFp Times(const DiyFp& a, const DiyFp& b) { - DiyFp result = a; - result.Multiply(b); - return result; - } - - void Normalize() { - ASSERT(f_ != 0); - uint64_t f = f_; - int e = e_; - - // This method is mainly called for normalizing boundaries. In general - // boundaries need to be shifted by 10 bits. We thus optimize for this case. - const uint64_t k10MSBits = UINT64_2PART_C(0xFFC00000, 00000000); - while ((f & k10MSBits) == 0) { - f <<= 10; - e -= 10; - } - while ((f & kUint64MSB) == 0) { - f <<= 1; - e--; - } - f_ = f; - e_ = e; - } - - static DiyFp Normalize(const DiyFp& a) { - DiyFp result = a; - result.Normalize(); - return result; - } - - uint64_t f() const { return f_; } - int e() const { return e_; } - - void set_f(uint64_t new_value) { f_ = new_value; } - void set_e(int new_value) { e_ = new_value; } - - private: - static const uint64_t kUint64MSB = UINT64_2PART_C(0x80000000, 00000000); - - uint64_t f_; - int e_; - }; - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_DIY_FP_H_ diff --git a/Source/JavaScriptCore/wtf/dtoa/double-conversion.cc b/Source/JavaScriptCore/wtf/dtoa/double-conversion.cc deleted file mode 100644 index cab1a51f2..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/double-conversion.cc +++ /dev/null @@ -1,870 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#include <limits.h> -#include <math.h> - -#include "double-conversion.h" - -#include "bignum-dtoa.h" -#include "double.h" -#include "fast-dtoa.h" -#include "fixed-dtoa.h" -#include "strtod.h" -#include "utils.h" - -namespace WTF { - -namespace double_conversion { - - const DoubleToStringConverter& DoubleToStringConverter::EcmaScriptConverter() { - int flags = UNIQUE_ZERO | EMIT_POSITIVE_EXPONENT_SIGN; - static DoubleToStringConverter converter(flags, - "Infinity", - "NaN", - 'e', - -6, 21, - 6, 0); - return converter; - } - - - bool DoubleToStringConverter::HandleSpecialValues( - double value, - StringBuilder* result_builder) const { - Double double_inspect(value); - if (double_inspect.IsInfinite()) { - if (infinity_symbol_ == NULL) return false; - if (value < 0) { - result_builder->AddCharacter('-'); - } - result_builder->AddString(infinity_symbol_); - return true; - } - if (double_inspect.IsNan()) { - if (nan_symbol_ == NULL) return false; - result_builder->AddString(nan_symbol_); - return true; - } - return false; - } - - - void DoubleToStringConverter::CreateExponentialRepresentation( - const char* decimal_digits, - int length, - int exponent, - StringBuilder* result_builder) const { - ASSERT(length != 0); - result_builder->AddCharacter(decimal_digits[0]); - if (length != 1) { - result_builder->AddCharacter('.'); - result_builder->AddSubstring(&decimal_digits[1], length-1); - } - result_builder->AddCharacter(exponent_character_); - if (exponent < 0) { - result_builder->AddCharacter('-'); - exponent = -exponent; - } else { - if ((flags_ & EMIT_POSITIVE_EXPONENT_SIGN) != 0) { - result_builder->AddCharacter('+'); - } - } - if (exponent == 0) { - result_builder->AddCharacter('0'); - return; - } - ASSERT(exponent < 1e4); - const int kMaxExponentLength = 5; - char buffer[kMaxExponentLength]; - int first_char_pos = kMaxExponentLength; - while (exponent > 0) { - buffer[--first_char_pos] = '0' + (exponent % 10); - exponent /= 10; - } - result_builder->AddSubstring(&buffer[first_char_pos], - kMaxExponentLength - first_char_pos); - } - - - void DoubleToStringConverter::CreateDecimalRepresentation( - const char* decimal_digits, - int length, - int decimal_point, - int digits_after_point, - StringBuilder* result_builder) const { - // Create a representation that is padded with zeros if needed. - if (decimal_point <= 0) { - // "0.00000decimal_rep". - result_builder->AddCharacter('0'); - if (digits_after_point > 0) { - result_builder->AddCharacter('.'); - result_builder->AddPadding('0', -decimal_point); - ASSERT(length <= digits_after_point - (-decimal_point)); - result_builder->AddSubstring(decimal_digits, length); - int remaining_digits = digits_after_point - (-decimal_point) - length; - result_builder->AddPadding('0', remaining_digits); - } - } else if (decimal_point >= length) { - // "decimal_rep0000.00000" or "decimal_rep.0000" - result_builder->AddSubstring(decimal_digits, length); - result_builder->AddPadding('0', decimal_point - length); - if (digits_after_point > 0) { - result_builder->AddCharacter('.'); - result_builder->AddPadding('0', digits_after_point); - } - } else { - // "decima.l_rep000" - ASSERT(digits_after_point > 0); - result_builder->AddSubstring(decimal_digits, decimal_point); - result_builder->AddCharacter('.'); - ASSERT(length - decimal_point <= digits_after_point); - result_builder->AddSubstring(&decimal_digits[decimal_point], - length - decimal_point); - int remaining_digits = digits_after_point - (length - decimal_point); - result_builder->AddPadding('0', remaining_digits); - } - if (digits_after_point == 0) { - if ((flags_ & EMIT_TRAILING_DECIMAL_POINT) != 0) { - result_builder->AddCharacter('.'); - } - if ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) { - result_builder->AddCharacter('0'); - } - } - } - - - bool DoubleToStringConverter::ToShortest(double value, - StringBuilder* result_builder) const { - if (Double(value).IsSpecial()) { - return HandleSpecialValues(value, result_builder); - } - - int decimal_point; - bool sign; - const int kDecimalRepCapacity = kBase10MaximalLength + 1; - char decimal_rep[kDecimalRepCapacity]; - int decimal_rep_length; - - DoubleToAscii(value, SHORTEST, 0, decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - - bool unique_zero = (flags_ & UNIQUE_ZERO) != 0; - if (sign && (value != 0.0 || !unique_zero)) { - result_builder->AddCharacter('-'); - } - - int exponent = decimal_point - 1; - if ((decimal_in_shortest_low_ <= exponent) && - (exponent < decimal_in_shortest_high_)) { - CreateDecimalRepresentation(decimal_rep, decimal_rep_length, - decimal_point, - Max(0, decimal_rep_length - decimal_point), - result_builder); - } else { - CreateExponentialRepresentation(decimal_rep, decimal_rep_length, exponent, - result_builder); - } - return true; - } - - - bool DoubleToStringConverter::ToFixed(double value, - int requested_digits, - StringBuilder* result_builder) const { - ASSERT(kMaxFixedDigitsBeforePoint == 60); - const double kFirstNonFixed = 1e60; - - if (Double(value).IsSpecial()) { - return HandleSpecialValues(value, result_builder); - } - - if (requested_digits > kMaxFixedDigitsAfterPoint) return false; - if (value >= kFirstNonFixed || value <= -kFirstNonFixed) return false; - - // Find a sufficiently precise decimal representation of n. - int decimal_point; - bool sign; - // Add space for the '\0' byte. - const int kDecimalRepCapacity = - kMaxFixedDigitsBeforePoint + kMaxFixedDigitsAfterPoint + 1; - char decimal_rep[kDecimalRepCapacity]; - int decimal_rep_length; - DoubleToAscii(value, FIXED, requested_digits, - decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - - bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); - if (sign && (value != 0.0 || !unique_zero)) { - result_builder->AddCharacter('-'); - } - - CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point, - requested_digits, result_builder); - return true; - } - - - bool DoubleToStringConverter::ToExponential( - double value, - int requested_digits, - StringBuilder* result_builder) const { - if (Double(value).IsSpecial()) { - return HandleSpecialValues(value, result_builder); - } - - if (requested_digits < -1) return false; - if (requested_digits > kMaxExponentialDigits) return false; - - int decimal_point; - bool sign; - // Add space for digit before the decimal point and the '\0' character. - const int kDecimalRepCapacity = kMaxExponentialDigits + 2; - ASSERT(kDecimalRepCapacity > kBase10MaximalLength); - char decimal_rep[kDecimalRepCapacity]; - int decimal_rep_length; - - if (requested_digits == -1) { - DoubleToAscii(value, SHORTEST, 0, - decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - } else { - DoubleToAscii(value, PRECISION, requested_digits + 1, - decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - ASSERT(decimal_rep_length <= requested_digits + 1); - - for (int i = decimal_rep_length; i < requested_digits + 1; ++i) { - decimal_rep[i] = '0'; - } - decimal_rep_length = requested_digits + 1; - } - - bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); - if (sign && (value != 0.0 || !unique_zero)) { - result_builder->AddCharacter('-'); - } - - int exponent = decimal_point - 1; - CreateExponentialRepresentation(decimal_rep, - decimal_rep_length, - exponent, - result_builder); - return true; - } - - - bool DoubleToStringConverter::ToPrecision(double value, - int precision, - StringBuilder* result_builder) const { - if (Double(value).IsSpecial()) { - return HandleSpecialValues(value, result_builder); - } - - if (precision < kMinPrecisionDigits || precision > kMaxPrecisionDigits) { - return false; - } - - // Find a sufficiently precise decimal representation of n. - int decimal_point; - bool sign; - // Add one for the terminating null character. - const int kDecimalRepCapacity = kMaxPrecisionDigits + 1; - char decimal_rep[kDecimalRepCapacity]; - int decimal_rep_length; - - DoubleToAscii(value, PRECISION, precision, - decimal_rep, kDecimalRepCapacity, - &sign, &decimal_rep_length, &decimal_point); - ASSERT(decimal_rep_length <= precision); - - bool unique_zero = ((flags_ & UNIQUE_ZERO) != 0); - if (sign && (value != 0.0 || !unique_zero)) { - result_builder->AddCharacter('-'); - } - - // The exponent if we print the number as x.xxeyyy. That is with the - // decimal point after the first digit. - int exponent = decimal_point - 1; - - int extra_zero = ((flags_ & EMIT_TRAILING_ZERO_AFTER_POINT) != 0) ? 1 : 0; - if ((-decimal_point + 1 > max_leading_padding_zeroes_in_precision_mode_) || - (decimal_point - precision + extra_zero > - max_trailing_padding_zeroes_in_precision_mode_)) { - // Fill buffer to contain 'precision' digits. - // Usually the buffer is already at the correct length, but 'DoubleToAscii' - // is allowed to return less characters. - for (int i = decimal_rep_length; i < precision; ++i) { - decimal_rep[i] = '0'; - } - - CreateExponentialRepresentation(decimal_rep, - precision, - exponent, - result_builder); - } else { - CreateDecimalRepresentation(decimal_rep, decimal_rep_length, decimal_point, - Max(0, precision - decimal_point), - result_builder); - } - return true; - } - - - static BignumDtoaMode DtoaToBignumDtoaMode( - DoubleToStringConverter::DtoaMode dtoa_mode) { - switch (dtoa_mode) { - case DoubleToStringConverter::SHORTEST: return BIGNUM_DTOA_SHORTEST; - case DoubleToStringConverter::FIXED: return BIGNUM_DTOA_FIXED; - case DoubleToStringConverter::PRECISION: return BIGNUM_DTOA_PRECISION; - default: - UNREACHABLE(); - return BIGNUM_DTOA_SHORTEST; // To silence compiler. - } - } - - - void DoubleToStringConverter::DoubleToAscii(double v, - DtoaMode mode, - int requested_digits, - char* buffer, - int buffer_length, - bool* sign, - int* length, - int* point) { - Vector<char> vector(buffer, buffer_length); - ASSERT(!Double(v).IsSpecial()); - ASSERT(mode == SHORTEST || requested_digits >= 0); - - if (Double(v).Sign() < 0) { - *sign = true; - v = -v; - } else { - *sign = false; - } - - if (mode == PRECISION && requested_digits == 0) { - vector[0] = '\0'; - *length = 0; - return; - } - - if (v == 0) { - vector[0] = '0'; - vector[1] = '\0'; - *length = 1; - *point = 1; - return; - } - - bool fast_worked; - switch (mode) { - case SHORTEST: - fast_worked = FastDtoa(v, FAST_DTOA_SHORTEST, 0, vector, length, point); - break; - case FIXED: - fast_worked = FastFixedDtoa(v, requested_digits, vector, length, point); - break; - case PRECISION: - fast_worked = FastDtoa(v, FAST_DTOA_PRECISION, requested_digits, - vector, length, point); - break; - default: - UNREACHABLE(); - fast_worked = false; - } - if (fast_worked) return; - - // If the fast dtoa didn't succeed use the slower bignum version. - BignumDtoaMode bignum_mode = DtoaToBignumDtoaMode(mode); - BignumDtoa(v, bignum_mode, requested_digits, vector, length, point); - vector[*length] = '\0'; - } - - - // Consumes the given substring from the iterator. - // Returns false, if the substring does not match. - static bool ConsumeSubString(const char** current, - const char* end, - const char* substring) { - ASSERT(**current == *substring); - for (substring++; *substring != '\0'; substring++) { - ++*current; - if (*current == end || **current != *substring) return false; - } - ++*current; - return true; - } - - - // Maximum number of significant digits in decimal representation. - // The longest possible double in decimal representation is - // (2^53 - 1) * 2 ^ -1074 that is (2 ^ 53 - 1) * 5 ^ 1074 / 10 ^ 1074 - // (768 digits). If we parse a number whose first digits are equal to a - // mean of 2 adjacent doubles (that could have up to 769 digits) the result - // must be rounded to the bigger one unless the tail consists of zeros, so - // we don't need to preserve all the digits. - const int kMaxSignificantDigits = 772; - - - // Returns true if a nonspace found and false if the end has reached. - static inline bool AdvanceToNonspace(const char** current, const char* end) { - while (*current != end) { - if (**current != ' ') return true; - ++*current; - } - return false; - } - - - static bool isDigit(int x, int radix) { - return (x >= '0' && x <= '9' && x < '0' + radix) - || (radix > 10 && x >= 'a' && x < 'a' + radix - 10) - || (radix > 10 && x >= 'A' && x < 'A' + radix - 10); - } - - - static double SignedZero(bool sign) { - return sign ? -0.0 : 0.0; - } - - - // Parsing integers with radix 2, 4, 8, 16, 32. Assumes current != end. - template <int radix_log_2> - static double RadixStringToDouble(const char* current, - const char* end, - bool sign, - bool allow_trailing_junk, - double junk_string_value, - const char** trailing_pointer) { - ASSERT(current != end); - - // Skip leading 0s. - while (*current == '0') { - ++current; - if (current == end) { - *trailing_pointer = end; - return SignedZero(sign); - } - } - - int64_t number = 0; - int exponent = 0; - const int radix = (1 << radix_log_2); - - do { - int digit; - if (*current >= '0' && *current <= '9' && *current < '0' + radix) { - digit = static_cast<char>(*current) - '0'; - } else if (radix > 10 && *current >= 'a' && *current < 'a' + radix - 10) { - digit = static_cast<char>(*current) - 'a' + 10; - } else if (radix > 10 && *current >= 'A' && *current < 'A' + radix - 10) { - digit = static_cast<char>(*current) - 'A' + 10; - } else { - if (allow_trailing_junk || !AdvanceToNonspace(¤t, end)) { - break; - } else { - return junk_string_value; - } - } - - number = number * radix + digit; - int overflow = static_cast<int>(number >> 53); - if (overflow != 0) { - // Overflow occurred. Need to determine which direction to round the - // result. - int overflow_bits_count = 1; - while (overflow > 1) { - overflow_bits_count++; - overflow >>= 1; - } - - int dropped_bits_mask = ((1 << overflow_bits_count) - 1); - int dropped_bits = static_cast<int>(number) & dropped_bits_mask; - number >>= overflow_bits_count; - exponent = overflow_bits_count; - - bool zero_tail = true; - while (true) { - ++current; - if (current == end || !isDigit(*current, radix)) break; - zero_tail = zero_tail && *current == '0'; - exponent += radix_log_2; - } - - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value; - } - - int middle_value = (1 << (overflow_bits_count - 1)); - if (dropped_bits > middle_value) { - number++; // Rounding up. - } else if (dropped_bits == middle_value) { - // Rounding to even to consistency with decimals: half-way case rounds - // up if significant part is odd and down otherwise. - if ((number & 1) != 0 || !zero_tail) { - number++; // Rounding up. - } - } - - // Rounding up may cause overflow. - if ((number & ((int64_t)1 << 53)) != 0) { - exponent++; - number >>= 1; - } - break; - } - ++current; - } while (current != end); - - ASSERT(number < ((int64_t)1 << 53)); - ASSERT(static_cast<int64_t>(static_cast<double>(number)) == number); - - *trailing_pointer = current; - - if (exponent == 0) { - if (sign) { - if (number == 0) return -0.0; - number = -number; - } - return static_cast<double>(number); - } - - ASSERT(number != 0); - return Double(DiyFp(number, exponent)).value(); - } - - - double StringToDoubleConverter::StringToDouble( - const char* input, - int length, - int* processed_characters_count) { - const char* current = input; - const char* end = input + length; - - *processed_characters_count = 0; - - const bool allow_trailing_junk = (flags_ & ALLOW_TRAILING_JUNK) != 0; - const bool allow_leading_spaces = (flags_ & ALLOW_LEADING_SPACES) != 0; - const bool allow_trailing_spaces = (flags_ & ALLOW_TRAILING_SPACES) != 0; - const bool allow_spaces_after_sign = (flags_ & ALLOW_SPACES_AFTER_SIGN) != 0; - - // To make sure that iterator dereferencing is valid the following - // convention is used: - // 1. Each '++current' statement is followed by check for equality to 'end'. - // 2. If AdvanceToNonspace returned false then current == end. - // 3. If 'current' becomes equal to 'end' the function returns or goes to - // 'parsing_done'. - // 4. 'current' is not dereferenced after the 'parsing_done' label. - // 5. Code before 'parsing_done' may rely on 'current != end'. - if (current == end) return empty_string_value_; - - if (allow_leading_spaces || allow_trailing_spaces) { - if (!AdvanceToNonspace(¤t, end)) { - *processed_characters_count = current - input; - return empty_string_value_; - } - if (!allow_leading_spaces && (input != current)) { - // No leading spaces allowed, but AdvanceToNonspace moved forward. - return junk_string_value_; - } - } - - // The longest form of simplified number is: "-<significant digits>.1eXXX\0". - const int kBufferSize = kMaxSignificantDigits + 10; - char buffer[kBufferSize]; // NOLINT: size is known at compile time. - int buffer_pos = 0; - - // Exponent will be adjusted if insignificant digits of the integer part - // or insignificant leading zeros of the fractional part are dropped. - int exponent = 0; - int significant_digits = 0; - int insignificant_digits = 0; - bool nonzero_digit_dropped = false; - bool sign = false; - - if (*current == '+' || *current == '-') { - sign = (*current == '-'); - ++current; - const char* next_non_space = current; - // Skip following spaces (if allowed). - if (!AdvanceToNonspace(&next_non_space, end)) return junk_string_value_; - if (!allow_spaces_after_sign && (current != next_non_space)) { - return junk_string_value_; - } - current = next_non_space; - } - - if (infinity_symbol_ != NULL) { - if (*current == infinity_symbol_[0]) { - if (!ConsumeSubString(¤t, end, infinity_symbol_)) { - return junk_string_value_; - } - - if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { - return junk_string_value_; - } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value_; - } - - ASSERT(buffer_pos == 0); - *processed_characters_count = current - input; - return sign ? -Double::Infinity() : Double::Infinity(); - } - } - - if (nan_symbol_ != NULL) { - if (*current == nan_symbol_[0]) { - if (!ConsumeSubString(¤t, end, nan_symbol_)) { - return junk_string_value_; - } - - if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { - return junk_string_value_; - } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value_; - } - - ASSERT(buffer_pos == 0); - *processed_characters_count = current - input; - return sign ? -Double::NaN() : Double::NaN(); - } - } - - bool leading_zero = false; - if (*current == '0') { - ++current; - if (current == end) { - *processed_characters_count = current - input; - return SignedZero(sign); - } - - leading_zero = true; - - // It could be hexadecimal value. - if ((flags_ & ALLOW_HEX) && (*current == 'x' || *current == 'X')) { - ++current; - if (current == end || !isDigit(*current, 16)) { - return junk_string_value_; // "0x". - } - - const char* tail_pointer = NULL; - double result = RadixStringToDouble<4>(current, - end, - sign, - allow_trailing_junk, - junk_string_value_, - &tail_pointer); - if (tail_pointer != NULL) { - if (allow_trailing_spaces) AdvanceToNonspace(&tail_pointer, end); - *processed_characters_count = tail_pointer - input; - } - return result; - } - - // Ignore leading zeros in the integer part. - while (*current == '0') { - ++current; - if (current == end) { - *processed_characters_count = current - input; - return SignedZero(sign); - } - } - } - - bool octal = leading_zero && (flags_ & ALLOW_OCTALS) != 0; - - // Copy significant digits of the integer part (if any) to the buffer. - while (*current >= '0' && *current <= '9') { - if (significant_digits < kMaxSignificantDigits) { - ASSERT(buffer_pos < kBufferSize); - buffer[buffer_pos++] = static_cast<char>(*current); - significant_digits++; - // Will later check if it's an octal in the buffer. - } else { - insignificant_digits++; // Move the digit into the exponential part. - nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; - } - octal = octal && *current < '8'; - ++current; - if (current == end) goto parsing_done; - } - - if (significant_digits == 0) { - octal = false; - } - - if (*current == '.') { - if (octal && !allow_trailing_junk) return junk_string_value_; - if (octal) goto parsing_done; - - ++current; - if (current == end) { - if (significant_digits == 0 && !leading_zero) { - return junk_string_value_; - } else { - goto parsing_done; - } - } - - if (significant_digits == 0) { - // octal = false; - // Integer part consists of 0 or is absent. Significant digits start after - // leading zeros (if any). - while (*current == '0') { - ++current; - if (current == end) { - *processed_characters_count = current - input; - return SignedZero(sign); - } - exponent--; // Move this 0 into the exponent. - } - } - - // There is a fractional part. - while (*current >= '0' && *current <= '9') { - if (significant_digits < kMaxSignificantDigits) { - ASSERT(buffer_pos < kBufferSize); - buffer[buffer_pos++] = static_cast<char>(*current); - significant_digits++; - exponent--; - } else { - // Ignore insignificant digits in the fractional part. - nonzero_digit_dropped = nonzero_digit_dropped || *current != '0'; - } - ++current; - if (current == end) goto parsing_done; - } - } - - if (!leading_zero && exponent == 0 && significant_digits == 0) { - // If leading_zeros is true then the string contains zeros. - // If exponent < 0 then string was [+-]\.0*... - // If significant_digits != 0 the string is not equal to 0. - // Otherwise there are no digits in the string. - return junk_string_value_; - } - - // Parse exponential part. - if (*current == 'e' || *current == 'E') { - if (octal && !allow_trailing_junk) return junk_string_value_; - if (octal) goto parsing_done; - ++current; - if (current == end) { - if (allow_trailing_junk) { - goto parsing_done; - } else { - return junk_string_value_; - } - } - char sign = '+'; - if (*current == '+' || *current == '-') { - sign = static_cast<char>(*current); - ++current; - if (current == end) { - if (allow_trailing_junk) { - goto parsing_done; - } else { - return junk_string_value_; - } - } - } - - if (current == end || *current < '0' || *current > '9') { - if (allow_trailing_junk) { - goto parsing_done; - } else { - return junk_string_value_; - } - } - - const int max_exponent = INT_MAX / 2; - ASSERT(-max_exponent / 2 <= exponent && exponent <= max_exponent / 2); - int num = 0; - do { - // Check overflow. - int digit = *current - '0'; - if (num >= max_exponent / 10 - && !(num == max_exponent / 10 && digit <= max_exponent % 10)) { - num = max_exponent; - } else { - num = num * 10 + digit; - } - ++current; - } while (current != end && *current >= '0' && *current <= '9'); - - exponent += (sign == '-' ? -num : num); - } - - if (!(allow_trailing_spaces || allow_trailing_junk) && (current != end)) { - return junk_string_value_; - } - if (!allow_trailing_junk && AdvanceToNonspace(¤t, end)) { - return junk_string_value_; - } - if (allow_trailing_spaces) { - AdvanceToNonspace(¤t, end); - } - - parsing_done: - exponent += insignificant_digits; - - if (octal) { - double result; - const char* tail_pointer = NULL; - result = RadixStringToDouble<3>(buffer, - buffer + buffer_pos, - sign, - allow_trailing_junk, - junk_string_value_, - &tail_pointer); - ASSERT(tail_pointer != NULL); - *processed_characters_count = current - input; - return result; - } - - if (nonzero_digit_dropped) { - buffer[buffer_pos++] = '1'; - exponent--; - } - - ASSERT(buffer_pos < kBufferSize); - buffer[buffer_pos] = '\0'; - - double converted = Strtod(Vector<const char>(buffer, buffer_pos), exponent); - *processed_characters_count = current - input; - return sign? -converted: converted; - } - -} // namespace double_conversion - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/dtoa/double-conversion.h b/Source/JavaScriptCore/wtf/dtoa/double-conversion.h deleted file mode 100644 index eec956a21..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/double-conversion.h +++ /dev/null @@ -1,502 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ -#define DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ - -#include <wtf/dtoa/utils.h> - -namespace WTF { - -namespace double_conversion { - - class DoubleToStringConverter { - public: - // When calling ToFixed with a double > 10^kMaxFixedDigitsBeforePoint - // or a requested_digits parameter > kMaxFixedDigitsAfterPoint then the - // function returns false. - static const int kMaxFixedDigitsBeforePoint = 60; - static const int kMaxFixedDigitsAfterPoint = 60; - - // When calling ToExponential with a requested_digits - // parameter > kMaxExponentialDigits then the function returns false. - static const int kMaxExponentialDigits = 120; - - // When calling ToPrecision with a requested_digits - // parameter < kMinPrecisionDigits or requested_digits > kMaxPrecisionDigits - // then the function returns false. - static const int kMinPrecisionDigits = 1; - static const int kMaxPrecisionDigits = 120; - - enum Flags { - NO_FLAGS = 0, - EMIT_POSITIVE_EXPONENT_SIGN = 1, - EMIT_TRAILING_DECIMAL_POINT = 2, - EMIT_TRAILING_ZERO_AFTER_POINT = 4, - UNIQUE_ZERO = 8 - }; - - // Flags should be a bit-or combination of the possible Flags-enum. - // - NO_FLAGS: no special flags. - // - EMIT_POSITIVE_EXPONENT_SIGN: when the number is converted into exponent - // form, emits a '+' for positive exponents. Example: 1.2e+2. - // - EMIT_TRAILING_DECIMAL_POINT: when the input number is an integer and is - // converted into decimal format then a trailing decimal point is appended. - // Example: 2345.0 is converted to "2345.". - // - EMIT_TRAILING_ZERO_AFTER_POINT: in addition to a trailing decimal point - // emits a trailing '0'-character. This flag requires the - // EXMIT_TRAILING_DECIMAL_POINT flag. - // Example: 2345.0 is converted to "2345.0". - // - UNIQUE_ZERO: "-0.0" is converted to "0.0". - // - // Infinity symbol and nan_symbol provide the string representation for these - // special values. If the string is NULL and the special value is encountered - // then the conversion functions return false. - // - // The exponent_character is used in exponential representations. It is - // usually 'e' or 'E'. - // - // When converting to the shortest representation the converter will - // represent input numbers in decimal format if they are in the interval - // [10^decimal_in_shortest_low; 10^decimal_in_shortest_high[ - // (lower boundary included, greater boundary excluded). - // Example: with decimal_in_shortest_low = -6 and - // decimal_in_shortest_high = 21: - // ToShortest(0.000001) -> "0.000001" - // ToShortest(0.0000001) -> "1e-7" - // ToShortest(111111111111111111111.0) -> "111111111111111110000" - // ToShortest(100000000000000000000.0) -> "100000000000000000000" - // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" - // - // When converting to precision mode the converter may add - // max_leading_padding_zeroes before returning the number in exponential - // format. - // Example with max_leading_padding_zeroes_in_precision_mode = 6. - // ToPrecision(0.0000012345, 2) -> "0.0000012" - // ToPrecision(0.00000012345, 2) -> "1.2e-7" - // Similarily the converter may add up to - // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid - // returning an exponential representation. A zero added by the - // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. - // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: - // ToPrecision(230.0, 2) -> "230" - // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. - // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. - DoubleToStringConverter(int flags, - const char* infinity_symbol, - const char* nan_symbol, - char exponent_character, - int decimal_in_shortest_low, - int decimal_in_shortest_high, - int max_leading_padding_zeroes_in_precision_mode, - int max_trailing_padding_zeroes_in_precision_mode) - : flags_(flags), - infinity_symbol_(infinity_symbol), - nan_symbol_(nan_symbol), - exponent_character_(exponent_character), - decimal_in_shortest_low_(decimal_in_shortest_low), - decimal_in_shortest_high_(decimal_in_shortest_high), - max_leading_padding_zeroes_in_precision_mode_( - max_leading_padding_zeroes_in_precision_mode), - max_trailing_padding_zeroes_in_precision_mode_( - max_trailing_padding_zeroes_in_precision_mode) { - // When 'trailing zero after the point' is set, then 'trailing point' - // must be set too. - ASSERT(((flags & EMIT_TRAILING_DECIMAL_POINT) != 0) || - !((flags & EMIT_TRAILING_ZERO_AFTER_POINT) != 0)); - } - - // Returns a converter following the EcmaScript specification. - static const DoubleToStringConverter& EcmaScriptConverter(); - - // Computes the shortest string of digits that correctly represent the input - // number. Depending on decimal_in_shortest_low and decimal_in_shortest_high - // (see constructor) it then either returns a decimal representation, or an - // exponential representation. - // Example with decimal_in_shortest_low = -6, - // decimal_in_shortest_high = 21, - // EMIT_POSITIVE_EXPONENT_SIGN activated, and - // EMIT_TRAILING_DECIMAL_POINT deactived: - // ToShortest(0.000001) -> "0.000001" - // ToShortest(0.0000001) -> "1e-7" - // ToShortest(111111111111111111111.0) -> "111111111111111110000" - // ToShortest(100000000000000000000.0) -> "100000000000000000000" - // ToShortest(1111111111111111111111.0) -> "1.1111111111111111e+21" - // - // Note: the conversion may round the output if the returned string - // is accurate enough to uniquely identify the input-number. - // For example the most precise representation of the double 9e59 equals - // "899999999999999918767229449717619953810131273674690656206848", but - // the converter will return the shorter (but still correct) "9e59". - // - // Returns true if the conversion succeeds. The conversion always succeeds - // except when the input value is special and no infinity_symbol or - // nan_symbol has been given to the constructor. - bool ToShortest(double value, StringBuilder* result_builder) const; - - - // Computes a decimal representation with a fixed number of digits after the - // decimal point. The last emitted digit is rounded. - // - // Examples: - // ToFixed(3.12, 1) -> "3.1" - // ToFixed(3.1415, 3) -> "3.142" - // ToFixed(1234.56789, 4) -> "1234.5679" - // ToFixed(1.23, 5) -> "1.23000" - // ToFixed(0.1, 4) -> "0.1000" - // ToFixed(1e30, 2) -> "1000000000000000019884624838656.00" - // ToFixed(0.1, 30) -> "0.100000000000000005551115123126" - // ToFixed(0.1, 17) -> "0.10000000000000001" - // - // If requested_digits equals 0, then the tail of the result depends on - // the EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT. - // Examples, for requested_digits == 0, - // let EMIT_TRAILING_DECIMAL_POINT and EMIT_TRAILING_ZERO_AFTER_POINT be - // - false and false: then 123.45 -> 123 - // 0.678 -> 1 - // - true and false: then 123.45 -> 123. - // 0.678 -> 1. - // - true and true: then 123.45 -> 123.0 - // 0.678 -> 1.0 - // - // Returns true if the conversion succeeds. The conversion always succeeds - // except for the following cases: - // - the input value is special and no infinity_symbol or nan_symbol has - // been provided to the constructor, - // - 'value' > 10^kMaxFixedDigitsBeforePoint, or - // - 'requested_digits' > kMaxFixedDigitsAfterPoint. - // The last two conditions imply that the result will never contain more than - // 1 + kMaxFixedDigitsBeforePoint + 1 + kMaxFixedDigitsAfterPoint characters - // (one additional character for the sign, and one for the decimal point). - bool ToFixed(double value, - int requested_digits, - StringBuilder* result_builder) const; - - // Computes a representation in exponential format with requested_digits - // after the decimal point. The last emitted digit is rounded. - // If requested_digits equals -1, then the shortest exponential representation - // is computed. - // - // Examples with EMIT_POSITIVE_EXPONENT_SIGN deactivated, and - // exponent_character set to 'e'. - // ToExponential(3.12, 1) -> "3.1e0" - // ToExponential(5.0, 3) -> "5.000e0" - // ToExponential(0.001, 2) -> "1.00e-3" - // ToExponential(3.1415, -1) -> "3.1415e0" - // ToExponential(3.1415, 4) -> "3.1415e0" - // ToExponential(3.1415, 3) -> "3.142e0" - // ToExponential(123456789000000, 3) -> "1.235e14" - // ToExponential(1000000000000000019884624838656.0, -1) -> "1e30" - // ToExponential(1000000000000000019884624838656.0, 32) -> - // "1.00000000000000001988462483865600e30" - // ToExponential(1234, 0) -> "1e3" - // - // Returns true if the conversion succeeds. The conversion always succeeds - // except for the following cases: - // - the input value is special and no infinity_symbol or nan_symbol has - // been provided to the constructor, - // - 'requested_digits' > kMaxExponentialDigits. - // The last condition implies that the result will never contain more than - // kMaxExponentialDigits + 8 characters (the sign, the digit before the - // decimal point, the decimal point, the exponent character, the - // exponent's sign, and at most 3 exponent digits). - bool ToExponential(double value, - int requested_digits, - StringBuilder* result_builder) const; - - // Computes 'precision' leading digits of the given 'value' and returns them - // either in exponential or decimal format, depending on - // max_{leading|trailing}_padding_zeroes_in_precision_mode (given to the - // constructor). - // The last computed digit is rounded. - // - // Example with max_leading_padding_zeroes_in_precision_mode = 6. - // ToPrecision(0.0000012345, 2) -> "0.0000012" - // ToPrecision(0.00000012345, 2) -> "1.2e-7" - // Similarily the converter may add up to - // max_trailing_padding_zeroes_in_precision_mode in precision mode to avoid - // returning an exponential representation. A zero added by the - // EMIT_TRAILING_ZERO_AFTER_POINT flag is counted for this limit. - // Examples for max_trailing_padding_zeroes_in_precision_mode = 1: - // ToPrecision(230.0, 2) -> "230" - // ToPrecision(230.0, 2) -> "230." with EMIT_TRAILING_DECIMAL_POINT. - // ToPrecision(230.0, 2) -> "2.3e2" with EMIT_TRAILING_ZERO_AFTER_POINT. - // Examples for max_trailing_padding_zeroes_in_precision_mode = 3, and no - // EMIT_TRAILING_ZERO_AFTER_POINT: - // ToPrecision(123450.0, 6) -> "123450" - // ToPrecision(123450.0, 5) -> "123450" - // ToPrecision(123450.0, 4) -> "123500" - // ToPrecision(123450.0, 3) -> "123000" - // ToPrecision(123450.0, 2) -> "1.2e5" - // - // Returns true if the conversion succeeds. The conversion always succeeds - // except for the following cases: - // - the input value is special and no infinity_symbol or nan_symbol has - // been provided to the constructor, - // - precision < kMinPericisionDigits - // - precision > kMaxPrecisionDigits - // The last condition implies that the result will never contain more than - // kMaxPrecisionDigits + 7 characters (the sign, the decimal point, the - // exponent character, the exponent's sign, and at most 3 exponent digits). - bool ToPrecision(double value, - int precision, - StringBuilder* result_builder) const; - - enum DtoaMode { - // Produce the shortest correct representation. - // For example the output of 0.299999999999999988897 is (the less accurate - // but correct) 0.3. - SHORTEST, - // Produce a fixed number of digits after the decimal point. - // For instance fixed(0.1, 4) becomes 0.1000 - // If the input number is big, the output will be big. - FIXED, - // Fixed number of digits (independent of the decimal point). - PRECISION - }; - - // The maximal number of digits that are needed to emit a double in base 10. - // A higher precision can be achieved by using more digits, but the shortest - // accurate representation of any double will never use more digits than - // kBase10MaximalLength. - // Note that DoubleToAscii null-terminates its input. So the given buffer - // should be at least kBase10MaximalLength + 1 characters long. - static const int kBase10MaximalLength = 17; - - // Converts the given double 'v' to ascii. - // The result should be interpreted as buffer * 10^(point-length). - // - // The output depends on the given mode: - // - SHORTEST: produce the least amount of digits for which the internal - // identity requirement is still satisfied. If the digits are printed - // (together with the correct exponent) then reading this number will give - // 'v' again. The buffer will choose the representation that is closest to - // 'v'. If there are two at the same distance, than the one farther away - // from 0 is chosen (halfway cases - ending with 5 - are rounded up). - // In this mode the 'requested_digits' parameter is ignored. - // - FIXED: produces digits necessary to print a given number with - // 'requested_digits' digits after the decimal point. The produced digits - // might be too short in which case the caller has to fill the remainder - // with '0's. - // Example: toFixed(0.001, 5) is allowed to return buffer="1", point=-2. - // Halfway cases are rounded towards +/-Infinity (away from 0). The call - // toFixed(0.15, 2) thus returns buffer="2", point=0. - // The returned buffer may contain digits that would be truncated from the - // shortest representation of the input. - // - PRECISION: produces 'requested_digits' where the first digit is not '0'. - // Even though the length of produced digits usually equals - // 'requested_digits', the function is allowed to return fewer digits, in - // which case the caller has to fill the missing digits with '0's. - // Halfway cases are again rounded away from 0. - // DoubleToAscii expects the given buffer to be big enough to hold all - // digits and a terminating null-character. In SHORTEST-mode it expects a - // buffer of at least kBase10MaximalLength + 1. In all other modes the - // requested_digits parameter (+ 1 for the null-character) limits the size of - // the output. The given length is only used in debug mode to ensure the - // buffer is big enough. - static void DoubleToAscii(double v, - DtoaMode mode, - int requested_digits, - char* buffer, - int buffer_length, - bool* sign, - int* length, - int* point); - - private: - // If the value is a special value (NaN or Infinity) constructs the - // corresponding string using the configured infinity/nan-symbol. - // If either of them is NULL or the value is not special then the - // function returns false. - bool HandleSpecialValues(double value, StringBuilder* result_builder) const; - // Constructs an exponential representation (i.e. 1.234e56). - // The given exponent assumes a decimal point after the first decimal digit. - void CreateExponentialRepresentation(const char* decimal_digits, - int length, - int exponent, - StringBuilder* result_builder) const; - // Creates a decimal representation (i.e 1234.5678). - void CreateDecimalRepresentation(const char* decimal_digits, - int length, - int decimal_point, - int digits_after_point, - StringBuilder* result_builder) const; - - const int flags_; - const char* const infinity_symbol_; - const char* const nan_symbol_; - const char exponent_character_; - const int decimal_in_shortest_low_; - const int decimal_in_shortest_high_; - const int max_leading_padding_zeroes_in_precision_mode_; - const int max_trailing_padding_zeroes_in_precision_mode_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(DoubleToStringConverter); - }; - - - class StringToDoubleConverter { - public: - // Enumeration for allowing octals and ignoring junk when converting - // strings to numbers. - enum Flags { - NO_FLAGS = 0, - ALLOW_HEX = 1, - ALLOW_OCTALS = 2, - ALLOW_TRAILING_JUNK = 4, - ALLOW_LEADING_SPACES = 8, - ALLOW_TRAILING_SPACES = 16, - ALLOW_SPACES_AFTER_SIGN = 32 - }; - - // Flags should be a bit-or combination of the possible Flags-enum. - // - NO_FLAGS: no special flags. - // - ALLOW_HEX: recognizes the prefix "0x". Hex numbers may only be integers. - // Ex: StringToDouble("0x1234") -> 4660.0 - // In StringToDouble("0x1234.56") the characters ".56" are trailing - // junk. The result of the call is hence dependent on - // the ALLOW_TRAILING_JUNK flag and/or the junk value. - // With this flag "0x" is a junk-string. Even with ALLOW_TRAILING_JUNK, - // the string will not be parsed as "0" followed by junk. - // - // - ALLOW_OCTALS: recognizes the prefix "0" for octals: - // If a sequence of octal digits starts with '0', then the number is - // read as octal integer. Octal numbers may only be integers. - // Ex: StringToDouble("01234") -> 668.0 - // StringToDouble("012349") -> 12349.0 // Not a sequence of octal - // // digits. - // In StringToDouble("01234.56") the characters ".56" are trailing - // junk. The result of the call is hence dependent on - // the ALLOW_TRAILING_JUNK flag and/or the junk value. - // In StringToDouble("01234e56") the characters "e56" are trailing - // junk, too. - // - ALLOW_TRAILING_JUNK: ignore trailing characters that are not part of - // a double literal. - // - ALLOW_LEADING_SPACES: skip over leading spaces. - // - ALLOW_TRAILING_SPACES: ignore trailing spaces. - // - ALLOW_SPACES_AFTER_SIGN: ignore spaces after the sign. - // Ex: StringToDouble("- 123.2") -> -123.2. - // StringToDouble("+ 123.2") -> 123.2 - // - // empty_string_value is returned when an empty string is given as input. - // If ALLOW_LEADING_SPACES or ALLOW_TRAILING_SPACES are set, then a string - // containing only spaces is converted to the 'empty_string_value', too. - // - // junk_string_value is returned when - // a) ALLOW_TRAILING_JUNK is not set, and a junk character (a character not - // part of a double-literal) is found. - // b) ALLOW_TRAILING_JUNK is set, but the string does not start with a - // double literal. - // - // infinity_symbol and nan_symbol are strings that are used to detect - // inputs that represent infinity and NaN. They can be null, in which case - // they are ignored. - // The conversion routine first reads any possible signs. Then it compares the - // following character of the input-string with the first character of - // the infinity, and nan-symbol. If either matches, the function assumes, that - // a match has been found, and expects the following input characters to match - // the remaining characters of the special-value symbol. - // This means that the following restrictions apply to special-value symbols: - // - they must not start with signs ('+', or '-'), - // - they must not have the same first character. - // - they must not start with digits. - // - // Examples: - // flags = ALLOW_HEX | ALLOW_TRAILING_JUNK, - // empty_string_value = 0.0, - // junk_string_value = NaN, - // infinity_symbol = "infinity", - // nan_symbol = "nan": - // StringToDouble("0x1234") -> 4660.0. - // StringToDouble("0x1234K") -> 4660.0. - // StringToDouble("") -> 0.0 // empty_string_value. - // StringToDouble(" ") -> NaN // junk_string_value. - // StringToDouble(" 1") -> NaN // junk_string_value. - // StringToDouble("0x") -> NaN // junk_string_value. - // StringToDouble("-123.45") -> -123.45. - // StringToDouble("--123.45") -> NaN // junk_string_value. - // StringToDouble("123e45") -> 123e45. - // StringToDouble("123E45") -> 123e45. - // StringToDouble("123e+45") -> 123e45. - // StringToDouble("123E-45") -> 123e-45. - // StringToDouble("123e") -> 123.0 // trailing junk ignored. - // StringToDouble("123e-") -> 123.0 // trailing junk ignored. - // StringToDouble("+NaN") -> NaN // NaN string literal. - // StringToDouble("-infinity") -> -inf. // infinity literal. - // StringToDouble("Infinity") -> NaN // junk_string_value. - // - // flags = ALLOW_OCTAL | ALLOW_LEADING_SPACES, - // empty_string_value = 0.0, - // junk_string_value = NaN, - // infinity_symbol = NULL, - // nan_symbol = NULL: - // StringToDouble("0x1234") -> NaN // junk_string_value. - // StringToDouble("01234") -> 668.0. - // StringToDouble("") -> 0.0 // empty_string_value. - // StringToDouble(" ") -> 0.0 // empty_string_value. - // StringToDouble(" 1") -> 1.0 - // StringToDouble("0x") -> NaN // junk_string_value. - // StringToDouble("0123e45") -> NaN // junk_string_value. - // StringToDouble("01239E45") -> 1239e45. - // StringToDouble("-infinity") -> NaN // junk_string_value. - // StringToDouble("NaN") -> NaN // junk_string_value. - StringToDoubleConverter(int flags, - double empty_string_value, - double junk_string_value, - const char* infinity_symbol, - const char* nan_symbol) - : flags_(flags), - empty_string_value_(empty_string_value), - junk_string_value_(junk_string_value), - infinity_symbol_(infinity_symbol), - nan_symbol_(nan_symbol) { - } - - // Performs the conversion. - // The output parameter 'processed_characters_count' is set to the number - // of characters that have been processed to read the number. - // Spaces than are processed with ALLOW_{LEADING|TRAILING}_SPACES are included - // in the 'processed_characters_count'. Trailing junk is never included. - double StringToDouble(const char* buffer, - int length, - int* processed_characters_count); - - private: - const int flags_; - const double empty_string_value_; - const double junk_string_value_; - const char* const infinity_symbol_; - const char* const nan_symbol_; - - DISALLOW_IMPLICIT_CONSTRUCTORS(StringToDoubleConverter); - }; - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_DOUBLE_CONVERSION_H_ diff --git a/Source/JavaScriptCore/wtf/dtoa/double.h b/Source/JavaScriptCore/wtf/dtoa/double.h deleted file mode 100644 index 0544fdb5a..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/double.h +++ /dev/null @@ -1,249 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_DOUBLE_H_ -#define DOUBLE_CONVERSION_DOUBLE_H_ - -#include "diy-fp.h" - -namespace WTF { - -namespace double_conversion { - - // We assume that doubles and uint64_t have the same endianness. - static uint64_t double_to_uint64(double d) { return BitCast<uint64_t>(d); } - static double uint64_to_double(uint64_t d64) { return BitCast<double>(d64); } - - // Helper functions for doubles. - class Double { - public: - static const uint64_t kSignMask = UINT64_2PART_C(0x80000000, 00000000); - static const uint64_t kExponentMask = UINT64_2PART_C(0x7FF00000, 00000000); - static const uint64_t kSignificandMask = UINT64_2PART_C(0x000FFFFF, FFFFFFFF); - static const uint64_t kHiddenBit = UINT64_2PART_C(0x00100000, 00000000); - static const int kPhysicalSignificandSize = 52; // Excludes the hidden bit. - static const int kSignificandSize = 53; - - Double() : d64_(0) {} - explicit Double(double d) : d64_(double_to_uint64(d)) {} - explicit Double(uint64_t d64) : d64_(d64) {} - explicit Double(DiyFp diy_fp) - : d64_(DiyFpToUint64(diy_fp)) {} - - // The value encoded by this Double must be greater or equal to +0.0. - // It must not be special (infinity, or NaN). - DiyFp AsDiyFp() const { - ASSERT(Sign() > 0); - ASSERT(!IsSpecial()); - return DiyFp(Significand(), Exponent()); - } - - // The value encoded by this Double must be strictly greater than 0. - DiyFp AsNormalizedDiyFp() const { - ASSERT(value() > 0.0); - uint64_t f = Significand(); - int e = Exponent(); - - // The current double could be a denormal. - while ((f & kHiddenBit) == 0) { - f <<= 1; - e--; - } - // Do the final shifts in one go. - f <<= DiyFp::kSignificandSize - kSignificandSize; - e -= DiyFp::kSignificandSize - kSignificandSize; - return DiyFp(f, e); - } - - // Returns the double's bit as uint64. - uint64_t AsUint64() const { - return d64_; - } - - // Returns the next greater double. Returns +infinity on input +infinity. - double NextDouble() const { - if (d64_ == kInfinity) return Double(kInfinity).value(); - if (Sign() < 0 && Significand() == 0) { - // -0.0 - return 0.0; - } - if (Sign() < 0) { - return Double(d64_ - 1).value(); - } else { - return Double(d64_ + 1).value(); - } - } - - int Exponent() const { - if (IsDenormal()) return kDenormalExponent; - - uint64_t d64 = AsUint64(); - int biased_e = - static_cast<int>((d64 & kExponentMask) >> kPhysicalSignificandSize); - return biased_e - kExponentBias; - } - - uint64_t Significand() const { - uint64_t d64 = AsUint64(); - uint64_t significand = d64 & kSignificandMask; - if (!IsDenormal()) { - return significand + kHiddenBit; - } else { - return significand; - } - } - - // Returns true if the double is a denormal. - bool IsDenormal() const { - uint64_t d64 = AsUint64(); - return (d64 & kExponentMask) == 0; - } - - // We consider denormals not to be special. - // Hence only Infinity and NaN are special. - bool IsSpecial() const { - uint64_t d64 = AsUint64(); - return (d64 & kExponentMask) == kExponentMask; - } - - bool IsNan() const { - uint64_t d64 = AsUint64(); - return ((d64 & kExponentMask) == kExponentMask) && - ((d64 & kSignificandMask) != 0); - } - - bool IsInfinite() const { - uint64_t d64 = AsUint64(); - return ((d64 & kExponentMask) == kExponentMask) && - ((d64 & kSignificandMask) == 0); - } - - int Sign() const { - uint64_t d64 = AsUint64(); - return (d64 & kSignMask) == 0? 1: -1; - } - - // Precondition: the value encoded by this Double must be greater or equal - // than +0.0. - DiyFp UpperBoundary() const { - ASSERT(Sign() > 0); - return DiyFp(Significand() * 2 + 1, Exponent() - 1); - } - - // Computes the two boundaries of this. - // The bigger boundary (m_plus) is normalized. The lower boundary has the same - // exponent as m_plus. - // Precondition: the value encoded by this Double must be greater than 0. - void NormalizedBoundaries(DiyFp* out_m_minus, DiyFp* out_m_plus) const { - ASSERT(value() > 0.0); - DiyFp v = this->AsDiyFp(); - bool significand_is_zero = (v.f() == kHiddenBit); - DiyFp m_plus = DiyFp::Normalize(DiyFp((v.f() << 1) + 1, v.e() - 1)); - DiyFp m_minus; - if (significand_is_zero && v.e() != kDenormalExponent) { - // The boundary is closer. Think of v = 1000e10 and v- = 9999e9. - // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but - // at a distance of 1e8. - // The only exception is for the smallest normal: the largest denormal is - // at the same distance as its successor. - // Note: denormals have the same exponent as the smallest normals. - m_minus = DiyFp((v.f() << 2) - 1, v.e() - 2); - } else { - m_minus = DiyFp((v.f() << 1) - 1, v.e() - 1); - } - m_minus.set_f(m_minus.f() << (m_minus.e() - m_plus.e())); - m_minus.set_e(m_plus.e()); - *out_m_plus = m_plus; - *out_m_minus = m_minus; - } - - double value() const { return uint64_to_double(d64_); } - - // Returns the significand size for a given order of magnitude. - // If v = f*2^e with 2^p-1 <= f <= 2^p then p+e is v's order of magnitude. - // This function returns the number of significant binary digits v will have - // once it's encoded into a double. In almost all cases this is equal to - // kSignificandSize. The only exceptions are denormals. They start with - // leading zeroes and their effective significand-size is hence smaller. - static int SignificandSizeForOrderOfMagnitude(int order) { - if (order >= (kDenormalExponent + kSignificandSize)) { - return kSignificandSize; - } - if (order <= kDenormalExponent) return 0; - return order - kDenormalExponent; - } - - static double Infinity() { - return Double(kInfinity).value(); - } - - static double NaN() { - return Double(kNaN).value(); - } - - private: - static const int kExponentBias = 0x3FF + kPhysicalSignificandSize; - static const int kDenormalExponent = -kExponentBias + 1; - static const int kMaxExponent = 0x7FF - kExponentBias; - static const uint64_t kInfinity = UINT64_2PART_C(0x7FF00000, 00000000); - static const uint64_t kNaN = UINT64_2PART_C(0x7FF80000, 00000000); - - const uint64_t d64_; - - static uint64_t DiyFpToUint64(DiyFp diy_fp) { - uint64_t significand = diy_fp.f(); - int exponent = diy_fp.e(); - while (significand > kHiddenBit + kSignificandMask) { - significand >>= 1; - exponent++; - } - if (exponent >= kMaxExponent) { - return kInfinity; - } - if (exponent < kDenormalExponent) { - return 0; - } - while (exponent > kDenormalExponent && (significand & kHiddenBit) == 0) { - significand <<= 1; - exponent--; - } - uint64_t biased_exponent; - if (exponent == kDenormalExponent && (significand & kHiddenBit) == 0) { - biased_exponent = 0; - } else { - biased_exponent = static_cast<uint64_t>(exponent + kExponentBias); - } - return (significand & kSignificandMask) | - (biased_exponent << kPhysicalSignificandSize); - } - }; - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_DOUBLE_H_ diff --git a/Source/JavaScriptCore/wtf/dtoa/fast-dtoa.cc b/Source/JavaScriptCore/wtf/dtoa/fast-dtoa.cc deleted file mode 100644 index 9d9872417..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/fast-dtoa.cc +++ /dev/null @@ -1,741 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#include "fast-dtoa.h" - -#include "cached-powers.h" -#include "diy-fp.h" -#include "double.h" - -namespace WTF { - -namespace double_conversion { - - // The minimal and maximal target exponent define the range of w's binary - // exponent, where 'w' is the result of multiplying the input by a cached power - // of ten. - // - // A different range might be chosen on a different platform, to optimize digit - // generation, but a smaller range requires more powers of ten to be cached. - static const int kMinimalTargetExponent = -60; - static const int kMaximalTargetExponent = -32; - - - // Adjusts the last digit of the generated number, and screens out generated - // solutions that may be inaccurate. A solution may be inaccurate if it is - // outside the safe interval, or if we cannot prove that it is closer to the - // input than a neighboring representation of the same length. - // - // Input: * buffer containing the digits of too_high / 10^kappa - // * the buffer's length - // * distance_too_high_w == (too_high - w).f() * unit - // * unsafe_interval == (too_high - too_low).f() * unit - // * rest = (too_high - buffer * 10^kappa).f() * unit - // * ten_kappa = 10^kappa * unit - // * unit = the common multiplier - // Output: returns true if the buffer is guaranteed to contain the closest - // representable number to the input. - // Modifies the generated digits in the buffer to approach (round towards) w. - static bool RoundWeed(Vector<char> buffer, - int length, - uint64_t distance_too_high_w, - uint64_t unsafe_interval, - uint64_t rest, - uint64_t ten_kappa, - uint64_t unit) { - uint64_t small_distance = distance_too_high_w - unit; - uint64_t big_distance = distance_too_high_w + unit; - // Let w_low = too_high - big_distance, and - // w_high = too_high - small_distance. - // Note: w_low < w < w_high - // - // The real w (* unit) must lie somewhere inside the interval - // ]w_low; w_high[ (often written as "(w_low; w_high)") - - // Basically the buffer currently contains a number in the unsafe interval - // ]too_low; too_high[ with too_low < w < too_high - // - // too_high - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // ^v 1 unit ^ ^ ^ ^ - // boundary_high --------------------- . . . . - // ^v 1 unit . . . . - // - - - - - - - - - - - - - - - - - - - + - - + - - - - - - . . - // . . ^ . . - // . big_distance . . . - // . . . . rest - // small_distance . . . . - // v . . . . - // w_high - - - - - - - - - - - - - - - - - - . . . . - // ^v 1 unit . . . . - // w ---------------------------------------- . . . . - // ^v 1 unit v . . . - // w_low - - - - - - - - - - - - - - - - - - - - - . . . - // . . v - // buffer --------------------------------------------------+-------+-------- - // . . - // safe_interval . - // v . - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - . - // ^v 1 unit . - // boundary_low ------------------------- unsafe_interval - // ^v 1 unit v - // too_low - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - // - // Note that the value of buffer could lie anywhere inside the range too_low - // to too_high. - // - // boundary_low, boundary_high and w are approximations of the real boundaries - // and v (the input number). They are guaranteed to be precise up to one unit. - // In fact the error is guaranteed to be strictly less than one unit. - // - // Anything that lies outside the unsafe interval is guaranteed not to round - // to v when read again. - // Anything that lies inside the safe interval is guaranteed to round to v - // when read again. - // If the number inside the buffer lies inside the unsafe interval but not - // inside the safe interval then we simply do not know and bail out (returning - // false). - // - // Similarly we have to take into account the imprecision of 'w' when finding - // the closest representation of 'w'. If we have two potential - // representations, and one is closer to both w_low and w_high, then we know - // it is closer to the actual value v. - // - // By generating the digits of too_high we got the largest (closest to - // too_high) buffer that is still in the unsafe interval. In the case where - // w_high < buffer < too_high we try to decrement the buffer. - // This way the buffer approaches (rounds towards) w. - // There are 3 conditions that stop the decrementation process: - // 1) the buffer is already below w_high - // 2) decrementing the buffer would make it leave the unsafe interval - // 3) decrementing the buffer would yield a number below w_high and farther - // away than the current number. In other words: - // (buffer{-1} < w_high) && w_high - buffer{-1} > buffer - w_high - // Instead of using the buffer directly we use its distance to too_high. - // Conceptually rest ~= too_high - buffer - // We need to do the following tests in this order to avoid over- and - // underflows. - ASSERT(rest <= unsafe_interval); - while (rest < small_distance && // Negated condition 1 - unsafe_interval - rest >= ten_kappa && // Negated condition 2 - (rest + ten_kappa < small_distance || // buffer{-1} > w_high - small_distance - rest >= rest + ten_kappa - small_distance)) { - buffer[length - 1]--; - rest += ten_kappa; - } - - // We have approached w+ as much as possible. We now test if approaching w- - // would require changing the buffer. If yes, then we have two possible - // representations close to w, but we cannot decide which one is closer. - if (rest < big_distance && - unsafe_interval - rest >= ten_kappa && - (rest + ten_kappa < big_distance || - big_distance - rest > rest + ten_kappa - big_distance)) { - return false; - } - - // Weeding test. - // The safe interval is [too_low + 2 ulp; too_high - 2 ulp] - // Since too_low = too_high - unsafe_interval this is equivalent to - // [too_high - unsafe_interval + 4 ulp; too_high - 2 ulp] - // Conceptually we have: rest ~= too_high - buffer - return (2 * unit <= rest) && (rest <= unsafe_interval - 4 * unit); - } - - - // Rounds the buffer upwards if the result is closer to v by possibly adding - // 1 to the buffer. If the precision of the calculation is not sufficient to - // round correctly, return false. - // The rounding might shift the whole buffer in which case the kappa is - // adjusted. For example "99", kappa = 3 might become "10", kappa = 4. - // - // If 2*rest > ten_kappa then the buffer needs to be round up. - // rest can have an error of +/- 1 unit. This function accounts for the - // imprecision and returns false, if the rounding direction cannot be - // unambiguously determined. - // - // Precondition: rest < ten_kappa. - static bool RoundWeedCounted(Vector<char> buffer, - int length, - uint64_t rest, - uint64_t ten_kappa, - uint64_t unit, - int* kappa) { - ASSERT(rest < ten_kappa); - // The following tests are done in a specific order to avoid overflows. They - // will work correctly with any uint64 values of rest < ten_kappa and unit. - // - // If the unit is too big, then we don't know which way to round. For example - // a unit of 50 means that the real number lies within rest +/- 50. If - // 10^kappa == 40 then there is no way to tell which way to round. - if (unit >= ten_kappa) return false; - // Even if unit is just half the size of 10^kappa we are already completely - // lost. (And after the previous test we know that the expression will not - // over/underflow.) - if (ten_kappa - unit <= unit) return false; - // If 2 * (rest + unit) <= 10^kappa we can safely round down. - if ((ten_kappa - rest > rest) && (ten_kappa - 2 * rest >= 2 * unit)) { - return true; - } - // If 2 * (rest - unit) >= 10^kappa, then we can safely round up. - if ((rest > unit) && (ten_kappa - (rest - unit) <= (rest - unit))) { - // Increment the last digit recursively until we find a non '9' digit. - buffer[length - 1]++; - for (int i = length - 1; i > 0; --i) { - if (buffer[i] != '0' + 10) break; - buffer[i] = '0'; - buffer[i - 1]++; - } - // If the first digit is now '0'+ 10 we had a buffer with all '9's. With the - // exception of the first digit all digits are now '0'. Simply switch the - // first digit to '1' and adjust the kappa. Example: "99" becomes "10" and - // the power (the kappa) is increased. - if (buffer[0] == '0' + 10) { - buffer[0] = '1'; - (*kappa) += 1; - } - return true; - } - return false; - } - - - static const uint32_t kTen4 = 10000; - static const uint32_t kTen5 = 100000; - static const uint32_t kTen6 = 1000000; - static const uint32_t kTen7 = 10000000; - static const uint32_t kTen8 = 100000000; - static const uint32_t kTen9 = 1000000000; - - // Returns the biggest power of ten that is less than or equal to the given - // number. We furthermore receive the maximum number of bits 'number' has. - // If number_bits == 0 then 0^-1 is returned - // The number of bits must be <= 32. - // Precondition: number < (1 << (number_bits + 1)). - static void BiggestPowerTen(uint32_t number, - int number_bits, - uint32_t* power, - int* exponent) { - ASSERT(number < (uint32_t)(1 << (number_bits + 1))); - - switch (number_bits) { - case 32: - case 31: - case 30: - if (kTen9 <= number) { - *power = kTen9; - *exponent = 9; - break; - } // else fallthrough - case 29: - case 28: - case 27: - if (kTen8 <= number) { - *power = kTen8; - *exponent = 8; - break; - } // else fallthrough - case 26: - case 25: - case 24: - if (kTen7 <= number) { - *power = kTen7; - *exponent = 7; - break; - } // else fallthrough - case 23: - case 22: - case 21: - case 20: - if (kTen6 <= number) { - *power = kTen6; - *exponent = 6; - break; - } // else fallthrough - case 19: - case 18: - case 17: - if (kTen5 <= number) { - *power = kTen5; - *exponent = 5; - break; - } // else fallthrough - case 16: - case 15: - case 14: - if (kTen4 <= number) { - *power = kTen4; - *exponent = 4; - break; - } // else fallthrough - case 13: - case 12: - case 11: - case 10: - if (1000 <= number) { - *power = 1000; - *exponent = 3; - break; - } // else fallthrough - case 9: - case 8: - case 7: - if (100 <= number) { - *power = 100; - *exponent = 2; - break; - } // else fallthrough - case 6: - case 5: - case 4: - if (10 <= number) { - *power = 10; - *exponent = 1; - break; - } // else fallthrough - case 3: - case 2: - case 1: - if (1 <= number) { - *power = 1; - *exponent = 0; - break; - } // else fallthrough - case 0: - *power = 0; - *exponent = -1; - break; - default: - // Following assignments are here to silence compiler warnings. - *power = 0; - *exponent = 0; - UNREACHABLE(); - } - } - - - // Generates the digits of input number w. - // w is a floating-point number (DiyFp), consisting of a significand and an - // exponent. Its exponent is bounded by kMinimalTargetExponent and - // kMaximalTargetExponent. - // Hence -60 <= w.e() <= -32. - // - // Returns false if it fails, in which case the generated digits in the buffer - // should not be used. - // Preconditions: - // * low, w and high are correct up to 1 ulp (unit in the last place). That - // is, their error must be less than a unit of their last digits. - // * low.e() == w.e() == high.e() - // * low < w < high, and taking into account their error: low~ <= high~ - // * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent - // Postconditions: returns false if procedure fails. - // otherwise: - // * buffer is not null-terminated, but len contains the number of digits. - // * buffer contains the shortest possible decimal digit-sequence - // such that LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the - // correct values of low and high (without their error). - // * if more than one decimal representation gives the minimal number of - // decimal digits then the one closest to W (where W is the correct value - // of w) is chosen. - // Remark: this procedure takes into account the imprecision of its input - // numbers. If the precision is not enough to guarantee all the postconditions - // then false is returned. This usually happens rarely (~0.5%). - // - // Say, for the sake of example, that - // w.e() == -48, and w.f() == 0x1234567890abcdef - // w's value can be computed by w.f() * 2^w.e() - // We can obtain w's integral digits by simply shifting w.f() by -w.e(). - // -> w's integral part is 0x1234 - // w's fractional part is therefore 0x567890abcdef. - // Printing w's integral part is easy (simply print 0x1234 in decimal). - // In order to print its fraction we repeatedly multiply the fraction by 10 and - // get each digit. Example the first digit after the point would be computed by - // (0x567890abcdef * 10) >> 48. -> 3 - // The whole thing becomes slightly more complicated because we want to stop - // once we have enough digits. That is, once the digits inside the buffer - // represent 'w' we can stop. Everything inside the interval low - high - // represents w. However we have to pay attention to low, high and w's - // imprecision. - static bool DigitGen(DiyFp low, - DiyFp w, - DiyFp high, - Vector<char> buffer, - int* length, - int* kappa) { - ASSERT(low.e() == w.e() && w.e() == high.e()); - ASSERT(low.f() + 1 <= high.f() - 1); - ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent); - // low, w and high are imprecise, but by less than one ulp (unit in the last - // place). - // If we remove (resp. add) 1 ulp from low (resp. high) we are certain that - // the new numbers are outside of the interval we want the final - // representation to lie in. - // Inversely adding (resp. removing) 1 ulp from low (resp. high) would yield - // numbers that are certain to lie in the interval. We will use this fact - // later on. - // We will now start by generating the digits within the uncertain - // interval. Later we will weed out representations that lie outside the safe - // interval and thus _might_ lie outside the correct interval. - uint64_t unit = 1; - DiyFp too_low = DiyFp(low.f() - unit, low.e()); - DiyFp too_high = DiyFp(high.f() + unit, high.e()); - // too_low and too_high are guaranteed to lie outside the interval we want the - // generated number in. - DiyFp unsafe_interval = DiyFp::Minus(too_high, too_low); - // We now cut the input number into two parts: the integral digits and the - // fractionals. We will not write any decimal separator though, but adapt - // kappa instead. - // Reminder: we are currently computing the digits (stored inside the buffer) - // such that: too_low < buffer * 10^kappa < too_high - // We use too_high for the digit_generation and stop as soon as possible. - // If we stop early we effectively round down. - DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e()); - // Division by one is a shift. - uint32_t integrals = static_cast<uint32_t>(too_high.f() >> -one.e()); - // Modulo by one is an and. - uint64_t fractionals = too_high.f() & (one.f() - 1); - uint32_t divisor; - int divisor_exponent; - BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()), - &divisor, &divisor_exponent); - *kappa = divisor_exponent + 1; - *length = 0; - // Loop invariant: buffer = too_high / 10^kappa (integer division) - // The invariant holds for the first iteration: kappa has been initialized - // with the divisor exponent + 1. And the divisor is the biggest power of ten - // that is smaller than integrals. - while (*kappa > 0) { - int digit = integrals / divisor; - buffer[*length] = '0' + digit; - (*length)++; - integrals %= divisor; - (*kappa)--; - // Note that kappa now equals the exponent of the divisor and that the - // invariant thus holds again. - uint64_t rest = - (static_cast<uint64_t>(integrals) << -one.e()) + fractionals; - // Invariant: too_high = buffer * 10^kappa + DiyFp(rest, one.e()) - // Reminder: unsafe_interval.e() == one.e() - if (rest < unsafe_interval.f()) { - // Rounding down (by not emitting the remaining digits) yields a number - // that lies within the unsafe interval. - return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f(), - unsafe_interval.f(), rest, - static_cast<uint64_t>(divisor) << -one.e(), unit); - } - divisor /= 10; - } - - // The integrals have been generated. We are at the point of the decimal - // separator. In the following loop we simply multiply the remaining digits by - // 10 and divide by one. We just need to pay attention to multiply associated - // data (like the interval or 'unit'), too. - // Note that the multiplication by 10 does not overflow, because w.e >= -60 - // and thus one.e >= -60. - ASSERT(one.e() >= -60); - ASSERT(fractionals < one.f()); - ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); - while (true) { - fractionals *= 10; - unit *= 10; - unsafe_interval.set_f(unsafe_interval.f() * 10); - // Integer division by one. - int digit = static_cast<int>(fractionals >> -one.e()); - buffer[*length] = '0' + digit; - (*length)++; - fractionals &= one.f() - 1; // Modulo by one. - (*kappa)--; - if (fractionals < unsafe_interval.f()) { - return RoundWeed(buffer, *length, DiyFp::Minus(too_high, w).f() * unit, - unsafe_interval.f(), fractionals, one.f(), unit); - } - } - } - - - - // Generates (at most) requested_digits digits of input number w. - // w is a floating-point number (DiyFp), consisting of a significand and an - // exponent. Its exponent is bounded by kMinimalTargetExponent and - // kMaximalTargetExponent. - // Hence -60 <= w.e() <= -32. - // - // Returns false if it fails, in which case the generated digits in the buffer - // should not be used. - // Preconditions: - // * w is correct up to 1 ulp (unit in the last place). That - // is, its error must be strictly less than a unit of its last digit. - // * kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent - // - // Postconditions: returns false if procedure fails. - // otherwise: - // * buffer is not null-terminated, but length contains the number of - // digits. - // * the representation in buffer is the most precise representation of - // requested_digits digits. - // * buffer contains at most requested_digits digits of w. If there are less - // than requested_digits digits then some trailing '0's have been removed. - // * kappa is such that - // w = buffer * 10^kappa + eps with |eps| < 10^kappa / 2. - // - // Remark: This procedure takes into account the imprecision of its input - // numbers. If the precision is not enough to guarantee all the postconditions - // then false is returned. This usually happens rarely, but the failure-rate - // increases with higher requested_digits. - static bool DigitGenCounted(DiyFp w, - int requested_digits, - Vector<char> buffer, - int* length, - int* kappa) { - ASSERT(kMinimalTargetExponent <= w.e() && w.e() <= kMaximalTargetExponent); - ASSERT(kMinimalTargetExponent >= -60); - ASSERT(kMaximalTargetExponent <= -32); - // w is assumed to have an error less than 1 unit. Whenever w is scaled we - // also scale its error. - uint64_t w_error = 1; - // We cut the input number into two parts: the integral digits and the - // fractional digits. We don't emit any decimal separator, but adapt kappa - // instead. Example: instead of writing "1.2" we put "12" into the buffer and - // increase kappa by 1. - DiyFp one = DiyFp(static_cast<uint64_t>(1) << -w.e(), w.e()); - // Division by one is a shift. - uint32_t integrals = static_cast<uint32_t>(w.f() >> -one.e()); - // Modulo by one is an and. - uint64_t fractionals = w.f() & (one.f() - 1); - uint32_t divisor; - int divisor_exponent; - BiggestPowerTen(integrals, DiyFp::kSignificandSize - (-one.e()), - &divisor, &divisor_exponent); - *kappa = divisor_exponent + 1; - *length = 0; - - // Loop invariant: buffer = w / 10^kappa (integer division) - // The invariant holds for the first iteration: kappa has been initialized - // with the divisor exponent + 1. And the divisor is the biggest power of ten - // that is smaller than 'integrals'. - while (*kappa > 0) { - int digit = integrals / divisor; - buffer[*length] = '0' + digit; - (*length)++; - requested_digits--; - integrals %= divisor; - (*kappa)--; - // Note that kappa now equals the exponent of the divisor and that the - // invariant thus holds again. - if (requested_digits == 0) break; - divisor /= 10; - } - - if (requested_digits == 0) { - uint64_t rest = - (static_cast<uint64_t>(integrals) << -one.e()) + fractionals; - return RoundWeedCounted(buffer, *length, rest, - static_cast<uint64_t>(divisor) << -one.e(), w_error, - kappa); - } - - // The integrals have been generated. We are at the point of the decimal - // separator. In the following loop we simply multiply the remaining digits by - // 10 and divide by one. We just need to pay attention to multiply associated - // data (the 'unit'), too. - // Note that the multiplication by 10 does not overflow, because w.e >= -60 - // and thus one.e >= -60. - ASSERT(one.e() >= -60); - ASSERT(fractionals < one.f()); - ASSERT(UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF) / 10 >= one.f()); - while (requested_digits > 0 && fractionals > w_error) { - fractionals *= 10; - w_error *= 10; - // Integer division by one. - int digit = static_cast<int>(fractionals >> -one.e()); - buffer[*length] = '0' + digit; - (*length)++; - requested_digits--; - fractionals &= one.f() - 1; // Modulo by one. - (*kappa)--; - } - if (requested_digits != 0) return false; - return RoundWeedCounted(buffer, *length, fractionals, one.f(), w_error, - kappa); - } - - - // Provides a decimal representation of v. - // Returns true if it succeeds, otherwise the result cannot be trusted. - // There will be *length digits inside the buffer (not null-terminated). - // If the function returns true then - // v == (double) (buffer * 10^decimal_exponent). - // The digits in the buffer are the shortest representation possible: no - // 0.09999999999999999 instead of 0.1. The shorter representation will even be - // chosen even if the longer one would be closer to v. - // The last digit will be closest to the actual v. That is, even if several - // digits might correctly yield 'v' when read again, the closest will be - // computed. - static bool Grisu3(double v, - Vector<char> buffer, - int* length, - int* decimal_exponent) { - DiyFp w = Double(v).AsNormalizedDiyFp(); - // boundary_minus and boundary_plus are the boundaries between v and its - // closest floating-point neighbors. Any number strictly between - // boundary_minus and boundary_plus will round to v when convert to a double. - // Grisu3 will never output representations that lie exactly on a boundary. - DiyFp boundary_minus, boundary_plus; - Double(v).NormalizedBoundaries(&boundary_minus, &boundary_plus); - ASSERT(boundary_plus.e() == w.e()); - DiyFp ten_mk; // Cached power of ten: 10^-k - int mk; // -k - int ten_mk_minimal_binary_exponent = - kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize); - int ten_mk_maximal_binary_exponent = - kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize); - PowersOfTenCache::GetCachedPowerForBinaryExponentRange( - ten_mk_minimal_binary_exponent, - ten_mk_maximal_binary_exponent, - &ten_mk, &mk); - ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + - DiyFp::kSignificandSize) && - (kMaximalTargetExponent >= w.e() + ten_mk.e() + - DiyFp::kSignificandSize)); - // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a - // 64 bit significand and ten_mk is thus only precise up to 64 bits. - - // The DiyFp::Times procedure rounds its result, and ten_mk is approximated - // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now - // off by a small amount. - // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w. - // In other words: let f = scaled_w.f() and e = scaled_w.e(), then - // (f-1) * 2^e < w*10^k < (f+1) * 2^e - DiyFp scaled_w = DiyFp::Times(w, ten_mk); - ASSERT(scaled_w.e() == - boundary_plus.e() + ten_mk.e() + DiyFp::kSignificandSize); - // In theory it would be possible to avoid some recomputations by computing - // the difference between w and boundary_minus/plus (a power of 2) and to - // compute scaled_boundary_minus/plus by subtracting/adding from - // scaled_w. However the code becomes much less readable and the speed - // enhancements are not terriffic. - DiyFp scaled_boundary_minus = DiyFp::Times(boundary_minus, ten_mk); - DiyFp scaled_boundary_plus = DiyFp::Times(boundary_plus, ten_mk); - - // DigitGen will generate the digits of scaled_w. Therefore we have - // v == (double) (scaled_w * 10^-mk). - // Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an - // integer than it will be updated. For instance if scaled_w == 1.23 then - // the buffer will be filled with "123" und the decimal_exponent will be - // decreased by 2. - int kappa; - bool result = DigitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus, - buffer, length, &kappa); - *decimal_exponent = -mk + kappa; - return result; - } - - - // The "counted" version of grisu3 (see above) only generates requested_digits - // number of digits. This version does not generate the shortest representation, - // and with enough requested digits 0.1 will at some point print as 0.9999999... - // Grisu3 is too imprecise for real halfway cases (1.5 will not work) and - // therefore the rounding strategy for halfway cases is irrelevant. - static bool Grisu3Counted(double v, - int requested_digits, - Vector<char> buffer, - int* length, - int* decimal_exponent) { - DiyFp w = Double(v).AsNormalizedDiyFp(); - DiyFp ten_mk; // Cached power of ten: 10^-k - int mk; // -k - int ten_mk_minimal_binary_exponent = - kMinimalTargetExponent - (w.e() + DiyFp::kSignificandSize); - int ten_mk_maximal_binary_exponent = - kMaximalTargetExponent - (w.e() + DiyFp::kSignificandSize); - PowersOfTenCache::GetCachedPowerForBinaryExponentRange( - ten_mk_minimal_binary_exponent, - ten_mk_maximal_binary_exponent, - &ten_mk, &mk); - ASSERT((kMinimalTargetExponent <= w.e() + ten_mk.e() + - DiyFp::kSignificandSize) && - (kMaximalTargetExponent >= w.e() + ten_mk.e() + - DiyFp::kSignificandSize)); - // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a - // 64 bit significand and ten_mk is thus only precise up to 64 bits. - - // The DiyFp::Times procedure rounds its result, and ten_mk is approximated - // too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now - // off by a small amount. - // In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w. - // In other words: let f = scaled_w.f() and e = scaled_w.e(), then - // (f-1) * 2^e < w*10^k < (f+1) * 2^e - DiyFp scaled_w = DiyFp::Times(w, ten_mk); - - // We now have (double) (scaled_w * 10^-mk). - // DigitGen will generate the first requested_digits digits of scaled_w and - // return together with a kappa such that scaled_w ~= buffer * 10^kappa. (It - // will not always be exactly the same since DigitGenCounted only produces a - // limited number of digits.) - int kappa; - bool result = DigitGenCounted(scaled_w, requested_digits, - buffer, length, &kappa); - *decimal_exponent = -mk + kappa; - return result; - } - - - bool FastDtoa(double v, - FastDtoaMode mode, - int requested_digits, - Vector<char> buffer, - int* length, - int* decimal_point) { - ASSERT(v > 0); - ASSERT(!Double(v).IsSpecial()); - - bool result = false; - int decimal_exponent = 0; - switch (mode) { - case FAST_DTOA_SHORTEST: - result = Grisu3(v, buffer, length, &decimal_exponent); - break; - case FAST_DTOA_PRECISION: - result = Grisu3Counted(v, requested_digits, - buffer, length, &decimal_exponent); - break; - default: - UNREACHABLE(); - } - if (result) { - *decimal_point = *length + decimal_exponent; - buffer[*length] = '\0'; - } - return result; - } - -} // namespace double_conversion - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/dtoa/fast-dtoa.h b/Source/JavaScriptCore/wtf/dtoa/fast-dtoa.h deleted file mode 100644 index 876a9f382..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/fast-dtoa.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_FAST_DTOA_H_ -#define DOUBLE_CONVERSION_FAST_DTOA_H_ - -#include "utils.h" - -namespace WTF { - -namespace double_conversion { - - enum FastDtoaMode { - // Computes the shortest representation of the given input. The returned - // result will be the most accurate number of this length. Longer - // representations might be more accurate. - FAST_DTOA_SHORTEST, - // Computes a representation where the precision (number of digits) is - // given as input. The precision is independent of the decimal point. - FAST_DTOA_PRECISION - }; - - // FastDtoa will produce at most kFastDtoaMaximalLength digits. This does not - // include the terminating '\0' character. - static const int kFastDtoaMaximalLength = 17; - - // Provides a decimal representation of v. - // The result should be interpreted as buffer * 10^(point - length). - // - // Precondition: - // * v must be a strictly positive finite double. - // - // Returns true if it succeeds, otherwise the result can not be trusted. - // There will be *length digits inside the buffer followed by a null terminator. - // If the function returns true and mode equals - // - FAST_DTOA_SHORTEST, then - // the parameter requested_digits is ignored. - // The result satisfies - // v == (double) (buffer * 10^(point - length)). - // The digits in the buffer are the shortest representation possible. E.g. - // if 0.099999999999 and 0.1 represent the same double then "1" is returned - // with point = 0. - // The last digit will be closest to the actual v. That is, even if several - // digits might correctly yield 'v' when read again, the buffer will contain - // the one closest to v. - // - FAST_DTOA_PRECISION, then - // the buffer contains requested_digits digits. - // the difference v - (buffer * 10^(point-length)) is closest to zero for - // all possible representations of requested_digits digits. - // If there are two values that are equally close, then FastDtoa returns - // false. - // For both modes the buffer must be large enough to hold the result. - bool FastDtoa(double d, - FastDtoaMode mode, - int requested_digits, - Vector<char> buffer, - int* length, - int* decimal_point); - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_FAST_DTOA_H_ diff --git a/Source/JavaScriptCore/wtf/dtoa/fixed-dtoa.cc b/Source/JavaScriptCore/wtf/dtoa/fixed-dtoa.cc deleted file mode 100644 index 40b7180e5..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/fixed-dtoa.cc +++ /dev/null @@ -1,410 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#include <math.h> - -#include "UnusedParam.h" -#include "fixed-dtoa.h" -#include "double.h" - -namespace WTF { - -namespace double_conversion { - - // Represents a 128bit type. This class should be replaced by a native type on - // platforms that support 128bit integers. - class UInt128 { - public: - UInt128() : high_bits_(0), low_bits_(0) { } - UInt128(uint64_t high, uint64_t low) : high_bits_(high), low_bits_(low) { } - - void Multiply(uint32_t multiplicand) { - uint64_t accumulator; - - accumulator = (low_bits_ & kMask32) * multiplicand; - uint32_t part = static_cast<uint32_t>(accumulator & kMask32); - accumulator >>= 32; - accumulator = accumulator + (low_bits_ >> 32) * multiplicand; - low_bits_ = (accumulator << 32) + part; - accumulator >>= 32; - accumulator = accumulator + (high_bits_ & kMask32) * multiplicand; - part = static_cast<uint32_t>(accumulator & kMask32); - accumulator >>= 32; - accumulator = accumulator + (high_bits_ >> 32) * multiplicand; - high_bits_ = (accumulator << 32) + part; - ASSERT((accumulator >> 32) == 0); - } - - void Shift(int shift_amount) { - ASSERT(-64 <= shift_amount && shift_amount <= 64); - if (shift_amount == 0) { - return; - } else if (shift_amount == -64) { - high_bits_ = low_bits_; - low_bits_ = 0; - } else if (shift_amount == 64) { - low_bits_ = high_bits_; - high_bits_ = 0; - } else if (shift_amount <= 0) { - high_bits_ <<= -shift_amount; - high_bits_ += low_bits_ >> (64 + shift_amount); - low_bits_ <<= -shift_amount; - } else { - low_bits_ >>= shift_amount; - low_bits_ += high_bits_ << (64 - shift_amount); - high_bits_ >>= shift_amount; - } - } - - // Modifies *this to *this MOD (2^power). - // Returns *this DIV (2^power). - int DivModPowerOf2(int power) { - if (power >= 64) { - int result = static_cast<int>(high_bits_ >> (power - 64)); - high_bits_ -= static_cast<uint64_t>(result) << (power - 64); - return result; - } else { - uint64_t part_low = low_bits_ >> power; - uint64_t part_high = high_bits_ << (64 - power); - int result = static_cast<int>(part_low + part_high); - high_bits_ = 0; - low_bits_ -= part_low << power; - return result; - } - } - - bool IsZero() const { - return high_bits_ == 0 && low_bits_ == 0; - } - - int BitAt(int position) { - if (position >= 64) { - return static_cast<int>(high_bits_ >> (position - 64)) & 1; - } else { - return static_cast<int>(low_bits_ >> position) & 1; - } - } - - private: - static const uint64_t kMask32 = 0xFFFFFFFF; - // Value == (high_bits_ << 64) + low_bits_ - uint64_t high_bits_; - uint64_t low_bits_; - }; - - - static const int kDoubleSignificandSize = 53; // Includes the hidden bit. - - - static void FillDigits32FixedLength(uint32_t number, int requested_length, - Vector<char> buffer, int* length) { - for (int i = requested_length - 1; i >= 0; --i) { - buffer[(*length) + i] = '0' + number % 10; - number /= 10; - } - *length += requested_length; - } - - - static void FillDigits32(uint32_t number, Vector<char> buffer, int* length) { - int number_length = 0; - // We fill the digits in reverse order and exchange them afterwards. - while (number != 0) { - int digit = number % 10; - number /= 10; - buffer[(*length) + number_length] = '0' + digit; - number_length++; - } - // Exchange the digits. - int i = *length; - int j = *length + number_length - 1; - while (i < j) { - char tmp = buffer[i]; - buffer[i] = buffer[j]; - buffer[j] = tmp; - i++; - j--; - } - *length += number_length; - } - - - static void FillDigits64FixedLength(uint64_t number, int requested_length, - Vector<char> buffer, int* length) { - UNUSED_PARAM(requested_length); - const uint32_t kTen7 = 10000000; - // For efficiency cut the number into 3 uint32_t parts, and print those. - uint32_t part2 = static_cast<uint32_t>(number % kTen7); - number /= kTen7; - uint32_t part1 = static_cast<uint32_t>(number % kTen7); - uint32_t part0 = static_cast<uint32_t>(number / kTen7); - - FillDigits32FixedLength(part0, 3, buffer, length); - FillDigits32FixedLength(part1, 7, buffer, length); - FillDigits32FixedLength(part2, 7, buffer, length); - } - - - static void FillDigits64(uint64_t number, Vector<char> buffer, int* length) { - const uint32_t kTen7 = 10000000; - // For efficiency cut the number into 3 uint32_t parts, and print those. - uint32_t part2 = static_cast<uint32_t>(number % kTen7); - number /= kTen7; - uint32_t part1 = static_cast<uint32_t>(number % kTen7); - uint32_t part0 = static_cast<uint32_t>(number / kTen7); - - if (part0 != 0) { - FillDigits32(part0, buffer, length); - FillDigits32FixedLength(part1, 7, buffer, length); - FillDigits32FixedLength(part2, 7, buffer, length); - } else if (part1 != 0) { - FillDigits32(part1, buffer, length); - FillDigits32FixedLength(part2, 7, buffer, length); - } else { - FillDigits32(part2, buffer, length); - } - } - - - static void RoundUp(Vector<char> buffer, int* length, int* decimal_point) { - // An empty buffer represents 0. - if (*length == 0) { - buffer[0] = '1'; - *decimal_point = 1; - *length = 1; - return; - } - // Round the last digit until we either have a digit that was not '9' or until - // we reached the first digit. - buffer[(*length) - 1]++; - for (int i = (*length) - 1; i > 0; --i) { - if (buffer[i] != '0' + 10) { - return; - } - buffer[i] = '0'; - buffer[i - 1]++; - } - // If the first digit is now '0' + 10, we would need to set it to '0' and add - // a '1' in front. However we reach the first digit only if all following - // digits had been '9' before rounding up. Now all trailing digits are '0' and - // we simply switch the first digit to '1' and update the decimal-point - // (indicating that the point is now one digit to the right). - if (buffer[0] == '0' + 10) { - buffer[0] = '1'; - (*decimal_point)++; - } - } - - - // The given fractionals number represents a fixed-point number with binary - // point at bit (-exponent). - // Preconditions: - // -128 <= exponent <= 0. - // 0 <= fractionals * 2^exponent < 1 - // The buffer holds the result. - // The function will round its result. During the rounding-process digits not - // generated by this function might be updated, and the decimal-point variable - // might be updated. If this function generates the digits 99 and the buffer - // already contained "199" (thus yielding a buffer of "19999") then a - // rounding-up will change the contents of the buffer to "20000". - static void FillFractionals(uint64_t fractionals, int exponent, - int fractional_count, Vector<char> buffer, - int* length, int* decimal_point) { - ASSERT(-128 <= exponent && exponent <= 0); - // 'fractionals' is a fixed-point number, with binary point at bit - // (-exponent). Inside the function the non-converted remainder of fractionals - // is a fixed-point number, with binary point at bit 'point'. - if (-exponent <= 64) { - // One 64 bit number is sufficient. - ASSERT(fractionals >> 56 == 0); - int point = -exponent; - for (int i = 0; i < fractional_count; ++i) { - if (fractionals == 0) break; - // Instead of multiplying by 10 we multiply by 5 and adjust the point - // location. This way the fractionals variable will not overflow. - // Invariant at the beginning of the loop: fractionals < 2^point. - // Initially we have: point <= 64 and fractionals < 2^56 - // After each iteration the point is decremented by one. - // Note that 5^3 = 125 < 128 = 2^7. - // Therefore three iterations of this loop will not overflow fractionals - // (even without the subtraction at the end of the loop body). At this - // time point will satisfy point <= 61 and therefore fractionals < 2^point - // and any further multiplication of fractionals by 5 will not overflow. - fractionals *= 5; - point--; - int digit = static_cast<int>(fractionals >> point); - buffer[*length] = '0' + digit; - (*length)++; - fractionals -= static_cast<uint64_t>(digit) << point; - } - // If the first bit after the point is set we have to round up. - if (((fractionals >> (point - 1)) & 1) == 1) { - RoundUp(buffer, length, decimal_point); - } - } else { // We need 128 bits. - ASSERT(64 < -exponent && -exponent <= 128); - UInt128 fractionals128 = UInt128(fractionals, 0); - fractionals128.Shift(-exponent - 64); - int point = 128; - for (int i = 0; i < fractional_count; ++i) { - if (fractionals128.IsZero()) break; - // As before: instead of multiplying by 10 we multiply by 5 and adjust the - // point location. - // This multiplication will not overflow for the same reasons as before. - fractionals128.Multiply(5); - point--; - int digit = fractionals128.DivModPowerOf2(point); - buffer[*length] = '0' + digit; - (*length)++; - } - if (fractionals128.BitAt(point - 1) == 1) { - RoundUp(buffer, length, decimal_point); - } - } - } - - - // Removes leading and trailing zeros. - // If leading zeros are removed then the decimal point position is adjusted. - static void TrimZeros(Vector<char> buffer, int* length, int* decimal_point) { - while (*length > 0 && buffer[(*length) - 1] == '0') { - (*length)--; - } - int first_non_zero = 0; - while (first_non_zero < *length && buffer[first_non_zero] == '0') { - first_non_zero++; - } - if (first_non_zero != 0) { - for (int i = first_non_zero; i < *length; ++i) { - buffer[i - first_non_zero] = buffer[i]; - } - *length -= first_non_zero; - *decimal_point -= first_non_zero; - } - } - - - bool FastFixedDtoa(double v, - int fractional_count, - Vector<char> buffer, - int* length, - int* decimal_point) { - const uint32_t kMaxUInt32 = 0xFFFFFFFF; - uint64_t significand = Double(v).Significand(); - int exponent = Double(v).Exponent(); - // v = significand * 2^exponent (with significand a 53bit integer). - // If the exponent is larger than 20 (i.e. we may have a 73bit number) then we - // don't know how to compute the representation. 2^73 ~= 9.5*10^21. - // If necessary this limit could probably be increased, but we don't need - // more. - if (exponent > 20) return false; - if (fractional_count > 20) return false; - *length = 0; - // At most kDoubleSignificandSize bits of the significand are non-zero. - // Given a 64 bit integer we have 11 0s followed by 53 potentially non-zero - // bits: 0..11*..0xxx..53*..xx - if (exponent + kDoubleSignificandSize > 64) { - // The exponent must be > 11. - // - // We know that v = significand * 2^exponent. - // And the exponent > 11. - // We simplify the task by dividing v by 10^17. - // The quotient delivers the first digits, and the remainder fits into a 64 - // bit number. - // Dividing by 10^17 is equivalent to dividing by 5^17*2^17. - const uint64_t kFive17 = UINT64_2PART_C(0xB1, A2BC2EC5); // 5^17 - uint64_t divisor = kFive17; - int divisor_power = 17; - uint64_t dividend = significand; - uint32_t quotient; - uint64_t remainder; - // Let v = f * 2^e with f == significand and e == exponent. - // Then need q (quotient) and r (remainder) as follows: - // v = q * 10^17 + r - // f * 2^e = q * 10^17 + r - // f * 2^e = q * 5^17 * 2^17 + r - // If e > 17 then - // f * 2^(e-17) = q * 5^17 + r/2^17 - // else - // f = q * 5^17 * 2^(17-e) + r/2^e - if (exponent > divisor_power) { - // We only allow exponents of up to 20 and therefore (17 - e) <= 3 - dividend <<= exponent - divisor_power; - quotient = static_cast<uint32_t>(dividend / divisor); - remainder = (dividend % divisor) << divisor_power; - } else { - divisor <<= divisor_power - exponent; - quotient = static_cast<uint32_t>(dividend / divisor); - remainder = (dividend % divisor) << exponent; - } - FillDigits32(quotient, buffer, length); - FillDigits64FixedLength(remainder, divisor_power, buffer, length); - *decimal_point = *length; - } else if (exponent >= 0) { - // 0 <= exponent <= 11 - significand <<= exponent; - FillDigits64(significand, buffer, length); - *decimal_point = *length; - } else if (exponent > -kDoubleSignificandSize) { - // We have to cut the number. - uint64_t integrals = significand >> -exponent; - uint64_t fractionals = significand - (integrals << -exponent); - if (integrals > kMaxUInt32) { - FillDigits64(integrals, buffer, length); - } else { - FillDigits32(static_cast<uint32_t>(integrals), buffer, length); - } - *decimal_point = *length; - FillFractionals(fractionals, exponent, fractional_count, - buffer, length, decimal_point); - } else if (exponent < -128) { - // This configuration (with at most 20 digits) means that all digits must be - // 0. - ASSERT(fractional_count <= 20); - buffer[0] = '\0'; - *length = 0; - *decimal_point = -fractional_count; - } else { - *decimal_point = 0; - FillFractionals(significand, exponent, fractional_count, - buffer, length, decimal_point); - } - TrimZeros(buffer, length, decimal_point); - buffer[*length] = '\0'; - if ((*length) == 0) { - // The string is empty and the decimal_point thus has no importance. Mimick - // Gay's dtoa and and set it to -fractional_count. - *decimal_point = -fractional_count; - } - return true; - } - -} // namespace double_conversion - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/dtoa/fixed-dtoa.h b/Source/JavaScriptCore/wtf/dtoa/fixed-dtoa.h deleted file mode 100644 index 8c0adb758..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/fixed-dtoa.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_FIXED_DTOA_H_ -#define DOUBLE_CONVERSION_FIXED_DTOA_H_ - -#include "utils.h" - -namespace WTF { - -namespace double_conversion { - - // Produces digits necessary to print a given number with - // 'fractional_count' digits after the decimal point. - // The buffer must be big enough to hold the result plus one terminating null - // character. - // - // The produced digits might be too short in which case the caller has to fill - // the gaps with '0's. - // Example: FastFixedDtoa(0.001, 5, ...) is allowed to return buffer = "1", and - // decimal_point = -2. - // Halfway cases are rounded towards +/-Infinity (away from 0). The call - // FastFixedDtoa(0.15, 2, ...) thus returns buffer = "2", decimal_point = 0. - // The returned buffer may contain digits that would be truncated from the - // shortest representation of the input. - // - // This method only works for some parameters. If it can't handle the input it - // returns false. The output is null-terminated when the function succeeds. - bool FastFixedDtoa(double v, int fractional_count, - Vector<char> buffer, int* length, int* decimal_point); - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_FIXED_DTOA_H_ diff --git a/Source/JavaScriptCore/wtf/dtoa/strtod.cc b/Source/JavaScriptCore/wtf/dtoa/strtod.cc deleted file mode 100644 index 477e7158c..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/strtod.cc +++ /dev/null @@ -1,447 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" - -#include <stdarg.h> -#include <limits.h> - -#include "strtod.h" -#include "bignum.h" -#include "cached-powers.h" -#include "double.h" - -namespace WTF { - -namespace double_conversion { - - // 2^53 = 9007199254740992. - // Any integer with at most 15 decimal digits will hence fit into a double - // (which has a 53bit significand) without loss of precision. - static const int kMaxExactDoubleIntegerDecimalDigits = 15; - // 2^64 = 18446744073709551616 > 10^19 - static const int kMaxUint64DecimalDigits = 19; - - // Max double: 1.7976931348623157 x 10^308 - // Min non-zero double: 4.9406564584124654 x 10^-324 - // Any x >= 10^309 is interpreted as +infinity. - // Any x <= 10^-324 is interpreted as 0. - // Note that 2.5e-324 (despite being smaller than the min double) will be read - // as non-zero (equal to the min non-zero double). - static const int kMaxDecimalPower = 309; - static const int kMinDecimalPower = -324; - - // 2^64 = 18446744073709551616 - static const uint64_t kMaxUint64 = UINT64_2PART_C(0xFFFFFFFF, FFFFFFFF); - - - static const double exact_powers_of_ten[] = { - 1.0, // 10^0 - 10.0, - 100.0, - 1000.0, - 10000.0, - 100000.0, - 1000000.0, - 10000000.0, - 100000000.0, - 1000000000.0, - 10000000000.0, // 10^10 - 100000000000.0, - 1000000000000.0, - 10000000000000.0, - 100000000000000.0, - 1000000000000000.0, - 10000000000000000.0, - 100000000000000000.0, - 1000000000000000000.0, - 10000000000000000000.0, - 100000000000000000000.0, // 10^20 - 1000000000000000000000.0, - // 10^22 = 0x21e19e0c9bab2400000 = 0x878678326eac9 * 2^22 - 10000000000000000000000.0 - }; - static const int kExactPowersOfTenSize = ARRAY_SIZE(exact_powers_of_ten); - - // Maximum number of significant digits in the decimal representation. - // In fact the value is 772 (see conversions.cc), but to give us some margin - // we round up to 780. - static const int kMaxSignificantDecimalDigits = 780; - - static Vector<const char> TrimLeadingZeros(Vector<const char> buffer) { - for (int i = 0; i < buffer.length(); i++) { - if (buffer[i] != '0') { - return buffer.SubVector(i, buffer.length()); - } - } - return Vector<const char>(buffer.start(), 0); - } - - - static Vector<const char> TrimTrailingZeros(Vector<const char> buffer) { - for (int i = buffer.length() - 1; i >= 0; --i) { - if (buffer[i] != '0') { - return buffer.SubVector(0, i + 1); - } - } - return Vector<const char>(buffer.start(), 0); - } - - - static void TrimToMaxSignificantDigits(Vector<const char> buffer, - int exponent, - char* significant_buffer, - int* significant_exponent) { - for (int i = 0; i < kMaxSignificantDecimalDigits - 1; ++i) { - significant_buffer[i] = buffer[i]; - } - // The input buffer has been trimmed. Therefore the last digit must be - // different from '0'. - ASSERT(buffer[buffer.length() - 1] != '0'); - // Set the last digit to be non-zero. This is sufficient to guarantee - // correct rounding. - significant_buffer[kMaxSignificantDecimalDigits - 1] = '1'; - *significant_exponent = - exponent + (buffer.length() - kMaxSignificantDecimalDigits); - } - - // Reads digits from the buffer and converts them to a uint64. - // Reads in as many digits as fit into a uint64. - // When the string starts with "1844674407370955161" no further digit is read. - // Since 2^64 = 18446744073709551616 it would still be possible read another - // digit if it was less or equal than 6, but this would complicate the code. - static uint64_t ReadUint64(Vector<const char> buffer, - int* number_of_read_digits) { - uint64_t result = 0; - int i = 0; - while (i < buffer.length() && result <= (kMaxUint64 / 10 - 1)) { - int digit = buffer[i++] - '0'; - ASSERT(0 <= digit && digit <= 9); - result = 10 * result + digit; - } - *number_of_read_digits = i; - return result; - } - - - // Reads a DiyFp from the buffer. - // The returned DiyFp is not necessarily normalized. - // If remaining_decimals is zero then the returned DiyFp is accurate. - // Otherwise it has been rounded and has error of at most 1/2 ulp. - static void ReadDiyFp(Vector<const char> buffer, - DiyFp* result, - int* remaining_decimals) { - int read_digits; - uint64_t significand = ReadUint64(buffer, &read_digits); - if (buffer.length() == read_digits) { - *result = DiyFp(significand, 0); - *remaining_decimals = 0; - } else { - // Round the significand. - if (buffer[read_digits] >= '5') { - significand++; - } - // Compute the binary exponent. - int exponent = 0; - *result = DiyFp(significand, exponent); - *remaining_decimals = buffer.length() - read_digits; - } - } - - - static bool DoubleStrtod(Vector<const char> trimmed, - int exponent, - double* result) { -#if !defined(DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS) - // On x86 the floating-point stack can be 64 or 80 bits wide. If it is - // 80 bits wide (as is the case on Linux) then double-rounding occurs and the - // result is not accurate. - // We know that Windows32 uses 64 bits and is therefore accurate. - // Note that the ARM simulator is compiled for 32bits. It therefore exhibits - // the same problem. - return false; -#endif - if (trimmed.length() <= kMaxExactDoubleIntegerDecimalDigits) { - int read_digits; - // The trimmed input fits into a double. - // If the 10^exponent (resp. 10^-exponent) fits into a double too then we - // can compute the result-double simply by multiplying (resp. dividing) the - // two numbers. - // This is possible because IEEE guarantees that floating-point operations - // return the best possible approximation. - if (exponent < 0 && -exponent < kExactPowersOfTenSize) { - // 10^-exponent fits into a double. - *result = static_cast<double>(ReadUint64(trimmed, &read_digits)); - ASSERT(read_digits == trimmed.length()); - *result /= exact_powers_of_ten[-exponent]; - return true; - } - if (0 <= exponent && exponent < kExactPowersOfTenSize) { - // 10^exponent fits into a double. - *result = static_cast<double>(ReadUint64(trimmed, &read_digits)); - ASSERT(read_digits == trimmed.length()); - *result *= exact_powers_of_ten[exponent]; - return true; - } - int remaining_digits = - kMaxExactDoubleIntegerDecimalDigits - trimmed.length(); - if ((0 <= exponent) && - (exponent - remaining_digits < kExactPowersOfTenSize)) { - // The trimmed string was short and we can multiply it with - // 10^remaining_digits. As a result the remaining exponent now fits - // into a double too. - *result = static_cast<double>(ReadUint64(trimmed, &read_digits)); - ASSERT(read_digits == trimmed.length()); - *result *= exact_powers_of_ten[remaining_digits]; - *result *= exact_powers_of_ten[exponent - remaining_digits]; - return true; - } - } - return false; - } - - - // Returns 10^exponent as an exact DiyFp. - // The given exponent must be in the range [1; kDecimalExponentDistance[. - static DiyFp AdjustmentPowerOfTen(int exponent) { - ASSERT(0 < exponent); - ASSERT(exponent < PowersOfTenCache::kDecimalExponentDistance); - // Simply hardcode the remaining powers for the given decimal exponent - // distance. - ASSERT(PowersOfTenCache::kDecimalExponentDistance == 8); - switch (exponent) { - case 1: return DiyFp(UINT64_2PART_C(0xa0000000, 00000000), -60); - case 2: return DiyFp(UINT64_2PART_C(0xc8000000, 00000000), -57); - case 3: return DiyFp(UINT64_2PART_C(0xfa000000, 00000000), -54); - case 4: return DiyFp(UINT64_2PART_C(0x9c400000, 00000000), -50); - case 5: return DiyFp(UINT64_2PART_C(0xc3500000, 00000000), -47); - case 6: return DiyFp(UINT64_2PART_C(0xf4240000, 00000000), -44); - case 7: return DiyFp(UINT64_2PART_C(0x98968000, 00000000), -40); - default: - UNREACHABLE(); - return DiyFp(0, 0); - } - } - - - // If the function returns true then the result is the correct double. - // Otherwise it is either the correct double or the double that is just below - // the correct double. - static bool DiyFpStrtod(Vector<const char> buffer, - int exponent, - double* result) { - DiyFp input; - int remaining_decimals; - ReadDiyFp(buffer, &input, &remaining_decimals); - // Since we may have dropped some digits the input is not accurate. - // If remaining_decimals is different than 0 than the error is at most - // .5 ulp (unit in the last place). - // We don't want to deal with fractions and therefore keep a common - // denominator. - const int kDenominatorLog = 3; - const int kDenominator = 1 << kDenominatorLog; - // Move the remaining decimals into the exponent. - exponent += remaining_decimals; - int error = (remaining_decimals == 0 ? 0 : kDenominator / 2); - - int old_e = input.e(); - input.Normalize(); - error <<= old_e - input.e(); - - ASSERT(exponent <= PowersOfTenCache::kMaxDecimalExponent); - if (exponent < PowersOfTenCache::kMinDecimalExponent) { - *result = 0.0; - return true; - } - DiyFp cached_power; - int cached_decimal_exponent; - PowersOfTenCache::GetCachedPowerForDecimalExponent(exponent, - &cached_power, - &cached_decimal_exponent); - - if (cached_decimal_exponent != exponent) { - int adjustment_exponent = exponent - cached_decimal_exponent; - DiyFp adjustment_power = AdjustmentPowerOfTen(adjustment_exponent); - input.Multiply(adjustment_power); - if (kMaxUint64DecimalDigits - buffer.length() >= adjustment_exponent) { - // The product of input with the adjustment power fits into a 64 bit - // integer. - ASSERT(DiyFp::kSignificandSize == 64); - } else { - // The adjustment power is exact. There is hence only an error of 0.5. - error += kDenominator / 2; - } - } - - input.Multiply(cached_power); - // The error introduced by a multiplication of a*b equals - // error_a + error_b + error_a*error_b/2^64 + 0.5 - // Substituting a with 'input' and b with 'cached_power' we have - // error_b = 0.5 (all cached powers have an error of less than 0.5 ulp), - // error_ab = 0 or 1 / kDenominator > error_a*error_b/ 2^64 - int error_b = kDenominator / 2; - int error_ab = (error == 0 ? 0 : 1); // We round up to 1. - int fixed_error = kDenominator / 2; - error += error_b + error_ab + fixed_error; - - old_e = input.e(); - input.Normalize(); - error <<= old_e - input.e(); - - // See if the double's significand changes if we add/subtract the error. - int order_of_magnitude = DiyFp::kSignificandSize + input.e(); - int effective_significand_size = - Double::SignificandSizeForOrderOfMagnitude(order_of_magnitude); - int precision_digits_count = - DiyFp::kSignificandSize - effective_significand_size; - if (precision_digits_count + kDenominatorLog >= DiyFp::kSignificandSize) { - // This can only happen for very small denormals. In this case the - // half-way multiplied by the denominator exceeds the range of an uint64. - // Simply shift everything to the right. - int shift_amount = (precision_digits_count + kDenominatorLog) - - DiyFp::kSignificandSize + 1; - input.set_f(input.f() >> shift_amount); - input.set_e(input.e() + shift_amount); - // We add 1 for the lost precision of error, and kDenominator for - // the lost precision of input.f(). - error = (error >> shift_amount) + 1 + kDenominator; - precision_digits_count -= shift_amount; - } - // We use uint64_ts now. This only works if the DiyFp uses uint64_ts too. - ASSERT(DiyFp::kSignificandSize == 64); - ASSERT(precision_digits_count < 64); - uint64_t one64 = 1; - uint64_t precision_bits_mask = (one64 << precision_digits_count) - 1; - uint64_t precision_bits = input.f() & precision_bits_mask; - uint64_t half_way = one64 << (precision_digits_count - 1); - precision_bits *= kDenominator; - half_way *= kDenominator; - DiyFp rounded_input(input.f() >> precision_digits_count, - input.e() + precision_digits_count); - if (precision_bits >= half_way + error) { - rounded_input.set_f(rounded_input.f() + 1); - } - // If the last_bits are too close to the half-way case than we are too - // inaccurate and round down. In this case we return false so that we can - // fall back to a more precise algorithm. - - *result = Double(rounded_input).value(); - if (half_way - error < precision_bits && precision_bits < half_way + error) { - // Too imprecise. The caller will have to fall back to a slower version. - // However the returned number is guaranteed to be either the correct - // double, or the next-lower double. - return false; - } else { - return true; - } - } - - - // Returns the correct double for the buffer*10^exponent. - // The variable guess should be a close guess that is either the correct double - // or its lower neighbor (the nearest double less than the correct one). - // Preconditions: - // buffer.length() + exponent <= kMaxDecimalPower + 1 - // buffer.length() + exponent > kMinDecimalPower - // buffer.length() <= kMaxDecimalSignificantDigits - static double BignumStrtod(Vector<const char> buffer, - int exponent, - double guess) { - if (guess == Double::Infinity()) { - return guess; - } - - DiyFp upper_boundary = Double(guess).UpperBoundary(); - - ASSERT(buffer.length() + exponent <= kMaxDecimalPower + 1); - ASSERT(buffer.length() + exponent > kMinDecimalPower); - ASSERT(buffer.length() <= kMaxSignificantDecimalDigits); - // Make sure that the Bignum will be able to hold all our numbers. - // Our Bignum implementation has a separate field for exponents. Shifts will - // consume at most one bigit (< 64 bits). - // ln(10) == 3.3219... - ASSERT(((kMaxDecimalPower + 1) * 333 / 100) < Bignum::kMaxSignificantBits); - Bignum input; - Bignum boundary; - input.AssignDecimalString(buffer); - boundary.AssignUInt64(upper_boundary.f()); - if (exponent >= 0) { - input.MultiplyByPowerOfTen(exponent); - } else { - boundary.MultiplyByPowerOfTen(-exponent); - } - if (upper_boundary.e() > 0) { - boundary.ShiftLeft(upper_boundary.e()); - } else { - input.ShiftLeft(-upper_boundary.e()); - } - int comparison = Bignum::Compare(input, boundary); - if (comparison < 0) { - return guess; - } else if (comparison > 0) { - return Double(guess).NextDouble(); - } else if ((Double(guess).Significand() & 1) == 0) { - // Round towards even. - return guess; - } else { - return Double(guess).NextDouble(); - } - } - - - double Strtod(Vector<const char> buffer, int exponent) { - Vector<const char> left_trimmed = TrimLeadingZeros(buffer); - Vector<const char> trimmed = TrimTrailingZeros(left_trimmed); - exponent += left_trimmed.length() - trimmed.length(); - if (trimmed.length() == 0) return 0.0; - if (trimmed.length() > kMaxSignificantDecimalDigits) { - char significant_buffer[kMaxSignificantDecimalDigits]; - int significant_exponent; - TrimToMaxSignificantDigits(trimmed, exponent, - significant_buffer, &significant_exponent); - return Strtod(Vector<const char>(significant_buffer, - kMaxSignificantDecimalDigits), - significant_exponent); - } - if (exponent + trimmed.length() - 1 >= kMaxDecimalPower) { - return Double::Infinity(); - } - if (exponent + trimmed.length() <= kMinDecimalPower) { - return 0.0; - } - - double guess; - if (DoubleStrtod(trimmed, exponent, &guess) || - DiyFpStrtod(trimmed, exponent, &guess)) { - return guess; - } - return BignumStrtod(trimmed, exponent, guess); - } - -} // namespace double_conversion - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/dtoa/strtod.h b/Source/JavaScriptCore/wtf/dtoa/strtod.h deleted file mode 100644 index 8ed350ad8..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/strtod.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_STRTOD_H_ -#define DOUBLE_CONVERSION_STRTOD_H_ - -#include "utils.h" - -namespace WTF { - -namespace double_conversion { - - // The buffer must only contain digits in the range [0-9]. It must not - // contain a dot or a sign. It must not start with '0', and must not be empty. - double Strtod(Vector<const char> buffer, int exponent); - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_STRTOD_H_ diff --git a/Source/JavaScriptCore/wtf/dtoa/utils.h b/Source/JavaScriptCore/wtf/dtoa/utils.h deleted file mode 100644 index da6e13226..000000000 --- a/Source/JavaScriptCore/wtf/dtoa/utils.h +++ /dev/null @@ -1,310 +0,0 @@ -// Copyright 2010 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef DOUBLE_CONVERSION_UTILS_H_ -#define DOUBLE_CONVERSION_UTILS_H_ - -#include <wtf/Assertions.h> -#include <stdlib.h> -#include <string.h> - -#define UNIMPLEMENTED ASSERT_NOT_REACHED -#define UNREACHABLE ASSERT_NOT_REACHED - -// Double operations detection based on target architecture. -// Linux uses a 80bit wide floating point stack on x86. This induces double -// rounding, which in turn leads to wrong results. -// An easy way to test if the floating-point operations are correct is to -// evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then -// the result is equal to 89255e-22. -// The best way to test this, is to create a division-function and to compare -// the output of the division with the expected result. (Inlining must be -// disabled.) -// On Linux,x86 89255e-22 != Div_double(89255.0/1e22) -#if defined(_M_X64) || defined(__x86_64__) || \ -defined(__ARMEL__) || \ -defined(_MIPS_ARCH_MIPS32R2) -#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 -#elif CPU(MIPS) || CPU(PPC) || CPU(PPC64) || OS(WINCE) || CPU(SH4) || CPU(S390) || CPU(S390X) || CPU(IA64) || CPU(SPARC) || CPU(ALPHA) -#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 -#elif defined(_M_IX86) || defined(__i386__) -#if defined(_WIN32) -// Windows uses a 64bit wide floating point stack. -#define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1 -#else -#undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS -#endif // _WIN32 -#else -#error Target architecture was not detected as supported by Double-Conversion. -#endif - - -#if defined(_WIN32) && !defined(__MINGW32__) - -typedef signed char int8_t; -typedef unsigned char uint8_t; -typedef short int16_t; // NOLINT -typedef unsigned short uint16_t; // NOLINT -typedef int int32_t; -typedef unsigned int uint32_t; -typedef __int64 int64_t; -typedef unsigned __int64 uint64_t; -// intptr_t and friends are defined in crtdefs.h through stdio.h. - -#else - -#include <stdint.h> - -#endif - -// The following macro works on both 32 and 64-bit platforms. -// Usage: instead of writing 0x1234567890123456 -// write UINT64_2PART_C(0x12345678,90123456); -#define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u)) - - -// The expression ARRAY_SIZE(a) is a compile-time constant of type -// size_t which represents the number of elements of the given -// array. You should only use ARRAY_SIZE on statically allocated -// arrays. -#define ARRAY_SIZE(a) \ -((sizeof(a) / sizeof(*(a))) / \ -static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) - -// A macro to disallow the evil copy constructor and operator= functions -// This should be used in the private: declarations for a class -#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ -TypeName(const TypeName&); \ -void operator=(const TypeName&) - -// A macro to disallow all the implicit constructors, namely the -// default constructor, copy constructor and operator= functions. -// -// This should be used in the private: declarations for a class -// that wants to prevent anyone from instantiating it. This is -// especially useful for classes containing only static methods. -#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ -TypeName(); \ -DISALLOW_COPY_AND_ASSIGN(TypeName) - -namespace WTF { - -namespace double_conversion { - - static const int kCharSize = sizeof(char); - - // Returns the maximum of the two parameters. - template <typename T> - static T Max(T a, T b) { - return a < b ? b : a; - } - - - // Returns the minimum of the two parameters. - template <typename T> - static T Min(T a, T b) { - return a < b ? a : b; - } - - - inline int StrLength(const char* string) { - size_t length = strlen(string); - ASSERT(length == static_cast<size_t>(static_cast<int>(length))); - return static_cast<int>(length); - } - - // This is a simplified version of V8's Vector class. - template <typename T> - class Vector { - public: - Vector() : start_(NULL), length_(0) {} - Vector(T* data, int length) : start_(data), length_(length) { - ASSERT(length == 0 || (length > 0 && data != NULL)); - } - - // Returns a vector using the same backing storage as this one, - // spanning from and including 'from', to but not including 'to'. - Vector<T> SubVector(int from, int to) { - ASSERT(to <= length_); - ASSERT(from < to); - ASSERT(0 <= from); - return Vector<T>(start() + from, to - from); - } - - // Returns the length of the vector. - int length() const { return length_; } - - // Returns whether or not the vector is empty. - bool is_empty() const { return length_ == 0; } - - // Returns the pointer to the start of the data in the vector. - T* start() const { return start_; } - - // Access individual vector elements - checks bounds in debug mode. - T& operator[](int index) const { - ASSERT(0 <= index && index < length_); - return start_[index]; - } - - T& first() { return start_[0]; } - - T& last() { return start_[length_ - 1]; } - - private: - T* start_; - int length_; - }; - - - // Helper class for building result strings in a character buffer. The - // purpose of the class is to use safe operations that checks the - // buffer bounds on all operations in debug mode. - class StringBuilder { - public: - StringBuilder(char* buffer, int size) - : buffer_(buffer, size), position_(0) { } - - ~StringBuilder() { if (!is_finalized()) Finalize(); } - - int size() const { return buffer_.length(); } - - // Get the current position in the builder. - int position() const { - ASSERT(!is_finalized()); - return position_; - } - - // Set the current position in the builder. - void SetPosition(int position) - { - ASSERT(!is_finalized()); - ASSERT(position < size()); - position_ = position; - } - - // Reset the position. - void Reset() { position_ = 0; } - - // Add a single character to the builder. It is not allowed to add - // 0-characters; use the Finalize() method to terminate the string - // instead. - void AddCharacter(char c) { - ASSERT(c != '\0'); - ASSERT(!is_finalized() && position_ < buffer_.length()); - buffer_[position_++] = c; - } - - // Add an entire string to the builder. Uses strlen() internally to - // compute the length of the input string. - void AddString(const char* s) { - AddSubstring(s, StrLength(s)); - } - - // Add the first 'n' characters of the given string 's' to the - // builder. The input string must have enough characters. - void AddSubstring(const char* s, int n) { - ASSERT(!is_finalized() && position_ + n < buffer_.length()); - ASSERT(static_cast<size_t>(n) <= strlen(s)); - memcpy(&buffer_[position_], s, n * kCharSize); - position_ += n; - } - - - // Add character padding to the builder. If count is non-positive, - // nothing is added to the builder. - void AddPadding(char c, int count) { - for (int i = 0; i < count; i++) { - AddCharacter(c); - } - } - - // Finalize the string by 0-terminating it and returning the buffer. - char* Finalize() { - ASSERT(!is_finalized() && position_ < buffer_.length()); - buffer_[position_] = '\0'; - // Make sure nobody managed to add a 0-character to the - // buffer while building the string. - ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_)); - position_ = -1; - ASSERT(is_finalized()); - return buffer_.start(); - } - - private: - Vector<char> buffer_; - int position_; - - bool is_finalized() const { return position_ < 0; } - - DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder); - }; - - // The type-based aliasing rule allows the compiler to assume that pointers of - // different types (for some definition of different) never alias each other. - // Thus the following code does not work: - // - // float f = foo(); - // int fbits = *(int*)(&f); - // - // The compiler 'knows' that the int pointer can't refer to f since the types - // don't match, so the compiler may cache f in a register, leaving random data - // in fbits. Using C++ style casts makes no difference, however a pointer to - // char data is assumed to alias any other pointer. This is the 'memcpy - // exception'. - // - // Bit_cast uses the memcpy exception to move the bits from a variable of one - // type of a variable of another type. Of course the end result is likely to - // be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005) - // will completely optimize BitCast away. - // - // There is an additional use for BitCast. - // Recent gccs will warn when they see casts that may result in breakage due to - // the type-based aliasing rule. If you have checked that there is no breakage - // you can use BitCast to cast one pointer type to another. This confuses gcc - // enough that it can no longer see that you have cast one pointer type to - // another thus avoiding the warning. - template <class Dest, class Source> - inline Dest BitCast(const Source& source) { - // Compile time assertion: sizeof(Dest) == sizeof(Source) - // A compile error here means your Dest and Source have different sizes. - typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1]; - - Dest dest; - memcpy(&dest, &source, sizeof(dest)); - return dest; - } - - template <class Dest, class Source> - inline Dest BitCast(Source* source) { - return BitCast<Dest>(reinterpret_cast<uintptr_t>(source)); - } - -} // namespace double_conversion - -} // namespace WTF - -#endif // DOUBLE_CONVERSION_UTILS_H_ diff --git a/Source/JavaScriptCore/wtf/efl/MainThreadEfl.cpp b/Source/JavaScriptCore/wtf/efl/MainThreadEfl.cpp deleted file mode 100644 index 53adcb2b1..000000000 --- a/Source/JavaScriptCore/wtf/efl/MainThreadEfl.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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> -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/StdLibExtras.h> - -namespace WTF { - -static OwnPtr<Ecore_Pipe>& pipeObject() -{ - DEFINE_STATIC_LOCAL(OwnPtr<Ecore_Pipe>, pipeObject, ()); - return pipeObject; -} - -static void monitorDispatchFunctions(void*, void*, unsigned int) -{ - dispatchFunctionsFromMainThread(); -} - -void initializeMainThreadPlatform() -{ - pipeObject() = adoptPtr(ecore_pipe_add(monitorDispatchFunctions, 0)); -} - -void scheduleDispatchFunctionsOnMainThread() -{ - ecore_pipe_write(pipeObject().get(), "", 0); -} - -} diff --git a/Source/JavaScriptCore/wtf/efl/OwnPtrEfl.cpp b/Source/JavaScriptCore/wtf/efl/OwnPtrEfl.cpp deleted file mode 100644 index 3f3ad6420..000000000 --- a/Source/JavaScriptCore/wtf/efl/OwnPtrEfl.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2011 ProFUSION embedded systems - * Copyright (C) 2011 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. - * - * 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 "OwnPtr.h" - -#include <Ecore.h> -#include <Ecore_Evas.h> -#include <Eina.h> -#include <Evas.h> - -namespace WTF { - -void deleteOwnedPtr(Ecore_Evas* ptr) -{ - if (ptr) - ecore_evas_free(ptr); -} - -void deleteOwnedPtr(Evas_Object* ptr) -{ - evas_object_del(ptr); -} - -void deleteOwnedPtr(Ecore_Pipe* ptr) -{ - if (ptr) - ecore_pipe_del(ptr); -} - -void deleteOwnedPtr(Eina_Module* ptr) -{ - if (ptr) - eina_module_free(ptr); // If module wasn't unloaded, eina_module_free() calls eina_module_unload(). -} - -} diff --git a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp deleted file mode 100644 index dfe187d78..000000000 --- a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2008 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "config.h" -#include "GOwnPtr.h" - -#if ENABLE(GLIB_SUPPORT) - -#include <gio/gio.h> -#include <glib.h> - -namespace WTF { - -template <> void freeOwnedGPtr<GError>(GError* ptr) -{ - if (ptr) - g_error_free(ptr); -} - -template <> void freeOwnedGPtr<GList>(GList* ptr) -{ - g_list_free(ptr); -} - -template <> void freeOwnedGPtr<GSList>(GSList* ptr) -{ - g_slist_free(ptr); -} - -template <> void freeOwnedGPtr<GPatternSpec>(GPatternSpec* ptr) -{ - if (ptr) - g_pattern_spec_free(ptr); -} - -template <> void freeOwnedGPtr<GDir>(GDir* ptr) -{ - if (ptr) - g_dir_close(ptr); -} - -template <> void freeOwnedGPtr<GTimer>(GTimer* ptr) -{ - if (ptr) - g_timer_destroy(ptr); -} - -template <> void freeOwnedGPtr<GKeyFile>(GKeyFile* ptr) -{ - if (ptr) - g_key_file_free(ptr); -} - -} // namespace WTF - -#endif // ENABLE(GLIB_SUPPORT) diff --git a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h b/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h deleted file mode 100644 index 4b2dcb77b..000000000 --- a/Source/JavaScriptCore/wtf/gobject/GOwnPtr.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. - * Copyright (C) 2008 Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef GOwnPtr_h -#define GOwnPtr_h - -#if ENABLE(GLIB_SUPPORT) - -#include <algorithm> -#include <wtf/Assertions.h> -#include <wtf/Noncopyable.h> - -extern "C" void g_free(void*); - -namespace WTF { - -template <typename T> inline void freeOwnedGPtr(T* ptr); -template<> void freeOwnedGPtr<GError>(GError*); -template<> void freeOwnedGPtr<GList>(GList*); -template<> void freeOwnedGPtr<GSList>(GSList*); -template<> void freeOwnedGPtr<GPatternSpec>(GPatternSpec*); -template<> void freeOwnedGPtr<GDir>(GDir*); -template<> void freeOwnedGPtr<GTimer>(GTimer*); -template<> void freeOwnedGPtr<GKeyFile>(GKeyFile*); - -template <typename T> class GOwnPtr { - WTF_MAKE_NONCOPYABLE(GOwnPtr); -public: - explicit GOwnPtr(T* ptr = 0) : m_ptr(ptr) { } - ~GOwnPtr() { freeOwnedGPtr(m_ptr); } - - T* get() const { return m_ptr; } - T* release() - { - T* ptr = m_ptr; - m_ptr = 0; - return ptr; - } - - T*& outPtr() - { - ASSERT(!m_ptr); - return m_ptr; - } - - void set(T* ptr) - { - ASSERT(!ptr || m_ptr != ptr); - freeOwnedGPtr(m_ptr); - m_ptr = ptr; - } - - void clear() - { - T* ptr = m_ptr; - m_ptr = 0; - freeOwnedGPtr(ptr); - } - - T& operator*() const - { - ASSERT(m_ptr); - return *m_ptr; - } - - T* operator->() const - { - ASSERT(m_ptr); - return m_ptr; - } - - bool operator!() const { return !m_ptr; } - - // This conversion operator allows implicit conversion to bool but not to other integer types. - typedef T* GOwnPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &GOwnPtr::m_ptr : 0; } - - void swap(GOwnPtr& o) { std::swap(m_ptr, o.m_ptr); } - -private: - T* m_ptr; -}; - -template <typename T> inline void swap(GOwnPtr<T>& a, GOwnPtr<T>& b) -{ - a.swap(b); -} - -template <typename T, typename U> inline bool operator==(const GOwnPtr<T>& a, U* b) -{ - return a.get() == b; -} - -template <typename T, typename U> inline bool operator==(T* a, const GOwnPtr<U>& b) -{ - return a == b.get(); -} - -template <typename T, typename U> inline bool operator!=(const GOwnPtr<T>& a, U* b) -{ - return a.get() != b; -} - -template <typename T, typename U> inline bool operator!=(T* a, const GOwnPtr<U>& b) -{ - return a != b.get(); -} - -template <typename T> inline typename GOwnPtr<T>::PtrType getPtr(const GOwnPtr<T>& p) -{ - return p.get(); -} - -template <typename T> inline void freeOwnedGPtr(T* ptr) -{ - g_free(ptr); -} - -} // namespace WTF - -using WTF::GOwnPtr; - -#endif // ENABLE(GLIB_SUPPORT) - -#endif // GOwnPtr_h - diff --git a/Source/JavaScriptCore/wtf/gobject/GRefPtr.cpp b/Source/JavaScriptCore/wtf/gobject/GRefPtr.cpp deleted file mode 100644 index 30df2c9a6..000000000 --- a/Source/JavaScriptCore/wtf/gobject/GRefPtr.cpp +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2009 Martin Robinson - * - * 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 "GRefPtr.h" - -#if ENABLE(GLIB_SUPPORT) - -#include <glib.h> - -namespace WTF { - -template <> GHashTable* refGPtr(GHashTable* ptr) -{ - if (ptr) - g_hash_table_ref(ptr); - return ptr; -} - -template <> void derefGPtr(GHashTable* ptr) -{ - g_hash_table_unref(ptr); -} - -template <> GMainContext* refGPtr(GMainContext* ptr) -{ - if (ptr) - g_main_context_ref(ptr); - return ptr; -} - -template <> void derefGPtr(GMainContext* ptr) -{ - if (ptr) - g_main_context_unref(ptr); -} - -template <> GMainLoop* refGPtr(GMainLoop* ptr) -{ - if (ptr) - g_main_loop_ref(ptr); - return ptr; -} - -template <> void derefGPtr(GMainLoop* ptr) -{ - if (ptr) - g_main_loop_unref(ptr); -} - -#if GLIB_CHECK_VERSION(2, 24, 0) -template <> GVariant* refGPtr(GVariant* ptr) -{ - if (ptr) - g_variant_ref(ptr); - return ptr; -} - -template <> void derefGPtr(GVariant* ptr) -{ - g_variant_unref(ptr); -} - -#else - -// We do this so that we can avoid including the glib.h header in GRefPtr.h. -typedef struct _GVariant { - bool fake; -} GVariant; - -template <> GVariant* refGPtr(GVariant* ptr) -{ - return ptr; -} - -template <> void derefGPtr(GVariant* ptr) -{ -} - -#endif - -template <> GSource* refGPtr(GSource* ptr) -{ - if (ptr) - g_source_ref(ptr); - return ptr; -} - -template <> void derefGPtr(GSource* ptr) -{ - if (ptr) - g_source_unref(ptr); -} - -} // namespace WTF - -#endif // ENABLE(GLIB_SUPPORT) diff --git a/Source/JavaScriptCore/wtf/gobject/GRefPtr.h b/Source/JavaScriptCore/wtf/gobject/GRefPtr.h deleted file mode 100644 index 92acffc0c..000000000 --- a/Source/JavaScriptCore/wtf/gobject/GRefPtr.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2008 Collabora Ltd. - * Copyright (C) 2009 Martin Robinson - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_GRefPtr_h -#define WTF_GRefPtr_h - -#if ENABLE(GLIB_SUPPORT) - -#include <wtf/AlwaysInline.h> -#include <wtf/RefPtr.h> -#include <algorithm> - -extern "C" void g_object_unref(gpointer); -extern "C" gpointer g_object_ref_sink(gpointer); - -namespace WTF { - -enum GRefPtrAdoptType { GRefPtrAdopt }; -template <typename T> inline T* refGPtr(T*); -template <typename T> inline void derefGPtr(T*); -template <typename T> class GRefPtr; -template <typename T> GRefPtr<T> adoptGRef(T*); - -template <typename T> class GRefPtr { -public: - GRefPtr() : m_ptr(0) { } - - GRefPtr(T* ptr) - : m_ptr(ptr) - { - if (ptr) - refGPtr(ptr); - } - - GRefPtr(const GRefPtr& o) - : m_ptr(o.m_ptr) - { - if (T* ptr = m_ptr) - refGPtr(ptr); - } - - template <typename U> GRefPtr(const GRefPtr<U>& o) - : m_ptr(o.get()) - { - if (T* ptr = m_ptr) - refGPtr(ptr); - } - - ~GRefPtr() - { - if (T* ptr = m_ptr) - derefGPtr(ptr); - } - - void clear() - { - T* ptr = m_ptr; - m_ptr = 0; - if (ptr) - derefGPtr(ptr); - } - - T* leakRef() WARN_UNUSED_RETURN - { - T* ptr = m_ptr; - m_ptr = 0; - return ptr; - } - - // Hash table deleted values, which are only constructed and never copied or destroyed. - GRefPtr(HashTableDeletedValueType) : m_ptr(hashTableDeletedValue()) { } - bool isHashTableDeletedValue() const { return m_ptr == hashTableDeletedValue(); } - - T* get() const { return m_ptr; } - T& operator*() const { return *m_ptr; } - ALWAYS_INLINE T* operator->() const { 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* GRefPtr::*UnspecifiedBoolType; - operator UnspecifiedBoolType() const { return m_ptr ? &GRefPtr::m_ptr : 0; } - - GRefPtr& operator=(const GRefPtr&); - GRefPtr& operator=(T*); - template <typename U> GRefPtr& operator=(const GRefPtr<U>&); - - void swap(GRefPtr&); - friend GRefPtr adoptGRef<T>(T*); - -private: - static T* hashTableDeletedValue() { return reinterpret_cast<T*>(-1); } - // Adopting constructor. - GRefPtr(T* ptr, GRefPtrAdoptType) : m_ptr(ptr) {} - - T* m_ptr; -}; - -template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(const GRefPtr<T>& o) -{ - T* optr = o.get(); - if (optr) - refGPtr(optr); - T* ptr = m_ptr; - m_ptr = optr; - if (ptr) - derefGPtr(ptr); - return *this; -} - -template <typename T> inline GRefPtr<T>& GRefPtr<T>::operator=(T* optr) -{ - T* ptr = m_ptr; - if (optr) - refGPtr(optr); - m_ptr = optr; - if (ptr) - derefGPtr(ptr); - return *this; -} - -template <class T> inline void GRefPtr<T>::swap(GRefPtr<T>& o) -{ - std::swap(m_ptr, o.m_ptr); -} - -template <class T> inline void swap(GRefPtr<T>& a, GRefPtr<T>& b) -{ - a.swap(b); -} - -template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, const GRefPtr<U>& b) -{ - return a.get() == b.get(); -} - -template <typename T, typename U> inline bool operator==(const GRefPtr<T>& a, U* b) -{ - return a.get() == b; -} - -template <typename T, typename U> inline bool operator==(T* a, const GRefPtr<U>& b) -{ - return a == b.get(); -} - -template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, const GRefPtr<U>& b) -{ - return a.get() != b.get(); -} - -template <typename T, typename U> inline bool operator!=(const GRefPtr<T>& a, U* b) -{ - return a.get() != b; -} - -template <typename T, typename U> inline bool operator!=(T* a, const GRefPtr<U>& b) -{ - return a != b.get(); -} - -template <typename T, typename U> inline GRefPtr<T> static_pointer_cast(const GRefPtr<U>& p) -{ - return GRefPtr<T>(static_cast<T*>(p.get())); -} - -template <typename T, typename U> inline GRefPtr<T> const_pointer_cast(const GRefPtr<U>& p) -{ - return GRefPtr<T>(const_cast<T*>(p.get())); -} - -template <typename T> inline T* getPtr(const GRefPtr<T>& p) -{ - return p.get(); -} - -template <typename T> GRefPtr<T> adoptGRef(T* p) -{ - return GRefPtr<T>(p, GRefPtrAdopt); -} - -template <> GHashTable* refGPtr(GHashTable* ptr); -template <> void derefGPtr(GHashTable* ptr); -template <> GMainContext* refGPtr(GMainContext* ptr); -template <> void derefGPtr(GMainContext* ptr); -template <> GMainLoop* refGPtr(GMainLoop* ptr); -template <> void derefGPtr(GMainLoop* ptr); -template <> GVariant* refGPtr(GVariant* ptr); -template <> void derefGPtr(GVariant* ptr); -template <> GSource* refGPtr(GSource* ptr); -template <> void derefGPtr(GSource* ptr); - -template <typename T> inline T* refGPtr(T* ptr) -{ - if (ptr) - g_object_ref_sink(ptr); - return ptr; -} - -template <typename T> inline void derefGPtr(T* ptr) -{ - if (ptr) - g_object_unref(ptr); -} - -} // namespace WTF - -using WTF::GRefPtr; -using WTF::adoptGRef; - -#endif // ENABLE(GLIB_SUPPORT) - -#endif // WTF_GRefPtr_h diff --git a/Source/JavaScriptCore/wtf/gobject/GTypedefs.h b/Source/JavaScriptCore/wtf/gobject/GTypedefs.h deleted file mode 100644 index e29250bef..000000000 --- a/Source/JavaScriptCore/wtf/gobject/GTypedefs.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2010 Igalia, S.L. - * - * 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 GtkTypedefs_h -#define GtkTypedefs_h - -/* Vanilla C code does not seem to be able to handle forward-declaration typedefs. */ -#ifdef __cplusplus - -typedef char gchar; -typedef double gdouble; -typedef float gfloat; -typedef int gint; -typedef gint gboolean; -typedef long glong; -typedef short gshort; -typedef unsigned char guchar; -typedef unsigned int guint; -typedef unsigned long gulong; -typedef unsigned short gushort; -typedef void* gpointer; - -typedef struct _GAsyncResult GAsyncResult; -typedef struct _GCancellable GCancellable; -typedef struct _GCharsetConverter GCharsetConverter; -typedef struct _GDir GDir; -typedef struct _GdkAtom* GdkAtom; -typedef struct _GdkCursor GdkCursor; -typedef struct _GdkDragContext GdkDragContext; -typedef struct _GdkEventConfigure GdkEventConfigure; -typedef struct _GdkEventExpose GdkEventExpose; -typedef struct _GdkPixbuf GdkPixbuf; -typedef struct _GError GError; -typedef struct _GFile GFile; -typedef struct _GHashTable GHashTable; -typedef struct _GInputStream GInputStream; -typedef struct _GList GList; -typedef struct _GMainContext GMainContext; -typedef struct _GMainLoop GMainLoop; -typedef struct _GPatternSpec GPatternSpec; -typedef struct _GPollableOutputStream GPollableOutputStream; -typedef struct _GSList GSList; -typedef struct _GSocketClient GSocketClient; -typedef struct _GSocketConnection GSocketConnection; -typedef struct _GSource GSource; -typedef struct _GVariant GVariant; -typedef union _GdkEvent GdkEvent; -typedef struct _GTimer GTimer; -typedef struct _GKeyFile GKeyFile; - -#if USE(CAIRO) -typedef struct _cairo_surface cairo_surface_t; -typedef struct _cairo_rectangle_int cairo_rectangle_int_t; -#endif - -#if PLATFORM(GTK) -typedef struct _GtkAction GtkAction; -typedef struct _GtkAdjustment GtkAdjustment; -typedef struct _GtkBorder GtkBorder; -typedef struct _GtkClipboard GtkClipboard; -typedef struct _GtkContainer GtkContainer; -typedef struct _GtkIconInfo GtkIconInfo; -typedef struct _GtkMenu GtkMenu; -typedef struct _GtkMenuItem GtkMenuItem; -typedef struct _GtkObject GtkObject; -typedef struct _GtkSelectionData GtkSelectionData; -typedef struct _GtkStyle GtkStyle; -typedef struct _GtkTargetList GtkTargetList; -typedef struct _GtkThemeParts GtkThemeParts; -typedef struct _GtkWidget GtkWidget; -typedef struct _GtkWindow GtkWindow; - -#ifdef GTK_API_VERSION_2 -typedef struct _GdkRectangle GdkRectangle; -typedef struct _GdkDrawable GdkWindow; -#else -typedef struct _GdkWindow GdkWindow; -typedef struct _GtkStyleContext GtkStyleContext; -#endif - -#endif - -#endif -#endif /* GtkTypedefs_h */ diff --git a/Source/JavaScriptCore/wtf/gobject/GlibUtilities.cpp b/Source/JavaScriptCore/wtf/gobject/GlibUtilities.cpp deleted file mode 100644 index 1a2a8b1f1..000000000 --- a/Source/JavaScriptCore/wtf/gobject/GlibUtilities.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2010 Igalia, S.L. - * - * 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 "GlibUtilities.h" - -#if OS(WINDOWS) -#include <windows.h> -#include <wtf/text/WTFString.h> -#else -#include <limits.h> -#include <unistd.h> -#endif - -#if OS(LINUX) -CString getCurrentExecutablePath() -{ - static char readLinkBuffer[PATH_MAX]; - ssize_t result = readlink("/proc/self/exe", readLinkBuffer, PATH_MAX); - if (result == -1) - return CString(); - return CString(readLinkBuffer, result); -} -#elif OS(UNIX) -CString getCurrentExecutablePath() -{ - static char readLinkBuffer[PATH_MAX]; - ssize_t result = readlink("/proc/curproc/file", readLinkBuffer, PATH_MAX); - if (result == -1) - return CString(); - return CString(readLinkBuffer, result); -} -#elif OS(WINDOWS) -CString getCurrentExecutablePath() -{ - static WCHAR buffer[MAX_PATH]; - DWORD length = GetModuleFileNameW(0, buffer, MAX_PATH); - if (!length || (length == MAX_PATH && GetLastError() == ERROR_INSUFFICIENT_BUFFER)) - return CString(); - - String path(buffer, length); - return path.utf8(); -} -#endif diff --git a/Source/JavaScriptCore/wtf/gobject/GlibUtilities.h b/Source/JavaScriptCore/wtf/gobject/GlibUtilities.h deleted file mode 100644 index ce10a05c8..000000000 --- a/Source/JavaScriptCore/wtf/gobject/GlibUtilities.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (C) 2010 Igalia, S.L. - * - * 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 GlibUtilities_h -#define GlibUtilities_h - -#include <wtf/Assertions.h> -#include <wtf/text/CString.h> - -CString getCurrentExecutablePath(); - -#endif diff --git a/Source/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp b/Source/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp deleted file mode 100644 index 7624247b6..000000000 --- a/Source/JavaScriptCore/wtf/gtk/MainThreadGtk.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2007 Justin Haygood (jhaygood@reaktix.com) - * - * 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 <glib.h> - -namespace WTF { - -void initializeMainThreadPlatform() -{ -} - -static gboolean timeoutFired(gpointer) -{ - dispatchFunctionsFromMainThread(); - return FALSE; -} - -void scheduleDispatchFunctionsOnMainThread() -{ - g_timeout_add(0, timeoutFired, 0); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/mac/MainThreadMac.mm b/Source/JavaScriptCore/wtf/mac/MainThreadMac.mm deleted file mode 100644 index 5a82f40a6..000000000 --- a/Source/JavaScriptCore/wtf/mac/MainThreadMac.mm +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2007, 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 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. - */ - -#import "config.h" -#import "MainThread.h" - -#import <CoreFoundation/CoreFoundation.h> -#import <Foundation/NSThread.h> -#import <stdio.h> -#import <wtf/Assertions.h> -#import <wtf/HashSet.h> -#import <wtf/Threading.h> - -@interface JSWTFMainThreadCaller : NSObject { -} -- (void)call; -@end - -@implementation JSWTFMainThreadCaller - -- (void)call -{ - WTF::dispatchFunctionsFromMainThread(); -} - -@end // implementation JSWTFMainThreadCaller - -namespace WTF { - -static JSWTFMainThreadCaller* staticMainThreadCaller; -static bool isTimerPosted; // This is only accessed on the 'main' thread. -static bool mainThreadEstablishedAsPthreadMain; -static pthread_t mainThreadPthread; -static NSThread* mainThreadNSThread; - -void initializeMainThreadPlatform() -{ - ASSERT(!staticMainThreadCaller); - staticMainThreadCaller = [[JSWTFMainThreadCaller alloc] init]; - - mainThreadEstablishedAsPthreadMain = false; - mainThreadPthread = pthread_self(); - mainThreadNSThread = [[NSThread currentThread] retain]; - - initializeGCThreads(); -} - -void initializeMainThreadToProcessMainThreadPlatform() -{ - if (!pthread_main_np()) - NSLog(@"WebKit Threading Violation - initial use of WebKit from a secondary thread."); - - ASSERT(!staticMainThreadCaller); - staticMainThreadCaller = [[JSWTFMainThreadCaller alloc] init]; - - mainThreadEstablishedAsPthreadMain = true; - mainThreadPthread = 0; - mainThreadNSThread = nil; - - initializeGCThreads(); -} - -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 (mainThreadEstablishedAsPthreadMain) { - ASSERT(!mainThreadNSThread); - [staticMainThreadCaller performSelectorOnMainThread:@selector(call) withObject:nil waitUntilDone:NO]; - return; - } - - ASSERT(mainThreadNSThread); - [staticMainThreadCaller performSelector:@selector(call) onThread:mainThreadNSThread withObject:nil waitUntilDone:NO]; -} - -bool isMainThread() -{ - if (mainThreadEstablishedAsPthreadMain) { - ASSERT(!mainThreadPthread); - return pthread_main_np(); - } - - ASSERT(mainThreadPthread); - return pthread_equal(pthread_self(), mainThreadPthread); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/qt/MainThreadQt.cpp b/Source/JavaScriptCore/wtf/qt/MainThreadQt.cpp deleted file mode 100644 index 606a7190e..000000000 --- a/Source/JavaScriptCore/wtf/qt/MainThreadQt.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2007 Staikos Computing Services Inc. - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) - * 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 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" -#include "MainThread.h" - -#include <QCoreApplication> -#include <QEvent> -#include <QObject> -#include <QThread> - -namespace WTF { - -static int s_mainThreadInvokerEventType; - -class MainThreadInvoker : public QObject { - Q_OBJECT -public: - MainThreadInvoker(); - virtual bool event(QEvent*); -}; - -MainThreadInvoker::MainThreadInvoker() -{ - s_mainThreadInvokerEventType = QEvent::registerEventType(); -} - -bool MainThreadInvoker::event(QEvent* e) -{ - if (e->type() != s_mainThreadInvokerEventType) - return QObject::event(e); - - dispatchFunctionsFromMainThread(); - return true; -} - -Q_GLOBAL_STATIC(MainThreadInvoker, webkit_main_thread_invoker) - -void initializeMainThreadPlatform() -{ - webkit_main_thread_invoker(); -} - -void scheduleDispatchFunctionsOnMainThread() -{ - QCoreApplication::postEvent(webkit_main_thread_invoker(), new QEvent(static_cast<QEvent::Type>(s_mainThreadInvokerEventType))); -} - -} // namespace WTF - -#include "MainThreadQt.moc" diff --git a/Source/JavaScriptCore/wtf/qt/StringQt.cpp b/Source/JavaScriptCore/wtf/qt/StringQt.cpp deleted file mode 100644 index 16dd439e3..000000000 --- a/Source/JavaScriptCore/wtf/qt/StringQt.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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/StdLibExtras.h> -#include <wtf/text/WTFString.h> - -#include <QString> - -namespace WTF { - -// String conversions -String::String(const QString& qstr) -{ - if (qstr.isNull()) - return; - m_impl = StringImpl::create(reinterpret_cast_ptr<const UChar*>(qstr.constData()), qstr.length()); -} - -String::String(const QStringRef& ref) -{ - if (!ref.string()) - return; - m_impl = StringImpl::create(reinterpret_cast_ptr<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/Source/JavaScriptCore/wtf/qt/UtilsQt.h b/Source/JavaScriptCore/wtf/qt/UtilsQt.h deleted file mode 100644 index 74067a8ee..000000000 --- a/Source/JavaScriptCore/wtf/qt/UtilsQt.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - Copyright (C) 2011 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 WTF_UtilsQt_h -#define WTF_UtilsQt_h - -#include <QString> -#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) -#include <QTextDocument> -#endif - -inline QString escapeHtml(const QString& string) -{ -#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) - return string.toHtmlEscaped(); -#else - return Qt::escape(string); -#endif -} - -#endif // WTF_UtilsQt_h diff --git a/Source/JavaScriptCore/wtf/qt/compat/QGuiApplication b/Source/JavaScriptCore/wtf/qt/compat/QGuiApplication deleted file mode 100644 index 0337e2526..000000000 --- a/Source/JavaScriptCore/wtf/qt/compat/QGuiApplication +++ /dev/null @@ -1 +0,0 @@ -#include "qguiapplication.h" diff --git a/Source/JavaScriptCore/wtf/qt/compat/qguiapplication.h b/Source/JavaScriptCore/wtf/qt/compat/qguiapplication.h deleted file mode 100644 index 2a2fc23cb..000000000 --- a/Source/JavaScriptCore/wtf/qt/compat/qguiapplication.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - Copyright (C) 2011 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 qguiapplication_h -#define qguiapplication_h - -#include <QApplication> - -struct QGuiApplication : public QApplication -{ - // Style hints in Qt 5 contain stuff that just used to be in QApplication in Qt 4, hence - // this hack. - static QApplication* styleHints() - { - return qApp; - } -}; - -#endif diff --git a/Source/JavaScriptCore/wtf/text/ASCIIFastPath.h b/Source/JavaScriptCore/wtf/text/ASCIIFastPath.h deleted file mode 100644 index ace1a687d..000000000 --- a/Source/JavaScriptCore/wtf/text/ASCIIFastPath.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2011 Apple Inc. All rights reserved. - * Copyright (C) 2011 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 ASCIIFastPath_h -#define ASCIIFastPath_h - -#include <stdint.h> -#include <wtf/unicode/Unicode.h> - -namespace WTF { - -// Assuming that a pointer is the size of a "machine word", then -// uintptr_t is an integer type that is also a machine word. -typedef uintptr_t MachineWord; -const uintptr_t machineWordAlignmentMask = sizeof(MachineWord) - 1; - -inline bool isAlignedToMachineWord(const void* pointer) -{ - return !(reinterpret_cast<uintptr_t>(pointer) & machineWordAlignmentMask); -} - -template<typename T> inline T* alignToMachineWord(T* pointer) -{ - return reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(pointer) & ~machineWordAlignmentMask); -} - -template<size_t size, typename CharacterType> struct NonASCIIMask; -template<> struct NonASCIIMask<4, UChar> { - static inline uint32_t value() { return 0xFF80FF80U; } -}; -template<> struct NonASCIIMask<4, LChar> { - static inline uint32_t value() { return 0x80808080U; } -}; -template<> struct NonASCIIMask<8, UChar> { - static inline uint64_t value() { return 0xFF80FF80FF80FF80ULL; } -}; -template<> struct NonASCIIMask<8, LChar> { - static inline uint64_t value() { return 0x8080808080808080ULL; } -}; - - -template<typename CharacterType> -inline bool isAllASCII(MachineWord word) -{ - return !(word & NonASCIIMask<sizeof(MachineWord), CharacterType>::value()); -} - -// Note: This function assume the input is likely all ASCII, and -// does not leave early if it is not the case. -template<typename CharacterType> -inline bool charactersAreAllASCII(const CharacterType* characters, size_t length) -{ - MachineWord allCharBits = 0; - const CharacterType* end = characters + length; - - // Prologue: align the input. - while (!isAlignedToMachineWord(characters) && characters != end) { - allCharBits |= *characters; - ++characters; - } - - // Compare the values of CPU word size. - const CharacterType* wordEnd = alignToMachineWord(end); - const size_t loopIncrement = sizeof(MachineWord) / sizeof(CharacterType); - while (characters < wordEnd) { - allCharBits |= *(reinterpret_cast<const MachineWord*>(characters)); - characters += loopIncrement; - } - - // Process the remaining bytes. - while (characters != end) { - allCharBits |= *characters; - ++characters; - } - - MachineWord nonASCIIBitMask = NonASCIIMask<sizeof(MachineWord), CharacterType>::value(); - return !(allCharBits & nonASCIIBitMask); -} - - -} // namespace WTF - -#endif // ASCIIFastPath_h diff --git a/Source/JavaScriptCore/wtf/text/AtomicString.cpp b/Source/JavaScriptCore/wtf/text/AtomicString.cpp deleted file mode 100644 index d775e7bb9..000000000 --- a/Source/JavaScriptCore/wtf/text/AtomicString.cpp +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> - * Copyright (C) 2012 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. - * - */ - -#include "config.h" - -#include "AtomicString.h" - -#include "StringHash.h" -#include <wtf/HashSet.h> -#include <wtf/Threading.h> -#include <wtf/WTFThreadData.h> -#include <wtf/unicode/UTF8.h> - -namespace WTF { - -using namespace Unicode; - -COMPILE_ASSERT(sizeof(AtomicString) == sizeof(String), atomic_string_and_string_must_be_same_size); - -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) - { - HashSet<StringImpl*>::iterator end = table->m_table.end(); - for (HashSet<StringImpl*>::iterator iter = table->m_table.begin(); iter != end; ++iter) - (*iter)->setIsAtomic(false); - 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(); -} - -template<typename T, typename HashTranslator> -static inline PassRefPtr<StringImpl> addToStringTable(const T& value) -{ - pair<HashSet<StringImpl*>::iterator, bool> addResult = stringTable().add<T, HashTranslator>(value); - - // 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; -} - -struct CStringTranslator { - static unsigned hash(const LChar* c) - { - return StringHasher::computeHash(c); - } - - static inline bool equal(StringImpl* r, const LChar* s) - { - return WTF::equal(r, s); - } - - static void translate(StringImpl*& location, const LChar* const& c, unsigned hash) - { - location = StringImpl::create(c).leakRef(); - location->setHash(hash); - location->setIsAtomic(true); - } -}; - -PassRefPtr<StringImpl> AtomicString::add(const LChar* c) -{ - if (!c) - return 0; - if (!*c) - return StringImpl::empty(); - - return addToStringTable<const LChar*, CStringTranslator>(c); -} - -struct UCharBuffer { - const UChar* s; - unsigned length; -}; - -struct UCharBufferTranslator { - static unsigned hash(const UCharBuffer& buf) - { - return StringHasher::computeHash(buf.s, buf.length); - } - - static bool equal(StringImpl* const& str, const UCharBuffer& buf) - { - return WTF::equal(str, buf.s, buf.length); - } - - static void translate(StringImpl*& location, const UCharBuffer& buf, unsigned hash) - { - location = StringImpl::create(buf.s, buf.length).leakRef(); - location->setHash(hash); - location->setIsAtomic(true); - } -}; - -struct HashAndCharacters { - unsigned hash; - const UChar* characters; - unsigned length; -}; - -struct HashAndCharactersTranslator { - static unsigned hash(const HashAndCharacters& buffer) - { - ASSERT(buffer.hash == StringHasher::computeHash(buffer.characters, buffer.length)); - return buffer.hash; - } - - static bool equal(StringImpl* const& string, const HashAndCharacters& buffer) - { - return WTF::equal(string, buffer.characters, buffer.length); - } - - static void translate(StringImpl*& location, const HashAndCharacters& buffer, unsigned hash) - { - location = StringImpl::create(buffer.characters, buffer.length).leakRef(); - location->setHash(hash); - location->setIsAtomic(true); - } -}; - -struct HashAndUTF8Characters { - unsigned hash; - const char* characters; - unsigned length; - unsigned utf16Length; -}; - -struct HashAndUTF8CharactersTranslator { - static unsigned hash(const HashAndUTF8Characters& buffer) - { - return buffer.hash; - } - - static bool equal(StringImpl* const& string, const HashAndUTF8Characters& buffer) - { - if (buffer.utf16Length != string->length()) - return false; - - const UChar* stringCharacters = string->characters(); - - // If buffer contains only ASCII characters UTF-8 and UTF16 length are the same. - if (buffer.utf16Length != buffer.length) - return equalUTF16WithUTF8(stringCharacters, stringCharacters + string->length(), buffer.characters, buffer.characters + buffer.length); - - for (unsigned i = 0; i < buffer.length; ++i) { - ASSERT(isASCII(buffer.characters[i])); - if (stringCharacters[i] != buffer.characters[i]) - return false; - } - - return true; - } - - static void translate(StringImpl*& location, const HashAndUTF8Characters& buffer, unsigned hash) - { - UChar* target; - location = StringImpl::createUninitialized(buffer.utf16Length, target).leakRef(); - - const char* source = buffer.characters; - if (convertUTF8ToUTF16(&source, source + buffer.length, &target, target + buffer.utf16Length) != conversionOK) - ASSERT_NOT_REACHED(); - - location->setHash(hash); - location->setIsAtomic(true); - } -}; - -PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length) -{ - if (!s) - return 0; - - if (!length) - return StringImpl::empty(); - - UCharBuffer buffer = { s, length }; - return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer); -} - -PassRefPtr<StringImpl> AtomicString::add(const UChar* s, unsigned length, unsigned existingHash) -{ - ASSERT(s); - ASSERT(existingHash); - - if (!length) - return StringImpl::empty(); - - HashAndCharacters buffer = { existingHash, s, length }; - return addToStringTable<HashAndCharacters, HashAndCharactersTranslator>(buffer); -} - -PassRefPtr<StringImpl> AtomicString::add(const UChar* s) -{ - if (!s) - return 0; - - int length = 0; - while (s[length] != UChar(0)) - length++; - - if (!length) - return StringImpl::empty(); - - UCharBuffer buffer = { s, length }; - return addToStringTable<UCharBuffer, UCharBufferTranslator>(buffer); -} - -struct SubstringLocation { - StringImpl* baseString; - unsigned start; - unsigned length; -}; - -struct SubstringTranslator { - static unsigned hash(const SubstringLocation& buffer) - { - return StringHasher::computeHash(buffer.baseString->characters() + buffer.start, buffer.length); - } - - static bool equal(StringImpl* const& string, const SubstringLocation& buffer) - { - return WTF::equal(string, buffer.baseString->characters() + buffer.start, buffer.length); - } - - static void translate(StringImpl*& location, const SubstringLocation& buffer, unsigned hash) - { - location = StringImpl::create(buffer.baseString, buffer.start, buffer.length).leakRef(); - location->setHash(hash); - location->setIsAtomic(true); - } -}; - -PassRefPtr<StringImpl> AtomicString::add(StringImpl* baseString, unsigned start, unsigned length) -{ - if (!baseString) - return 0; - - if (!length || start >= baseString->length()) - return StringImpl::empty(); - - unsigned maxLength = baseString->length() - start; - if (length >= maxLength) { - if (!start) - return add(baseString); - length = maxLength; - } - - SubstringLocation buffer = { baseString, start, length }; - return addToStringTable<SubstringLocation, SubstringTranslator>(buffer); -} - -PassRefPtr<StringImpl> AtomicString::addSlowCase(StringImpl* r) -{ - if (!r->length()) - return StringImpl::empty(); - - StringImpl* result = *stringTable().add(r).first; - if (result == r) - r->setIsAtomic(true); - return result; -} - -AtomicStringImpl* AtomicString::find(const UChar* s, unsigned length, unsigned existingHash) -{ - ASSERT(s); - ASSERT(existingHash); - - if (!length) - 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(); - if (UNLIKELY(!impl)) - return *this; - RefPtr<StringImpl> newImpl = impl->lower(); - if (LIKELY(newImpl == impl)) - return *this; - return AtomicString(newImpl); -} - -AtomicString AtomicString::fromUTF8Internal(const char* charactersStart, const char* charactersEnd) -{ - HashAndUTF8Characters buffer; - buffer.characters = charactersStart; - buffer.hash = calculateStringHashAndLengthFromUTF8(charactersStart, charactersEnd, buffer.length, buffer.utf16Length); - - if (!buffer.hash) - return nullAtom; - - AtomicString atomicString; - atomicString.m_string = addToStringTable<HashAndUTF8Characters, HashAndUTF8CharactersTranslator>(buffer); - return atomicString; -} - -#ifndef NDEBUG -void AtomicString::show() const -{ - m_string.show(); -} -#endif - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/text/AtomicString.h b/Source/JavaScriptCore/wtf/text/AtomicString.h deleted file mode 100644 index e7323f94a..000000000 --- a/Source/JavaScriptCore/wtf/text/AtomicString.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * 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 <wtf/text/AtomicStringImpl.h> -#include <wtf/text/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 - -namespace WTF { - -struct AtomicStringHash; - -class AtomicString { -public: - WTF_EXPORT_PRIVATE static void init(); - - AtomicString() { } - AtomicString(const LChar* s) : m_string(add(s)) { } - 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())) { } - AtomicString(StringImpl* baseString, unsigned start, unsigned length) : m_string(add(baseString, start, length)) { } - - // 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(); } - - WTF_EXPORT_PRIVATE 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 LChar* 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); } - - size_t find(UChar c, size_t start = 0) const { return m_string.find(c, start); } - size_t find(const LChar* s, size_t start = 0, bool caseSentitive = true) const - { return m_string.find(s, start, caseSentitive); } - size_t find(const String& s, size_t 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); } - - WTF_EXPORT_PRIVATE 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 USE(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 - - // AtomicString::fromUTF8 will return a null string if - // the input data contains invalid UTF-8 sequences. - static AtomicString fromUTF8(const char*, size_t); - static AtomicString fromUTF8(const char*); - -#ifndef NDEBUG - void show() const; -#endif -private: - String m_string; - - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const LChar*); - ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s) { return add(reinterpret_cast<const LChar*>(s)); }; - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const UChar*, unsigned length); - ALWAYS_INLINE static PassRefPtr<StringImpl> add(const char* s, unsigned length) { return add(reinterpret_cast<const char*>(s), length); }; - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const UChar*, unsigned length, unsigned existingHash); - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(const UChar*); - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> add(StringImpl*, unsigned offset, unsigned length); - ALWAYS_INLINE static PassRefPtr<StringImpl> add(StringImpl* r) - { - if (!r || r->isAtomic()) - return r; - return addSlowCase(r); - } - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> addSlowCase(StringImpl*); - WTF_EXPORT_PRIVATE static AtomicString fromUTF8Internal(const char*, const char*); -}; - -inline bool operator==(const AtomicString& a, const AtomicString& b) { return a.impl() == b.impl(); } -bool operator==(const AtomicString&, const LChar*); -inline bool operator==(const AtomicString& a, const char* b) { return WTF::equal(a.impl(), reinterpret_cast<const LChar*>(b)); } -inline bool operator==(const AtomicString& a, const Vector<UChar>& b) { return a.impl() && equal(a.impl(), b.data(), b.size()); } -inline bool operator==(const AtomicString& a, const String& b) { return equal(a.impl(), b.impl()); } -inline bool operator==(const LChar* 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 Vector<UChar>& a, const AtomicString& b) { return b == a; } - -inline bool operator!=(const AtomicString& a, const AtomicString& b) { return a.impl() != b.impl(); } -inline bool operator!=(const AtomicString& a, const LChar* b) { return !(a == b); } -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 AtomicString& a, const Vector<UChar>& b) { return !(a == b); } -inline bool operator!=(const LChar* 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 Vector<UChar>& a, const AtomicString& b) { return !(a == b); } - -inline bool equalIgnoringCase(const AtomicString& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); } -inline bool equalIgnoringCase(const AtomicString& a, const LChar* b) { return equalIgnoringCase(a.impl(), b); } -inline bool equalIgnoringCase(const AtomicString& a, const char* b) { return equalIgnoringCase(a.impl(), reinterpret_cast<const LChar*>(b)); } -inline bool equalIgnoringCase(const AtomicString& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); } -inline bool equalIgnoringCase(const LChar* a, const AtomicString& b) { return equalIgnoringCase(a, b.impl()); } -inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(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 WTF_EXPORTDATA AtomicString nullAtom; -extern const WTF_EXPORTDATA AtomicString emptyAtom; -extern const WTF_EXPORTDATA AtomicString textAtom; -extern const WTF_EXPORTDATA AtomicString commentAtom; -extern const WTF_EXPORTDATA AtomicString starAtom; -extern const WTF_EXPORTDATA AtomicString xmlAtom; -extern const WTF_EXPORTDATA AtomicString xmlnsAtom; - -inline AtomicString AtomicString::fromUTF8(const char* characters, size_t length) -{ - if (!characters) - return nullAtom; - if (!length) - return emptyAtom; - return fromUTF8Internal(characters, characters + length); -} - -inline AtomicString AtomicString::fromUTF8(const char* characters) -{ - if (!characters) - return nullAtom; - if (!*characters) - return emptyAtom; - return fromUTF8Internal(characters, 0); -} -#endif - -// AtomicStringHash is the default hash for AtomicString -template<typename T> struct DefaultHash; -template<> struct DefaultHash<AtomicString> { - typedef AtomicStringHash Hash; -}; - -} // namespace WTF - -#ifndef ATOMICSTRING_HIDE_GLOBALS -using WTF::AtomicString; -using WTF::nullAtom; -using WTF::emptyAtom; -using WTF::textAtom; -using WTF::commentAtom; -using WTF::starAtom; -using WTF::xmlAtom; -using WTF::xmlnsAtom; -#endif - -#include <wtf/text/StringConcatenate.h> -#endif // AtomicString_h diff --git a/Source/JavaScriptCore/wtf/text/AtomicStringHash.h b/Source/JavaScriptCore/wtf/text/AtomicStringHash.h deleted file mode 100644 index 6130d9493..000000000 --- a/Source/JavaScriptCore/wtf/text/AtomicStringHash.h +++ /dev/null @@ -1,62 +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. - * 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 AtomicStringHash_h -#define AtomicStringHash_h - -#include <wtf/text/AtomicString.h> -#include <wtf/HashTraits.h> - -namespace WTF { - - struct AtomicStringHash { - static unsigned hash(const AtomicString& key) - { - return key.impl()->existingHash(); - } - - static bool equal(const AtomicString& a, const AtomicString& b) - { - return a == b; - } - - static const bool safeToCompareToEmptyOrDeleted = false; - }; - - // AtomicStringHash is the default hash for AtomicString - template<> struct HashTraits<WTF::AtomicString> : GenericHashTraits<WTF::AtomicString> { - static const bool emptyValueIsZero = true; - static void constructDeletedValue(WTF::AtomicString& slot) { new (NotNull, &slot) WTF::AtomicString(HashTableDeletedValue); } - static bool isDeletedValue(const WTF::AtomicString& slot) { return slot.isHashTableDeletedValue(); } - }; - -} - -using WTF::AtomicStringHash; - -#endif diff --git a/Source/JavaScriptCore/wtf/text/AtomicStringImpl.h b/Source/JavaScriptCore/wtf/text/AtomicStringImpl.h deleted file mode 100644 index 0716275a8..000000000 --- a/Source/JavaScriptCore/wtf/text/AtomicStringImpl.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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 <wtf/text/StringImpl.h> - -namespace WTF { - -class AtomicStringImpl : public StringImpl -{ -public: - AtomicStringImpl() : StringImpl(0) {} -}; - -} - -using WTF::AtomicStringImpl; - -#endif diff --git a/Source/JavaScriptCore/wtf/text/CString.cpp b/Source/JavaScriptCore/wtf/text/CString.cpp deleted file mode 100644 index 981d77a1d..000000000 --- a/Source/JavaScriptCore/wtf/text/CString.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * 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. - */ - - -#include "config.h" -#include "CString.h" - -using namespace std; - -namespace WTF { - -CString::CString(const char* str) -{ - if (!str) - return; - - init(str, strlen(str)); -} - -CString::CString(const char* str, size_t length) -{ - init(str, length); -} - -void CString::init(const char* str, size_t length) -{ - if (!str) - return; - - // We need to be sure we can add 1 to length without overflowing. - // Since the passed-in length is the length of an actual existing - // string, and we know the string doesn't occupy the entire address - // space, we can assert here and there's no need for a runtime check. - ASSERT(length < numeric_limits<size_t>::max()); - - m_buffer = CStringBuffer::create(length + 1); - memcpy(m_buffer->mutableData(), str, length); - m_buffer->mutableData()[length] = '\0'; -} - -char* CString::mutableData() -{ - copyBufferIfNeeded(); - if (!m_buffer) - return 0; - return m_buffer->mutableData(); -} - -CString CString::newUninitialized(size_t length, char*& characterBuffer) -{ - if (length >= numeric_limits<size_t>::max()) - CRASH(); - - 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; - - RefPtr<CStringBuffer> buffer = m_buffer.release(); - size_t length = buffer->length(); - m_buffer = CStringBuffer::create(length); - memcpy(m_buffer->mutableData(), buffer->data(), length); -} - -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/Source/JavaScriptCore/wtf/text/CString.h b/Source/JavaScriptCore/wtf/text/CString.h deleted file mode 100644 index 9abfa70f7..000000000 --- a/Source/JavaScriptCore/wtf/text/CString.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 <wtf/PassRefPtr.h> -#include <wtf/RefCounted.h> -#include <wtf/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(size_t length) { return adoptRef(new CStringBuffer(length)); } - CStringBuffer(size_t 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() { } - WTF_EXPORT_PRIVATE CString(const char*); - WTF_EXPORT_PRIVATE CString(const char*, size_t length); - CString(CStringBuffer* buffer) : m_buffer(buffer) { } - WTF_EXPORT_PRIVATE static CString newUninitialized(size_t length, char*& characterBuffer); - - const char* data() const - { - return m_buffer ? m_buffer->data() : 0; - } - WTF_EXPORT_PRIVATE char* mutableData(); - size_t length() const - { - return m_buffer ? m_buffer->length() - 1 : 0; - } - - bool isNull() const { return !m_buffer; } - - CStringBuffer* buffer() const { return m_buffer.get(); } - -private: - void copyBufferIfNeeded(); - void init(const char*, size_t length); - RefPtr<CStringBuffer> m_buffer; -}; - -WTF_EXPORT_PRIVATE 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/Source/JavaScriptCore/wtf/text/StringBuffer.h b/Source/JavaScriptCore/wtf/text/StringBuffer.h deleted file mode 100644 index 739260d27..000000000 --- a/Source/JavaScriptCore/wtf/text/StringBuffer.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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 - * 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/unicode/Unicode.h> -#include <limits> - -namespace WTF { - -template <typename CharType> -class StringBuffer { - WTF_MAKE_NONCOPYABLE(StringBuffer); -public: - explicit StringBuffer(unsigned length) - : m_length(length) - { - if (m_length > std::numeric_limits<unsigned>::max() / sizeof(CharType)) - CRASH(); - m_data = static_cast<CharType*>(fastMalloc(m_length * sizeof(CharType))); - } - - ~StringBuffer() - { - fastFree(m_data); - } - - void shrink(unsigned newLength) - { - ASSERT(newLength <= m_length); - m_length = newLength; - } - - void resize(unsigned newLength) - { - if (newLength > m_length) { - if (newLength > std::numeric_limits<unsigned>::max() / sizeof(UChar)) - CRASH(); - m_data = static_cast<UChar*>(fastRealloc(m_data, newLength * sizeof(UChar))); - } - m_length = newLength; - } - - unsigned length() const { return m_length; } - CharType* characters() { return m_data; } - - UChar& operator[](unsigned i) { ASSERT(i < m_length); return m_data[i]; } - - CharType* release() { CharType* data = m_data; m_data = 0; return data; } - -private: - unsigned m_length; - CharType* m_data; -}; - -} // namespace WTF - -using WTF::StringBuffer; - -#endif // StringBuffer_h diff --git a/Source/JavaScriptCore/wtf/text/StringBuilder.cpp b/Source/JavaScriptCore/wtf/text/StringBuilder.cpp deleted file mode 100644 index 4eac75649..000000000 --- a/Source/JavaScriptCore/wtf/text/StringBuilder.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 2010 Apple Inc. All rights reserved. - * Copyright (C) 2012 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 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 "StringBuilder.h" - -#include "WTFString.h" - -namespace WTF { - -static const unsigned minimumCapacity = 16; - -void StringBuilder::reifyString() const -{ - // Check if the string already exists. - if (!m_string.isNull()) { - ASSERT(m_string.length() == m_length); - return; - } - - // Check for empty. - if (!m_length) { - m_string = StringImpl::empty(); - return; - } - - // Must be valid in the buffer, take a substring (unless string fills the buffer). - ASSERT(m_buffer && m_length <= m_buffer->length()); - m_string = (m_length == m_buffer->length()) - ? m_buffer.get() - : StringImpl::create(m_buffer, 0, m_length); - - if (m_buffer->has16BitShadow() && m_valid16BitShadowLength < m_length) - m_buffer->upconvertCharacters(m_valid16BitShadowLength, m_length); - - m_valid16BitShadowLength = m_length; -} - -void StringBuilder::resize(unsigned newSize) -{ - // Check newSize < m_length, hence m_length > 0. - ASSERT(newSize <= m_length); - if (newSize == m_length) - return; - ASSERT(m_length); - - // If there is a buffer, we only need to duplicate it if it has more than one ref. - if (m_buffer) { - m_string = String(); // Clear the string to remove the reference to m_buffer if any before checking the reference count of m_buffer. - if (!m_buffer->hasOneRef()) { - if (m_buffer->is8Bit()) - allocateBuffer(m_buffer->characters8(), m_buffer->length()); - else - allocateBuffer(m_buffer->characters16(), m_buffer->length()); - } - m_length = newSize; - return; - } - - // Since m_length && !m_buffer, the string must be valid in m_string, and m_string.length() > 0. - ASSERT(!m_string.isEmpty()); - ASSERT(m_length == m_string.length()); - ASSERT(newSize < m_string.length()); - m_length = newSize; - m_string = StringImpl::create(m_string.impl(), 0, newSize); -} - -// Allocate a new 8 bit buffer, copying in currentCharacters (these may come from either m_string -// or m_buffer, neither will be reassigned until the copy has completed). -void StringBuilder::allocateBuffer(const LChar* currentCharacters, unsigned requiredLength) -{ - ASSERT(m_is8Bit); - // Copy the existing data into a new buffer, set result to point to the end of the existing data. - RefPtr<StringImpl> buffer = StringImpl::createUninitialized(requiredLength, m_bufferCharacters8); - memcpy(m_bufferCharacters8, currentCharacters, static_cast<size_t>(m_length) * sizeof(LChar)); // This can't overflow. - - // Update the builder state. - m_buffer = buffer.release(); - m_string = String(); -} - -// Allocate a new 16 bit buffer, copying in currentCharacters (these may come from either m_string -// or m_buffer, neither will be reassigned until the copy has completed). -void StringBuilder::allocateBuffer(const UChar* currentCharacters, unsigned requiredLength) -{ - ASSERT(!m_is8Bit); - // Copy the existing data into a new buffer, set result to point to the end of the existing data. - RefPtr<StringImpl> buffer = StringImpl::createUninitialized(requiredLength, m_bufferCharacters16); - memcpy(m_bufferCharacters16, currentCharacters, static_cast<size_t>(m_length) * sizeof(UChar)); // This can't overflow. - - // Update the builder state. - m_buffer = buffer.release(); - m_string = String(); -} - -// Allocate a new 16 bit buffer, copying in currentCharacters (which is 8 bit and may come -// from either m_string or m_buffer, neither will be reassigned until the copy has completed). -void StringBuilder::allocateBufferUpConvert(const LChar* currentCharacters, unsigned requiredLength) -{ - ASSERT(m_is8Bit); - // Copy the existing data into a new buffer, set result to point to the end of the existing data. - RefPtr<StringImpl> buffer = StringImpl::createUninitialized(requiredLength, m_bufferCharacters16); - for (unsigned i = 0; i < m_length; i++) - m_bufferCharacters16[i] = currentCharacters[i]; - - m_is8Bit = false; - - // Update the builder state. - m_buffer = buffer.release(); - m_string = String(); -} - -template <> -void StringBuilder::reallocateBuffer<LChar>(unsigned requiredLength) -{ - // If the buffer has only one ref (by this StringBuilder), reallocate it, - // otherwise fall back to "allocate and copy" method. - m_string = String(); - - ASSERT(m_is8Bit); - ASSERT(m_buffer->is8Bit()); - - if (m_buffer->hasOneRef()) - m_buffer = StringImpl::reallocate(m_buffer.release(), requiredLength, m_bufferCharacters8); - else - allocateBuffer(m_buffer->characters8(), requiredLength); -} - -template <> -void StringBuilder::reallocateBuffer<UChar>(unsigned requiredLength) -{ - // If the buffer has only one ref (by this StringBuilder), reallocate it, - // otherwise fall back to "allocate and copy" method. - m_string = String(); - - if (m_buffer->is8Bit()) - allocateBufferUpConvert(m_buffer->characters8(), requiredLength); - else if (m_buffer->hasOneRef()) - m_buffer = StringImpl::reallocate(m_buffer.release(), requiredLength, m_bufferCharacters16); - else - allocateBuffer(m_buffer->characters16(), requiredLength); -} - -void StringBuilder::reserveCapacity(unsigned newCapacity) -{ - if (m_buffer) { - // If there is already a buffer, then grow if necessary. - if (newCapacity > m_buffer->length()) { - if (m_buffer->is8Bit()) - reallocateBuffer<LChar>(newCapacity); - else - reallocateBuffer<UChar>(newCapacity); - } - } else { - // Grow the string, if necessary. - if (newCapacity > m_length) { - if (!m_length) { - LChar* nullPlaceholder = 0; - allocateBuffer(nullPlaceholder, newCapacity); - } else if (m_string.is8Bit()) - allocateBuffer(m_string.characters8(), newCapacity); - else - allocateBuffer(m_string.characters16(), newCapacity); - } - } -} - -// Make 'length' additional capacity be available in m_buffer, update m_string & m_length, -// return a pointer to the newly allocated storage. -template <typename CharType> -ALWAYS_INLINE CharType* StringBuilder::appendUninitialized(unsigned length) -{ - ASSERT(length); - - // Calculate the new size of the builder after appending. - unsigned requiredLength = length + m_length; - if (requiredLength < length) - CRASH(); - - if ((m_buffer) && (requiredLength <= m_buffer->length())) { - // If the buffer is valid it must be at least as long as the current builder contents! - ASSERT(m_buffer->length() >= m_length); - unsigned currentLength = m_length; - m_string = String(); - m_length = requiredLength; - return getBufferCharacters<CharType>() + currentLength; - } - - return appendUninitializedSlow<CharType>(requiredLength); -} - -// Make 'length' additional capacity be available in m_buffer, update m_string & m_length, -// return a pointer to the newly allocated storage. -template <typename CharType> -CharType* StringBuilder::appendUninitializedSlow(unsigned requiredLength) -{ - ASSERT(requiredLength); - - if (m_buffer) { - // If the buffer is valid it must be at least as long as the current builder contents! - ASSERT(m_buffer->length() >= m_length); - - reallocateBuffer<CharType>(std::max(requiredLength, std::max(minimumCapacity, m_buffer->length() * 2))); - } else { - ASSERT(m_string.length() == m_length); - allocateBuffer(m_length ? m_string.getCharacters<CharType>() : 0, std::max(requiredLength, std::max(minimumCapacity, m_length * 2))); - } - - CharType* result = getBufferCharacters<CharType>() + m_length; - m_length = requiredLength; - return result; -} - -void StringBuilder::append(const UChar* characters, unsigned length) -{ - if (!length) - return; - - ASSERT(characters); - - if (m_is8Bit) { - // Calculate the new size of the builder after appending. - unsigned requiredLength = length + m_length; - if (requiredLength < length) - CRASH(); - - if (m_buffer) { - // If the buffer is valid it must be at least as long as the current builder contents! - ASSERT(m_buffer->length() >= m_length); - - allocateBufferUpConvert(m_buffer->characters8(), requiredLength); - } else { - ASSERT(m_string.length() == m_length); - allocateBufferUpConvert(m_string.isNull() ? 0 : m_string.characters8(), std::max(requiredLength, std::max(minimumCapacity, m_length * 2))); - } - - memcpy(m_bufferCharacters16 + m_length, characters, static_cast<size_t>(length) * sizeof(UChar)); - m_length = requiredLength; - } else - memcpy(appendUninitialized<UChar>(length), characters, static_cast<size_t>(length) * sizeof(UChar)); -} - -void StringBuilder::append(const LChar* characters, unsigned length) -{ - if (!length) - return; - ASSERT(characters); - - if (m_is8Bit) { - LChar* dest = appendUninitialized<LChar>(length); - if (length > 8) - memcpy(dest, characters, static_cast<size_t>(length) * sizeof(LChar)); - else { - const LChar* end = characters + length; - while (characters < end) - *(dest++) = *(characters++); - } - } else { - UChar* dest = appendUninitialized<UChar>(length); - const LChar* end = characters + length; - while (characters < end) - *(dest++) = *(characters++); - } -} - -bool StringBuilder::canShrink() const -{ - // Only shrink the buffer if it's less than 80% full. Need to tune this heuristic! - return m_buffer && m_buffer->length() > (m_length + (m_length >> 2)); -} - -void StringBuilder::shrinkToFit() -{ - if (canShrink()) { - if (m_is8Bit) - reallocateBuffer<LChar>(m_length); - else - reallocateBuffer<UChar>(m_length); - m_string = m_buffer; - m_buffer = 0; - } -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/text/StringBuilder.h b/Source/JavaScriptCore/wtf/text/StringBuilder.h deleted file mode 100644 index d896d17b1..000000000 --- a/Source/JavaScriptCore/wtf/text/StringBuilder.h +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) 2012 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 SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef StringBuilder_h -#define StringBuilder_h - -#include <wtf/text/AtomicString.h> -#include <wtf/text/WTFString.h> - -namespace WTF { - -class StringBuilder { - // Disallow copying since it's expensive and we don't want code to do it by accident. - WTF_MAKE_NONCOPYABLE(StringBuilder); - -public: - StringBuilder() - : m_length(0) - , m_is8Bit(true) - , m_valid16BitShadowLength(0) - , m_bufferCharacters8(0) - { - } - - WTF_EXPORT_PRIVATE void append(const UChar*, unsigned); - WTF_EXPORT_PRIVATE void append(const LChar*, unsigned); - - ALWAYS_INLINE void append(const char* characters, unsigned length) { append(reinterpret_cast<const LChar*>(characters), length); } - - void append(const String& string) - { - if (!string.length()) - return; - - // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called) - // then just retain the string. - if (!m_length && !m_buffer) { - m_string = string; - m_length = string.length(); - m_is8Bit = m_string.is8Bit(); - return; - } - - if (string.is8Bit()) - append(string.characters8(), string.length()); - else - append(string.characters16(), string.length()); - } - - void append(const StringBuilder& other) - { - if (!other.m_length) - return; - - // If we're appending to an empty string, and there is not a buffer (reserveCapacity has not been called) - // then just retain the string. - if (!m_length && !m_buffer && !other.m_string.isNull()) { - m_string = other.m_string; - m_length = other.m_length; - return; - } - - append(other.characters(), other.m_length); - } - - void append(const String& string, unsigned offset, unsigned length) - { - if (!string.length()) - return; - - if ((offset + length) > string.length()) - return; - - if (string.is8Bit()) - append(string.characters8() + offset, length); - else - append(string.characters16() + offset, length); - } - - void append(const char* characters) - { - if (characters) - append(characters, strlen(characters)); - } - - void append(UChar c) - { - if (m_buffer && !m_is8Bit && m_length < m_buffer->length() && m_string.isNull()) - m_bufferCharacters16[m_length++] = c; - else - append(&c, 1); - } - - void append(LChar c) - { - if (m_buffer && m_length < m_buffer->length() && m_string.isNull()) { - if (m_is8Bit) - m_bufferCharacters8[m_length++] = c; - else - m_bufferCharacters16[m_length++] = c; - } else - append(&c, 1); - } - - void append(char c) - { - append(static_cast<LChar>(c)); - } - - String toString() - { - shrinkToFit(); - if (m_string.isNull()) - reifyString(); - return m_string; - } - - const String& toStringPreserveCapacity() const - { - if (m_string.isNull()) - reifyString(); - return m_string; - } - - AtomicString toAtomicString() const - { - if (!m_length) - return AtomicString(); - - // If the buffer is sufficiently over-allocated, make a new AtomicString from a copy so its buffer is not so large. - if (canShrink()) - return AtomicString(characters(), length()); - - if (!m_string.isNull()) - return AtomicString(m_string); - - ASSERT(m_buffer); - return AtomicString(m_buffer.get(), 0, m_length); - } - - unsigned length() const - { - return m_length; - } - - bool isEmpty() const { return !m_length; } - - WTF_EXPORT_PRIVATE void reserveCapacity(unsigned newCapacity); - - unsigned capacity() const - { - return m_buffer ? m_buffer->length() : m_length; - } - - WTF_EXPORT_PRIVATE void resize(unsigned newSize); - - WTF_EXPORT_PRIVATE bool canShrink() const; - - WTF_EXPORT_PRIVATE void shrinkToFit(); - - UChar operator[](unsigned i) const - { - ASSERT(i < m_length); - if (m_is8Bit) - return characters8()[i]; - return characters16()[i]; - } - - const LChar* characters8() const - { - ASSERT(m_is8Bit); - if (!m_length) - return 0; - if (!m_string.isNull()) - return m_string.characters8(); - ASSERT(m_buffer); - return m_buffer->characters8(); - } - - const UChar* characters16() const - { - ASSERT(!m_is8Bit); - if (!m_length) - return 0; - if (!m_string.isNull()) - return m_string.characters16(); - ASSERT(m_buffer); - return m_buffer->characters16(); - } - - const UChar* characters() const - { - if (!m_length) - return 0; - if (!m_string.isNull()) - return m_string.characters(); - ASSERT(m_buffer); - if (m_buffer->has16BitShadow() && m_valid16BitShadowLength < m_length) - m_buffer->upconvertCharacters(m_valid16BitShadowLength, m_length); - - m_valid16BitShadowLength = m_length; - - return m_buffer->characters(); - } - - bool is8Bit() const { return m_is8Bit; } - - void clear() - { - m_length = 0; - m_string = String(); - m_buffer = 0; - m_bufferCharacters8 = 0; - m_is8Bit = true; - m_valid16BitShadowLength = 0; - } - - void swap(StringBuilder& stringBuilder) - { - std::swap(m_length, stringBuilder.m_length); - m_string.swap(stringBuilder.m_string); - m_buffer.swap(stringBuilder.m_buffer); - std::swap(m_is8Bit, stringBuilder.m_is8Bit); - std::swap(m_valid16BitShadowLength, stringBuilder.m_valid16BitShadowLength); - std::swap(m_bufferCharacters8, stringBuilder.m_bufferCharacters8); - } - -private: - void allocateBuffer(const LChar* currentCharacters, unsigned requiredLength); - void allocateBuffer(const UChar* currentCharacters, unsigned requiredLength); - void allocateBufferUpConvert(const LChar* currentCharacters, unsigned requiredLength); - template <typename CharType> - void reallocateBuffer(unsigned requiredLength); - template <typename CharType> - ALWAYS_INLINE CharType* appendUninitialized(unsigned length); - template <typename CharType> - CharType* appendUninitializedSlow(unsigned length); - template <typename CharType> - ALWAYS_INLINE CharType * getBufferCharacters(); - WTF_EXPORT_PRIVATE void reifyString() const; - - unsigned m_length; - mutable String m_string; - RefPtr<StringImpl> m_buffer; - bool m_is8Bit; - mutable unsigned m_valid16BitShadowLength; - union { - LChar* m_bufferCharacters8; - UChar* m_bufferCharacters16; - }; -}; - -template <> -ALWAYS_INLINE LChar* StringBuilder::getBufferCharacters<LChar>() -{ - ASSERT(m_is8Bit); - return m_bufferCharacters8; -} - -template <> -ALWAYS_INLINE UChar* StringBuilder::getBufferCharacters<UChar>() -{ - ASSERT(!m_is8Bit); - return m_bufferCharacters16; -} - -template <typename CharType> -bool equal(const StringBuilder& s, const CharType* buffer, unsigned length) -{ - if (s.length() != length) - return false; - - if (s.is8Bit()) - return equal(s.characters8(), buffer, length); - - return equal(s.characters16(), buffer, length); -} - -template <typename StringType> -bool equal(const StringBuilder& a, const StringType& b) -{ - if (a.length() != b.length()) - return false; - - if (!a.length()) - return true; - - if (a.is8Bit()) { - if (b.is8Bit()) - return equal(a.characters8(), b.characters8(), a.length()); - return equal(a.characters8(), b.characters16(), a.length()); - } - - if (b.is8Bit()) - return equal(a.characters16(), b.characters8(), a.length()); - return equal(a.characters16(), b.characters16(), a.length()); -} - -inline bool operator==(const StringBuilder& a, const StringBuilder& b) { return equal(a, b); } -inline bool operator!=(const StringBuilder& a, const StringBuilder& b) { return !equal(a, b); } -inline bool operator==(const StringBuilder& a, const String& b) { return equal(a, b); } -inline bool operator!=(const StringBuilder& a, const String& b) { return !equal(a, b); } -inline bool operator==(const String& a, const StringBuilder& b) { return equal(b, a); } -inline bool operator!=(const String& a, const StringBuilder& b) { return !equal(b, a); } - -} // namespace WTF - -using WTF::StringBuilder; - -#endif // StringBuilder_h diff --git a/Source/JavaScriptCore/wtf/text/StringConcatenate.h b/Source/JavaScriptCore/wtf/text/StringConcatenate.h deleted file mode 100644 index 479ed8ca2..000000000 --- a/Source/JavaScriptCore/wtf/text/StringConcatenate.h +++ /dev/null @@ -1,964 +0,0 @@ -/* - * 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 StringConcatenate_h -#define StringConcatenate_h - -#ifndef WTFString_h -#include <wtf/text/AtomicString.h> -#endif - -// This macro is helpful for testing how many intermediate Strings are created while evaluating an -// expression containing operator+. -#ifndef WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING -#define WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING() ((void)0) -#endif - -namespace WTF { - -template<typename StringType> -class StringTypeAdapter { -}; - -template<> -class StringTypeAdapter<char> { -public: - StringTypeAdapter<char>(char buffer) - : m_buffer(buffer) - { - } - - unsigned length() { return 1; } - - bool is8Bit() { return true; } - - void writeTo(LChar* destination) - { - *destination = m_buffer; - } - - void writeTo(UChar* destination) { *destination = m_buffer; } - -private: - unsigned char m_buffer; -}; - -template<> -class StringTypeAdapter<LChar> { -public: - StringTypeAdapter<LChar>(LChar buffer) - : m_buffer(buffer) - { - } - - unsigned length() { return 1; } - - bool is8Bit() { return true; } - - void writeTo(LChar* destination) - { - *destination = m_buffer; - } - - void writeTo(UChar* destination) { *destination = m_buffer; } - -private: - LChar m_buffer; -}; - -template<> -class StringTypeAdapter<UChar> { -public: - StringTypeAdapter<UChar>(UChar buffer) - : m_buffer(buffer) - { - } - - unsigned length() { return 1; } - - bool is8Bit() { return m_buffer <= 0xff; } - - void writeTo(LChar* destination) - { - ASSERT(is8Bit()); - *destination = static_cast<LChar>(m_buffer); - } - - void writeTo(UChar* destination) { *destination = m_buffer; } - -private: - UChar m_buffer; -}; - -template<> -class StringTypeAdapter<char*> { -public: - StringTypeAdapter<char*>(char* buffer) - : m_buffer(buffer) - , m_length(strlen(buffer)) - { - } - - unsigned length() { return m_length; } - - bool is8Bit() { return true; } - - void writeTo(LChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = static_cast<LChar>(m_buffer[i]); - } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) { - unsigned char c = m_buffer[i]; - destination[i] = c; - } - } - -private: - const char* m_buffer; - unsigned m_length; -}; - -template<> -class StringTypeAdapter<LChar*> { -public: - StringTypeAdapter<LChar*>(LChar* buffer) - : m_buffer(buffer) - , m_length(strlen(reinterpret_cast<char*>(buffer))) - { - } - - unsigned length() { return m_length; } - - bool is8Bit() { return true; } - - void writeTo(LChar* destination) - { - memcpy(destination, m_buffer, m_length * sizeof(LChar)); - } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_buffer[i]; - } - -private: - const LChar* m_buffer; - unsigned m_length; -}; - -template<> -class StringTypeAdapter<const UChar*> { -public: - StringTypeAdapter<const UChar*>(const UChar* buffer) - : m_buffer(buffer) - { - size_t len = 0; - while (m_buffer[len] != UChar(0)) - len++; - - if (len > std::numeric_limits<unsigned>::max()) - CRASH(); - - m_length = len; - } - - unsigned length() { return m_length; } - - bool is8Bit() { return false; } - - NO_RETURN_DUE_TO_CRASH void writeTo(LChar*) - { - CRASH(); - } - - void writeTo(UChar* destination) - { - memcpy(destination, m_buffer, m_length * sizeof(UChar)); - } - -private: - const UChar* m_buffer; - unsigned m_length; -}; - -template<> -class StringTypeAdapter<const char*> { -public: - StringTypeAdapter<const char*>(const char* buffer) - : m_buffer(buffer) - , m_length(strlen(buffer)) - { - } - - unsigned length() { return m_length; } - - bool is8Bit() { return true; } - - void writeTo(LChar* destination) - { - memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar)); - } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) { - unsigned char c = m_buffer[i]; - destination[i] = c; - } - } - -private: - const char* m_buffer; - unsigned m_length; -}; - -template<> -class StringTypeAdapter<const LChar*> { -public: - StringTypeAdapter<const LChar*>(const LChar* buffer) - : m_buffer(buffer) - , m_length(strlen(reinterpret_cast<const char*>(buffer))) - { - } - - unsigned length() { return m_length; } - - bool is8Bit() { return true; } - - void writeTo(LChar* destination) - { - memcpy(destination, m_buffer, static_cast<size_t>(m_length) * sizeof(LChar)); - } - - void writeTo(UChar* destination) - { - for (unsigned i = 0; i < m_length; ++i) - destination[i] = m_buffer[i]; - } - -private: - const LChar* m_buffer; - unsigned m_length; -}; - -template<> -class StringTypeAdapter<Vector<char> > { -public: - StringTypeAdapter<Vector<char> >(const Vector<char>& buffer) - : m_buffer(buffer) - { - } - - size_t length() { return m_buffer.size(); } - - bool is8Bit() { return true; } - - void writeTo(LChar* destination) - { - for (size_t i = 0; i < m_buffer.size(); ++i) - destination[i] = static_cast<unsigned char>(m_buffer[i]); - } - - void writeTo(UChar* destination) - { - for (size_t i = 0; i < m_buffer.size(); ++i) - destination[i] = static_cast<unsigned char>(m_buffer[i]); - } - -private: - const Vector<char>& m_buffer; -}; - -template<> -class StringTypeAdapter<Vector<LChar> > { -public: - StringTypeAdapter<Vector<LChar> >(const Vector<LChar>& buffer) - : m_buffer(buffer) - { - } - - size_t length() { return m_buffer.size(); } - - bool is8Bit() { return true; } - - void writeTo(LChar* destination) - { - for (size_t i = 0; i < m_buffer.size(); ++i) - destination[i] = m_buffer[i]; - } - - void writeTo(UChar* destination) - { - for (size_t i = 0; i < m_buffer.size(); ++i) - destination[i] = m_buffer[i]; - } - -private: - const Vector<LChar>& m_buffer; -}; - -template<> -class StringTypeAdapter<String> { -public: - StringTypeAdapter<String>(const String& string) - : m_buffer(string) - { - } - - unsigned length() { return m_buffer.length(); } - - bool is8Bit() { return m_buffer.isNull() || m_buffer.is8Bit(); } - - void writeTo(LChar* destination) - { - unsigned length = m_buffer.length(); - - ASSERT(is8Bit()); - const LChar* data = m_buffer.characters8(); - for (unsigned i = 0; i < length; ++i) - destination[i] = data[i]; - - WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING(); - } - - void writeTo(UChar* destination) - { - unsigned length = m_buffer.length(); - - if (is8Bit()) { - const LChar* data = m_buffer.characters8(); - for (unsigned i = 0; i < length; ++i) - destination[i] = data[i]; - } else { - const UChar* data = m_buffer.characters16(); - for (unsigned i = 0; i < length; ++i) - destination[i] = data[i]; - } - - WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING(); - } - -private: - const String& m_buffer; -}; - -template<> -class StringTypeAdapter<AtomicString> { -public: - StringTypeAdapter<AtomicString>(const AtomicString& string) - : m_adapter(string.string()) - { - } - - unsigned length() { return m_adapter.length(); } - - bool is8Bit() { return m_adapter.is8Bit(); } - - void writeTo(LChar* destination) { m_adapter.writeTo(destination); } - void writeTo(UChar* destination) { m_adapter.writeTo(destination); } - -private: - StringTypeAdapter<String> m_adapter; -}; - -inline void sumWithOverflow(unsigned& total, unsigned addend, bool& overflow) -{ - unsigned oldTotal = total; - total = oldTotal + addend; - if (total < oldTotal) - overflow = true; -} - -template<typename StringType1, typename StringType2> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - if (overflow) - return 0; - - if (adapter1.is8Bit() && adapter2.is8Bit()) { - LChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - LChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - - return resultImpl.release(); - } - - UChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - if (overflow) - return 0; - - if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit()) { - LChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - LChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - - return resultImpl.release(); - } - - UChar* buffer = 0; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - if (overflow) - return 0; - - if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit()) { - LChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - LChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - - return resultImpl.release(); - } - - UChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - if (overflow) - return 0; - - if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit()) { - LChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - LChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - - return resultImpl.release(); - } - - UChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - if (overflow) - return 0; - - if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit()) { - LChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - LChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - - return resultImpl.release(); - } - - UChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - StringTypeAdapter<StringType7> adapter7(string7); - - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - sumWithOverflow(length, adapter7.length(), overflow); - if (overflow) - return 0; - - if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit()) { - LChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - LChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - - return resultImpl.release(); - } - - UChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - StringTypeAdapter<StringType7> adapter7(string7); - StringTypeAdapter<StringType8> adapter8(string8); - - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - sumWithOverflow(length, adapter7.length(), overflow); - sumWithOverflow(length, adapter8.length(), overflow); - if (overflow) - return 0; - - if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit() && adapter8.is8Bit()) { - LChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - LChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - result += adapter7.length(); - adapter8.writeTo(result); - - return resultImpl.release(); - } - - UChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - result += adapter7.length(); - adapter8.writeTo(result); - - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9> -PassRefPtr<StringImpl> tryMakeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9) -{ - StringTypeAdapter<StringType1> adapter1(string1); - StringTypeAdapter<StringType2> adapter2(string2); - StringTypeAdapter<StringType3> adapter3(string3); - StringTypeAdapter<StringType4> adapter4(string4); - StringTypeAdapter<StringType5> adapter5(string5); - StringTypeAdapter<StringType6> adapter6(string6); - StringTypeAdapter<StringType7> adapter7(string7); - StringTypeAdapter<StringType8> adapter8(string8); - StringTypeAdapter<StringType9> adapter9(string9); - - bool overflow = false; - unsigned length = adapter1.length(); - sumWithOverflow(length, adapter2.length(), overflow); - sumWithOverflow(length, adapter3.length(), overflow); - sumWithOverflow(length, adapter4.length(), overflow); - sumWithOverflow(length, adapter5.length(), overflow); - sumWithOverflow(length, adapter6.length(), overflow); - sumWithOverflow(length, adapter7.length(), overflow); - sumWithOverflow(length, adapter8.length(), overflow); - sumWithOverflow(length, adapter9.length(), overflow); - if (overflow) - return 0; - - if (adapter1.is8Bit() && adapter2.is8Bit() && adapter3.is8Bit() && adapter4.is8Bit() && adapter5.is8Bit() && adapter6.is8Bit() && adapter7.is8Bit() && adapter8.is8Bit() && adapter9.is8Bit()) { - LChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - LChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - result += adapter7.length(); - adapter8.writeTo(result); - result += adapter8.length(); - adapter9.writeTo(result); - - return resultImpl.release(); - } - - UChar* buffer; - RefPtr<StringImpl> resultImpl = StringImpl::tryCreateUninitialized(length, buffer); - if (!resultImpl) - return 0; - - UChar* result = buffer; - adapter1.writeTo(result); - result += adapter1.length(); - adapter2.writeTo(result); - result += adapter2.length(); - adapter3.writeTo(result); - result += adapter3.length(); - adapter4.writeTo(result); - result += adapter4.length(); - adapter5.writeTo(result); - result += adapter5.length(); - adapter6.writeTo(result); - result += adapter6.length(); - adapter7.writeTo(result); - result += adapter7.length(); - adapter8.writeTo(result); - result += adapter8.length(); - adapter9.writeTo(result); - - return resultImpl.release(); -} - - -// Convenience only. -template<typename StringType1> -String makeString(StringType1 string1) -{ - return String(string1); -} - -template<typename StringType1, typename StringType2> -String makeString(StringType1 string1, StringType2 string2) -{ - RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2); - if (!resultImpl) - CRASH(); - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3> -String makeString(StringType1 string1, StringType2 string2, StringType3 string3) -{ - RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3); - if (!resultImpl) - CRASH(); - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4> -String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4) -{ - RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4); - if (!resultImpl) - CRASH(); - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5> -String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5) -{ - RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5); - if (!resultImpl) - CRASH(); - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6> -String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6) -{ - RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6); - if (!resultImpl) - CRASH(); - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7> -String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7) -{ - RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7); - if (!resultImpl) - CRASH(); - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8> -String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8) -{ - RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8); - if (!resultImpl) - CRASH(); - return resultImpl.release(); -} - -template<typename StringType1, typename StringType2, typename StringType3, typename StringType4, typename StringType5, typename StringType6, typename StringType7, typename StringType8, typename StringType9> -String makeString(StringType1 string1, StringType2 string2, StringType3 string3, StringType4 string4, StringType5 string5, StringType6 string6, StringType7 string7, StringType8 string8, StringType9 string9) -{ - RefPtr<StringImpl> resultImpl = tryMakeString(string1, string2, string3, string4, string5, string6, string7, string8, string9); - if (!resultImpl) - CRASH(); - return resultImpl.release(); -} - -} // namespace WTF - -using WTF::makeString; - -#include <wtf/text/StringOperators.h> -#endif diff --git a/Source/JavaScriptCore/wtf/text/StringHash.h b/Source/JavaScriptCore/wtf/text/StringHash.h deleted file mode 100644 index acc97b995..000000000 --- a/Source/JavaScriptCore/wtf/text/StringHash.h +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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 <wtf/text/AtomicString.h> -#include <wtf/text/WTFString.h> -#include <wtf/Forward.h> -#include <wtf/HashTraits.h> -#include <wtf/StringHasher.h> -#include <wtf/unicode/Unicode.h> - -namespace WTF { - - // 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; - - if (a->is8Bit()) { - if (b->is8Bit()) { - // Both a & b are 8 bit. - return WTF::equal(a->characters8(), b->characters8(), aLength); - } - - // We know that a is 8 bit & b is 16 bit. - return WTF::equal(a->characters8(), b->characters16(), aLength); - } - - if (b->is8Bit()) { - // We know that a is 8 bit and b is 16 bit. - return WTF::equal(a->characters16(), b->characters8(), aLength); - } - - return WTF::equal(a->characters16(), b->characters16(), aLength); - } - - 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: - template<typename T> static inline UChar foldCase(T ch) - { - return WTF::Unicode::foldCase(ch); - } - - static unsigned hash(const UChar* data, unsigned length) - { - return StringHasher::computeHash<UChar, foldCase<UChar> >(data, length); - } - - static unsigned hash(StringImpl* str) - { - if (str->is8Bit()) - return hash(str->characters8(), str->length()); - return hash(str->characters16(), str->length()); - } - - static unsigned hash(const LChar* data, unsigned length) - { - return StringHasher::computeHash<LChar, foldCase<LChar> >(data, length); - } - - static inline unsigned hash(const char* data, unsigned length) - { - return CaseFoldingHash::hash(reinterpret_cast<const LChar*>(data), length); - } - - 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; - } - }; - -} - -using WTF::StringHash; -using WTF::CaseFoldingHash; -using WTF::AlreadyHashed; - -#endif diff --git a/Source/JavaScriptCore/wtf/text/StringImpl.cpp b/Source/JavaScriptCore/wtf/text/StringImpl.cpp deleted file mode 100644 index 3f73556b5..000000000 --- a/Source/JavaScriptCore/wtf/text/StringImpl.cpp +++ /dev/null @@ -1,1619 +0,0 @@ -/* - * 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> -#include <wtf/unicode/CharacterNames.h> - - -using namespace std; - -namespace WTF { - -using namespace Unicode; - -COMPILE_ASSERT(sizeof(StringImpl) == 2 * sizeof(int) + 3 * sizeof(void*), StringImpl_should_stay_small); - -StringImpl::~StringImpl() -{ - ASSERT(!isStatic()); - - if (isAtomic()) - AtomicString::remove(this); -#if USE(JSC) - if (isIdentifier()) { - if (!wtfThreadData().currentIdentifierTable()->remove(this)) - CRASH(); - } -#endif - - BufferOwnership ownership = bufferOwnership(); - - if (has16BitShadow()) { - ASSERT(m_copyData16); - fastFree(m_copyData16); - } - - if (ownership == BufferInternal) - return; - if (ownership == BufferOwned) { - // We use m_data8, but since it is a union with m_data16 this works either way. - ASSERT(m_data8); - fastFree(const_cast<LChar*>(m_data8)); - return; - } - - ASSERT(ownership == BufferSubstring); - ASSERT(m_substringBuffer); - m_substringBuffer->deref(); -} - -PassRefPtr<StringImpl> StringImpl::createUninitialized(unsigned length, LChar*& 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<unsigned>::max() - sizeof(StringImpl)) / sizeof(LChar))) - CRASH(); - size_t size = sizeof(StringImpl) + length * sizeof(LChar); - StringImpl* string = static_cast<StringImpl*>(fastMalloc(size)); - - data = reinterpret_cast<LChar*>(string + 1); - return adoptRef(new (NotNull, string) StringImpl(length, Force8BitConstructor)); -} - -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<unsigned>::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 (NotNull, string) StringImpl(length)); -} - -PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalString, unsigned length, LChar*& data) -{ - ASSERT(originalString->is8Bit()); - ASSERT(originalString->hasOneRef()); - ASSERT(originalString->bufferOwnership() == BufferInternal); - - if (!length) { - data = 0; - return empty(); - } - - // Same as createUninitialized() except here we use fastRealloc. - if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(LChar))) - CRASH(); - size_t size = sizeof(StringImpl) + length * sizeof(LChar); - originalString->~StringImpl(); - StringImpl* string = static_cast<StringImpl*>(fastRealloc(originalString.leakRef(), size)); - - data = reinterpret_cast<LChar*>(string + 1); - return adoptRef(new (NotNull, string) StringImpl(length, Force8BitConstructor)); -} - -PassRefPtr<StringImpl> StringImpl::reallocate(PassRefPtr<StringImpl> originalString, unsigned length, UChar*& data) -{ - ASSERT(!originalString->is8Bit()); - ASSERT(originalString->hasOneRef()); - ASSERT(originalString->bufferOwnership() == BufferInternal); - - if (!length) { - data = 0; - return empty(); - } - - // Same as createUninitialized() except here we use fastRealloc. - if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(UChar))) - CRASH(); - size_t size = sizeof(StringImpl) + length * sizeof(UChar); - originalString->~StringImpl(); - StringImpl* string = static_cast<StringImpl*>(fastRealloc(originalString.leakRef(), size)); - - data = reinterpret_cast<UChar*>(string + 1); - return adoptRef(new (NotNull, string) StringImpl(length)); -} - -PassRefPtr<StringImpl> StringImpl::create(const UChar* characters, unsigned length) -{ - if (!characters || !length) - return empty(); - - UChar* data; - RefPtr<StringImpl> string = createUninitialized(length, data); - memcpy(data, characters, length * sizeof(UChar)); - return string.release(); -} - -PassRefPtr<StringImpl> StringImpl::create(const LChar* characters, unsigned length) -{ - if (!characters || !length) - return empty(); - - LChar* data; - RefPtr<StringImpl> string = createUninitialized(length, data); - memcpy(data, characters, length * sizeof(LChar)); - return string.release(); -} - -PassRefPtr<StringImpl> StringImpl::create(const LChar* string) -{ - if (!string) - return empty(); - size_t length = strlen(reinterpret_cast<const char*>(string)); - if (length > numeric_limits<unsigned>::max()) - CRASH(); - return create(string, length); -} - -const UChar* StringImpl::getData16SlowCase() const -{ - if (has16BitShadow()) - return m_copyData16; - - if (bufferOwnership() == BufferSubstring) { - // If this is a substring, return a pointer into the parent string. - // TODO: Consider severing this string from the parent string - unsigned offset = m_data8 - m_substringBuffer->characters8(); - return m_substringBuffer->characters() + offset; - } - - unsigned len = length(); - if (hasTerminatingNullCharacter()) - len++; - - m_copyData16 = static_cast<UChar*>(fastMalloc(len * sizeof(UChar))); - - m_hashAndFlags |= s_hashFlagHas16BitShadow; - - upconvertCharacters(0, len); - - return m_copyData16; -} - -void StringImpl::upconvertCharacters(unsigned start, unsigned end) const -{ - ASSERT(is8Bit()); - ASSERT(has16BitShadow()); - - for (size_t i = start; i < end; i++) - m_copyData16[i] = m_data8[i]; -} - - -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. - if (is8Bit()) { - for (unsigned i = 0; i < m_length; i++) { - UChar c = m_data8[i]; - if (!isASCIISpace(c)) - return false; - } - - return true; - } - - for (unsigned i = 0; i < m_length; i++) { - UChar c = m_data16[i]; - if (!isASCIISpace(c)) - 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; - } - if (is8Bit()) - return create(m_data8 + start, length); - - return create(m_data16 + start, length); -} - -UChar32 StringImpl::characterStartingAt(unsigned i) -{ - if (is8Bit()) - return m_data8[i]; - if (U16_IS_SINGLE(m_data16[i])) - return m_data16[i]; - if (i + 1 < m_length && U16_IS_LEAD(m_data16[i]) && U16_IS_TRAIL(m_data16[i + 1])) - return U16_GET_SUPPLEMENTARY(m_data16[i], m_data16[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: - bool noUpper = true; - UChar ored = 0; - if (is8Bit()) { - const LChar* end = m_data8 + m_length; - for (const LChar* chp = m_data8; 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; - - if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max())) - CRASH(); - int32_t length = m_length; - - LChar* data8; - RefPtr<StringImpl> newImpl = createUninitialized(length, data8); - - if (!(ored & ~0x7F)) { - for (int32_t i = 0; i < length; i++) - data8[i] = toASCIILower(m_data8[i]); - - return newImpl.release(); - } - - // Do a slower implementation for cases that include non-ASCII Latin-1 characters. - for (int32_t i = 0; i < length; i++) - data8[i] = static_cast<LChar>(Unicode::toLower(m_data8[i])); - - return newImpl.release(); - } - - const UChar *end = m_data16 + m_length; - for (const UChar* chp = m_data16; 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; - - if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max())) - CRASH(); - int32_t length = m_length; - - if (!(ored & ~0x7F)) { - UChar* data16; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16); - - for (int32_t i = 0; i < length; i++) { - UChar c = m_data16[i]; - data16[i] = toASCIILower(c); - } - return newImpl.release(); - } - - // Do a slower implementation for cases that include non-ASCII characters. - UChar* data16; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16); - - bool error; - int32_t realLength = Unicode::toLower(data16, length, m_data16, m_length, &error); - if (!error && realLength == length) - return newImpl.release(); - - newImpl = createUninitialized(realLength, data16); - Unicode::toLower(data16, realLength, m_data16, m_length, &error); - if (error) - return this; - return newImpl.release(); -} - -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. - - if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max())) - CRASH(); - int32_t length = m_length; - - if (is8Bit()) { - LChar* data8; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data8); - - // Do a faster loop for the case where all the characters are ASCII. - LChar ored = 0; - for (int i = 0; i < length; i++) { - LChar c = m_data8[i]; - ored |= c; - data8[i] = toASCIIUpper(c); - } - if (!(ored & ~0x7F)) - return newImpl.release(); - - // Do a slower implementation for cases that include non-ASCII Latin-1 characters. - int numberSharpSCharacters = 0; - - // There are two special cases. - // 1. latin-1 characters when converted to upper case are 16 bit characters. - // 2. Lower case sharp-S converts to "SS" (two characters) - for (int32_t i = 0; i < length; i++) { - LChar c = m_data8[i]; - if (UNLIKELY(c == smallLetterSharpS)) - numberSharpSCharacters++; - UChar upper = Unicode::toUpper(c); - if (UNLIKELY(upper > 0xff)) { - // Since this upper-cased character does not fit in an 8-bit string, we need to take the 16-bit path. - goto upconvert; - } - data8[i] = static_cast<LChar>(upper); - } - - if (!numberSharpSCharacters) - return newImpl.release(); - - // We have numberSSCharacters sharp-s characters, but none of the other special characters. - newImpl = createUninitialized(m_length + numberSharpSCharacters, data8); - - LChar* dest = data8; - - for (int32_t i = 0; i < length; i++) { - LChar c = m_data8[i]; - if (c == smallLetterSharpS) { - *dest++ = 'S'; - *dest++ = 'S'; - } else - *dest++ = static_cast<LChar>(Unicode::toUpper(c)); - } - - return newImpl.release(); - } - -upconvert: - const UChar* source16 = characters(); - - UChar* data16; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data16); - - // 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 = source16[i]; - ored |= c; - data16[i] = toASCIIUpper(c); - } - if (!(ored & ~0x7F)) - return newImpl.release(); - - // Do a slower implementation for cases that include non-ASCII characters. - bool error; - newImpl = createUninitialized(m_length, data16); - int32_t realLength = Unicode::toUpper(data16, length, source16, m_length, &error); - if (!error && realLength == length) - return newImpl; - newImpl = createUninitialized(realLength, data16); - Unicode::toUpper(data16, realLength, source16, m_length, &error); - if (error) - return this; - return newImpl.release(); -} - -PassRefPtr<StringImpl> StringImpl::fill(UChar character) -{ - if (!m_length) - return this; - - if (!(character & ~0x7F)) { - LChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - for (unsigned i = 0; i < m_length; ++i) - data[i] = character; - return newImpl.release(); - } - UChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - for (unsigned i = 0; i < m_length; ++i) - data[i] = character; - return newImpl.release(); -} - -PassRefPtr<StringImpl> StringImpl::foldCase() -{ - if (m_length > static_cast<unsigned>(numeric_limits<int32_t>::max())) - CRASH(); - int32_t length = m_length; - - if (is8Bit()) { - // Do a faster loop for the case where all the characters are ASCII. - LChar* data; - RefPtr <StringImpl>newImpl = createUninitialized(m_length, data); - LChar ored = 0; - - for (int32_t i = 0; i < length; i++) { - LChar c = m_data8[i]; - data[i] = toASCIILower(c); - ored |= c; - } - - if (!(ored & ~0x7F)) - return newImpl.release(); - - // Do a slower implementation for cases that include non-ASCII Latin-1 characters. - for (int32_t i = 0; i < length; i++) - data[i] = static_cast<LChar>(Unicode::toLower(m_data8[i])); - - return newImpl.release(); - } - - // Do a faster loop for the case where all the characters are ASCII. - UChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - UChar ored = 0; - for (int32_t i = 0; i < length; i++) { - UChar c = m_data16[i]; - ored |= c; - data[i] = toASCIILower(c); - } - if (!(ored & ~0x7F)) - return newImpl.release(); - - // Do a slower implementation for cases that include non-ASCII characters. - bool error; - int32_t realLength = Unicode::foldCase(data, length, m_data16, m_length, &error); - if (!error && realLength == length) - return newImpl.release(); - newImpl = createUninitialized(realLength, data); - Unicode::foldCase(data, realLength, m_data16, m_length, &error); - if (error) - return this; - return newImpl.release(); -} - -template <class UCharPredicate> -inline PassRefPtr<StringImpl> StringImpl::stripMatchedCharacters(UCharPredicate predicate) -{ - if (!m_length) - return empty(); - - unsigned start = 0; - unsigned end = m_length - 1; - - // skip white space from start - while (start <= end && predicate(is8Bit() ? m_data8[start] : m_data16[start])) - start++; - - // only white space - if (start > end) - return empty(); - - // skip white space from end - while (end && predicate(is8Bit() ? m_data8[end] : m_data16[end])) - end--; - - if (!start && end == m_length - 1) - return this; - if (is8Bit()) - return create(m_data8 + start, end + 1 - start); - return create(m_data16 + start, end + 1 - start); -} - -class UCharPredicate { -public: - inline UCharPredicate(CharacterMatchFunctionPtr function): m_function(function) { } - - inline bool operator()(UChar ch) const - { - return m_function(ch); - } - -private: - const CharacterMatchFunctionPtr m_function; -}; - -class SpaceOrNewlinePredicate { -public: - inline bool operator()(UChar ch) const - { - return isSpaceOrNewline(ch); - } -}; - -PassRefPtr<StringImpl> StringImpl::stripWhiteSpace() -{ - return stripMatchedCharacters(SpaceOrNewlinePredicate()); -} - -PassRefPtr<StringImpl> StringImpl::stripWhiteSpace(IsWhiteSpaceFunctionPtr isWhiteSpace) -{ - return stripMatchedCharacters(UCharPredicate(isWhiteSpace)); -} - -template <typename CharType> -ALWAYS_INLINE PassRefPtr<StringImpl> StringImpl::removeCharacters(const CharType* characters, CharacterMatchFunctionPtr findMatch) -{ - const CharType* from = characters; - const CharType* 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<CharType> data(m_length); - CharType* to = data.characters(); - unsigned outc = from - characters; - - if (outc) - memcpy(to, characters, outc * sizeof(CharType)); - - 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::removeCharacters(CharacterMatchFunctionPtr findMatch) -{ - if (is8Bit()) - return removeCharacters(characters8(), findMatch); - return removeCharacters(characters16(), findMatch); -} - -template <typename CharType, class UCharPredicate> -inline PassRefPtr<StringImpl> StringImpl::simplifyMatchedCharactersToSpace(UCharPredicate predicate) -{ - StringBuffer<CharType> data(m_length); - - const CharType* from = getCharacters<CharType>(); - const CharType* fromend = from + m_length; - int outc = 0; - bool changedToSpace = false; - - CharType* to = data.characters(); - - while (true) { - while (from != fromend && predicate(*from)) { - if (*from != ' ') - changedToSpace = true; - from++; - } - while (from != fromend && !predicate(*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); -} - -PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace() -{ - if (is8Bit()) - return StringImpl::simplifyMatchedCharactersToSpace<LChar>(SpaceOrNewlinePredicate()); - return StringImpl::simplifyMatchedCharactersToSpace<UChar>(SpaceOrNewlinePredicate()); -} - -PassRefPtr<StringImpl> StringImpl::simplifyWhiteSpace(IsWhiteSpaceFunctionPtr isWhiteSpace) -{ - if (is8Bit()) - return StringImpl::simplifyMatchedCharactersToSpace<LChar>(UCharPredicate(isWhiteSpace)); - return StringImpl::simplifyMatchedCharactersToSpace<UChar>(UCharPredicate(isWhiteSpace)); -} - -int StringImpl::toIntStrict(bool* ok, int base) -{ - if (is8Bit()) - return charactersToIntStrict(characters8(), m_length, ok, base); - return charactersToIntStrict(characters16(), m_length, ok, base); -} - -unsigned StringImpl::toUIntStrict(bool* ok, int base) -{ - if (is8Bit()) - return charactersToUIntStrict(characters8(), m_length, ok, base); - return charactersToUIntStrict(characters16(), m_length, ok, base); -} - -int64_t StringImpl::toInt64Strict(bool* ok, int base) -{ - if (is8Bit()) - return charactersToInt64Strict(characters8(), m_length, ok, base); - return charactersToInt64Strict(characters16(), m_length, ok, base); -} - -uint64_t StringImpl::toUInt64Strict(bool* ok, int base) -{ - if (is8Bit()) - return charactersToUInt64Strict(characters8(), m_length, ok, base); - return charactersToUInt64Strict(characters16(), m_length, ok, base); -} - -intptr_t StringImpl::toIntPtrStrict(bool* ok, int base) -{ - if (is8Bit()) - return charactersToIntPtrStrict(characters8(), m_length, ok, base); - return charactersToIntPtrStrict(characters16(), m_length, ok, base); -} - -int StringImpl::toInt(bool* ok) -{ - if (is8Bit()) - return charactersToInt(characters8(), m_length, ok); - return charactersToInt(characters16(), m_length, ok); -} - -unsigned StringImpl::toUInt(bool* ok) -{ - if (is8Bit()) - return charactersToUInt(characters8(), m_length, ok); - return charactersToUInt(characters16(), m_length, ok); -} - -int64_t StringImpl::toInt64(bool* ok) -{ - if (is8Bit()) - return charactersToInt64(characters8(), m_length, ok); - return charactersToInt64(characters16(), m_length, ok); -} - -uint64_t StringImpl::toUInt64(bool* ok) -{ - if (is8Bit()) - return charactersToUInt64(characters8(), m_length, ok); - return charactersToUInt64(characters16(), m_length, ok); -} - -intptr_t StringImpl::toIntPtr(bool* ok) -{ - if (is8Bit()) - return charactersToIntPtr(characters8(), m_length, ok); - return charactersToIntPtr(characters16(), m_length, ok); -} - -double StringImpl::toDouble(bool* ok, bool* didReadNumber) -{ - if (is8Bit()) - return charactersToDouble(characters8(), m_length, ok, didReadNumber); - return charactersToDouble(characters16(), m_length, ok, didReadNumber); -} - -float StringImpl::toFloat(bool* ok, bool* didReadNumber) -{ - if (is8Bit()) - return charactersToFloat(characters8(), m_length, ok, didReadNumber); - return charactersToFloat(characters16(), m_length, ok, didReadNumber); -} - -bool equalIgnoringCase(const LChar* a, const LChar* b, unsigned length) -{ - while (length--) { - LChar bc = *b++; - if (foldCase(*a++) != foldCase(bc)) - return false; - } - return true; -} - -bool equalIgnoringCase(const UChar* a, const LChar* b, unsigned length) -{ - while (length--) { - LChar 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 codePointCompare(const StringImpl* s1, const StringImpl* s2) -{ - const unsigned l1 = s1 ? s1->length() : 0; - const unsigned l2 = s2 ? s2->length() : 0; - const unsigned lmin = l1 < l2 ? l1 : l2; - const UChar* c1 = s1 ? s1->characters() : 0; - const UChar* c2 = s2 ? s2->characters() : 0; - unsigned pos = 0; - while (pos < lmin && *c1 == *c2) { - c1++; - c2++; - pos++; - } - - if (pos < lmin) - return (c1[0] > c2[0]) ? 1 : -1; - - if (l1 == l2) - return 0; - - return (l1 > l2) ? 1 : -1; -} - -size_t StringImpl::find(UChar c, unsigned start) -{ - if (is8Bit()) - return WTF::find(characters8(), m_length, c, start); - return WTF::find(characters16(), m_length, c, start); -} - -size_t StringImpl::find(CharacterMatchFunctionPtr matchFunction, unsigned start) -{ - if (is8Bit()) - return WTF::find(characters8(), m_length, matchFunction, start); - return WTF::find(characters16(), m_length, matchFunction, start); -} - -size_t StringImpl::find(const LChar* matchString, unsigned index) -{ - // Check for null or empty string to match against - if (!matchString) - return notFound; - size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString)); - if (matchStringLength > numeric_limits<unsigned>::max()) - CRASH(); - unsigned matchLength = matchStringLength; - if (!matchLength) - return min(index, length()); - - // Optimization 1: fast case for strings of length 1. - if (matchLength == 1) - return WTF::find(characters16(), length(), *matchString, index); - - // Check index & matchLength are in range. - if (index > length()) - return notFound; - unsigned searchLength = length() - index; - if (matchLength > searchLength) - return notFound; - // delta is the number of additional times to test; delta == 0 means test only once. - unsigned delta = searchLength - matchLength; - - const UChar* searchCharacters = characters() + index; - - // Optimization 2: keep a running hash of the strings, - // only call memcmp if the hashes match. - unsigned searchHash = 0; - unsigned matchHash = 0; - for (unsigned i = 0; i < matchLength; ++i) { - searchHash += searchCharacters[i]; - matchHash += matchString[i]; - } - - unsigned i = 0; - // keep looping until we match - while (searchHash != matchHash || !equal(searchCharacters + i, matchString, matchLength)) { - if (i == delta) - return notFound; - searchHash += searchCharacters[i + matchLength]; - searchHash -= searchCharacters[i]; - ++i; - } - return index + i; -} - -size_t StringImpl::findIgnoringCase(const LChar* matchString, unsigned index) -{ - // Check for null or empty string to match against - if (!matchString) - return notFound; - size_t matchStringLength = strlen(reinterpret_cast<const char*>(matchString)); - if (matchStringLength > numeric_limits<unsigned>::max()) - CRASH(); - unsigned matchLength = matchStringLength; - if (!matchLength) - return min(index, length()); - - // Check index & matchLength are in range. - if (index > length()) - return notFound; - unsigned searchLength = length() - index; - if (matchLength > searchLength) - return notFound; - // delta is the number of additional times to test; delta == 0 means test only once. - unsigned delta = searchLength - matchLength; - - const UChar* searchCharacters = characters() + index; - - unsigned i = 0; - // keep looping until we match - while (!equalIgnoringCase(searchCharacters + i, matchString, matchLength)) { - if (i == delta) - return notFound; - ++i; - } - return index + i; -} - -template <typename CharType> -ALWAYS_INLINE static size_t findInner(const CharType* searchCharacters, const CharType* matchCharacters, unsigned index, unsigned searchLength, unsigned matchLength) -{ - // Optimization: keep a running hash of the strings, - // only call memcmp if the hashes match. - - // delta is the number of additional times to test; delta == 0 means test only once. - unsigned delta = searchLength - matchLength; - - unsigned searchHash = 0; - unsigned matchHash = 0; - - for (unsigned i = 0; i < matchLength; ++i) { - searchHash += searchCharacters[i]; - matchHash += matchCharacters[i]; - } - - unsigned i = 0; - // keep looping until we match - while (searchHash != matchHash || memcmp(searchCharacters + i, matchCharacters, matchLength * sizeof(CharType))) { - if (i == delta) - return notFound; - searchHash += searchCharacters[i + matchLength]; - searchHash -= searchCharacters[i]; - ++i; - } - return index + i; -} - -size_t StringImpl::find(StringImpl* matchString, unsigned index) -{ - // Check for null or empty string to match against - if (!matchString) - return notFound; - unsigned matchLength = matchString->length(); - if (!matchLength) - return min(index, length()); - - // Optimization 1: fast case for strings of length 1. - if (matchLength == 1) { - if (is8Bit() && matchString->is8Bit()) - return WTF::find(characters8(), length(), matchString->characters8()[0], index); - return WTF::find(characters(), length(), matchString->characters()[0], index); - } - - // Check index & matchLength are in range. - if (index > length()) - return notFound; - unsigned searchLength = length() - index; - if (matchLength > searchLength) - return notFound; - - if (is8Bit() && matchString->is8Bit()) - return findInner(characters8() + index, matchString->characters8(), index, searchLength, matchLength); - - return findInner(characters() + index, matchString->characters(), index, searchLength, matchLength); - -} - -size_t StringImpl::findIgnoringCase(StringImpl* matchString, unsigned index) -{ - // Check for null or empty string to match against - if (!matchString) - return notFound; - unsigned matchLength = matchString->length(); - if (!matchLength) - return min(index, length()); - - // Check index & matchLength are in range. - if (index > length()) - return notFound; - unsigned searchLength = length() - index; - if (matchLength > searchLength) - return notFound; - // delta is the number of additional times to test; delta == 0 means test only once. - unsigned delta = searchLength - matchLength; - - const UChar* searchCharacters = characters() + index; - const UChar* matchCharacters = matchString->characters(); - - unsigned i = 0; - // keep looping until we match - while (!equalIgnoringCase(searchCharacters + i, matchCharacters, matchLength)) { - if (i == delta) - return notFound; - ++i; - } - return index + i; -} - -size_t StringImpl::reverseFind(UChar c, unsigned index) -{ - if (is8Bit()) - return WTF::reverseFind(characters8(), m_length, c, index); - return WTF::reverseFind(characters16(), m_length, c, index); -} - -template <typename CharType> -ALWAYS_INLINE static size_t reverseFindInner(const CharType* searchCharacters, const CharType* matchCharacters, unsigned index, unsigned length, unsigned matchLength) -{ - // Optimization: keep a running hash of the strings, - // only call memcmp if the hashes match. - - // delta is the number of additional times to test; delta == 0 means test only once. - unsigned delta = min(index, length - matchLength); - - unsigned searchHash = 0; - unsigned matchHash = 0; - for (unsigned i = 0; i < matchLength; ++i) { - searchHash += searchCharacters[delta + i]; - matchHash += matchCharacters[i]; - } - - // keep looping until we match - while (searchHash != matchHash || memcmp(searchCharacters + delta, matchCharacters, matchLength * sizeof(CharType))) { - if (!delta) - return notFound; - delta--; - searchHash -= searchCharacters[delta + matchLength]; - searchHash += searchCharacters[delta]; - } - return delta; -} - -size_t StringImpl::reverseFind(StringImpl* matchString, unsigned index) -{ - // Check for null or empty string to match against - if (!matchString) - return notFound; - unsigned matchLength = matchString->length(); - unsigned ourLength = length(); - if (!matchLength) - return min(index, ourLength); - - // Optimization 1: fast case for strings of length 1. - if (matchLength == 1) { - if (is8Bit() && matchString->is8Bit()) - return WTF::reverseFind(characters8(), ourLength, matchString->characters8()[0], index); - return WTF::reverseFind(characters(), ourLength, matchString->characters()[0], index); - } - - // Check index & matchLength are in range. - if (matchLength > ourLength) - return notFound; - - if (is8Bit() && matchString->is8Bit()) - return reverseFindInner(characters8(), matchString->characters8(), index, ourLength, matchLength); - - return reverseFindInner(characters(), matchString->characters(), index, ourLength, matchLength); -} - -size_t StringImpl::reverseFindIgnoringCase(StringImpl* matchString, unsigned index) -{ - // Check for null or empty string to match against - if (!matchString) - return notFound; - unsigned matchLength = matchString->length(); - if (!matchLength) - return min(index, length()); - - // Check index & matchLength are in range. - if (matchLength > length()) - return notFound; - // delta is the number of additional times to test; delta == 0 means test only once. - unsigned delta = min(index, length() - matchLength); - - if (is8Bit() && matchString->is8Bit()) { - const LChar *searchCharacters = characters8(); - const LChar *matchCharacters = matchString->characters8(); - - // keep looping until we match - while (!equalIgnoringCase(searchCharacters + delta, matchCharacters, matchLength)) { - if (!delta) - return notFound; - delta--; - } - return delta; - } - - const UChar *searchCharacters = characters(); - const UChar *matchCharacters = matchString->characters(); - - // keep looping until we match - while (!equalIgnoringCase(searchCharacters + delta, matchCharacters, matchLength)) { - if (!delta) - return notFound; - delta--; - } - return delta; -} - -bool StringImpl::endsWith(StringImpl* matchString, bool caseSensitive) -{ - ASSERT(matchString); - if (m_length >= matchString->m_length) { - unsigned start = m_length - matchString->m_length; - return (caseSensitive ? find(matchString, start) : findIgnoringCase(matchString, start)) == 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) { - UChar c = is8Bit() ? m_data8[i] : m_data16[i]; - if (c == oldC) - break; - } - if (i == m_length) - return this; - - if (is8Bit()) { - if (oldC > 0xff) - // Looking for a 16 bit char in an 8 bit string, we're done. - return this; - - if (newC <= 0xff) { - LChar* data; - LChar oldChar = static_cast<LChar>(oldC); - LChar newChar = static_cast<LChar>(newC); - - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - - for (i = 0; i != m_length; ++i) { - LChar ch = m_data8[i]; - if (ch == oldChar) - ch = newChar; - data[i] = ch; - } - return newImpl.release(); - } - - // There is the possibility we need to up convert from 8 to 16 bit, - // create a 16 bit string for the result. - UChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - - for (i = 0; i != m_length; ++i) { - UChar ch = m_data8[i]; - if (ch == oldC) - ch = newC; - data[i] = ch; - } - - return newImpl.release(); - } - - UChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(m_length, data); - - for (i = 0; i != m_length; ++i) { - UChar ch = m_data16[i]; - if (ch == oldC) - ch = newC; - data[i] = ch; - } - return newImpl.release(); -} - -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; - - if ((length() - lengthToReplace) >= (numeric_limits<unsigned>::max() - lengthToInsert)) - CRASH(); - - if (is8Bit() && (!str || str->is8Bit())) { - LChar* data; - RefPtr<StringImpl> newImpl = - createUninitialized(length() - lengthToReplace + lengthToInsert, data); - memcpy(data, m_data8, position * sizeof(LChar)); - if (str) - memcpy(data + position, str->m_data8, lengthToInsert * sizeof(LChar)); - memcpy(data + position + lengthToInsert, m_data8 + position + lengthToReplace, - (length() - position - lengthToReplace) * sizeof(LChar)); - return newImpl.release(); - } - UChar* data; - RefPtr<StringImpl> newImpl = - createUninitialized(length() - lengthToReplace + lengthToInsert, data); - if (is8Bit()) - for (unsigned i = 0; i < position; i++) - data[i] = m_data8[i]; - else - memcpy(data, m_data16, position * sizeof(UChar)); - if (str) { - if (str->is8Bit()) - for (unsigned i = 0; i < lengthToInsert; i++) - data[i + position] = str->m_data8[i]; - else - memcpy(data + position, str->m_data16, lengthToInsert * sizeof(UChar)); - } - if (is8Bit()) { - for (unsigned i = 0; i < length() - position - lengthToReplace; i++) - data[i + position + lengthToInsert] = m_data8[i + position + lengthToReplace]; - } else { - memcpy(data + position + lengthToInsert, characters() + position + lengthToReplace, - (length() - position - lengthToReplace) * sizeof(UChar)); - } - return newImpl.release(); -} - -PassRefPtr<StringImpl> StringImpl::replace(UChar pattern, StringImpl* replacement) -{ - if (!replacement) - return this; - - unsigned repStrLength = replacement->length(); - size_t srcSegmentStart = 0; - unsigned matchCount = 0; - - // Count the matches. - while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) { - ++matchCount; - ++srcSegmentStart; - } - - // If we have 0 matches then we don't have to do any more work. - if (!matchCount) - return this; - - if (repStrLength && matchCount > numeric_limits<unsigned>::max() / repStrLength) - CRASH(); - - unsigned replaceSize = matchCount * repStrLength; - unsigned newSize = m_length - matchCount; - if (newSize >= (numeric_limits<unsigned>::max() - replaceSize)) - CRASH(); - - newSize += replaceSize; - - // Construct the new data. - size_t srcSegmentEnd; - unsigned srcSegmentLength; - srcSegmentStart = 0; - unsigned dstOffset = 0; - bool srcIs8Bit = is8Bit(); - bool replacementIs8Bit = replacement->is8Bit(); - - // There are 4 cases: - // 1. This and replacement are both 8 bit. - // 2. This and replacement are both 16 bit. - // 3. This is 8 bit and replacement is 16 bit. - // 4. This is 16 bit and replacement is 8 bit. - if (srcIs8Bit && replacementIs8Bit) { - // Case 1 - LChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(newSize, data); - - while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) { - srcSegmentLength = srcSegmentEnd - srcSegmentStart; - memcpy(data + dstOffset, m_data8 + srcSegmentStart, srcSegmentLength * sizeof(LChar)); - dstOffset += srcSegmentLength; - memcpy(data + dstOffset, replacement->m_data8, repStrLength * sizeof(LChar)); - dstOffset += repStrLength; - srcSegmentStart = srcSegmentEnd + 1; - } - - srcSegmentLength = m_length - srcSegmentStart; - memcpy(data + dstOffset, m_data8 + srcSegmentStart, srcSegmentLength * sizeof(LChar)); - - ASSERT(dstOffset + srcSegmentLength == newImpl->length()); - - return newImpl.release(); - } - - UChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(newSize, data); - - while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) { - srcSegmentLength = srcSegmentEnd - srcSegmentStart; - if (srcIs8Bit) { - // Case 3. - for (unsigned i = 0; i < srcSegmentLength; i++) - data[i + dstOffset] = m_data8[i + srcSegmentStart]; - } else { - // Cases 2 & 4. - memcpy(data + dstOffset, m_data16 + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - } - dstOffset += srcSegmentLength; - if (replacementIs8Bit) { - // Case 4. - for (unsigned i = 0; i < repStrLength; i++) - data[i + dstOffset] = replacement->m_data8[i]; - } else { - // Cases 2 & 3. - memcpy(data + dstOffset, replacement->m_data16, repStrLength * sizeof(UChar)); - } - dstOffset += repStrLength; - srcSegmentStart = srcSegmentEnd + 1; - } - - srcSegmentLength = m_length - srcSegmentStart; - if (srcIs8Bit) { - // Case 3. - for (unsigned i = 0; i < srcSegmentLength; i++) - data[i + dstOffset] = m_data8[i + srcSegmentStart]; - } else { - // Cases 2 & 4. - memcpy(data + dstOffset, m_data16 + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - } - - ASSERT(dstOffset + srcSegmentLength == newImpl->length()); - - return newImpl.release(); -} - -PassRefPtr<StringImpl> StringImpl::replace(StringImpl* pattern, StringImpl* replacement) -{ - if (!pattern || !replacement) - return this; - - unsigned patternLength = pattern->length(); - if (!patternLength) - return this; - - unsigned repStrLength = replacement->length(); - size_t srcSegmentStart = 0; - unsigned matchCount = 0; - - // Count the matches. - while ((srcSegmentStart = find(pattern, srcSegmentStart)) != notFound) { - ++matchCount; - srcSegmentStart += patternLength; - } - - // If we have 0 matches, we don't have to do any more work - if (!matchCount) - return this; - - unsigned newSize = m_length - matchCount * patternLength; - if (repStrLength && matchCount > numeric_limits<unsigned>::max() / repStrLength) - CRASH(); - - if (newSize > (numeric_limits<unsigned>::max() - matchCount * repStrLength)) - CRASH(); - - newSize += matchCount * repStrLength; - - - // Construct the new data - size_t srcSegmentEnd; - unsigned srcSegmentLength; - srcSegmentStart = 0; - unsigned dstOffset = 0; - bool srcIs8Bit = is8Bit(); - bool replacementIs8Bit = replacement->is8Bit(); - - // There are 4 cases: - // 1. This and replacement are both 8 bit. - // 2. This and replacement are both 16 bit. - // 3. This is 8 bit and replacement is 16 bit. - // 4. This is 16 bit and replacement is 8 bit. - if (srcIs8Bit && replacementIs8Bit) { - // Case 1 - LChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(newSize, data); - while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) { - srcSegmentLength = srcSegmentEnd - srcSegmentStart; - memcpy(data + dstOffset, m_data8 + srcSegmentStart, srcSegmentLength * sizeof(LChar)); - dstOffset += srcSegmentLength; - memcpy(data + dstOffset, replacement->m_data8, repStrLength * sizeof(LChar)); - dstOffset += repStrLength; - srcSegmentStart = srcSegmentEnd + patternLength; - } - - srcSegmentLength = m_length - srcSegmentStart; - memcpy(data + dstOffset, m_data8 + srcSegmentStart, srcSegmentLength * sizeof(LChar)); - - ASSERT(dstOffset + srcSegmentLength == newImpl->length()); - - return newImpl.release(); - } - - UChar* data; - RefPtr<StringImpl> newImpl = createUninitialized(newSize, data); - while ((srcSegmentEnd = find(pattern, srcSegmentStart)) != notFound) { - srcSegmentLength = srcSegmentEnd - srcSegmentStart; - if (srcIs8Bit) { - // Case 3. - for (unsigned i = 0; i < srcSegmentLength; i++) - data[i + dstOffset] = m_data8[i + srcSegmentStart]; - } else { - // Case 2 & 4. - memcpy(data + dstOffset, m_data16 + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - } - dstOffset += srcSegmentLength; - if (replacementIs8Bit) { - // Cases 2 & 3. - for (unsigned i = 0; i < repStrLength; i++) - data[i + dstOffset] = replacement->m_data8[i]; - } else { - // Case 4 - memcpy(data + dstOffset, replacement->m_data16, repStrLength * sizeof(UChar)); - } - dstOffset += repStrLength; - srcSegmentStart = srcSegmentEnd + patternLength; - } - - srcSegmentLength = m_length - srcSegmentStart; - if (srcIs8Bit) { - // Case 3. - for (unsigned i = 0; i < srcSegmentLength; i++) - data[i + dstOffset] = m_data8[i + srcSegmentStart]; - } else { - // Cases 2 & 4. - memcpy(data + dstOffset, m_data16 + srcSegmentStart, srcSegmentLength * sizeof(UChar)); - } - - ASSERT(dstOffset + srcSegmentLength == newImpl->length()); - - return newImpl.release(); -} - -bool equal(const StringImpl* a, const StringImpl* b) -{ - return StringHash::equal(a, b); -} - -bool equal(const StringImpl* a, const LChar* b, unsigned length) -{ - if (!a) - return !b; - if (!b) - return !a; - - if (length != a->length()) - return false; - - if (a->is8Bit()) - return equal(a->characters8(), b, length); - return equal(a->characters16(), b, length); -} - -bool equal(const StringImpl* a, const LChar* b) -{ - if (!a) - return !b; - if (!b) - return !a; - - unsigned length = a->length(); - - if (a->is8Bit()) { - const LChar* aPtr = a->characters8(); - for (unsigned i = 0; i != length; ++i) { - LChar bc = b[i]; - LChar ac = aPtr[i]; - if (!bc) - return false; - if (ac != bc) - return false; - } - - return !b[length]; - } - - const UChar* aPtr = a->characters16(); - for (unsigned i = 0; i != length; ++i) { - LChar bc = b[i]; - if (!bc) - return false; - if (aPtr[i] != bc) - return false; - } - - return !b[length]; -} - -bool equal(const StringImpl* a, const UChar* b, unsigned length) -{ - if (!a) - return !b; - if (!b) - return false; - - if (a->length() != length) - return false; - if (a->is8Bit()) - return equal(a->characters8(), b, length); - return equal(a->characters16(), b, length); -} - -bool equalIgnoringCase(StringImpl* a, StringImpl* b) -{ - return CaseFoldingHash::equal(a, b); -} - -bool equalIgnoringCase(StringImpl* a, const LChar* b) -{ - if (!a) - return !b; - if (!b) - return !a; - - unsigned length = a->length(); - - // Do a faster loop for the case where all the characters are ASCII. - UChar ored = 0; - bool equal = true; - if (a->is8Bit()) { - const LChar* as = a->characters8(); - for (unsigned i = 0; i != length; ++i) { - LChar 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) - equal = equal && (foldCase(as[i]) == foldCase(b[i])); - } - - return equal && !b[length]; - } - - const UChar* as = a->characters16(); - for (unsigned i = 0; i != length; ++i) { - LChar 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) { - equal = equal && (foldCase(as[i]) == foldCase(b[i])); - } - } - - 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; -} - -WTF::Unicode::Direction StringImpl::defaultWritingDirection(bool* hasStrongDirectionality) -{ - for (unsigned i = 0; i < m_length; ++i) { - WTF::Unicode::Direction charDirection = WTF::Unicode::direction(is8Bit() ? m_data8[i] : m_data16[i]); - if (charDirection == WTF::Unicode::LeftToRight) { - if (hasStrongDirectionality) - *hasStrongDirectionality = true; - return WTF::Unicode::LeftToRight; - } - if (charDirection == WTF::Unicode::RightToLeft || charDirection == WTF::Unicode::RightToLeftArabic) { - if (hasStrongDirectionality) - *hasStrongDirectionality = true; - return WTF::Unicode::RightToLeft; - } - } - if (hasStrongDirectionality) - *hasStrongDirectionality = false; - return WTF::Unicode::LeftToRight; -} - -PassRefPtr<StringImpl> StringImpl::adopt(StringBuffer<LChar>& buffer) -{ -unsigned length = buffer.length(); -if (!length) - return empty(); -return adoptRef(new StringImpl(buffer.release(), length)); -} - -PassRefPtr<StringImpl> StringImpl::adopt(StringBuffer<UChar>& buffer) -{ - unsigned length = buffer.length(); - if (!length) - 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 memory block. - unsigned length = string.m_length; - if (length >= numeric_limits<unsigned>::max()) - CRASH(); - RefPtr<StringImpl> terminatedString; - if (string.is8Bit()) { - LChar* data; - terminatedString = createUninitialized(length + 1, data); - memcpy(data, string.m_data8, length * sizeof(LChar)); - data[length] = 0; - } else { - UChar* data; - terminatedString = createUninitialized(length + 1, data); - memcpy(data, string.m_data16, length * sizeof(UChar)); - data[length] = 0; - } - terminatedString->m_length--; - terminatedString->m_hashAndFlags = (string.m_hashAndFlags & (~s_flagMask | s_hashFlag8BitBuffer)) | s_hashFlagHasTerminatingNullCharacter; - return terminatedString.release(); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/text/StringImpl.h b/Source/JavaScriptCore/wtf/text/StringImpl.h deleted file mode 100644 index 667335b86..000000000 --- a/Source/JavaScriptCore/wtf/text/StringImpl.h +++ /dev/null @@ -1,780 +0,0 @@ -/* - * 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/Forward.h> -#include <wtf/StdLibExtras.h> -#include <wtf/StringHasher.h> -#include <wtf/Vector.h> -#include <wtf/unicode/Unicode.h> - -#if USE(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; -namespace LLInt { class Data; } -class LLIntOffsetsExtractor; -template <typename T> struct IdentifierCharBufferTranslator; -struct IdentifierLCharFromUCharTranslator; -} - -namespace WTF { - -struct CStringTranslator; -struct HashAndCharactersTranslator; -struct HashAndUTF8CharactersTranslator; -struct SubstringTranslator; -struct UCharBufferTranslator; - -enum TextCaseSensitivity { TextCaseSensitive, TextCaseInsensitive }; - -typedef bool (*CharacterMatchFunctionPtr)(UChar); -typedef bool (*IsWhiteSpaceFunctionPtr)(UChar); - -class StringImpl { - WTF_MAKE_NONCOPYABLE(StringImpl); WTF_MAKE_FAST_ALLOCATED; - friend struct JSC::IdentifierCStringTranslator; - friend struct JSC::IdentifierCharBufferTranslator<LChar>; - friend struct JSC::IdentifierCharBufferTranslator<UChar>; - friend struct JSC::IdentifierLCharFromUCharTranslator; - friend struct WTF::CStringTranslator; - friend struct WTF::HashAndCharactersTranslator; - friend struct WTF::HashAndUTF8CharactersTranslator; - friend struct WTF::SubstringTranslator; - friend struct WTF::UCharBufferTranslator; - friend class AtomicStringImpl; - friend class JSC::LLInt::Data; - friend class JSC::LLIntOffsetsExtractor; - -private: - enum BufferOwnership { - BufferInternal, - BufferOwned, - BufferSubstring, - }; - - // Used to construct static strings, which have an special refCount that can never hit zero. - // This means that the static string will never be destroyed, which is important because - // static strings will be shared across threads & ref-counted in a non-threadsafe manner. - enum ConstructStaticStringTag { ConstructStaticString }; - StringImpl(const UChar* characters, unsigned length, ConstructStaticStringTag) - : m_refCount(s_refCountFlagIsStaticString) - , m_length(length) - , m_data16(characters) - , m_buffer(0) - , m_hashAndFlags(s_hashFlagIsIdentifier | BufferOwned) - { - // 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(); - } - - // 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 LChar* characters, unsigned length, ConstructStaticStringTag) - : m_refCount(s_refCountFlagIsStaticString) - , m_length(length) - , m_data8(characters) - , m_buffer(0) - , m_hashAndFlags(s_hashFlag8BitBuffer | s_hashFlagIsIdentifier | BufferOwned) - { - // 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(); - } - - // FIXME: there has to be a less hacky way to do this. - enum Force8Bit { Force8BitConstructor }; - // Create a normal 8-bit string with internal storage (BufferInternal) - StringImpl(unsigned length, Force8Bit) - : m_refCount(s_refCountIncrement) - , m_length(length) - , m_data8(reinterpret_cast<const LChar*>(this + 1)) - , m_buffer(0) - , m_hashAndFlags(s_hashFlag8BitBuffer | BufferInternal) - { - ASSERT(m_data8); - ASSERT(m_length); - } - - // Create a normal 16-bit string with internal storage (BufferInternal) - StringImpl(unsigned length) - : m_refCount(s_refCountIncrement) - , m_length(length) - , m_data16(reinterpret_cast<const UChar*>(this + 1)) - , m_buffer(0) - , m_hashAndFlags(BufferInternal) - { - ASSERT(m_data16); - ASSERT(m_length); - } - - // Create a StringImpl adopting ownership of the provided buffer (BufferOwned) - StringImpl(const LChar* characters, unsigned length) - : m_refCount(s_refCountIncrement) - , m_length(length) - , m_data8(characters) - , m_buffer(0) - , m_hashAndFlags(s_hashFlag8BitBuffer | BufferOwned) - { - ASSERT(m_data8); - ASSERT(m_length); - } - - // Create a StringImpl adopting ownership of the provided buffer (BufferOwned) - StringImpl(const UChar* characters, unsigned length) - : m_refCount(s_refCountIncrement) - , m_length(length) - , m_data16(characters) - , m_buffer(0) - , m_hashAndFlags(BufferOwned) - { - ASSERT(m_data16); - ASSERT(m_length); - } - - // Used to create new strings that are a substring of an existing 8-bit StringImpl (BufferSubstring) - StringImpl(const LChar* characters, unsigned length, PassRefPtr<StringImpl> base) - : m_refCount(s_refCountIncrement) - , m_length(length) - , m_data8(characters) - , m_substringBuffer(base.leakRef()) - , m_hashAndFlags(s_hashFlag8BitBuffer | BufferSubstring) - { - ASSERT(is8Bit()); - ASSERT(m_data8); - ASSERT(m_length); - ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring); - } - - // Used to create new strings that are a substring of an existing 16-bit StringImpl (BufferSubstring) - StringImpl(const UChar* characters, unsigned length, PassRefPtr<StringImpl> base) - : m_refCount(s_refCountIncrement) - , m_length(length) - , m_data16(characters) - , m_substringBuffer(base.leakRef()) - , m_hashAndFlags(BufferSubstring) - { - ASSERT(!is8Bit()); - ASSERT(m_data16); - ASSERT(m_length); - ASSERT(m_substringBuffer->bufferOwnership() != BufferSubstring); - } - -public: - WTF_EXPORT_PRIVATE ~StringImpl(); - - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> create(const UChar*, unsigned length); - static PassRefPtr<StringImpl> create(const LChar*, unsigned length); - ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s, unsigned length) { return create(reinterpret_cast<const LChar*>(s), length); } - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> create(const LChar*); - ALWAYS_INLINE static PassRefPtr<StringImpl> create(const char* s) { return create(reinterpret_cast<const LChar*>(s)); } - - static ALWAYS_INLINE PassRefPtr<StringImpl> create8(PassRefPtr<StringImpl> rep, unsigned offset, unsigned length) - { - ASSERT(rep); - ASSERT(length <= rep->length()); - - if (!length) - return empty(); - - ASSERT(rep->is8Bit()); - StringImpl* ownerRep = (rep->bufferOwnership() == BufferSubstring) ? rep->m_substringBuffer : rep.get(); - return adoptRef(new StringImpl(rep->m_data8 + offset, length, ownerRep)); - } - - static ALWAYS_INLINE 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(); - if (rep->is8Bit()) - return adoptRef(new StringImpl(rep->m_data8 + offset, length, ownerRep)); - return adoptRef(new StringImpl(rep->m_data16 + offset, length, ownerRep)); - } - - static PassRefPtr<StringImpl> createUninitialized(unsigned length, LChar*& data); - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> createUninitialized(unsigned length, UChar*& data); - template <typename T> static ALWAYS_INLINE PassRefPtr<StringImpl> tryCreateUninitialized(unsigned length, T*& output) - { - if (!length) { - output = 0; - return empty(); - } - - if (length > ((std::numeric_limits<unsigned>::max() - sizeof(StringImpl)) / sizeof(T))) { - output = 0; - return 0; - } - StringImpl* resultImpl; - if (!tryFastMalloc(sizeof(T) * length + sizeof(StringImpl)).getValue(resultImpl)) { - output = 0; - return 0; - } - output = reinterpret_cast<T*>(resultImpl + 1); - - if (sizeof(T) == sizeof(char)) - return adoptRef(new (NotNull, resultImpl) StringImpl(length, Force8BitConstructor)); - - return adoptRef(new (NotNull, resultImpl) StringImpl(length)); - } - - // Reallocate the StringImpl. The originalString must be only owned by the PassRefPtr, - // and the buffer ownership must be BufferInternal. Just like the input pointer of realloc(), - // the originalString can't be used after this function. - static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalString, unsigned length, LChar*& data); - static PassRefPtr<StringImpl> reallocate(PassRefPtr<StringImpl> originalString, unsigned length, UChar*& data); - - static unsigned flagsOffset() { return OBJECT_OFFSETOF(StringImpl, m_hashAndFlags); } - static unsigned flagIs8Bit() { return s_hashFlag8BitBuffer; } - static unsigned dataOffset() { return OBJECT_OFFSETOF(StringImpl, m_data8); } - static PassRefPtr<StringImpl> createWithTerminatingNullCharacter(const StringImpl&); - - template<typename CharType, size_t inlineCapacity> - static PassRefPtr<StringImpl> adopt(Vector<CharType, inlineCapacity>& vector) - { - if (size_t size = vector.size()) { - ASSERT(vector.data()); - if (size > std::numeric_limits<unsigned>::max()) - CRASH(); - return adoptRef(new StringImpl(vector.releaseBuffer(), size)); - } - return empty(); - } - - static PassRefPtr<StringImpl> adopt(StringBuffer<LChar>& buffer); - WTF_EXPORT_PRIVATE static PassRefPtr<StringImpl> adopt(StringBuffer<UChar>& buffer); - - unsigned length() const { return m_length; } - bool is8Bit() const { return m_hashAndFlags & s_hashFlag8BitBuffer; } - - // FIXME: Remove all unnecessary usages of characters() - ALWAYS_INLINE const LChar* characters8() const { ASSERT(is8Bit()); return m_data8; } - ALWAYS_INLINE const UChar* characters16() const { ASSERT(!is8Bit()); return m_data16; } - ALWAYS_INLINE const UChar* characters() const - { - if (!is8Bit()) - return m_data16; - - return getData16SlowCase(); - } - - template <typename CharType> - ALWAYS_INLINE const CharType * getCharacters() const; - - size_t cost() - { - // For substrings, return the cost of the base string. - if (bufferOwnership() == BufferSubstring) - return m_substringBuffer->cost(); - - if (m_hashAndFlags & s_hashFlagDidReportCost) - return 0; - - m_hashAndFlags |= s_hashFlagDidReportCost; - return m_length; - } - - bool has16BitShadow() const { return m_hashAndFlags & s_hashFlagHas16BitShadow; } - WTF_EXPORT_PRIVATE void upconvertCharacters(unsigned, unsigned) const; - bool isIdentifier() const { return m_hashAndFlags & s_hashFlagIsIdentifier; } - void setIsIdentifier(bool isIdentifier) - { - ASSERT(!isStatic()); - if (isIdentifier) - m_hashAndFlags |= s_hashFlagIsIdentifier; - else - m_hashAndFlags &= ~s_hashFlagIsIdentifier; - } - - bool hasTerminatingNullCharacter() const { return m_hashAndFlags & s_hashFlagHasTerminatingNullCharacter; } - - bool isAtomic() const { return m_hashAndFlags & s_hashFlagIsAtomic; } - void setIsAtomic(bool isIdentifier) - { - ASSERT(!isStatic()); - if (isIdentifier) - m_hashAndFlags |= s_hashFlagIsAtomic; - else - m_hashAndFlags &= ~s_hashFlagIsAtomic; - } - -private: - // The high bits of 'hash' are always empty, but we prefer to store our flags - // in the low bits because it makes them slightly more efficient to access. - // So, we shift left and right when setting and getting our hash code. - void setHash(unsigned hash) const - { - ASSERT(!hasHash()); - // Multiple clients assume that StringHasher is the canonical string hash function. - ASSERT(hash == (is8Bit() ? StringHasher::computeHash(m_data8, m_length) : StringHasher::computeHash(m_data16, m_length))); - ASSERT(!(hash & (s_flagMask << (8 * sizeof(hash) - s_flagCount)))); // Verify that enough high bits are empty. - - hash <<= s_flagCount; - ASSERT(!(hash & m_hashAndFlags)); // Verify that enough low bits are empty after shift. - ASSERT(hash); // Verify that 0 is a valid sentinel hash value. - - m_hashAndFlags |= hash; // Store hash with flags in low bits. - } - - unsigned rawHash() const - { - return m_hashAndFlags >> s_flagCount; - } - -public: - bool hasHash() const - { - return rawHash() != 0; - } - - unsigned existingHash() const - { - ASSERT(hasHash()); - return rawHash(); - } - - unsigned hash() const - { - if (hasHash()) - return existingHash(); - return hashSlowCase(); - } - - inline bool hasOneRef() const - { - return m_refCount == s_refCountIncrement; - } - - inline void ref() - { - m_refCount += s_refCountIncrement; - } - - inline void deref() - { - if (m_refCount == s_refCountIncrement) { - delete this; - return; - } - - m_refCount -= s_refCountIncrement; - } - - WTF_EXPORT_PRIVATE static StringImpl* empty(); - - // FIXME: Does this really belong in StringImpl? - template <typename T> static void copyChars(T* destination, const T* source, unsigned numCharacters) - { - if (numCharacters == 1) { - *destination = *source; - return; - } - - if (numCharacters <= s_copyCharsInlineCutOff) { - unsigned i = 0; -#if (CPU(X86) || CPU(X86_64)) - const unsigned charsPerInt = sizeof(uint32_t) / sizeof(T); - - if (numCharacters > charsPerInt) { - unsigned stopCount = numCharacters & ~(charsPerInt - 1); - - const uint32_t* srcCharacters = reinterpret_cast<const uint32_t*>(source); - uint32_t* destCharacters = reinterpret_cast<uint32_t*>(destination); - for (unsigned j = 0; i < stopCount; i += charsPerInt, ++j) - destCharacters[j] = srcCharacters[j]; - } -#endif - for (; i < numCharacters; ++i) - destination[i] = source[i]; - } else - memcpy(destination, source, numCharacters * sizeof(T)); - } - - // Some string features, like refcounting and the atomicity flag, are not - // thread-safe. We achieve thread safety by isolation, giving each thread - // its own copy of the string. - PassRefPtr<StringImpl> isolatedCopy() const; - - WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> substring(unsigned pos, unsigned len = UINT_MAX); - - UChar operator[](unsigned i) const - { - ASSERT(i < m_length); - if (is8Bit()) - return m_data8[i]; - return m_data16[i]; - } - WTF_EXPORT_PRIVATE UChar32 characterStartingAt(unsigned); - - WTF_EXPORT_PRIVATE 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); - - WTF_EXPORT_PRIVATE 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, bool* didReadNumber = 0); - float toFloat(bool* ok = 0, bool* didReadNumber = 0); - - WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> lower(); - WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> upper(); - - WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> fill(UChar); - // FIXME: Do we need fill(char) or can we just do the right thing if UChar is ASCII? - PassRefPtr<StringImpl> foldCase(); - - PassRefPtr<StringImpl> stripWhiteSpace(); - PassRefPtr<StringImpl> stripWhiteSpace(IsWhiteSpaceFunctionPtr); - WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> simplifyWhiteSpace(); - PassRefPtr<StringImpl> simplifyWhiteSpace(IsWhiteSpaceFunctionPtr); - - PassRefPtr<StringImpl> removeCharacters(CharacterMatchFunctionPtr); - template <typename CharType> - ALWAYS_INLINE PassRefPtr<StringImpl> removeCharacters(const CharType* characters, CharacterMatchFunctionPtr); - - WTF_EXPORT_PRIVATE size_t find(UChar, unsigned index = 0); - WTF_EXPORT_PRIVATE size_t find(CharacterMatchFunctionPtr, unsigned index = 0); - size_t find(const LChar*, unsigned index = 0); - ALWAYS_INLINE size_t find(const char* s, unsigned index = 0) { return find(reinterpret_cast<const LChar*>(s), index); }; - WTF_EXPORT_PRIVATE size_t find(StringImpl*, unsigned index = 0); - size_t findIgnoringCase(const LChar*, unsigned index = 0); - ALWAYS_INLINE size_t findIgnoringCase(const char* s, unsigned index = 0) { return findIgnoringCase(reinterpret_cast<const LChar*>(s), index); }; - WTF_EXPORT_PRIVATE size_t findIgnoringCase(StringImpl*, unsigned index = 0); - - WTF_EXPORT_PRIVATE size_t reverseFind(UChar, unsigned index = UINT_MAX); - WTF_EXPORT_PRIVATE size_t reverseFind(StringImpl*, unsigned index = UINT_MAX); - WTF_EXPORT_PRIVATE size_t reverseFindIgnoringCase(StringImpl*, unsigned index = UINT_MAX); - - bool startsWith(StringImpl* str, bool caseSensitive = true) { return (caseSensitive ? reverseFind(str, 0) : reverseFindIgnoringCase(str, 0)) == 0; } - WTF_EXPORT_PRIVATE bool endsWith(StringImpl*, bool caseSensitive = true); - - WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> replace(UChar, UChar); - WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> replace(UChar, StringImpl*); - WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> replace(StringImpl*, StringImpl*); - WTF_EXPORT_PRIVATE PassRefPtr<StringImpl> replace(unsigned index, unsigned len, StringImpl*); - - WTF_EXPORT_PRIVATE WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0); - -#if USE(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; - - BufferOwnership bufferOwnership() const { return static_cast<BufferOwnership>(m_hashAndFlags & s_hashMaskBufferOwnership); } - bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; } - template <class UCharPredicate> PassRefPtr<StringImpl> stripMatchedCharacters(UCharPredicate); - template <typename CharType, class UCharPredicate> PassRefPtr<StringImpl> simplifyMatchedCharactersToSpace(UCharPredicate); - WTF_EXPORT_PRIVATE NEVER_INLINE const UChar* getData16SlowCase() const; - WTF_EXPORT_PRIVATE NEVER_INLINE unsigned hashSlowCase() const; - - // The bottom bit in the ref count indicates a static (immortal) string. - static const unsigned s_refCountFlagIsStaticString = 0x1; - static const unsigned s_refCountIncrement = 0x2; // This allows us to ref / deref without disturbing the static string flag. - - // The bottom 8 bits in the hash are flags. - static const unsigned s_flagCount = 8; - static const unsigned s_flagMask = (1u << s_flagCount) - 1; - COMPILE_ASSERT(s_flagCount == StringHasher::flagCount, StringHasher_reserves_enough_bits_for_StringImpl_flags); - - static const unsigned s_hashFlagHas16BitShadow = 1u << 7; - static const unsigned s_hashFlag8BitBuffer = 1u << 6; - static const unsigned s_hashFlagHasTerminatingNullCharacter = 1u << 5; - static const unsigned s_hashFlagIsAtomic = 1u << 4; - static const unsigned s_hashFlagDidReportCost = 1u << 3; - static const unsigned s_hashFlagIsIdentifier = 1u << 2; - static const unsigned s_hashMaskBufferOwnership = 1u | (1u << 1); - - unsigned m_refCount; - unsigned m_length; - union { - const LChar* m_data8; - const UChar* m_data16; - }; - union { - void* m_buffer; - StringImpl* m_substringBuffer; - mutable UChar* m_copyData16; - }; - mutable unsigned m_hashAndFlags; -}; - -template <> -ALWAYS_INLINE const LChar* StringImpl::getCharacters<LChar>() const { return characters8(); } - -template <> -ALWAYS_INLINE const UChar* StringImpl::getCharacters<UChar>() const { return characters(); } - -WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const StringImpl*); -WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const LChar*); -inline bool equal(const StringImpl* a, const char* b) { return equal(a, reinterpret_cast<const LChar*>(b)); } -WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const LChar*, unsigned); -inline bool equal(const StringImpl* a, const char* b, unsigned length) { return equal(a, reinterpret_cast<const LChar*>(b), length); } -inline bool equal(const LChar* a, StringImpl* b) { return equal(b, a); } -inline bool equal(const char* a, StringImpl* b) { return equal(b, reinterpret_cast<const LChar*>(a)); } -WTF_EXPORT_PRIVATE bool equal(const StringImpl*, const UChar*, unsigned); - -// Do comparisons 8 or 4 bytes-at-a-time on architectures where it's safe. -#if CPU(X86_64) -ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length) -{ - unsigned dwordLength = length >> 3; - - if (dwordLength) { - const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a); - const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b); - - for (unsigned i = 0; i != dwordLength; ++i) { - if (*aDWordCharacters++ != *bDWordCharacters++) - return false; - } - - a = reinterpret_cast<const LChar*>(aDWordCharacters); - b = reinterpret_cast<const LChar*>(bDWordCharacters); - } - - if (length & 4) { - if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b)) - return false; - - a += 4; - b += 4; - } - - if (length & 2) { - if (*reinterpret_cast<const uint16_t*>(a) != *reinterpret_cast<const uint16_t*>(b)) - return false; - - a += 2; - b += 2; - } - - if (length & 1 && (*a != *b)) - return false; - - return true; -} - -ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length) -{ - unsigned dwordLength = length >> 2; - - if (dwordLength) { - const uint64_t* aDWordCharacters = reinterpret_cast<const uint64_t*>(a); - const uint64_t* bDWordCharacters = reinterpret_cast<const uint64_t*>(b); - - for (unsigned i = 0; i != dwordLength; ++i) { - if (*aDWordCharacters++ != *bDWordCharacters++) - return false; - } - - a = reinterpret_cast<const UChar*>(aDWordCharacters); - b = reinterpret_cast<const UChar*>(bDWordCharacters); - } - - if (length & 2) { - if (*reinterpret_cast<const uint32_t*>(a) != *reinterpret_cast<const uint32_t*>(b)) - return false; - - a += 2; - b += 2; - } - - if (length & 1 && (*a != *b)) - return false; - - return true; -} -#elif CPU(X86) -ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length) -{ - const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a); - const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b); - - unsigned wordLength = length >> 2; - for (unsigned i = 0; i != wordLength; ++i) { - if (*aCharacters++ != *bCharacters++) - return false; - } - - length &= 3; - - if (length) { - const LChar* aRemainder = reinterpret_cast<const LChar*>(aCharacters); - const LChar* bRemainder = reinterpret_cast<const LChar*>(bCharacters); - - for (unsigned i = 0; i < length; ++i) { - if (aRemainder[i] != bRemainder[i]) - return false; - } - } - - return true; -} - -ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length) -{ - const uint32_t* aCharacters = reinterpret_cast<const uint32_t*>(a); - const uint32_t* bCharacters = reinterpret_cast<const uint32_t*>(b); - - unsigned wordLength = length >> 1; - for (unsigned i = 0; i != wordLength; ++i) { - if (*aCharacters++ != *bCharacters++) - return false; - } - - if (length & 1 && *reinterpret_cast<const UChar*>(aCharacters) != *reinterpret_cast<const UChar*>(bCharacters)) - return false; - - return true; -} -#else -ALWAYS_INLINE bool equal(const LChar* a, const LChar* b, unsigned length) -{ - for (unsigned i = 0; i != length; ++i) { - if (a[i] != b[i]) - return false; - } - - return true; -} - -ALWAYS_INLINE bool equal(const UChar* a, const UChar* b, unsigned length) -{ - for (unsigned i = 0; i != length; ++i) { - if (a[i] != b[i]) - return false; - } - - return true; -} -#endif - -ALWAYS_INLINE bool equal(const LChar* a, const UChar* b, unsigned length) -{ - for (unsigned i = 0; i != length; ++i) { - if (a[i] != b[i]) - return false; - } - - return true; -} - -ALWAYS_INLINE bool equal(const UChar* a, const LChar* b, unsigned length) -{ - for (unsigned i = 0; i != length; ++i) { - if (a[i] != b[i]) - return false; - } - - return true; -} - -WTF_EXPORT_PRIVATE bool equalIgnoringCase(StringImpl*, StringImpl*); -WTF_EXPORT_PRIVATE bool equalIgnoringCase(StringImpl*, const LChar*); -inline bool equalIgnoringCase(const LChar* a, StringImpl* b) { return equalIgnoringCase(b, a); } -WTF_EXPORT_PRIVATE bool equalIgnoringCase(const LChar*, const LChar*, unsigned); -WTF_EXPORT_PRIVATE bool equalIgnoringCase(const UChar*, const LChar*, unsigned); -inline bool equalIgnoringCase(const UChar* a, const char* b, unsigned length) { return equalIgnoringCase(a, reinterpret_cast<const LChar*>(b), length); } -inline bool equalIgnoringCase(const LChar* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, a, length); } -inline bool equalIgnoringCase(const char* a, const UChar* b, unsigned length) { return equalIgnoringCase(b, reinterpret_cast<const LChar*>(a), length); } - -WTF_EXPORT_PRIVATE bool equalIgnoringNullity(StringImpl*, StringImpl*); - -template<size_t inlineCapacity> -bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>& a, StringImpl* b) -{ - if (!b) - return !a.size(); - if (a.size() != b->length()) - return false; - return !memcmp(a.data(), b->characters(), b->length() * sizeof(UChar)); -} - -WTF_EXPORT_PRIVATE int codePointCompare(const StringImpl*, const 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; -} - -inline PassRefPtr<StringImpl> StringImpl::isolatedCopy() const -{ - if (is8Bit()) - return create(m_data8, m_length); - return create(m_data16, m_length); -} - -struct StringHash; - -// StringHash is the default hash for StringImpl* and RefPtr<StringImpl> -template<typename T> struct DefaultHash; -template<> struct DefaultHash<StringImpl*> { - typedef StringHash Hash; -}; -template<> struct DefaultHash<RefPtr<StringImpl> > { - typedef StringHash Hash; -}; - -} - -using WTF::StringImpl; -using WTF::equal; -using WTF::TextCaseSensitivity; -using WTF::TextCaseSensitive; -using WTF::TextCaseInsensitive; - -#endif diff --git a/Source/JavaScriptCore/wtf/text/StringOperators.h b/Source/JavaScriptCore/wtf/text/StringOperators.h deleted file mode 100644 index 9e1637be1..000000000 --- a/Source/JavaScriptCore/wtf/text/StringOperators.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * Copyright (C) Research In Motion Limited 2011. 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 StringOperators_h -#define StringOperators_h - -namespace WTF { - -template<typename StringType1, typename StringType2> -class StringAppend { -public: - StringAppend(StringType1 string1, StringType2 string2) - : m_string1(string1) - , m_string2(string2) - { - } - - operator String() const - { - RefPtr<StringImpl> resultImpl = tryMakeString(m_string1, m_string2); - if (!resultImpl) - CRASH(); - return resultImpl.release(); - } - - operator AtomicString() const - { - return operator String(); - } - - bool is8Bit() - { - StringTypeAdapter<StringType1> adapter1(m_string1); - StringTypeAdapter<StringType2> adapter2(m_string2); - return adapter1.is8Bit() && adapter2.is8Bit(); - } - - void writeTo(LChar* destination) - { - ASSERT(is8Bit()); - StringTypeAdapter<StringType1> adapter1(m_string1); - StringTypeAdapter<StringType2> adapter2(m_string2); - adapter1.writeTo(destination); - adapter2.writeTo(destination + adapter1.length()); - } - - void writeTo(UChar* destination) - { - StringTypeAdapter<StringType1> adapter1(m_string1); - StringTypeAdapter<StringType2> adapter2(m_string2); - adapter1.writeTo(destination); - adapter2.writeTo(destination + adapter1.length()); - } - - unsigned length() - { - StringTypeAdapter<StringType1> adapter1(m_string1); - StringTypeAdapter<StringType2> adapter2(m_string2); - return adapter1.length() + adapter2.length(); - } - -private: - StringType1 m_string1; - StringType2 m_string2; -}; - -template<typename StringType1, typename StringType2> -class StringTypeAdapter<StringAppend<StringType1, StringType2> > { -public: - StringTypeAdapter<StringAppend<StringType1, StringType2> >(StringAppend<StringType1, StringType2>& buffer) - : m_buffer(buffer) - { - } - - unsigned length() { return m_buffer.length(); } - - bool is8Bit() { return m_buffer.is8Bit(); } - - void writeTo(LChar* destination) { m_buffer.writeTo(destination); } - void writeTo(UChar* destination) { m_buffer.writeTo(destination); } - -private: - StringAppend<StringType1, StringType2>& m_buffer; -}; - -inline StringAppend<const char*, String> operator+(const char* string1, const String& string2) -{ - return StringAppend<const char*, String>(string1, string2); -} - -inline StringAppend<const char*, AtomicString> operator+(const char* string1, const AtomicString& string2) -{ - return StringAppend<const char*, AtomicString>(string1, string2); -} - -template<typename U, typename V> -StringAppend<const char*, StringAppend<U, V> > operator+(const char* string1, const StringAppend<U, V>& string2) -{ - return StringAppend<const char*, StringAppend<U, V> >(string1, string2); -} - -inline StringAppend<const UChar*, String> operator+(const UChar* string1, const String& string2) -{ - return StringAppend<const UChar*, String>(string1, string2); -} - -inline StringAppend<const UChar*, AtomicString> operator+(const UChar* string1, const AtomicString& string2) -{ - return StringAppend<const UChar*, AtomicString>(string1, string2); -} - -template<typename U, typename V> -StringAppend<const UChar*, StringAppend<U, V> > operator+(const UChar* string1, const StringAppend<U, V>& string2) -{ - return StringAppend<const UChar*, StringAppend<U, V> >(string1, string2); -} - -template<typename T> -StringAppend<String, T> operator+(const String& string1, T string2) -{ - return StringAppend<String, T>(string1, string2); -} - -template<typename U, typename V, typename W> -StringAppend<StringAppend<U, V>, W> operator+(const StringAppend<U, V>& string1, W string2) -{ - return StringAppend<StringAppend<U, V>, W>(string1, string2); -} - -} // namespace WTF - -#endif // StringOperators_h diff --git a/Source/JavaScriptCore/wtf/text/StringStatics.cpp b/Source/JavaScriptCore/wtf/text/StringStatics.cpp deleted file mode 100644 index 1a80f6d48..000000000 --- a/Source/JavaScriptCore/wtf/text/StringStatics.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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. - */ - -#include "config.h" - -#ifdef SKIP_STATIC_CONSTRUCTORS_ON_GCC -#define ATOMICSTRING_HIDE_GLOBALS 1 -#endif - -#include "AtomicString.h" -#include "DynamicAnnotations.h" -#include "MainThread.h" -#include "StaticConstructors.h" -#include "StringImpl.h" - -namespace WTF { - -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 LChar emptyLCharData = 0; - DEFINE_STATIC_LOCAL(StringImpl, emptyString, (&emptyLCharData, 0, ConstructStaticString)); - WTF_ANNOTATE_BENIGN_RACE(&emptyString, "Benign race on StringImpl::emptyString reference counter"); - return &emptyString; -} - -WTF_EXPORTDATA DEFINE_GLOBAL(AtomicString, nullAtom) -WTF_EXPORTDATA DEFINE_GLOBAL(AtomicString, emptyAtom, "") -WTF_EXPORTDATA DEFINE_GLOBAL(AtomicString, textAtom, "#text") -WTF_EXPORTDATA DEFINE_GLOBAL(AtomicString, commentAtom, "#comment") -WTF_EXPORTDATA DEFINE_GLOBAL(AtomicString, starAtom, "*") -WTF_EXPORTDATA DEFINE_GLOBAL(AtomicString, xmlAtom, "xml") -WTF_EXPORTDATA DEFINE_GLOBAL(AtomicString, xmlnsAtom, "xmlns") - -NEVER_INLINE unsigned StringImpl::hashSlowCase() const -{ - if (is8Bit()) - setHash(StringHasher::computeHash(m_data8, m_length)); - else - setHash(StringHasher::computeHash(m_data16, m_length)); - return existingHash(); -} - -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 (NotNull, (void*)&nullAtom) AtomicString; - new (NotNull, (void*)&emptyAtom) AtomicString(""); - new (NotNull, (void*)&textAtom) AtomicString("#text"); - new (NotNull, (void*)&commentAtom) AtomicString("#comment"); - new (NotNull, (void*)&starAtom) AtomicString("*"); - new (NotNull, (void*)&xmlAtom) AtomicString("xml"); - new (NotNull, (void*)&xmlnsAtom) AtomicString("xmlns"); - - initialized = true; - } -} - -} diff --git a/Source/JavaScriptCore/wtf/text/TextPosition.h b/Source/JavaScriptCore/wtf/text/TextPosition.h deleted file mode 100644 index be49c157a..000000000 --- a/Source/JavaScriptCore/wtf/text/TextPosition.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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. - * - * 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 TextPosition_h -#define TextPosition_h - -#include <wtf/Assertions.h> - -namespace WTF { - -// An abstract number of element in a sequence. The sequence has a first element. -// This type should be used instead of integer because 2 contradicting traditions can -// call a first element '0' or '1' which makes integer type ambiguous. -class OrdinalNumber { -public: - static OrdinalNumber fromZeroBasedInt(int zeroBasedInt) { return OrdinalNumber(zeroBasedInt); } - static OrdinalNumber fromOneBasedInt(int oneBasedInt) { return OrdinalNumber(oneBasedInt - 1); } - OrdinalNumber() : m_zeroBasedValue(0) { } - - int zeroBasedInt() const { return m_zeroBasedValue; } - int oneBasedInt() const { return m_zeroBasedValue + 1; } - - bool operator==(OrdinalNumber other) { return m_zeroBasedValue == other.m_zeroBasedValue; } - bool operator!=(OrdinalNumber other) { return !((*this) == other); } - - static OrdinalNumber first() { return OrdinalNumber(0); } - static OrdinalNumber beforeFirst() { return OrdinalNumber(-1); } - -private: - OrdinalNumber(int zeroBasedInt) : m_zeroBasedValue(zeroBasedInt) { } - int m_zeroBasedValue; -}; - - -// TextPosition structure specifies coordinates within an text resource. It is used mostly -// for saving script source position. -class TextPosition { -public: - TextPosition(OrdinalNumber line, OrdinalNumber column) - : m_line(line) - , m_column(column) - { - } - TextPosition() { } - bool operator==(const TextPosition& other) { return m_line == other.m_line && m_column == other.m_column; } - bool operator!=(const TextPosition& other) { return !((*this) == other); } - - // A 'minimum' value of position, used as a default value. - static TextPosition minimumPosition() { return TextPosition(OrdinalNumber::first(), OrdinalNumber::first()); } - - // A value with line value less than a minimum; used as an impossible position. - static TextPosition belowRangePosition() { return TextPosition(OrdinalNumber::beforeFirst(), OrdinalNumber::beforeFirst()); } - - OrdinalNumber m_line; - OrdinalNumber m_column; -}; - -} - -using WTF::OrdinalNumber; - -using WTF::TextPosition; - -#endif // TextPosition_h diff --git a/Source/JavaScriptCore/wtf/text/WTFString.cpp b/Source/JavaScriptCore/wtf/text/WTFString.cpp deleted file mode 100644 index 04c970a7c..000000000 --- a/Source/JavaScriptCore/wtf/text/WTFString.cpp +++ /dev/null @@ -1,1147 +0,0 @@ -/* - * (C) 1999 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 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 <stdarg.h> -#include <wtf/ASCIICType.h> -#include <wtf/DataLog.h> -#include <wtf/MathExtras.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 std; - -namespace WTF { - -using namespace Unicode; -using namespace std; - -// Construct a string with UTF-16 data. -String::String(const UChar* characters, unsigned length) - : m_impl(characters ? StringImpl::create(characters, length) : 0) -{ -} - -// Construct a string with UTF-16 data, from a null-terminated source. -String::String(const UChar* str) -{ - if (!str) - return; - - size_t len = 0; - while (str[len] != UChar(0)) - len++; - - if (len > numeric_limits<unsigned>::max()) - CRASH(); - - m_impl = StringImpl::create(str, len); -} - -// Construct a string with latin1 data. -String::String(const LChar* characters, unsigned length) - : m_impl(characters ? StringImpl::create(characters, length) : 0) -{ -} - -String::String(const char* characters, unsigned length) - : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters), length) : 0) -{ -} - -// Construct a string with latin1 data, from a null-terminated source. -String::String(const LChar* characters) - : m_impl(characters ? StringImpl::create(characters) : 0) -{ -} - -String::String(const char* characters) - : m_impl(characters ? StringImpl::create(reinterpret_cast<const LChar*>(characters)) : 0) -{ -} - -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; - if (str.length() > numeric_limits<unsigned>::max() - m_impl->length()) - CRASH(); - 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(LChar 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; - if (m_impl->length() >= numeric_limits<unsigned>::max()) - CRASH(); - 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; - if (m_impl->length() >= numeric_limits<unsigned>::max()) - CRASH(); - 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); -} - -int codePointCompare(const String& a, const String& b) -{ - return codePointCompare(a.impl(), b.impl()); -} - -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; - if (lengthToAppend > numeric_limits<unsigned>::max() - length()) - CRASH(); - 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; - if (lengthToInsert > numeric_limits<unsigned>::max() - length()) - CRASH(); - 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(); -} - -UChar32 String::characterStartingAt(unsigned i) const -{ - if (!m_impl || i >= m_impl->length()) - return 0; - return m_impl->characterStartingAt(i); -} - -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::substringSharingImpl(unsigned offset, unsigned length) const -{ - // FIXME: We used to check against a limit of Heap::minExtraCost / sizeof(UChar). - - unsigned stringLength = this->length(); - offset = min(offset, stringLength); - length = min(length, stringLength - offset); - - if (!offset && length == stringLength) - return *this; - return String(StringImpl::create(m_impl, offset, length)); -} - -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::stripWhiteSpace(IsWhiteSpaceFunctionPtr isWhiteSpace) const -{ - if (!m_impl) - return String(); - return m_impl->stripWhiteSpace(isWhiteSpace); -} - -String String::simplifyWhiteSpace() const -{ - if (!m_impl) - return String(); - return m_impl->simplifyWhiteSpace(); -} - -String String::simplifyWhiteSpace(IsWhiteSpaceFunctionPtr isWhiteSpace) const -{ - if (!m_impl) - return String(); - return m_impl->simplifyWhiteSpace(isWhiteSpace); -} - -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::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); - - QByteArray ba = buffer.toUtf8(); - return StringImpl::create(reinterpret_cast<const LChar*>(ba.constData()), ba.length()); - -#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(reinterpret_cast<const LChar*>(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(reinterpret_cast<const LChar*>(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 number, unsigned flags, unsigned precision) -{ - NumberToStringBuffer buffer; - - // Mimic String::format("%.[precision]g", ...), but use dtoas rounding facilities. - if (flags & ShouldRoundSignificantFigures) - return String(numberToFixedPrecisionString(number, precision, buffer, flags & ShouldTruncateTrailingZeros)); - - // Mimic String::format("%.[precision]f", ...), but use dtoas rounding facilities. - return String(numberToFixedWidthString(number, precision, buffer)); -} - -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, bool* didReadNumber) const -{ - if (!m_impl) { - if (ok) - *ok = false; - if (didReadNumber) - *didReadNumber = false; - return 0.0; - } - return m_impl->toDouble(ok, didReadNumber); -} - -float String::toFloat(bool* ok, bool* didReadNumber) const -{ - if (!m_impl) { - if (ok) - *ok = false; - if (didReadNumber) - *didReadNumber = false; - return 0.0f; - } - return m_impl->toFloat(ok, didReadNumber); -} - -String String::isolatedCopy() const -{ - if (!m_impl) - return String(); - return m_impl->isolatedCopy(); -} - -void String::split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const -{ - result.clear(); - - unsigned startPos = 0; - size_t endPos; - while ((endPos = find(separator, startPos)) != notFound) { - if (allowEmptyEntries || startPos != endPos) - result.append(substring(startPos, endPos - startPos)); - startPos = endPos + separator.length(); - } - if (allowEmptyEntries || startPos != length()) - result.append(substring(startPos)); -} - -void String::split(const String& separator, Vector<String>& result) const -{ - split(separator, false, result); -} - -void String::split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const -{ - result.clear(); - - unsigned startPos = 0; - size_t endPos; - while ((endPos = find(separator, startPos)) != notFound) { - if (allowEmptyEntries || startPos != endPos) - result.append(substring(startPos, endPos - startPos)); - startPos = endPos + 1; - } - if (allowEmptyEntries || startPos != length()) - result.append(substring(startPos)); -} - -void String::split(UChar separator, Vector<String>& result) const -{ - split(String(&separator, 1), false, result); -} - -CString String::ascii() const -{ - // Printable ASCII characters 32..127 and the null character are - // preserved, characters outside of this range are converted to '?'. - - unsigned length = this->length(); - - if (!length) { - char* characterBuffer; - return CString::newUninitialized(length, characterBuffer); - } - - if (this->is8Bit()) { - const LChar* characters = this->characters8(); - - char* characterBuffer; - CString result = CString::newUninitialized(length, characterBuffer); - - for (unsigned i = 0; i < length; ++i) { - LChar ch = characters[i]; - characterBuffer[i] = ch && (ch < 0x20 || ch > 0x7f) ? '?' : ch; - } - - return result; - } - - const UChar* characters = this->characters16(); - - char* characterBuffer; - CString result = CString::newUninitialized(length, characterBuffer); - - for (unsigned i = 0; i < length; ++i) { - UChar ch = characters[i]; - characterBuffer[i] = ch && (ch < 0x20 || ch > 0x7f) ? '?' : ch; - } - - return result; -} - -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(); - - if (!length) - return CString("", 0); - - if (is8Bit()) - return CString(reinterpret_cast<const char*>(this->characters8()), 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 > 0xff ? '?' : 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(bool strict) const -{ - unsigned length = this->length(); - - if (!length) - return CString("", 0); - - // 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). - if (length > numeric_limits<unsigned>::max() / 3) - return CString(); - Vector<char, 1024> bufferVector(length * 3); - - char* buffer = bufferVector.data(); - - if (is8Bit()) { - const LChar* characters = this->characters8(); - - ConversionResult result = convertLatin1ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size()); - ASSERT_UNUSED(result, result != targetExhausted); // (length * 3) should be sufficient for any conversion - } else { - const UChar* characters = this->characters16(); - - ConversionResult result = convertUTF16ToUTF8(&characters, characters + length, &buffer, buffer + bufferVector.size(), strict); - ASSERT(result != targetExhausted); // (length * 3) should be sufficient for any conversion - - // Only produced from strict conversion. - if (result == sourceIllegal) - return CString(); - - // Check for an unconverted high surrogate. - if (result == sourceExhausted) { - if (strict) - return CString(); - // This should be one unpaired high surrogate. 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. - ASSERT((characters + 1) == (this->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 LChar* stringStart, size_t length) -{ - if (length > numeric_limits<unsigned>::max()) - CRASH(); - - 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 = reinterpret_cast<const char*>(stringStart); - if (convertUTF8ToUTF16(&stringCurrent, reinterpret_cast<const char *>(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 LChar* string) -{ - if (!string) - return String(); - return fromUTF8(string, strlen(reinterpret_cast<const char*>(string))); -} - -String String::fromUTF8WithLatin1Fallback(const LChar* 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, typename CharType> -static inline IntegralType toIntegralType(const CharType* data, size_t length, bool* ok, int base) -{ - static const IntegralType integralMax = numeric_limits<IntegralType>::max(); - static const bool isSigned = 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; - CharType 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; -} - -template <typename CharType> -static unsigned lengthOfCharactersAsInteger(const CharType* 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 LChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<int, LChar>(data, length, ok, base); -} - -int charactersToIntStrict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<int, UChar>(data, length, ok, base); -} - -unsigned charactersToUIntStrict(const LChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<unsigned, LChar>(data, length, ok, base); -} - -unsigned charactersToUIntStrict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<unsigned, UChar>(data, length, ok, base); -} - -int64_t charactersToInt64Strict(const LChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<int64_t, LChar>(data, length, ok, base); -} - -int64_t charactersToInt64Strict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<int64_t, UChar>(data, length, ok, base); -} - -uint64_t charactersToUInt64Strict(const LChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<uint64_t, LChar>(data, length, ok, base); -} - -uint64_t charactersToUInt64Strict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<uint64_t, UChar>(data, length, ok, base); -} - -intptr_t charactersToIntPtrStrict(const LChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<intptr_t, LChar>(data, length, ok, base); -} - -intptr_t charactersToIntPtrStrict(const UChar* data, size_t length, bool* ok, int base) -{ - return toIntegralType<intptr_t, UChar>(data, length, ok, base); -} - -int charactersToInt(const LChar* data, size_t length, bool* ok) -{ - return toIntegralType<int, LChar>(data, lengthOfCharactersAsInteger<LChar>(data, length), ok, 10); -} - -int charactersToInt(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<int, UChar>(data, lengthOfCharactersAsInteger(data, length), ok, 10); -} - -unsigned charactersToUInt(const LChar* data, size_t length, bool* ok) -{ - return toIntegralType<unsigned, LChar>(data, lengthOfCharactersAsInteger<LChar>(data, length), ok, 10); -} - -unsigned charactersToUInt(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<unsigned, UChar>(data, lengthOfCharactersAsInteger<UChar>(data, length), ok, 10); -} - -int64_t charactersToInt64(const LChar* data, size_t length, bool* ok) -{ - return toIntegralType<int64_t, LChar>(data, lengthOfCharactersAsInteger<LChar>(data, length), ok, 10); -} - -int64_t charactersToInt64(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<int64_t, UChar>(data, lengthOfCharactersAsInteger<UChar>(data, length), ok, 10); -} - -uint64_t charactersToUInt64(const LChar* data, size_t length, bool* ok) -{ - return toIntegralType<uint64_t, LChar>(data, lengthOfCharactersAsInteger<LChar>(data, length), ok, 10); -} - -uint64_t charactersToUInt64(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<uint64_t, UChar>(data, lengthOfCharactersAsInteger<UChar>(data, length), ok, 10); -} - -intptr_t charactersToIntPtr(const LChar* data, size_t length, bool* ok) -{ - return toIntegralType<intptr_t, LChar>(data, lengthOfCharactersAsInteger<LChar>(data, length), ok, 10); -} - -intptr_t charactersToIntPtr(const UChar* data, size_t length, bool* ok) -{ - return toIntegralType<intptr_t, UChar>(data, lengthOfCharactersAsInteger<UChar>(data, length), ok, 10); -} - -template <typename CharType, WTF::AllowTrailingJunkTag allowTrailingJunk> -static inline double toDoubleType(const CharType* data, size_t length, bool* ok, bool* didReadNumber) -{ - if (!length) { - if (ok) - *ok = false; - if (didReadNumber) - *didReadNumber = 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* start = bytes.data(); - char* end; - double val = WTF::strtod<allowTrailingJunk>(start, &end); - if (ok) - *ok = (end == 0 || *end == '\0') && !isnan(val); - if (didReadNumber) - *didReadNumber = end - start; - return val; -} - -double charactersToDouble(const LChar* data, size_t length, bool* ok, bool* didReadNumber) -{ - return toDoubleType<LChar, WTF::DisallowTrailingJunk>(data, length, ok, didReadNumber); -} - -double charactersToDouble(const UChar* data, size_t length, bool* ok, bool* didReadNumber) -{ - return toDoubleType<UChar, WTF::DisallowTrailingJunk>(data, length, ok, didReadNumber); -} - -float charactersToFloat(const LChar* data, size_t length, bool* ok, bool* didReadNumber) -{ - // FIXME: This will return ok even when the string fits into a double but not a float. - return static_cast<float>(toDoubleType<LChar, WTF::DisallowTrailingJunk>(data, length, ok, didReadNumber)); -} - -float charactersToFloat(const UChar* data, size_t length, bool* ok, bool* didReadNumber) -{ - // FIXME: This will return ok even when the string fits into a double but not a float. - return static_cast<float>(toDoubleType<UChar, WTF::DisallowTrailingJunk>(data, length, ok, didReadNumber)); -} - -float charactersToFloatIgnoringJunk(const LChar* data, size_t length, bool* ok, bool* didReadNumber) -{ - // FIXME: This will return ok even when the string fits into a double but not a float. - return static_cast<float>(toDoubleType<LChar, WTF::AllowTrailingJunk>(data, length, ok, didReadNumber)); -} - -float charactersToFloatIgnoringJunk(const UChar* data, size_t length, bool* ok, bool* didReadNumber) -{ - // FIXME: This will return ok even when the string fits into a double but not a float. - return static_cast<float>(toDoubleType<UChar, WTF::AllowTrailingJunk>(data, length, ok, didReadNumber)); -} - -const String& emptyString() -{ - DEFINE_STATIC_LOCAL(String, emptyString, (StringImpl::empty())); - return emptyString; -} - -} // namespace WTF - -#ifndef NDEBUG -// For use in the debugger -String* string(const char*); -Vector<char> asciiDebug(StringImpl* impl); -Vector<char> asciiDebug(String& string); - -void String::show() const -{ - dataLog("%s\n", asciiDebug(impl()).data()); -} - -String* string(const char* s) -{ - // leaks memory! - return new String(s); -} - -Vector<char> asciiDebug(StringImpl* impl) -{ - if (!impl) - return asciiDebug(String("[null]").impl()); - - Vector<char> buffer; - unsigned length = impl->length(); - const UChar* characters = impl->characters(); - - buffer.resize(length + 1); - for (unsigned i = 0; i < length; ++i) { - UChar ch = characters[i]; - buffer[i] = ch && (ch < 0x20 || ch > 0x7f) ? '?' : ch; - } - buffer[length] = '\0'; - - return buffer; -} - -Vector<char> asciiDebug(String& string) -{ - return asciiDebug(string.impl()); -} - -#endif diff --git a/Source/JavaScriptCore/wtf/text/WTFString.h b/Source/JavaScriptCore/wtf/text/WTFString.h deleted file mode 100644 index 85e223f9e..000000000 --- a/Source/JavaScriptCore/wtf/text/WTFString.h +++ /dev/null @@ -1,650 +0,0 @@ -/* - * (C) 1999 Lars Knoll (knoll@kde.org) - * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef 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 <wtf/text/ASCIIFastPath.h> -#include <wtf/text/StringImpl.h> - -#ifdef __OBJC__ -#include <objc/objc.h> -#endif - -#if USE(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(BLACKBERRY) -namespace BlackBerry { -namespace WebKit { - class WebString; -} -} -#endif - -namespace WTF { - -class CString; -struct StringHash; - -// Declarations of string operations - -int charactersToIntStrict(const LChar*, size_t, bool* ok = 0, int base = 10); -WTF_EXPORT_PRIVATE int charactersToIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10); -unsigned charactersToUIntStrict(const LChar*, size_t, bool* ok = 0, int base = 10); -WTF_EXPORT_PRIVATE unsigned charactersToUIntStrict(const UChar*, size_t, bool* ok = 0, int base = 10); -int64_t charactersToInt64Strict(const LChar*, 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 LChar*, 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 LChar*, size_t, bool* ok = 0, int base = 10); -intptr_t charactersToIntPtrStrict(const UChar*, size_t, bool* ok = 0, int base = 10); - -int charactersToInt(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage -WTF_EXPORT_PRIVATE int charactersToInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage -unsigned charactersToUInt(const LChar*, size_t, bool* ok = 0); // ignores trailing garbage -unsigned charactersToUInt(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage -int64_t charactersToInt64(const LChar*, 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 LChar*, 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 LChar*, size_t, bool* ok = 0); // ignores trailing garbage -intptr_t charactersToIntPtr(const UChar*, size_t, bool* ok = 0); // ignores trailing garbage - -WTF_EXPORT_PRIVATE double charactersToDouble(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); -WTF_EXPORT_PRIVATE double charactersToDouble(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); -float charactersToFloat(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); -WTF_EXPORT_PRIVATE float charactersToFloatIgnoringJunk(const LChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); -WTF_EXPORT_PRIVATE float charactersToFloat(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); -WTF_EXPORT_PRIVATE float charactersToFloatIgnoringJunk(const UChar*, size_t, bool* ok = 0, bool* didReadNumber = 0); - -enum FloatConversionFlags { - ShouldRoundSignificantFigures = 1 << 0, - ShouldRoundDecimalPlaces = 1 << 1, - ShouldTruncateTrailingZeros = 1 << 2 -}; - -template<bool isSpecialCharacter(UChar)> bool isAllSpecialCharacters(const UChar*, size_t); - -class String { -public: - // Construct a null string, distinguishable from an empty string. - String() { } - - // Construct a string with UTF-16 data. - WTF_EXPORT_PRIVATE String(const UChar* characters, unsigned length); - - // Construct a string by copying the contents of a vector. To avoid - // copying, consider using String::adopt instead. - template<size_t inlineCapacity> - explicit String(const Vector<UChar, inlineCapacity>&); - - // Construct a string with UTF-16 data, from a null-terminated source. - WTF_EXPORT_PRIVATE String(const UChar*); - - // Construct a string with latin1 data. - WTF_EXPORT_PRIVATE String(const LChar* characters, unsigned length); - WTF_EXPORT_PRIVATE String(const char* characters, unsigned length); - - // Construct a string with latin1 data, from a null-terminated source. - WTF_EXPORT_PRIVATE String(const LChar* characters); - WTF_EXPORT_PRIVATE String(const char* characters); - - // Construct a string referencing an existing StringImpl. - String(StringImpl* impl) : m_impl(impl) { } - String(PassRefPtr<StringImpl> impl) : m_impl(impl) { } - String(RefPtr<StringImpl> impl) : m_impl(impl) { } - - // Inline the destructor. - ALWAYS_INLINE ~String() { } - - void swap(String& o) { m_impl.swap(o.m_impl); } - - static String adopt(StringBuffer<LChar>& buffer) { return StringImpl::adopt(buffer); } - static String adopt(StringBuffer<UChar>& buffer) { return StringImpl::adopt(buffer); } - template<size_t inlineCapacity> - static String adopt(Vector<UChar, inlineCapacity>& vector) { return StringImpl::adopt(vector); } - - bool isNull() const { return !m_impl; } - bool isEmpty() const { return !m_impl || !m_impl->length(); } - - StringImpl* impl() const { return m_impl.get(); } - - unsigned length() const - { - if (!m_impl) - return 0; - return m_impl->length(); - } - - const UChar* characters() const - { - if (!m_impl) - return 0; - return m_impl->characters(); - } - - const LChar* characters8() const - { - if (!m_impl) - return 0; - ASSERT(m_impl->is8Bit()); - return m_impl->characters8(); - } - - const UChar* characters16() const - { - if (!m_impl) - return 0; - ASSERT(!m_impl->is8Bit()); - return m_impl->characters16(); - } - - template <typename CharType> - inline const CharType* getCharacters() const; - - bool is8Bit() const { return m_impl->is8Bit(); } - - WTF_EXPORT_PRIVATE CString ascii() const; - WTF_EXPORT_PRIVATE CString latin1() const; - WTF_EXPORT_PRIVATE CString utf8(bool strict = false) const; - - UChar operator[](unsigned index) const - { - if (!m_impl || index >= m_impl->length()) - return 0; - return m_impl->characters()[index]; - } - - static String number(short); - WTF_EXPORT_PRIVATE static String number(unsigned short); - WTF_EXPORT_PRIVATE static String number(int); - WTF_EXPORT_PRIVATE static String number(unsigned); - WTF_EXPORT_PRIVATE static String number(long); - WTF_EXPORT_PRIVATE static String number(unsigned long); - WTF_EXPORT_PRIVATE static String number(long long); - WTF_EXPORT_PRIVATE static String number(unsigned long long); - WTF_EXPORT_PRIVATE static String number(double, unsigned = ShouldRoundSignificantFigures | ShouldTruncateTrailingZeros, unsigned precision = 6); - - // Find a single character or string, also with match function & latin1 forms. - size_t find(UChar c, unsigned start = 0) const - { return m_impl ? m_impl->find(c, start) : notFound; } - size_t find(const String& str, unsigned start = 0) const - { return m_impl ? m_impl->find(str.impl(), start) : notFound; } - size_t find(CharacterMatchFunctionPtr matchFunction, unsigned start = 0) const - { return m_impl ? m_impl->find(matchFunction, start) : notFound; } - size_t find(const LChar* str, unsigned start = 0) const - { return m_impl ? m_impl->find(str, start) : notFound; } - - // Find the last instance of a single character or string. - size_t reverseFind(UChar c, unsigned start = UINT_MAX) const - { return m_impl ? m_impl->reverseFind(c, start) : notFound; } - size_t reverseFind(const String& str, unsigned start = UINT_MAX) const - { return m_impl ? m_impl->reverseFind(str.impl(), start) : notFound; } - - // Case insensitive string matching. - size_t findIgnoringCase(const LChar* str, unsigned start = 0) const - { return m_impl ? m_impl->findIgnoringCase(str, start) : notFound; } - size_t findIgnoringCase(const String& str, unsigned start = 0) const - { return m_impl ? m_impl->findIgnoringCase(str.impl(), start) : notFound; } - size_t reverseFindIgnoringCase(const String& str, unsigned start = UINT_MAX) const - { return m_impl ? m_impl->reverseFindIgnoringCase(str.impl(), start) : notFound; } - - // Wrappers for find & reverseFind adding dynamic sensitivity check. - size_t find(const LChar* str, unsigned start, bool caseSensitive) const - { return caseSensitive ? find(str, start) : findIgnoringCase(str, start); } - size_t find(const String& str, unsigned start, bool caseSensitive) const - { return caseSensitive ? find(str, start) : findIgnoringCase(str, start); } - size_t reverseFind(const String& str, unsigned start, bool caseSensitive) const - { return caseSensitive ? reverseFind(str, start) : reverseFindIgnoringCase(str, start); } - - WTF_EXPORT_PRIVATE const UChar* charactersWithNullTermination(); - - WTF_EXPORT_PRIVATE UChar32 characterStartingAt(unsigned) const; // Ditto. - - bool contains(UChar c) const { return find(c) != notFound; } - bool contains(const LChar* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; } - bool contains(const String& str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; } - - 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(); } - - WTF_EXPORT_PRIVATE void append(const String&); - WTF_EXPORT_PRIVATE void append(LChar); - void append(char c) { append(static_cast<LChar>(c)); }; - WTF_EXPORT_PRIVATE void append(UChar); - WTF_EXPORT_PRIVATE void append(const UChar*, unsigned length); - WTF_EXPORT_PRIVATE 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 fill(UChar c) { if (m_impl) m_impl = m_impl->fill(c); } - - WTF_EXPORT_PRIVATE void truncate(unsigned len); - WTF_EXPORT_PRIVATE void remove(unsigned pos, int len = 1); - - WTF_EXPORT_PRIVATE String substring(unsigned pos, unsigned len = UINT_MAX) const; - String substringSharingImpl(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 - WTF_EXPORT_PRIVATE String lower() const; - WTF_EXPORT_PRIVATE String upper() const; - - WTF_EXPORT_PRIVATE String stripWhiteSpace() const; - WTF_EXPORT_PRIVATE String stripWhiteSpace(IsWhiteSpaceFunctionPtr) const; - WTF_EXPORT_PRIVATE String simplifyWhiteSpace() const; - WTF_EXPORT_PRIVATE String simplifyWhiteSpace(IsWhiteSpaceFunctionPtr) const; - - WTF_EXPORT_PRIVATE String removeCharacters(CharacterMatchFunctionPtr) const; - template<bool isSpecialCharacter(UChar)> bool isAllSpecialCharacters() const; - - // Return the string with case folded for case insensitive comparison. - WTF_EXPORT_PRIVATE String foldCase() const; - -#if !PLATFORM(QT) - WTF_EXPORT_PRIVATE static String format(const char *, ...) WTF_ATTRIBUTE_PRINTF(1, 2); -#else - WTF_EXPORT_PRIVATE static String format(const char *, ...); -#endif - - // 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); } - - WTF_EXPORT_PRIVATE void split(const String& separator, Vector<String>& result) const; - WTF_EXPORT_PRIVATE void split(const String& separator, bool allowEmptyEntries, Vector<String>& result) const; - WTF_EXPORT_PRIVATE void split(UChar separator, Vector<String>& result) const; - WTF_EXPORT_PRIVATE void split(UChar separator, bool allowEmptyEntries, Vector<String>& result) const; - - WTF_EXPORT_PRIVATE int toIntStrict(bool* ok = 0, int base = 10) const; - WTF_EXPORT_PRIVATE unsigned toUIntStrict(bool* ok = 0, int base = 10) const; - WTF_EXPORT_PRIVATE 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; - - WTF_EXPORT_PRIVATE int toInt(bool* ok = 0) const; - WTF_EXPORT_PRIVATE unsigned toUInt(bool* ok = 0) const; - int64_t toInt64(bool* ok = 0) const; - WTF_EXPORT_PRIVATE uint64_t toUInt64(bool* ok = 0) const; - WTF_EXPORT_PRIVATE intptr_t toIntPtr(bool* ok = 0) const; - WTF_EXPORT_PRIVATE double toDouble(bool* ok = 0, bool* didReadNumber = 0) const; - WTF_EXPORT_PRIVATE float toFloat(bool* ok = 0, bool* didReadNumber = 0) const; - - bool percentage(int& percentage) const; - - WTF_EXPORT_PRIVATE String isolatedCopy() const; - - // Prevent Strings from being implicitly convertable to bool as it will be ambiguous on any platform that - // allows implicit conversion to another pointer type (e.g., Mac allows implicit conversion to NSString*). - typedef struct ImplicitConversionFromWTFStringToBoolDisallowedA* (String::*UnspecifiedBoolTypeA); - typedef struct ImplicitConversionFromWTFStringToBoolDisallowedB* (String::*UnspecifiedBoolTypeB); - operator UnspecifiedBoolTypeA() const; - operator UnspecifiedBoolTypeB() const; - -#if USE(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) - WTF_EXPORT_PRIVATE String(const wxString&); - WTF_EXPORT_PRIVATE operator wxString() const; -#endif - -#if PLATFORM(BLACKBERRY) - String(const BlackBerry::WebKit::WebString&); - operator BlackBerry::WebKit::WebString() const; -#endif - - // String::fromUTF8 will return a null string if - // the input data contains invalid UTF-8 sequences. - WTF_EXPORT_PRIVATE static String fromUTF8(const LChar*, size_t); - WTF_EXPORT_PRIVATE static String fromUTF8(const LChar*); - static String fromUTF8(const char* s, size_t length) { return fromUTF8(reinterpret_cast<const LChar*>(s), length); }; - static String fromUTF8(const char* s) { return fromUTF8(reinterpret_cast<const LChar*>(s)); }; - - // 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. - WTF_EXPORT_PRIVATE static String fromUTF8WithLatin1Fallback(const LChar*, size_t); - static String fromUTF8WithLatin1Fallback(const char* s, size_t length) { return fromUTF8WithLatin1Fallback(reinterpret_cast<const LChar*>(s), length); }; - - // Determines the writing direction using the Unicode Bidi Algorithm rules P2 and P3. - WTF::Unicode::Direction defaultWritingDirection(bool* hasStrongDirectionality = 0) const - { - if (m_impl) - return m_impl->defaultWritingDirection(hasStrongDirectionality); - if (hasStrongDirectionality) - *hasStrongDirectionality = false; - return WTF::Unicode::LeftToRight; - } - - bool containsOnlyASCII() const; - bool containsOnlyLatin1() const; - bool containsOnlyWhitespace() const { return !m_impl || m_impl->containsOnlyWhitespace(); } - - // 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(); } - -#ifndef NDEBUG - void show() const; -#endif - -private: - RefPtr<StringImpl> m_impl; -}; - -#if PLATFORM(QT) -QDataStream& operator<<(QDataStream& stream, const String& str); -QDataStream& operator>>(QDataStream& stream, String& str); -#endif - -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 LChar* b) { return equal(a.impl(), b); } -inline bool operator==(const String& a, const char* b) { return equal(a.impl(), reinterpret_cast<const LChar*>(b)); } -inline bool operator==(const LChar* a, const String& b) { return equal(a, b.impl()); } -inline bool operator==(const char* a, const String& b) { return equal(reinterpret_cast<const LChar*>(a), b.impl()); } -template<size_t inlineCapacity> -inline bool operator==(const Vector<char, inlineCapacity>& a, const String& b) { return equal(b.impl(), a.data(), a.size()); } -template<size_t inlineCapacity> -inline bool operator==(const String& a, const Vector<char, inlineCapacity>& b) { return b == a; } - - -inline bool operator!=(const String& a, const String& b) { return !equal(a.impl(), b.impl()); } -inline bool operator!=(const String& a, const LChar* b) { return !equal(a.impl(), b); } -inline bool operator!=(const String& a, const char* b) { return !equal(a.impl(), reinterpret_cast<const LChar*>(b)); } -inline bool operator!=(const LChar* a, const String& b) { return !equal(a, b.impl()); } -inline bool operator!=(const char* a, const String& b) { return !equal(reinterpret_cast<const LChar*>(a), b.impl()); } -template<size_t inlineCapacity> -inline bool operator!=(const Vector<char, inlineCapacity>& a, const String& b) { return !(a == b); } -template<size_t inlineCapacity> -inline bool operator!=(const String& a, const Vector<char, inlineCapacity>& b) { return b != a; } - -inline bool equalIgnoringCase(const String& a, const String& b) { return equalIgnoringCase(a.impl(), b.impl()); } -inline bool equalIgnoringCase(const String& a, const LChar* b) { return equalIgnoringCase(a.impl(), b); } -inline bool equalIgnoringCase(const String& a, const char* b) { return equalIgnoringCase(a.impl(), reinterpret_cast<const LChar*>(b)); } -inline bool equalIgnoringCase(const LChar* a, const String& b) { return equalIgnoringCase(a, b.impl()); } -inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(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()); } - -template<size_t inlineCapacity> -inline bool equalIgnoringNullity(const Vector<UChar, inlineCapacity>& a, const String& b) { return equalIgnoringNullity(a, 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 - -template<size_t inlineCapacity> -String::String(const Vector<UChar, inlineCapacity>& vector) - : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) : 0) -{ -} - -template<> -inline const LChar* String::getCharacters<LChar>() const -{ - ASSERT(is8Bit()); - return characters8(); -} - -template<> -inline const UChar* String::getCharacters<UChar>() const -{ - ASSERT(!is8Bit()); - return characters16(); -} - -inline bool String::containsOnlyLatin1() const -{ - if (isEmpty()) - return true; - - if (is8Bit()) - return true; - - const UChar* characters = characters16(); - UChar ored = 0; - for (size_t i = 0; i < m_impl->length(); ++i) - ored |= characters[i]; - return !(ored & 0xFF00); -} - - -#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 String::containsOnlyASCII() const -{ - if (isEmpty()) - return true; - - if (is8Bit()) - return charactersAreAllASCII(characters8(), m_impl->length()); - - return charactersAreAllASCII(characters16(), m_impl->length()); -} - -WTF_EXPORT_PRIVATE int codePointCompare(const String&, const String&); - -inline bool codePointCompareLessThan(const String& a, const String& b) -{ - return codePointCompare(a.impl(), b.impl()) < 0; -} - -inline size_t find(const LChar* characters, unsigned length, LChar matchCharacter, unsigned index = 0) -{ - while (index < length) { - if (characters[index] == matchCharacter) - return index; - ++index; - } - return notFound; -} - -inline size_t find(const UChar* characters, unsigned length, UChar matchCharacter, unsigned index = 0) -{ - while (index < length) { - if (characters[index] == matchCharacter) - return index; - ++index; - } - return notFound; -} - -inline size_t find(const LChar* characters, unsigned length, CharacterMatchFunctionPtr matchFunction, unsigned index = 0) -{ - while (index < length) { - if (matchFunction(characters[index])) - return index; - ++index; - } - return notFound; -} - -inline size_t find(const UChar* characters, unsigned length, CharacterMatchFunctionPtr matchFunction, unsigned index = 0) -{ - while (index < length) { - if (matchFunction(characters[index])) - return index; - ++index; - } - return notFound; -} - -inline size_t reverseFind(const LChar* characters, unsigned length, LChar matchCharacter, unsigned index = UINT_MAX) -{ - if (!length) - return notFound; - if (index >= length) - index = length - 1; - while (characters[index] != matchCharacter) { - if (!index--) - return notFound; - } - return index; -} - -inline size_t reverseFind(const UChar* characters, unsigned length, UChar matchCharacter, unsigned index = UINT_MAX) -{ - if (!length) - return notFound; - if (index >= length) - index = length - 1; - while (characters[index] != matchCharacter) { - if (!index--) - return notFound; - } - return index; -} - -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'; - } -} - -template<bool isSpecialCharacter(UChar)> inline bool isAllSpecialCharacters(const UChar* characters, size_t length) -{ - for (size_t i = 0; i < length; ++i) { - if (!isSpecialCharacter(characters[i])) - return false; - } - return true; -} - -template<bool isSpecialCharacter(UChar)> inline bool String::isAllSpecialCharacters() const -{ - return WTF::isAllSpecialCharacters<isSpecialCharacter>(characters(), length()); -} - -// StringHash is the default hash for String -template<typename T> struct DefaultHash; -template<> struct DefaultHash<String> { - typedef StringHash Hash; -}; - -template <> struct VectorTraits<String> : SimpleClassVectorTraits { }; - -// Shared global empty string. -WTF_EXPORT_PRIVATE const String& emptyString(); - -} - -using WTF::CString; -using WTF::String; -using WTF::emptyString; -using WTF::append; -using WTF::appendNumber; -using WTF::charactersAreAllASCII; -using WTF::charactersToIntStrict; -using WTF::charactersToUIntStrict; -using WTF::charactersToInt64Strict; -using WTF::charactersToUInt64Strict; -using WTF::charactersToIntPtrStrict; -using WTF::charactersToInt; -using WTF::charactersToUInt; -using WTF::charactersToInt64; -using WTF::charactersToUInt64; -using WTF::charactersToIntPtr; -using WTF::charactersToDouble; -using WTF::charactersToFloat; -using WTF::equal; -using WTF::equalIgnoringCase; -using WTF::find; -using WTF::isAllSpecialCharacters; -using WTF::isSpaceOrNewline; -using WTF::reverseFind; -using WTF::ShouldRoundDecimalPlaces; - -#include <wtf/text/AtomicString.h> -#endif diff --git a/Source/JavaScriptCore/wtf/threads/BinarySemaphore.cpp b/Source/JavaScriptCore/wtf/threads/BinarySemaphore.cpp deleted file mode 100644 index 5f60aaf22..000000000 --- a/Source/JavaScriptCore/wtf/threads/BinarySemaphore.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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 "BinarySemaphore.h" - -#if !PLATFORM(WIN) - -namespace WTF { - -BinarySemaphore::BinarySemaphore() - : m_isSet(false) -{ -} - -BinarySemaphore::~BinarySemaphore() -{ -} - -void BinarySemaphore::signal() -{ - MutexLocker locker(m_mutex); - - m_isSet = true; - m_condition.signal(); -} - -bool BinarySemaphore::wait(double absoluteTime) -{ - MutexLocker locker(m_mutex); - - bool timedOut = false; - while (!m_isSet) { - timedOut = !m_condition.timedWait(m_mutex, absoluteTime); - if (timedOut) - return false; - } - - // Reset the semaphore. - m_isSet = false; - return true; -} - -} // namespace WTF - -#endif // !PLATFORM(WIN) diff --git a/Source/JavaScriptCore/wtf/threads/win/BinarySemaphoreWin.cpp b/Source/JavaScriptCore/wtf/threads/win/BinarySemaphoreWin.cpp deleted file mode 100644 index adc9e9b90..000000000 --- a/Source/JavaScriptCore/wtf/threads/win/BinarySemaphoreWin.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2011 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 "BinarySemaphore.h" - -namespace WTF { - -BinarySemaphore::BinarySemaphore() - : m_event(::CreateEventW(0, FALSE, FALSE, 0)) -{ -} - -BinarySemaphore::~BinarySemaphore() -{ - ::CloseHandle(m_event); -} - -void BinarySemaphore::signal() -{ - ::SetEvent(m_event); -} - -bool BinarySemaphore::wait(double absoluteTime) -{ - DWORD interval = absoluteTimeToWaitTimeoutInterval(absoluteTime); - if (!interval) { - // Consider the wait to have timed out, even if the event has already been signaled, to - // match the WTF::ThreadCondition implementation. - return false; - } - - DWORD result = ::WaitForSingleObjectEx(m_event, interval, FALSE); - switch (result) { - case WAIT_OBJECT_0: - // The event was signaled. - return true; - - case WAIT_TIMEOUT: - // The wait timed out. - return false; - - case WAIT_FAILED: - ASSERT_WITH_MESSAGE(false, "::WaitForSingleObjectEx failed with error %lu", ::GetLastError()); - return false; - default: - ASSERT_WITH_MESSAGE(false, "::WaitForSingleObjectEx returned unexpected result %lu", result); - return false; - } -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/unicode/CharacterNames.h b/Source/JavaScriptCore/wtf/unicode/CharacterNames.h deleted file mode 100644 index 78b7bf7b9..000000000 --- a/Source/JavaScriptCore/wtf/unicode/CharacterNames.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2007, 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 CharacterNames_h -#define CharacterNames_h - -#include <wtf/unicode/Unicode.h> - -namespace WTF { -namespace Unicode { - -// Names here are taken from the Unicode standard. - -// Most of these are UChar constants, not UChar32, which makes them -// more convenient for WebCore code that mostly uses UTF-16. - -const UChar32 aegeanWordSeparatorLine = 0x10100; -const UChar32 aegeanWordSeparatorDot = 0x10101; -const UChar blackCircle = 0x25CF; -const UChar blackSquare = 0x25A0; -const UChar blackUpPointingTriangle = 0x25B2; -const UChar bullet = 0x2022; -const UChar bullseye = 0x25CE; -const UChar carriageReturn = 0x000D; -const UChar ethiopicPrefaceColon = 0x1366; -const UChar ethiopicWordspace = 0x1361; -const UChar fisheye = 0x25C9; -const UChar hebrewPunctuationGeresh = 0x05F3; -const UChar hebrewPunctuationGershayim = 0x05F4; -const UChar horizontalEllipsis = 0x2026; -const UChar hyphen = 0x2010; -const UChar hyphenMinus = 0x002D; -const UChar ideographicComma = 0x3001; -const UChar ideographicFullStop = 0x3002; -const UChar ideographicSpace = 0x3000; -const UChar leftDoubleQuotationMark = 0x201C; -const UChar leftSingleQuotationMark = 0x2018; -const UChar leftToRightEmbed = 0x202A; -const UChar leftToRightMark = 0x200E; -const UChar leftToRightOverride = 0x202D; -const UChar minusSign = 0x2212; -const UChar newlineCharacter = 0x000A; -const UChar noBreakSpace = 0x00A0; -const UChar objectReplacementCharacter = 0xFFFC; -const UChar popDirectionalFormatting = 0x202C; -const UChar replacementCharacter = 0xFFFD; -const UChar rightDoubleQuotationMark = 0x201D; -const UChar rightSingleQuotationMark = 0x2019; -const UChar rightToLeftEmbed = 0x202B; -const UChar rightToLeftMark = 0x200F; -const UChar rightToLeftOverride = 0x202E; -const UChar sesameDot = 0xFE45; -const UChar smallLetterSharpS = 0x00DF; -const UChar softHyphen = 0x00AD; -const UChar space = 0x0020; -const UChar tibetanMarkIntersyllabicTsheg = 0x0F0B; -const UChar tibetanMarkDelimiterTshegBstar = 0x0F0C; -const UChar32 ugariticWordDivider = 0x1039F; -const UChar whiteBullet = 0x25E6; -const UChar whiteCircle = 0x25CB; -const UChar whiteSesameDot = 0xFE46; -const UChar whiteUpPointingTriangle = 0x25B3; -const UChar yenSign = 0x00A5; -const UChar zeroWidthJoiner = 0x200D; -const UChar zeroWidthNonJoiner = 0x200C; -const UChar zeroWidthSpace = 0x200B; -const UChar zeroWidthNoBreakSpace = 0xFEFF; - -} // namespace Unicode -} // namespace WTF - -using WTF::Unicode::aegeanWordSeparatorLine; -using WTF::Unicode::aegeanWordSeparatorDot; -using WTF::Unicode::blackCircle; -using WTF::Unicode::blackSquare; -using WTF::Unicode::blackUpPointingTriangle; -using WTF::Unicode::bullet; -using WTF::Unicode::bullseye; -using WTF::Unicode::carriageReturn; -using WTF::Unicode::ethiopicPrefaceColon; -using WTF::Unicode::ethiopicWordspace; -using WTF::Unicode::fisheye; -using WTF::Unicode::hebrewPunctuationGeresh; -using WTF::Unicode::hebrewPunctuationGershayim; -using WTF::Unicode::horizontalEllipsis; -using WTF::Unicode::hyphen; -using WTF::Unicode::hyphenMinus; -using WTF::Unicode::ideographicComma; -using WTF::Unicode::ideographicFullStop; -using WTF::Unicode::ideographicSpace; -using WTF::Unicode::leftDoubleQuotationMark; -using WTF::Unicode::leftSingleQuotationMark; -using WTF::Unicode::leftToRightEmbed; -using WTF::Unicode::leftToRightMark; -using WTF::Unicode::leftToRightOverride; -using WTF::Unicode::minusSign; -using WTF::Unicode::newlineCharacter; -using WTF::Unicode::noBreakSpace; -using WTF::Unicode::objectReplacementCharacter; -using WTF::Unicode::popDirectionalFormatting; -using WTF::Unicode::replacementCharacter; -using WTF::Unicode::rightDoubleQuotationMark; -using WTF::Unicode::rightSingleQuotationMark; -using WTF::Unicode::rightToLeftEmbed; -using WTF::Unicode::rightToLeftMark; -using WTF::Unicode::rightToLeftOverride; -using WTF::Unicode::sesameDot; -using WTF::Unicode::softHyphen; -using WTF::Unicode::space; -using WTF::Unicode::tibetanMarkIntersyllabicTsheg; -using WTF::Unicode::tibetanMarkDelimiterTshegBstar; -using WTF::Unicode::ugariticWordDivider; -using WTF::Unicode::whiteBullet; -using WTF::Unicode::whiteCircle; -using WTF::Unicode::whiteSesameDot; -using WTF::Unicode::whiteUpPointingTriangle; -using WTF::Unicode::yenSign; -using WTF::Unicode::zeroWidthJoiner; -using WTF::Unicode::zeroWidthNonJoiner; -using WTF::Unicode::zeroWidthSpace; -using WTF::Unicode::zeroWidthNoBreakSpace; - -#endif // CharacterNames_h diff --git a/Source/JavaScriptCore/wtf/unicode/Collator.h b/Source/JavaScriptCore/wtf/unicode/Collator.h deleted file mode 100644 index 7994ff8e5..000000000 --- a/Source/JavaScriptCore/wtf/unicode/Collator.h +++ /dev/null @@ -1,69 +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. - * 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 WTF_Collator_h -#define WTF_Collator_h - -#include <wtf/FastAllocBase.h> -#include <wtf/Noncopyable.h> -#include <wtf/PassOwnPtr.h> -#include <wtf/unicode/Unicode.h> - -#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION -struct UCollator; -#endif - -namespace WTF { - - class Collator { - WTF_MAKE_NONCOPYABLE(Collator); WTF_MAKE_FAST_ALLOCATED; - public: - enum Result { Equal = 0, Greater = 1, Less = -1 }; - - WTF_EXPORT_PRIVATE Collator(const char* locale); // Parsing is lenient; e.g. language identifiers (such as "en-US") are accepted, too. - WTF_EXPORT_PRIVATE ~Collator(); - WTF_EXPORT_PRIVATE void setOrderLowerFirst(bool); - - static PassOwnPtr<Collator> userDefault(); - - WTF_EXPORT_PRIVATE Result collate(const ::UChar*, size_t, const ::UChar*, size_t) const; - - private: -#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION - void createCollator() const; - void releaseCollator(); - mutable UCollator* m_collator; -#endif - char* m_locale; - bool m_lowerFirst; - }; -} - -using WTF::Collator; - -#endif diff --git a/Source/JavaScriptCore/wtf/unicode/CollatorDefault.cpp b/Source/JavaScriptCore/wtf/unicode/CollatorDefault.cpp deleted file mode 100644 index 7bde114a4..000000000 --- a/Source/JavaScriptCore/wtf/unicode/CollatorDefault.cpp +++ /dev/null @@ -1,75 +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. - * 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" -#include "Collator.h" - -#if !USE(ICU_UNICODE) || UCONFIG_NO_COLLATION - -namespace WTF { - -Collator::Collator(const char*) -{ -} - -Collator::~Collator() -{ -} - -void Collator::setOrderLowerFirst(bool) -{ -} - -PassOwnPtr<Collator> Collator::userDefault() -{ - return adoptPtr(new Collator(0)); -} - -// A default implementation for platforms that lack Unicode-aware collation. -Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const -{ - int lmin = lhsLength < rhsLength ? lhsLength : rhsLength; - int l = 0; - while (l < lmin && *lhs == *rhs) { - lhs++; - rhs++; - l++; - } - - if (l < lmin) - return (*lhs > *rhs) ? Greater : Less; - - if (lhsLength == rhsLength) - return Equal; - - return (lhsLength > rhsLength) ? Greater : Less; -} - -} - -#endif diff --git a/Source/JavaScriptCore/wtf/unicode/ScriptCodesFromICU.h b/Source/JavaScriptCore/wtf/unicode/ScriptCodesFromICU.h deleted file mode 100644 index 4760399a1..000000000 --- a/Source/JavaScriptCore/wtf/unicode/ScriptCodesFromICU.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (C) 1997-2006, International Business Machines - * Corporation and others. All Rights Reserved. - */ - -#ifndef WTF_ScriptCodesFromICU_h -#define WTF_ScriptCodesFromICU_h - -/** - * Constants for ISO 15924 script codes. - * - * Many of these script codes - those from Unicode's ScriptNames.txt - - * are character property values for Unicode's Script property. - * See UAX #24 Script Names (http://www.unicode.org/reports/tr24/). - * - * Starting with ICU 3.6, constants for most ISO 15924 script codes - * are included (currently excluding private-use codes Qaaa..Qabx). - * For scripts for which there are codes in ISO 15924 but which are not - * used in the Unicode Character Database (UCD), there are no Unicode characters - * associated with those scripts. - * - * For example, there are no characters that have a UCD script code of - * Hans or Hant. All Han ideographs have the Hani script code. - * The Hans and Hant script codes are used with CLDR data. - * - * ISO 15924 script codes are included for use with CLDR and similar. - * - * @stable ICU 2.2 - */ -typedef enum UScriptCode { - USCRIPT_INVALID_CODE = -1, - USCRIPT_COMMON = 0 , /* Zyyy */ - USCRIPT_INHERITED = 1, /* Qaai */ - USCRIPT_ARABIC = 2, /* Arab */ - USCRIPT_ARMENIAN = 3, /* Armn */ - USCRIPT_BENGALI = 4, /* Beng */ - USCRIPT_BOPOMOFO = 5, /* Bopo */ - USCRIPT_CHEROKEE = 6, /* Cher */ - USCRIPT_COPTIC = 7, /* Copt */ - USCRIPT_CYRILLIC = 8, /* Cyrl */ - USCRIPT_DESERET = 9, /* Dsrt */ - USCRIPT_DEVANAGARI = 10, /* Deva */ - USCRIPT_ETHIOPIC = 11, /* Ethi */ - USCRIPT_GEORGIAN = 12, /* Geor */ - USCRIPT_GOTHIC = 13, /* Goth */ - USCRIPT_GREEK = 14, /* Grek */ - USCRIPT_GUJARATI = 15, /* Gujr */ - USCRIPT_GURMUKHI = 16, /* Guru */ - USCRIPT_HAN = 17, /* Hani */ - USCRIPT_HANGUL = 18, /* Hang */ - USCRIPT_HEBREW = 19, /* Hebr */ - USCRIPT_HIRAGANA = 20, /* Hira */ - USCRIPT_KANNADA = 21, /* Knda */ - USCRIPT_KATAKANA = 22, /* Kana */ - USCRIPT_KHMER = 23, /* Khmr */ - USCRIPT_LAO = 24, /* Laoo */ - USCRIPT_LATIN = 25, /* Latn */ - USCRIPT_MALAYALAM = 26, /* Mlym */ - USCRIPT_MONGOLIAN = 27, /* Mong */ - USCRIPT_MYANMAR = 28, /* Mymr */ - USCRIPT_OGHAM = 29, /* Ogam */ - USCRIPT_OLD_ITALIC = 30, /* Ital */ - USCRIPT_ORIYA = 31, /* Orya */ - USCRIPT_RUNIC = 32, /* Runr */ - USCRIPT_SINHALA = 33, /* Sinh */ - USCRIPT_SYRIAC = 34, /* Syrc */ - USCRIPT_TAMIL = 35, /* Taml */ - USCRIPT_TELUGU = 36, /* Telu */ - USCRIPT_THAANA = 37, /* Thaa */ - USCRIPT_THAI = 38, /* Thai */ - USCRIPT_TIBETAN = 39, /* Tibt */ - /** Canadian_Aboriginal script. @stable ICU 2.6 */ - USCRIPT_CANADIAN_ABORIGINAL = 40, /* Cans */ - /** Canadian_Aboriginal script (alias). @stable ICU 2.2 */ - USCRIPT_UCAS = USCRIPT_CANADIAN_ABORIGINAL, - USCRIPT_YI = 41, /* Yiii */ - USCRIPT_TAGALOG = 42, /* Tglg */ - USCRIPT_HANUNOO = 43, /* Hano */ - USCRIPT_BUHID = 44, /* Buhd */ - USCRIPT_TAGBANWA = 45, /* Tagb */ - - /* New scripts in Unicode 4 @stable ICU 2.6 */ - USCRIPT_BRAILLE = 46, /* Brai */ - USCRIPT_CYPRIOT = 47, /* Cprt */ - USCRIPT_LIMBU = 48, /* Limb */ - USCRIPT_LINEAR_B = 49, /* Linb */ - USCRIPT_OSMANYA = 50, /* Osma */ - USCRIPT_SHAVIAN = 51, /* Shaw */ - USCRIPT_TAI_LE = 52, /* Tale */ - USCRIPT_UGARITIC = 53, /* Ugar */ - - /** New script code in Unicode 4.0.1 @stable ICU 3.0 */ - USCRIPT_KATAKANA_OR_HIRAGANA = 54,/*Hrkt */ - -#ifndef U_HIDE_DRAFT_API - /* New scripts in Unicode 4.1 @draft ICU 3.4 */ - USCRIPT_BUGINESE = 55, /* Bugi */ - USCRIPT_GLAGOLITIC = 56, /* Glag */ - USCRIPT_KHAROSHTHI = 57, /* Khar */ - USCRIPT_SYLOTI_NAGRI = 58, /* Sylo */ - USCRIPT_NEW_TAI_LUE = 59, /* Talu */ - USCRIPT_TIFINAGH = 60, /* Tfng */ - USCRIPT_OLD_PERSIAN = 61, /* Xpeo */ - - /* New script codes from ISO 15924 @draft ICU 3.6 */ - USCRIPT_BALINESE = 62, /* Bali */ - USCRIPT_BATAK = 63, /* Batk */ - USCRIPT_BLISSYMBOLS = 64, /* Blis */ - USCRIPT_BRAHMI = 65, /* Brah */ - USCRIPT_CHAM = 66, /* Cham */ - USCRIPT_CIRTH = 67, /* Cirt */ - USCRIPT_OLD_CHURCH_SLAVONIC_CYRILLIC = 68, /* Cyrs */ - USCRIPT_DEMOTIC_EGYPTIAN = 69, /* Egyd */ - USCRIPT_HIERATIC_EGYPTIAN = 70, /* Egyh */ - USCRIPT_EGYPTIAN_HIEROGLYPHS = 71, /* Egyp */ - USCRIPT_KHUTSURI = 72, /* Geok */ - USCRIPT_SIMPLIFIED_HAN = 73, /* Hans */ - USCRIPT_TRADITIONAL_HAN = 74, /* Hant */ - USCRIPT_PAHAWH_HMONG = 75, /* Hmng */ - USCRIPT_OLD_HUNGARIAN = 76, /* Hung */ - USCRIPT_HARAPPAN_INDUS = 77, /* Inds */ - USCRIPT_JAVANESE = 78, /* Java */ - USCRIPT_KAYAH_LI = 79, /* Kali */ - USCRIPT_LATIN_FRAKTUR = 80, /* Latf */ - USCRIPT_LATIN_GAELIC = 81, /* Latg */ - USCRIPT_LEPCHA = 82, /* Lepc */ - USCRIPT_LINEAR_A = 83, /* Lina */ - USCRIPT_MANDAEAN = 84, /* Mand */ - USCRIPT_MAYAN_HIEROGLYPHS = 85, /* Maya */ - USCRIPT_MEROITIC = 86, /* Mero */ - USCRIPT_NKO = 87, /* Nkoo */ - USCRIPT_ORKHON = 88, /* Orkh */ - USCRIPT_OLD_PERMIC = 89, /* Perm */ - USCRIPT_PHAGS_PA = 90, /* Phag */ - USCRIPT_PHOENICIAN = 91, /* Phnx */ - USCRIPT_PHONETIC_POLLARD = 92, /* Plrd */ - USCRIPT_RONGORONGO = 93, /* Roro */ - USCRIPT_SARATI = 94, /* Sara */ - USCRIPT_ESTRANGELO_SYRIAC = 95, /* Syre */ - USCRIPT_WESTERN_SYRIAC = 96, /* Syrj */ - USCRIPT_EASTERN_SYRIAC = 97, /* Syrn */ - USCRIPT_TENGWAR = 98, /* Teng */ - USCRIPT_VAI = 99, /* Vaii */ - USCRIPT_VISIBLE_SPEECH = 100, /* Visp */ - USCRIPT_CUNEIFORM = 101,/* Xsux */ - USCRIPT_UNWRITTEN_LANGUAGES = 102,/* Zxxx */ - USCRIPT_UNKNOWN = 103,/* Zzzz */ /* Unknown="Code for uncoded script", for unassigned code points */ - /* Private use codes from Qaaa - Qabx are not supported*/ -#endif /* U_HIDE_DRAFT_API */ - USCRIPT_CODE_LIMIT = 104 -} UScriptCode; - -#endif diff --git a/Source/JavaScriptCore/wtf/unicode/UTF8.cpp b/Source/JavaScriptCore/wtf/unicode/UTF8.cpp deleted file mode 100644 index 8ea5c6992..000000000 --- a/Source/JavaScriptCore/wtf/unicode/UTF8.cpp +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (C) 2007 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 - * 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 "UTF8.h" - -#include "ASCIICType.h" -#include <wtf/StringHasher.h> -#include <wtf/unicode/CharacterNames.h> - -namespace WTF { -namespace Unicode { - -inline int inlineUTF8SequenceLengthNonASCII(char b0) -{ - if ((b0 & 0xC0) != 0xC0) - return 0; - if ((b0 & 0xE0) == 0xC0) - return 2; - if ((b0 & 0xF0) == 0xE0) - return 3; - if ((b0 & 0xF8) == 0xF0) - return 4; - return 0; -} - -inline int inlineUTF8SequenceLength(char b0) -{ - return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); -} - -int UTF8SequenceLength(char b0) -{ - return isASCII(b0) ? 1 : inlineUTF8SequenceLengthNonASCII(b0); -} - -int decodeUTF8Sequence(const char* sequence) -{ - // Handle 0-byte sequences (never valid). - const unsigned char b0 = sequence[0]; - const int length = inlineUTF8SequenceLength(b0); - if (length == 0) - return -1; - - // Handle 1-byte sequences (plain ASCII). - const unsigned char b1 = sequence[1]; - if (length == 1) { - if (b1) - return -1; - return b0; - } - - // Handle 2-byte sequences. - if ((b1 & 0xC0) != 0x80) - return -1; - const unsigned char b2 = sequence[2]; - if (length == 2) { - if (b2) - return -1; - const int c = ((b0 & 0x1F) << 6) | (b1 & 0x3F); - if (c < 0x80) - return -1; - return c; - } - - // Handle 3-byte sequences. - if ((b2 & 0xC0) != 0x80) - return -1; - const unsigned char b3 = sequence[3]; - if (length == 3) { - if (b3) - return -1; - const int c = ((b0 & 0xF) << 12) | ((b1 & 0x3F) << 6) | (b2 & 0x3F); - if (c < 0x800) - return -1; - // UTF-16 surrogates should never appear in UTF-8 data. - if (c >= 0xD800 && c <= 0xDFFF) - return -1; - return c; - } - - // Handle 4-byte sequences. - if ((b3 & 0xC0) != 0x80) - return -1; - const unsigned char b4 = sequence[4]; - if (length == 4) { - if (b4) - return -1; - const int c = ((b0 & 0x7) << 18) | ((b1 & 0x3F) << 12) | ((b2 & 0x3F) << 6) | (b3 & 0x3F); - if (c < 0x10000 || c > 0x10FFFF) - return -1; - return c; - } - - return -1; -} - -// Once the bits are split out into bytes of UTF-8, this is a mask OR-ed -// into the first byte, depending on how many bytes follow. There are -// as many entries in this table as there are UTF-8 sequence types. -// (I.e., one byte sequence, two byte... etc.). Remember that sequencs -// for *legal* UTF-8 will be 4 or fewer bytes total. -static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -ConversionResult convertLatin1ToUTF8( - const LChar** sourceStart, const LChar* sourceEnd, - char** targetStart, char* targetEnd) -{ - ConversionResult result = conversionOK; - const LChar* source = *sourceStart; - char* target = *targetStart; - while (source < sourceEnd) { - UChar32 ch; - unsigned short bytesToWrite = 0; - const UChar32 byteMask = 0xBF; - const UChar32 byteMark = 0x80; - const LChar* oldSource = source; // In case we have to back up because of target overflow. - ch = static_cast<unsigned short>(*source++); - - // Figure out how many bytes the result will require - if (ch < (UChar32)0x80) - bytesToWrite = 1; - else - bytesToWrite = 2; - - target += bytesToWrite; - if (target > targetEnd) { - source = oldSource; // Back up source pointer! - target -= bytesToWrite; - result = targetExhausted; - break; - } - switch (bytesToWrite) { // note: everything falls through. - case 2: - *--target = (char)((ch | byteMark) & byteMask); - ch >>= 6; - case 1: - *--target = (char)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -ConversionResult convertUTF16ToUTF8( - const UChar** sourceStart, const UChar* sourceEnd, - char** targetStart, char* targetEnd, bool strict) -{ - ConversionResult result = conversionOK; - const UChar* source = *sourceStart; - char* target = *targetStart; - while (source < sourceEnd) { - UChar32 ch; - unsigned short bytesToWrite = 0; - const UChar32 byteMask = 0xBF; - const UChar32 byteMark = 0x80; - const UChar* oldSource = source; // In case we have to back up because of target overflow. - ch = static_cast<unsigned short>(*source++); - // If we have a surrogate pair, convert to UChar32 first. - if (ch >= 0xD800 && ch <= 0xDBFF) { - // If the 16 bits following the high surrogate are in the source buffer... - if (source < sourceEnd) { - UChar32 ch2 = static_cast<unsigned short>(*source); - // If it's a low surrogate, convert to UChar32. - if (ch2 >= 0xDC00 && ch2 <= 0xDFFF) { - ch = ((ch - 0xD800) << 10) + (ch2 - 0xDC00) + 0x0010000; - ++source; - } else if (strict) { // it's an unpaired high surrogate - --source; // return to the illegal value itself - result = sourceIllegal; - break; - } - } else { // We don't have the 16 bits following the high surrogate. - --source; // return to the high surrogate - result = sourceExhausted; - break; - } - } else if (strict) { - // UTF-16 surrogate values are illegal in UTF-32 - if (ch >= 0xDC00 && ch <= 0xDFFF) { - --source; // return to the illegal value itself - result = sourceIllegal; - break; - } - } - // Figure out how many bytes the result will require - if (ch < (UChar32)0x80) { - bytesToWrite = 1; - } else if (ch < (UChar32)0x800) { - bytesToWrite = 2; - } else if (ch < (UChar32)0x10000) { - bytesToWrite = 3; - } else if (ch < (UChar32)0x110000) { - bytesToWrite = 4; - } else { - bytesToWrite = 3; - ch = replacementCharacter; - } - - target += bytesToWrite; - if (target > targetEnd) { - source = oldSource; // Back up source pointer! - target -= bytesToWrite; - result = targetExhausted; - break; - } - switch (bytesToWrite) { // note: everything falls through. - case 4: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6; - case 3: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6; - case 2: *--target = (char)((ch | byteMark) & byteMask); ch >>= 6; - case 1: *--target = (char)(ch | firstByteMark[bytesToWrite]); - } - target += bytesToWrite; - } - *sourceStart = source; - *targetStart = target; - return result; -} - -// This must be called with the length pre-determined by the first byte. -// If presented with a length > 4, this returns false. The Unicode -// definition of UTF-8 goes up to 4-byte sequences. -static bool isLegalUTF8(const unsigned char* source, int length) -{ - unsigned char a; - const unsigned char* srcptr = source + length; - switch (length) { - default: return false; - // Everything else falls through when "true"... - case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false; - case 2: if ((a = (*--srcptr)) > 0xBF) return false; - - switch (*source) { - // no fall-through in this inner switch - case 0xE0: if (a < 0xA0) return false; break; - case 0xED: if (a > 0x9F) return false; break; - case 0xF0: if (a < 0x90) return false; break; - case 0xF4: if (a > 0x8F) return false; break; - default: if (a < 0x80) return false; - } - - case 1: if (*source >= 0x80 && *source < 0xC2) return false; - } - if (*source > 0xF4) - return false; - return true; -} - -// Magic values subtracted from a buffer value during UTF8 conversion. -// This table contains as many values as there might be trailing bytes -// in a UTF-8 sequence. -static const UChar32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; - -static inline UChar32 readUTF8Sequence(const char*& sequence, unsigned length) -{ - UChar32 character = 0; - - // The cases all fall through. - switch (length) { - case 6: character += static_cast<unsigned char>(*sequence++); character <<= 6; - case 5: character += static_cast<unsigned char>(*sequence++); character <<= 6; - case 4: character += static_cast<unsigned char>(*sequence++); character <<= 6; - case 3: character += static_cast<unsigned char>(*sequence++); character <<= 6; - case 2: character += static_cast<unsigned char>(*sequence++); character <<= 6; - case 1: character += static_cast<unsigned char>(*sequence++); - } - - return character - offsetsFromUTF8[length - 1]; -} - -ConversionResult convertUTF8ToUTF16( - const char** sourceStart, const char* sourceEnd, - UChar** targetStart, UChar* targetEnd, bool strict) -{ - ConversionResult result = conversionOK; - const char* source = *sourceStart; - UChar* target = *targetStart; - while (source < sourceEnd) { - int utf8SequenceLength = inlineUTF8SequenceLength(*source); - if (sourceEnd - source < utf8SequenceLength) { - result = sourceExhausted; - break; - } - // Do this check whether lenient or strict - if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(source), utf8SequenceLength)) { - result = sourceIllegal; - break; - } - - UChar32 character = readUTF8Sequence(source, utf8SequenceLength); - - if (target >= targetEnd) { - source -= utf8SequenceLength; // Back up source pointer! - result = targetExhausted; - break; - } - - if (U_IS_BMP(character)) { - // UTF-16 surrogate values are illegal in UTF-32 - if (U_IS_SURROGATE(character)) { - if (strict) { - source -= utf8SequenceLength; // return to the illegal value itself - result = sourceIllegal; - break; - } else - *target++ = replacementCharacter; - } else - *target++ = character; // normal case - } else if (U_IS_SUPPLEMENTARY(character)) { - // target is a character in range 0xFFFF - 0x10FFFF - if (target + 1 >= targetEnd) { - source -= utf8SequenceLength; // Back up source pointer! - result = targetExhausted; - break; - } - *target++ = U16_LEAD(character); - *target++ = U16_TRAIL(character); - } else { - if (strict) { - source -= utf8SequenceLength; // return to the start - result = sourceIllegal; - break; // Bail out; shouldn't continue - } else - *target++ = replacementCharacter; - } - } - *sourceStart = source; - *targetStart = target; - return result; -} - -unsigned calculateStringHashAndLengthFromUTF8(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length) -{ - if (!data) - return 0; - - StringHasher stringHasher; - dataLength = 0; - utf16Length = 0; - - while (data < dataEnd || (!dataEnd && *data)) { - if (isASCII(*data)) { - stringHasher.addCharacter(*data++); - dataLength++; - utf16Length++; - continue; - } - - int utf8SequenceLength = inlineUTF8SequenceLengthNonASCII(*data); - dataLength += utf8SequenceLength; - - if (!dataEnd) { - for (int i = 1; i < utf8SequenceLength; ++i) { - if (!data[i]) - return 0; - } - } else if (dataEnd - data < utf8SequenceLength) - return 0; - - if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(data), utf8SequenceLength)) - return 0; - - UChar32 character = readUTF8Sequence(data, utf8SequenceLength); - ASSERT(!isASCII(character)); - - if (U_IS_BMP(character)) { - // UTF-16 surrogate values are illegal in UTF-32 - if (U_IS_SURROGATE(character)) - return 0; - stringHasher.addCharacter(static_cast<UChar>(character)); // normal case - utf16Length++; - } else if (U_IS_SUPPLEMENTARY(character)) { - stringHasher.addCharacters(static_cast<UChar>(U16_LEAD(character)), - static_cast<UChar>(U16_TRAIL(character))); - utf16Length += 2; - } else - return 0; - } - - return stringHasher.hash(); -} - -bool equalUTF16WithUTF8(const UChar* a, const UChar* aEnd, const char* b, const char* bEnd) -{ - while (b < bEnd) { - if (isASCII(*b)) { - if (*a++ != *b++) - return false; - continue; - } - - int utf8SequenceLength = inlineUTF8SequenceLengthNonASCII(*b); - - if (bEnd - b < utf8SequenceLength) - return false; - - if (!isLegalUTF8(reinterpret_cast<const unsigned char*>(b), utf8SequenceLength)) - return 0; - - UChar32 character = readUTF8Sequence(b, utf8SequenceLength); - ASSERT(!isASCII(character)); - - if (U_IS_BMP(character)) { - // UTF-16 surrogate values are illegal in UTF-32 - if (U_IS_SURROGATE(character)) - return false; - if (*a++ != character) - return false; - } else if (U_IS_SUPPLEMENTARY(character)) { - if (*a++ != U16_LEAD(character)) - return false; - if (*a++ != U16_TRAIL(character)) - return false; - } else - return false; - } - - return a == aEnd; -} - -} // namespace Unicode -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/unicode/UTF8.h b/Source/JavaScriptCore/wtf/unicode/UTF8.h deleted file mode 100644 index 59f6994be..000000000 --- a/Source/JavaScriptCore/wtf/unicode/UTF8.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2007 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 WTF_UTF8_h -#define WTF_UTF8_h - -#include <wtf/unicode/Unicode.h> - -namespace WTF { -namespace Unicode { - - // Given a first byte, gives the length of the UTF-8 sequence it begins. - // Returns 0 for bytes that are not legal starts of UTF-8 sequences. - // Only allows sequences of up to 4 bytes, since that works for all Unicode characters (U-00000000 to U-0010FFFF). - int UTF8SequenceLength(char); - - // Takes a null-terminated C-style string with a UTF-8 sequence in it and converts it to a character. - // Only allows Unicode characters (U-00000000 to U-0010FFFF). - // Returns -1 if the sequence is not valid (including presence of extra bytes). - int decodeUTF8Sequence(const char*); - - typedef enum { - conversionOK, // conversion successful - sourceExhausted, // partial character in source, but hit end - targetExhausted, // insuff. room in target for conversion - sourceIllegal // source sequence is illegal/malformed - } ConversionResult; - - // These conversion functions take a "strict" argument. When this - // flag is set to strict, both irregular sequences and isolated surrogates - // will cause an error. When the flag is set to lenient, both irregular - // sequences and isolated surrogates are converted. - // - // Whether the flag is strict or lenient, all illegal sequences will cause - // an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>, - // or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code - // must check for illegal sequences. - // - // When the flag is set to lenient, characters over 0x10FFFF are converted - // to the replacement character; otherwise (when the flag is set to strict) - // they constitute an error. - - WTF_EXPORT_PRIVATE ConversionResult convertUTF8ToUTF16( - const char** sourceStart, const char* sourceEnd, - UChar** targetStart, UChar* targetEnd, bool strict = true); - - ConversionResult convertLatin1ToUTF8( - const LChar** sourceStart, const LChar* sourceEnd, - char** targetStart, char* targetEnd); - - WTF_EXPORT_PRIVATE ConversionResult convertUTF16ToUTF8( - const UChar** sourceStart, const UChar* sourceEnd, - char** targetStart, char* targetEnd, bool strict = true); - - unsigned calculateStringHashAndLengthFromUTF8(const char* data, const char* dataEnd, unsigned& dataLength, unsigned& utf16Length); - - bool equalUTF16WithUTF8(const UChar* a, const UChar* aEnd, const char* b, const char* bEnd); - -} // namespace Unicode -} // namespace WTF - -#endif // WTF_UTF8_h diff --git a/Source/JavaScriptCore/wtf/unicode/Unicode.h b/Source/JavaScriptCore/wtf/unicode/Unicode.h deleted file mode 100644 index cc44476a6..000000000 --- a/Source/JavaScriptCore/wtf/unicode/Unicode.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2006 George Staikos <staikos@kde.org> - * Copyright (C) 2006, 2008, 2009 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. - * - */ - -#ifndef WTF_UNICODE_H -#define WTF_UNICODE_H - -#include <wtf/Assertions.h> - -// Define platform neutral 8 bit character type (L is for Latin-1). -typedef unsigned char LChar; - -#if USE(QT4_UNICODE) -#include "qt4/UnicodeQt4.h" -#elif USE(ICU_UNICODE) -#include <wtf/unicode/icu/UnicodeIcu.h> -#elif USE(GLIB_UNICODE) -#include <wtf/unicode/glib/UnicodeGLib.h> -#elif USE(WINCE_UNICODE) -#include <wtf/unicode/wince/UnicodeWinCE.h> -#else -#error "Unknown Unicode implementation" -#endif - -COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes); - -#endif // WTF_UNICODE_H diff --git a/Source/JavaScriptCore/wtf/unicode/UnicodeMacrosFromICU.h b/Source/JavaScriptCore/wtf/unicode/UnicodeMacrosFromICU.h deleted file mode 100644 index 09a7036e3..000000000 --- a/Source/JavaScriptCore/wtf/unicode/UnicodeMacrosFromICU.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 1999-2004, International Business Machines Corporation and others. All Rights Reserved. - * - */ - -#ifndef UnicodeMacrosFromICU_h -#define UnicodeMacrosFromICU_h - -// some defines from ICU - -#define U_IS_BMP(c) ((UChar32)(c)<=0xffff) -#define U16_IS_LEAD(c) (((c)&0xfffffc00)==0xd800) -#define U16_IS_TRAIL(c) (((c)&0xfffffc00)==0xdc00) -#define U16_SURROGATE_OFFSET ((0xd800<<10UL)+0xdc00-0x10000) -#define U16_GET_SUPPLEMENTARY(lead, trail) \ - (((UChar32)(lead)<<10UL)+(UChar32)(trail)-U16_SURROGATE_OFFSET) - -#define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0) -#define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00) -#define U16_LENGTH(c) ((uint32_t)(c) <= 0xffff ? 1 : 2) - -#define U_IS_SUPPLEMENTARY(c) ((UChar32)((c)-0x10000)<=0xfffff) -#define U_IS_SURROGATE(c) (((c)&0xfffff800)==0xd800) -#define U16_IS_SINGLE(c) !U_IS_SURROGATE(c) -#define U16_IS_SURROGATE(c) U_IS_SURROGATE(c) -#define U16_IS_SURROGATE_LEAD(c) (((c)&0x400)==0) - -#define U16_GET(s, start, i, length, c) { \ - (c)=(s)[i]; \ - if(U16_IS_SURROGATE(c)) { \ - uint16_t __c2; \ - if(U16_IS_SURROGATE_LEAD(c)) { \ - if((i)+1<(length) && U16_IS_TRAIL(__c2=(s)[(i)+1])) { \ - (c)=U16_GET_SUPPLEMENTARY((c), __c2); \ - } \ - } else { \ - if((i)-1>=(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ - (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ - } \ - } \ - } \ -} - -#define U16_PREV(s, start, i, c) { \ - (c)=(s)[--(i)]; \ - if(U16_IS_TRAIL(c)) { \ - uint16_t __c2; \ - if((i)>(start) && U16_IS_LEAD(__c2=(s)[(i)-1])) { \ - --(i); \ - (c)=U16_GET_SUPPLEMENTARY(__c2, (c)); \ - } \ - } \ -} - -#define U16_BACK_1(s, start, i) { \ - if(U16_IS_TRAIL((s)[--(i)]) && (i)>(start) && U16_IS_LEAD((s)[(i)-1])) { \ - --(i); \ - } \ -} - -#define U16_NEXT(s, i, length, c) { \ - (c)=(s)[(i)++]; \ - if(U16_IS_LEAD(c)) { \ - uint16_t __c2; \ - if((i)<(length) && U16_IS_TRAIL(__c2=(s)[(i)])) { \ - ++(i); \ - (c)=U16_GET_SUPPLEMENTARY((c), __c2); \ - } \ - } \ -} - -#define U16_FWD_1(s, i, length) { \ - if(U16_IS_LEAD((s)[(i)++]) && (i)<(length) && U16_IS_TRAIL((s)[i])) { \ - ++(i); \ - } \ -} - -#define U_MASK(x) ((uint32_t)1<<(x)) - -#define U8_MAX_LENGTH 4 - -#define U8_APPEND_UNSAFE(s, i, c) { \ - if((uint32_t)(c)<=0x7f) { \ - (s)[(i)++]=(uint8_t)(c); \ - } else { \ - if((uint32_t)(c)<=0x7ff) { \ - (s)[(i)++]=(uint8_t)(((c)>>6)|0xc0); \ - } else { \ - if((uint32_t)(c)<=0xffff) { \ - (s)[(i)++]=(uint8_t)(((c)>>12)|0xe0); \ - } else { \ - (s)[(i)++]=(uint8_t)(((c)>>18)|0xf0); \ - (s)[(i)++]=(uint8_t)((((c)>>12)&0x3f)|0x80); \ - } \ - (s)[(i)++]=(uint8_t)((((c)>>6)&0x3f)|0x80); \ - } \ - (s)[(i)++]=(uint8_t)(((c)&0x3f)|0x80); \ - } \ -} -#endif diff --git a/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp b/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp deleted file mode 100644 index a01c3ee9d..000000000 --- a/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> - * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> - * Copyright (C) 2010 Igalia S.L. - * - * 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 "UnicodeGLib.h" - -#include <wtf/Vector.h> -#include <wtf/unicode/UTF8.h> - -#define UTF8_IS_SURROGATE(character) (character >= 0x10000 && character <= 0x10FFFF) - -namespace WTF { -namespace Unicode { - -UChar32 foldCase(UChar32 ch) -{ - GOwnPtr<GError> gerror; - - GOwnPtr<char> utf8char; - utf8char.set(g_ucs4_to_utf8(reinterpret_cast<gunichar*>(&ch), 1, 0, 0, &gerror.outPtr())); - if (gerror) - return ch; - - GOwnPtr<char> utf8caseFolded; - utf8caseFolded.set(g_utf8_casefold(utf8char.get(), -1)); - - GOwnPtr<gunichar> ucs4Result; - ucs4Result.set(g_utf8_to_ucs4_fast(utf8caseFolded.get(), -1, 0)); - - return *ucs4Result; -} - -static int getUTF16LengthFromUTF8(const gchar* utf8String, int length) -{ - int utf16Length = 0; - const gchar* inputString = utf8String; - - while ((utf8String + length - inputString > 0) && *inputString) { - gunichar character = g_utf8_get_char(inputString); - - utf16Length += UTF8_IS_SURROGATE(character) ? 2 : 1; - inputString = g_utf8_next_char(inputString); - } - - return utf16Length; -} - -typedef gchar* (*UTF8CaseFunction)(const gchar*, gssize length); - -static int convertCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error, UTF8CaseFunction caseFunction) -{ - *error = false; - - // Allocate a buffer big enough to hold all the characters. - Vector<char> buffer(srcLength * 3); - char* utf8Target = buffer.data(); - const UChar* utf16Source = src; - ConversionResult conversionResult = convertUTF16ToUTF8(&utf16Source, utf16Source + srcLength, &utf8Target, utf8Target + buffer.size(), true); - if (conversionResult != conversionOK) { - *error = true; - return -1; - } - buffer.shrink(utf8Target - buffer.data()); - - GOwnPtr<char> utf8Result(caseFunction(buffer.data(), buffer.size())); - long utf8ResultLength = strlen(utf8Result.get()); - - // Calculate the destination buffer size. - int realLength = getUTF16LengthFromUTF8(utf8Result.get(), utf8ResultLength); - if (realLength > resultLength) { - *error = true; - return realLength; - } - - // Convert the result to UTF-16. - UChar* utf16Target = result; - const char* utf8Source = utf8Result.get(); - conversionResult = convertUTF8ToUTF16(&utf8Source, utf8Source + utf8ResultLength, &utf16Target, utf16Target + resultLength, true); - long utf16ResultLength = utf16Target - result; - if (conversionResult != conversionOK) - *error = true; - - return utf16ResultLength <= 0 ? -1 : utf16ResultLength; -} -int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - return convertCase(result, resultLength, src, srcLength, error, g_utf8_casefold); -} - -int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - return convertCase(result, resultLength, src, srcLength, error, g_utf8_strdown); -} - -int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - return convertCase(result, resultLength, src, srcLength, error, g_utf8_strup); -} - -Direction direction(UChar32 c) -{ - PangoBidiType type = pango_bidi_type_for_unichar(c); - switch (type) { - case PANGO_BIDI_TYPE_L: - return LeftToRight; - case PANGO_BIDI_TYPE_R: - return RightToLeft; - case PANGO_BIDI_TYPE_AL: - return RightToLeftArabic; - case PANGO_BIDI_TYPE_LRE: - return LeftToRightEmbedding; - case PANGO_BIDI_TYPE_RLE: - return RightToLeftEmbedding; - case PANGO_BIDI_TYPE_LRO: - return LeftToRightOverride; - case PANGO_BIDI_TYPE_RLO: - return RightToLeftOverride; - case PANGO_BIDI_TYPE_PDF: - return PopDirectionalFormat; - case PANGO_BIDI_TYPE_EN: - return EuropeanNumber; - case PANGO_BIDI_TYPE_AN: - return ArabicNumber; - case PANGO_BIDI_TYPE_ES: - return EuropeanNumberSeparator; - case PANGO_BIDI_TYPE_ET: - return EuropeanNumberTerminator; - case PANGO_BIDI_TYPE_CS: - return CommonNumberSeparator; - case PANGO_BIDI_TYPE_NSM: - return NonSpacingMark; - case PANGO_BIDI_TYPE_BN: - return BoundaryNeutral; - case PANGO_BIDI_TYPE_B: - return BlockSeparator; - case PANGO_BIDI_TYPE_S: - return SegmentSeparator; - case PANGO_BIDI_TYPE_WS: - return WhiteSpaceNeutral; - default: - return OtherNeutral; - } -} - -int umemcasecmp(const UChar* a, const UChar* b, int len) -{ - GOwnPtr<char> utf8a; - GOwnPtr<char> utf8b; - - utf8a.set(g_utf16_to_utf8(a, len, 0, 0, 0)); - utf8b.set(g_utf16_to_utf8(b, len, 0, 0, 0)); - - GOwnPtr<char> foldedA; - GOwnPtr<char> foldedB; - - foldedA.set(g_utf8_casefold(utf8a.get(), -1)); - foldedB.set(g_utf8_casefold(utf8b.get(), -1)); - - // FIXME: umemcasecmp needs to mimic u_memcasecmp of icu - // from the ICU docs: - // "Compare two strings case-insensitively using full case folding. - // his is equivalent to u_strcmp(u_strFoldCase(s1, n, options), u_strFoldCase(s2, n, options))." - // - // So it looks like we don't need the full g_utf8_collate here, - // but really a bitwise comparison of casefolded unicode chars (not utf-8 bytes). - // As there is no direct equivalent to this icu function in GLib, for now - // we'll use g_utf8_collate(): - - return g_utf8_collate(foldedA.get(), foldedB.get()); -} - -} -} diff --git a/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h b/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h deleted file mode 100644 index 8ad532917..000000000 --- a/Source/JavaScriptCore/wtf/unicode/glib/UnicodeGLib.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2006 George Staikos <staikos@kde.org> - * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> - * Copyright (C) 2007 Apple Computer, Inc. All rights reserved. - * Copyright (C) 2008 Jürg Billeter <j@bitron.ch> - * Copyright (C) 2008 Dominik Röttsches <dominik.roettsches@access-company.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef UnicodeGLib_h -#define UnicodeGLib_h - -#include <wtf/gobject/GOwnPtr.h> -#include <wtf/unicode/ScriptCodesFromICU.h> -#include <wtf/unicode/UnicodeMacrosFromICU.h> - -#include <glib.h> -#include <pango/pango.h> -#include <stdint.h> -#include <stdlib.h> -#include <string.h> - -typedef uint16_t UChar; -typedef int32_t UChar32; - -namespace WTF { -namespace Unicode { - -enum Direction { - LeftToRight, - RightToLeft, - EuropeanNumber, - EuropeanNumberSeparator, - EuropeanNumberTerminator, - ArabicNumber, - CommonNumberSeparator, - BlockSeparator, - SegmentSeparator, - WhiteSpaceNeutral, - OtherNeutral, - LeftToRightEmbedding, - LeftToRightOverride, - RightToLeftArabic, - RightToLeftEmbedding, - RightToLeftOverride, - PopDirectionalFormat, - NonSpacingMark, - BoundaryNeutral -}; - -enum DecompositionType { - DecompositionNone, - DecompositionCanonical, - DecompositionCompat, - DecompositionCircle, - DecompositionFinal, - DecompositionFont, - DecompositionFraction, - DecompositionInitial, - DecompositionIsolated, - DecompositionMedial, - DecompositionNarrow, - DecompositionNoBreak, - DecompositionSmall, - DecompositionSquare, - DecompositionSub, - DecompositionSuper, - DecompositionVertical, - DecompositionWide, -}; - -enum CharCategory { - NoCategory = 0, - Other_NotAssigned = U_MASK(G_UNICODE_UNASSIGNED), - Letter_Uppercase = U_MASK(G_UNICODE_UPPERCASE_LETTER), - Letter_Lowercase = U_MASK(G_UNICODE_LOWERCASE_LETTER), - Letter_Titlecase = U_MASK(G_UNICODE_TITLECASE_LETTER), - Letter_Modifier = U_MASK(G_UNICODE_MODIFIER_LETTER), - Letter_Other = U_MASK(G_UNICODE_OTHER_LETTER), - - Mark_NonSpacing = U_MASK(G_UNICODE_NON_SPACING_MARK), - Mark_Enclosing = U_MASK(G_UNICODE_ENCLOSING_MARK), - Mark_SpacingCombining = U_MASK(G_UNICODE_COMBINING_MARK), - - Number_DecimalDigit = U_MASK(G_UNICODE_DECIMAL_NUMBER), - Number_Letter = U_MASK(G_UNICODE_LETTER_NUMBER), - Number_Other = U_MASK(G_UNICODE_OTHER_NUMBER), - - Separator_Space = U_MASK(G_UNICODE_SPACE_SEPARATOR), - Separator_Line = U_MASK(G_UNICODE_LINE_SEPARATOR), - Separator_Paragraph = U_MASK(G_UNICODE_PARAGRAPH_SEPARATOR), - - Other_Control = U_MASK(G_UNICODE_CONTROL), - Other_Format = U_MASK(G_UNICODE_FORMAT), - Other_PrivateUse = U_MASK(G_UNICODE_PRIVATE_USE), - Other_Surrogate = U_MASK(G_UNICODE_SURROGATE), - - Punctuation_Dash = U_MASK(G_UNICODE_DASH_PUNCTUATION), - Punctuation_Open = U_MASK(G_UNICODE_OPEN_PUNCTUATION), - Punctuation_Close = U_MASK(G_UNICODE_CLOSE_PUNCTUATION), - Punctuation_Connector = U_MASK(G_UNICODE_CONNECT_PUNCTUATION), - Punctuation_Other = U_MASK(G_UNICODE_OTHER_PUNCTUATION), - - Symbol_Math = U_MASK(G_UNICODE_MATH_SYMBOL), - Symbol_Currency = U_MASK(G_UNICODE_CURRENCY_SYMBOL), - Symbol_Modifier = U_MASK(G_UNICODE_MODIFIER_SYMBOL), - Symbol_Other = U_MASK(G_UNICODE_OTHER_SYMBOL), - - Punctuation_InitialQuote = U_MASK(G_UNICODE_INITIAL_PUNCTUATION), - Punctuation_FinalQuote = U_MASK(G_UNICODE_FINAL_PUNCTUATION) -}; - -UChar32 foldCase(UChar32); - -int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); - -int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); - -inline UChar32 toLower(UChar32 c) -{ - return g_unichar_tolower(c); -} - -inline UChar32 toUpper(UChar32 c) -{ - return g_unichar_toupper(c); -} - -int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error); - -inline UChar32 toTitleCase(UChar32 c) -{ - return g_unichar_totitle(c); -} - -inline bool isArabicChar(UChar32 c) -{ - return c >= 0x0600 && c <= 0x06FF; -} - -inline bool isAlphanumeric(UChar32 c) -{ - return g_unichar_isalnum(c); -} - -inline bool isFormatChar(UChar32 c) -{ - return g_unichar_type(c) == G_UNICODE_FORMAT; -} - -inline bool isSeparatorSpace(UChar32 c) -{ - return g_unichar_type(c) == G_UNICODE_SPACE_SEPARATOR; -} - -inline bool isPrintableChar(UChar32 c) -{ - return g_unichar_isprint(c); -} - -inline bool isDigit(UChar32 c) -{ - return g_unichar_isdigit(c); -} - -inline bool isPunct(UChar32 c) -{ - return g_unichar_ispunct(c); -} - -inline bool hasLineBreakingPropertyComplexContext(UChar32 c) -{ - // FIXME - return false; -} - -inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c) -{ - // FIXME - return false; -} - -inline UChar32 mirroredChar(UChar32 c) -{ - gunichar mirror = 0; - g_unichar_get_mirror_char(c, &mirror); - return mirror; -} - -inline CharCategory category(UChar32 c) -{ - if (c > 0xffff) - return NoCategory; - - return (CharCategory) U_MASK(g_unichar_type(c)); -} - -Direction direction(UChar32); - -inline bool isLower(UChar32 c) -{ - return g_unichar_islower(c); -} - -inline int digitValue(UChar32 c) -{ - return g_unichar_digit_value(c); -} - -inline uint8_t combiningClass(UChar32 c) -{ - // FIXME - // return g_unichar_combining_class(c); - return 0; -} - -inline DecompositionType decompositionType(UChar32 c) -{ - // FIXME - return DecompositionNone; -} - -int umemcasecmp(const UChar*, const UChar*, int len); - -} -} - -#endif - diff --git a/Source/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp b/Source/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp deleted file mode 100644 index 348693f4d..000000000 --- a/Source/JavaScriptCore/wtf/unicode/icu/CollatorICU.cpp +++ /dev/null @@ -1,149 +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. - * 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" -#include "Collator.h" - -#if USE(ICU_UNICODE) && !UCONFIG_NO_COLLATION - -#include "Assertions.h" -#include "Threading.h" -#include <unicode/ucol.h> -#include <string.h> - -#if OS(DARWIN) -#include "RetainPtr.h" -#include <CoreFoundation/CoreFoundation.h> -#endif - -namespace WTF { - -static UCollator* cachedCollator; -static Mutex& cachedCollatorMutex() -{ - AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); - return mutex; -} - -Collator::Collator(const char* locale) - : m_collator(0) - , m_locale(locale ? strdup(locale) : 0) - , m_lowerFirst(false) -{ -} - -PassOwnPtr<Collator> Collator::userDefault() -{ -#if OS(DARWIN) && USE(CF) - // Mac OS X doesn't set UNIX locale to match user-selected one, so ICU default doesn't work. -#if !defined(BUILDING_ON_LEOPARD) && !OS(IOS) - RetainPtr<CFLocaleRef> currentLocale(AdoptCF, CFLocaleCopyCurrent()); - CFStringRef collationOrder = (CFStringRef)CFLocaleGetValue(currentLocale.get(), kCFLocaleCollatorIdentifier); -#else - RetainPtr<CFStringRef> collationOrderRetainer(AdoptCF, (CFStringRef)CFPreferencesCopyValue(CFSTR("AppleCollationOrder"), kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)); - CFStringRef collationOrder = collationOrderRetainer.get(); -#endif - char buf[256]; - if (!collationOrder) - return adoptPtr(new Collator("")); - CFStringGetCString(collationOrder, buf, sizeof(buf), kCFStringEncodingASCII); - return adoptPtr(new Collator(buf)); -#else - return adoptPtr(new Collator(0)); -#endif -} - -Collator::~Collator() -{ - releaseCollator(); - free(m_locale); -} - -void Collator::setOrderLowerFirst(bool lowerFirst) -{ - m_lowerFirst = lowerFirst; -} - -Collator::Result Collator::collate(const UChar* lhs, size_t lhsLength, const UChar* rhs, size_t rhsLength) const -{ - if (!m_collator) - createCollator(); - - return static_cast<Result>(ucol_strcoll(m_collator, lhs, lhsLength, rhs, rhsLength)); -} - -void Collator::createCollator() const -{ - ASSERT(!m_collator); - UErrorCode status = U_ZERO_ERROR; - - { - Locker<Mutex> lock(cachedCollatorMutex()); - if (cachedCollator) { - const char* cachedCollatorLocale = ucol_getLocaleByType(cachedCollator, ULOC_REQUESTED_LOCALE, &status); - ASSERT(U_SUCCESS(status)); - ASSERT(cachedCollatorLocale); - - UColAttributeValue cachedCollatorLowerFirst = ucol_getAttribute(cachedCollator, UCOL_CASE_FIRST, &status); - ASSERT(U_SUCCESS(status)); - - // FIXME: default locale is never matched, because ucol_getLocaleByType returns the actual one used, not 0. - if (m_locale && 0 == strcmp(cachedCollatorLocale, m_locale) - && ((UCOL_LOWER_FIRST == cachedCollatorLowerFirst && m_lowerFirst) || (UCOL_UPPER_FIRST == cachedCollatorLowerFirst && !m_lowerFirst))) { - m_collator = cachedCollator; - cachedCollator = 0; - return; - } - } - } - - m_collator = ucol_open(m_locale, &status); - if (U_FAILURE(status)) { - status = U_ZERO_ERROR; - m_collator = ucol_open("", &status); // Fallback to Unicode Collation Algorithm. - } - ASSERT(U_SUCCESS(status)); - - ucol_setAttribute(m_collator, UCOL_CASE_FIRST, m_lowerFirst ? UCOL_LOWER_FIRST : UCOL_UPPER_FIRST, &status); - ASSERT(U_SUCCESS(status)); -} - -void Collator::releaseCollator() -{ - { - Locker<Mutex> lock(cachedCollatorMutex()); - if (cachedCollator) - ucol_close(cachedCollator); - cachedCollator = m_collator; - m_collator = 0; - } -} - -} - -#endif diff --git a/Source/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h b/Source/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h deleted file mode 100644 index fe524b2a2..000000000 --- a/Source/JavaScriptCore/wtf/unicode/icu/UnicodeIcu.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2006 George Staikos <staikos@kde.org> - * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_UNICODE_ICU_H -#define WTF_UNICODE_ICU_H - -#include <stdlib.h> -#include <unicode/uchar.h> -#include <unicode/uscript.h> -#include <unicode/ustring.h> -#include <unicode/utf16.h> - -namespace WTF { -namespace Unicode { - -enum Direction { - LeftToRight = U_LEFT_TO_RIGHT, - RightToLeft = U_RIGHT_TO_LEFT, - EuropeanNumber = U_EUROPEAN_NUMBER, - EuropeanNumberSeparator = U_EUROPEAN_NUMBER_SEPARATOR, - EuropeanNumberTerminator = U_EUROPEAN_NUMBER_TERMINATOR, - ArabicNumber = U_ARABIC_NUMBER, - CommonNumberSeparator = U_COMMON_NUMBER_SEPARATOR, - BlockSeparator = U_BLOCK_SEPARATOR, - SegmentSeparator = U_SEGMENT_SEPARATOR, - WhiteSpaceNeutral = U_WHITE_SPACE_NEUTRAL, - OtherNeutral = U_OTHER_NEUTRAL, - LeftToRightEmbedding = U_LEFT_TO_RIGHT_EMBEDDING, - LeftToRightOverride = U_LEFT_TO_RIGHT_OVERRIDE, - RightToLeftArabic = U_RIGHT_TO_LEFT_ARABIC, - RightToLeftEmbedding = U_RIGHT_TO_LEFT_EMBEDDING, - RightToLeftOverride = U_RIGHT_TO_LEFT_OVERRIDE, - PopDirectionalFormat = U_POP_DIRECTIONAL_FORMAT, - NonSpacingMark = U_DIR_NON_SPACING_MARK, - BoundaryNeutral = U_BOUNDARY_NEUTRAL -}; - -enum DecompositionType { - DecompositionNone = U_DT_NONE, - DecompositionCanonical = U_DT_CANONICAL, - DecompositionCompat = U_DT_COMPAT, - DecompositionCircle = U_DT_CIRCLE, - DecompositionFinal = U_DT_FINAL, - DecompositionFont = U_DT_FONT, - DecompositionFraction = U_DT_FRACTION, - DecompositionInitial = U_DT_INITIAL, - DecompositionIsolated = U_DT_ISOLATED, - DecompositionMedial = U_DT_MEDIAL, - DecompositionNarrow = U_DT_NARROW, - DecompositionNoBreak = U_DT_NOBREAK, - DecompositionSmall = U_DT_SMALL, - DecompositionSquare = U_DT_SQUARE, - DecompositionSub = U_DT_SUB, - DecompositionSuper = U_DT_SUPER, - DecompositionVertical = U_DT_VERTICAL, - DecompositionWide = U_DT_WIDE, -}; - -enum CharCategory { - NoCategory = 0, - Other_NotAssigned = U_MASK(U_GENERAL_OTHER_TYPES), - Letter_Uppercase = U_MASK(U_UPPERCASE_LETTER), - Letter_Lowercase = U_MASK(U_LOWERCASE_LETTER), - Letter_Titlecase = U_MASK(U_TITLECASE_LETTER), - Letter_Modifier = U_MASK(U_MODIFIER_LETTER), - Letter_Other = U_MASK(U_OTHER_LETTER), - - Mark_NonSpacing = U_MASK(U_NON_SPACING_MARK), - Mark_Enclosing = U_MASK(U_ENCLOSING_MARK), - Mark_SpacingCombining = U_MASK(U_COMBINING_SPACING_MARK), - - Number_DecimalDigit = U_MASK(U_DECIMAL_DIGIT_NUMBER), - Number_Letter = U_MASK(U_LETTER_NUMBER), - Number_Other = U_MASK(U_OTHER_NUMBER), - - Separator_Space = U_MASK(U_SPACE_SEPARATOR), - Separator_Line = U_MASK(U_LINE_SEPARATOR), - Separator_Paragraph = U_MASK(U_PARAGRAPH_SEPARATOR), - - Other_Control = U_MASK(U_CONTROL_CHAR), - Other_Format = U_MASK(U_FORMAT_CHAR), - Other_PrivateUse = U_MASK(U_PRIVATE_USE_CHAR), - Other_Surrogate = U_MASK(U_SURROGATE), - - Punctuation_Dash = U_MASK(U_DASH_PUNCTUATION), - Punctuation_Open = U_MASK(U_START_PUNCTUATION), - Punctuation_Close = U_MASK(U_END_PUNCTUATION), - Punctuation_Connector = U_MASK(U_CONNECTOR_PUNCTUATION), - Punctuation_Other = U_MASK(U_OTHER_PUNCTUATION), - - Symbol_Math = U_MASK(U_MATH_SYMBOL), - Symbol_Currency = U_MASK(U_CURRENCY_SYMBOL), - Symbol_Modifier = U_MASK(U_MODIFIER_SYMBOL), - Symbol_Other = U_MASK(U_OTHER_SYMBOL), - - Punctuation_InitialQuote = U_MASK(U_INITIAL_PUNCTUATION), - Punctuation_FinalQuote = U_MASK(U_FINAL_PUNCTUATION) -}; - -inline UChar32 foldCase(UChar32 c) -{ - return u_foldCase(c, U_FOLD_CASE_DEFAULT); -} - -inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - UErrorCode status = U_ZERO_ERROR; - int realLength = u_strFoldCase(result, resultLength, src, srcLength, U_FOLD_CASE_DEFAULT, &status); - *error = !U_SUCCESS(status); - return realLength; -} - -inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - UErrorCode status = U_ZERO_ERROR; - int realLength = u_strToLower(result, resultLength, src, srcLength, "", &status); - *error = !!U_FAILURE(status); - return realLength; -} - -inline UChar32 toLower(UChar32 c) -{ - return u_tolower(c); -} - -inline UChar32 toUpper(UChar32 c) -{ - return u_toupper(c); -} - -inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - UErrorCode status = U_ZERO_ERROR; - int realLength = u_strToUpper(result, resultLength, src, srcLength, "", &status); - *error = !!U_FAILURE(status); - return realLength; -} - -inline UChar32 toTitleCase(UChar32 c) -{ - return u_totitle(c); -} - -inline bool isArabicChar(UChar32 c) -{ - return ublock_getCode(c) == UBLOCK_ARABIC; -} - -inline bool isAlphanumeric(UChar32 c) -{ - return u_isalnum(c); -} - -inline bool isSeparatorSpace(UChar32 c) -{ - return u_charType(c) == U_SPACE_SEPARATOR; -} - -inline bool isPrintableChar(UChar32 c) -{ - return !!u_isprint(c); -} - -inline bool isPunct(UChar32 c) -{ - return !!u_ispunct(c); -} - -inline bool hasLineBreakingPropertyComplexContext(UChar32 c) -{ - return u_getIntPropertyValue(c, UCHAR_LINE_BREAK) == U_LB_COMPLEX_CONTEXT; -} - -inline bool hasLineBreakingPropertyComplexContextOrIdeographic(UChar32 c) -{ - int32_t prop = u_getIntPropertyValue(c, UCHAR_LINE_BREAK); - return prop == U_LB_COMPLEX_CONTEXT || prop == U_LB_IDEOGRAPHIC; -} - -inline UChar32 mirroredChar(UChar32 c) -{ - return u_charMirror(c); -} - -inline CharCategory category(UChar32 c) -{ - return static_cast<CharCategory>(U_GET_GC_MASK(c)); -} - -inline Direction direction(UChar32 c) -{ - return static_cast<Direction>(u_charDirection(c)); -} - -inline bool isLower(UChar32 c) -{ - return !!u_islower(c); -} - -inline uint8_t combiningClass(UChar32 c) -{ - return u_getCombiningClass(c); -} - -inline DecompositionType decompositionType(UChar32 c) -{ - return static_cast<DecompositionType>(u_getIntPropertyValue(c, UCHAR_DECOMPOSITION_TYPE)); -} - -inline int umemcasecmp(const UChar* a, const UChar* b, int len) -{ - return u_memcasecmp(a, b, len, U_FOLD_CASE_DEFAULT); -} - -} } - -#endif // WTF_UNICODE_ICU_H diff --git a/Source/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h b/Source/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h deleted file mode 100644 index a2d1ad4c1..000000000 --- a/Source/JavaScriptCore/wtf/unicode/qt4/UnicodeQt4.h +++ /dev/null @@ -1,377 +0,0 @@ -/* - * Copyright (C) 2006 George Staikos <staikos@kde.org> - * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> - * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_UNICODE_QT4_H -#define WTF_UNICODE_QT4_H - -#include <wtf/unicode/ScriptCodesFromICU.h> -#include <wtf/unicode/UnicodeMacrosFromICU.h> - -#include <QChar> -#include <QString> - -#include <config.h> - -#include <stdint.h> -#if USE(ICU_UNICODE) -#include <unicode/ubrk.h> -#endif - -QT_BEGIN_NAMESPACE -namespace QUnicodeTables { - struct Properties { - ushort category : 8; - ushort line_break_class : 8; - ushort direction : 8; - ushort combiningClass :8; - ushort joining : 2; - signed short digitValue : 6; /* 5 needed */ - ushort unicodeVersion : 4; - ushort lowerCaseSpecial : 1; - ushort upperCaseSpecial : 1; - ushort titleCaseSpecial : 1; - ushort caseFoldSpecial : 1; /* currently unused */ - signed short mirrorDiff : 16; - signed short lowerCaseDiff : 16; - signed short upperCaseDiff : 16; - signed short titleCaseDiff : 16; - signed short caseFoldDiff : 16; - }; - Q_CORE_EXPORT const Properties * QT_FASTCALL properties(uint ucs4); - Q_CORE_EXPORT const Properties * QT_FASTCALL properties(ushort ucs2); -} -QT_END_NAMESPACE - -// ugly hack to make UChar compatible with JSChar in API/JSStringRef.h -#if defined(Q_OS_WIN) || (COMPILER(RVCT) && !OS(LINUX)) -typedef wchar_t UChar; -#else -typedef uint16_t UChar; -#endif - -#if !USE(ICU_UNICODE) -typedef uint32_t UChar32; -#endif - -namespace WTF { -namespace Unicode { - -enum Direction { - LeftToRight = QChar::DirL, - RightToLeft = QChar::DirR, - EuropeanNumber = QChar::DirEN, - EuropeanNumberSeparator = QChar::DirES, - EuropeanNumberTerminator = QChar::DirET, - ArabicNumber = QChar::DirAN, - CommonNumberSeparator = QChar::DirCS, - BlockSeparator = QChar::DirB, - SegmentSeparator = QChar::DirS, - WhiteSpaceNeutral = QChar::DirWS, - OtherNeutral = QChar::DirON, - LeftToRightEmbedding = QChar::DirLRE, - LeftToRightOverride = QChar::DirLRO, - RightToLeftArabic = QChar::DirAL, - RightToLeftEmbedding = QChar::DirRLE, - RightToLeftOverride = QChar::DirRLO, - PopDirectionalFormat = QChar::DirPDF, - NonSpacingMark = QChar::DirNSM, - BoundaryNeutral = QChar::DirBN -}; - -enum DecompositionType { - DecompositionNone = QChar::NoDecomposition, - DecompositionCanonical = QChar::Canonical, - DecompositionCompat = QChar::Compat, - DecompositionCircle = QChar::Circle, - DecompositionFinal = QChar::Final, - DecompositionFont = QChar::Font, - DecompositionFraction = QChar::Fraction, - DecompositionInitial = QChar::Initial, - DecompositionIsolated = QChar::Isolated, - DecompositionMedial = QChar::Medial, - DecompositionNarrow = QChar::Narrow, - DecompositionNoBreak = QChar::NoBreak, - DecompositionSmall = QChar::Small, - DecompositionSquare = QChar::Square, - DecompositionSub = QChar::Sub, - DecompositionSuper = QChar::Super, - DecompositionVertical = QChar::Vertical, - DecompositionWide = QChar::Wide -}; - -enum CharCategory { - NoCategory = 0, - Mark_NonSpacing = U_MASK(QChar::Mark_NonSpacing), - Mark_SpacingCombining = U_MASK(QChar::Mark_SpacingCombining), - Mark_Enclosing = U_MASK(QChar::Mark_Enclosing), - Number_DecimalDigit = U_MASK(QChar::Number_DecimalDigit), - Number_Letter = U_MASK(QChar::Number_Letter), - Number_Other = U_MASK(QChar::Number_Other), - Separator_Space = U_MASK(QChar::Separator_Space), - Separator_Line = U_MASK(QChar::Separator_Line), - Separator_Paragraph = U_MASK(QChar::Separator_Paragraph), - Other_Control = U_MASK(QChar::Other_Control), - Other_Format = U_MASK(QChar::Other_Format), - Other_Surrogate = U_MASK(QChar::Other_Surrogate), - Other_PrivateUse = U_MASK(QChar::Other_PrivateUse), - Other_NotAssigned = U_MASK(QChar::Other_NotAssigned), - Letter_Uppercase = U_MASK(QChar::Letter_Uppercase), - Letter_Lowercase = U_MASK(QChar::Letter_Lowercase), - Letter_Titlecase = U_MASK(QChar::Letter_Titlecase), - Letter_Modifier = U_MASK(QChar::Letter_Modifier), - Letter_Other = U_MASK(QChar::Letter_Other), - Punctuation_Connector = U_MASK(QChar::Punctuation_Connector), - Punctuation_Dash = U_MASK(QChar::Punctuation_Dash), - Punctuation_Open = U_MASK(QChar::Punctuation_Open), - Punctuation_Close = U_MASK(QChar::Punctuation_Close), - Punctuation_InitialQuote = U_MASK(QChar::Punctuation_InitialQuote), - Punctuation_FinalQuote = U_MASK(QChar::Punctuation_FinalQuote), - Punctuation_Other = U_MASK(QChar::Punctuation_Other), - Symbol_Math = U_MASK(QChar::Symbol_Math), - Symbol_Currency = U_MASK(QChar::Symbol_Currency), - Symbol_Modifier = U_MASK(QChar::Symbol_Modifier), - Symbol_Other = U_MASK(QChar::Symbol_Other) -}; - - -// FIXME: handle surrogates correctly in all methods - -inline UChar32 toLower(UChar32 ch) -{ - return QChar::toLower(uint32_t(ch)); -} - -inline int toLower(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - const UChar *e = src + srcLength; - const UChar *s = src; - UChar *r = result; - uint rindex = 0; - - // this avoids one out of bounds check in the loop - if (s < e && QChar(*s).isLowSurrogate()) { - if (r) - r[rindex] = *s++; - ++rindex; - } - - int needed = 0; - while (s < e && (rindex < uint(resultLength) || !r)) { - uint c = *s; - if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate()) - c = QChar::surrogateToUcs4(*(s - 1), c); - const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c); - if (prop->lowerCaseSpecial) { - QString qstring; - if (c < 0x10000) { - qstring += QChar(c); - } else { - qstring += QChar(*(s-1)); - qstring += QChar(*s); - } - qstring = qstring.toLower(); - for (int i = 0; i < qstring.length(); ++i) { - if (rindex >= uint(resultLength)) { - needed += qstring.length() - i; - break; - } - if (r) - r[rindex] = qstring.at(i).unicode(); - ++rindex; - } - } else { - if (r) - r[rindex] = *s + prop->lowerCaseDiff; - ++rindex; - } - ++s; - } - if (s < e) - needed += e - s; - *error = (needed != 0); - if (rindex < uint(resultLength)) - r[rindex] = 0; - return rindex + needed; -} - -inline UChar32 toUpper(UChar32 c) -{ - return QChar::toUpper(uint32_t(c)); -} - -inline int toUpper(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - const UChar *e = src + srcLength; - const UChar *s = src; - UChar *r = result; - int rindex = 0; - - // this avoids one out of bounds check in the loop - if (s < e && QChar(*s).isLowSurrogate()) { - if (r) - r[rindex] = *s++; - ++rindex; - } - - int needed = 0; - while (s < e && (rindex < resultLength || !r)) { - uint c = *s; - if (QChar(c).isLowSurrogate() && QChar(*(s - 1)).isHighSurrogate()) - c = QChar::surrogateToUcs4(*(s - 1), c); - const QUnicodeTables::Properties *prop = QUnicodeTables::properties(c); - if (prop->upperCaseSpecial) { - QString qstring; - if (c < 0x10000) { - qstring += QChar(c); - } else { - qstring += QChar(*(s-1)); - qstring += QChar(*s); - } - qstring = qstring.toUpper(); - for (int i = 0; i < qstring.length(); ++i) { - if (rindex >= resultLength) { - needed += qstring.length() - i; - break; - } - if (r) - r[rindex] = qstring.at(i).unicode(); - ++rindex; - } - } else { - if (r) - r[rindex] = *s + prop->upperCaseDiff; - ++rindex; - } - ++s; - } - if (s < e) - needed += e - s; - *error = (needed != 0); - if (rindex < resultLength) - r[rindex] = 0; - return rindex + needed; -} - -inline int toTitleCase(UChar32 c) -{ - return QChar::toTitleCase(uint32_t(c)); -} - -inline UChar32 foldCase(UChar32 c) -{ - return QChar::toCaseFolded(uint32_t(c)); -} - -inline int foldCase(UChar* result, int resultLength, const UChar* src, int srcLength, bool* error) -{ - // FIXME: handle special casing. Easiest with some low level API in Qt - *error = false; - if (resultLength < srcLength) { - *error = true; - return srcLength; - } - for (int i = 0; i < srcLength; ++i) - result[i] = QChar::toCaseFolded(ushort(src[i])); - return srcLength; -} - -inline bool isArabicChar(UChar32 c) -{ - return c >= 0x0600 && c <= 0x06FF; -} - -inline bool isPrintableChar(UChar32 c) -{ - const uint test = U_MASK(QChar::Other_Control) | - U_MASK(QChar::Other_NotAssigned); - return !(U_MASK(QChar::category(uint32_t(c))) & test); -} - -inline bool isSeparatorSpace(UChar32 c) -{ - return QChar::category(uint32_t(c)) == QChar::Separator_Space; -} - -inline bool isPunct(UChar32 c) -{ - const uint test = U_MASK(QChar::Punctuation_Connector) | - U_MASK(QChar::Punctuation_Dash) | - U_MASK(QChar::Punctuation_Open) | - U_MASK(QChar::Punctuation_Close) | - U_MASK(QChar::Punctuation_InitialQuote) | - U_MASK(QChar::Punctuation_FinalQuote) | - U_MASK(QChar::Punctuation_Other); - return U_MASK(QChar::category(uint32_t(c))) & test; -} - -inline bool isLower(UChar32 c) -{ - return QChar::category(uint32_t(c)) == QChar::Letter_Lowercase; -} - -inline bool hasLineBreakingPropertyComplexContext(UChar32) -{ - // FIXME: Implement this to return whether the character has line breaking property SA (Complex Context). - return false; -} - -inline UChar32 mirroredChar(UChar32 c) -{ - return QChar::mirroredChar(uint32_t(c)); -} - -inline uint8_t combiningClass(UChar32 c) -{ - return QChar::combiningClass(uint32_t(c)); -} - -inline DecompositionType decompositionType(UChar32 c) -{ - return (DecompositionType)QChar::decompositionTag(c); -} - -inline int umemcasecmp(const UChar* a, const UChar* b, int len) -{ - // handle surrogates correctly - for (int i = 0; i < len; ++i) { - uint c1 = QChar::toCaseFolded(ushort(a[i])); - uint c2 = QChar::toCaseFolded(ushort(b[i])); - if (c1 != c2) - return c1 - c2; - } - return 0; -} - -inline Direction direction(UChar32 c) -{ - return (Direction)QChar::direction(uint32_t(c)); -} - -inline CharCategory category(UChar32 c) -{ - return (CharCategory) U_MASK(QChar::category(uint32_t(c))); -} - -} // namespace Unicode -} // namespace WTF - -#endif // WTF_UNICODE_QT4_H diff --git a/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.cpp b/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.cpp deleted file mode 100644 index 96dac7d40..000000000 --- a/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2006 George Staikos <staikos@kde.org> - * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> - * 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 "UnicodeWinCE.h" - -#include <wchar.h> - -namespace WTF { -namespace Unicode { - -UChar toLower(UChar c) -{ - return towlower(c); -} - -UChar toUpper(UChar c) -{ - return towupper(c); -} - -UChar foldCase(UChar c) -{ - return towlower(c); -} - -bool isPrintableChar(UChar c) -{ - return !!iswprint(c); -} - -bool isSpace(UChar c) -{ - return !!iswspace(c); -} - -bool isLetter(UChar c) -{ - return !!iswalpha(c); -} - -bool isUpper(UChar c) -{ - return !!iswupper(c); -} - -bool isLower(UChar c) -{ - return !!iswlower(c); -} - -bool isDigit(UChar c) -{ - return !!iswdigit(c); -} - -bool isPunct(UChar c) -{ - return !!iswpunct(c); -} - -bool isAlphanumeric(UChar c) -{ - return !!iswalnum(c); -} - -int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError) -{ - const UChar* sourceIterator = source; - const UChar* sourceEnd = source + sourceLength; - UChar* resultIterator = result; - UChar* resultEnd = result + resultLength; - - int remainingCharacters = 0; - if (sourceLength <= resultLength) - while (sourceIterator < sourceEnd) - *resultIterator++ = towlower(*sourceIterator++); - else - while (resultIterator < resultEnd) - *resultIterator++ = towlower(*sourceIterator++); - - if (sourceIterator < sourceEnd) - remainingCharacters += sourceEnd - sourceIterator; - *isError = !!remainingCharacters; - if (resultIterator < resultEnd) - *resultIterator = 0; - - return (resultIterator - result) + remainingCharacters; -} - -int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError) -{ - const UChar* sourceIterator = source; - const UChar* sourceEnd = source + sourceLength; - UChar* resultIterator = result; - UChar* resultEnd = result + resultLength; - - int remainingCharacters = 0; - if (sourceLength <= resultLength) - while (sourceIterator < sourceEnd) - *resultIterator++ = towupper(*sourceIterator++); - else - while (resultIterator < resultEnd) - *resultIterator++ = towupper(*sourceIterator++); - - if (sourceIterator < sourceEnd) - remainingCharacters += sourceEnd - sourceIterator; - *isError = !!remainingCharacters; - if (resultIterator < resultEnd) - *resultIterator = 0; - - return (resultIterator - result) + remainingCharacters; -} - -int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError) -{ - *isError = false; - if (resultLength < sourceLength) { - *isError = true; - return sourceLength; - } - for (int i = 0; i < sourceLength; ++i) - result[i] = foldCase(source[i]); - return sourceLength; -} - -UChar toTitleCase(UChar c) -{ - return towupper(c); -} - -Direction direction(UChar32 c) -{ - return static_cast<Direction>(UnicodeCE::direction(c)); -} - -CharCategory category(unsigned int c) -{ - return static_cast<CharCategory>(TO_MASK((__int8) UnicodeCE::category(c))); -} - -DecompositionType decompositionType(UChar32 c) -{ - return static_cast<DecompositionType>(UnicodeCE::decompositionType(c)); -} - -unsigned char combiningClass(UChar32 c) -{ - return UnicodeCE::combiningClass(c); -} - -UChar mirroredChar(UChar32 c) -{ - return UnicodeCE::mirroredChar(c); -} - -int digitValue(UChar c) -{ - return UnicodeCE::digitValue(c); -} - -} // namespace Unicode -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h b/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h deleted file mode 100644 index 1663fc969..000000000 --- a/Source/JavaScriptCore/wtf/unicode/wince/UnicodeWinCE.h +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2006 George Staikos <staikos@kde.org> - * Copyright (C) 2006 Alexey Proskuryakov <ap@nypop.com> - * Copyright (C) 2007 Apple Computer, 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. - * - */ - -#ifndef WTF_UnicodeWinCE_h -#define WTF_UnicodeWinCE_h - -#include <wtf/unicode/ScriptCodesFromICU.h> -#include <wtf/unicode/UnicodeMacrosFromICU.h> - -#include "ce_unicode.h" - -#define TO_MASK(x) (1 << (x)) - -namespace WTF { -namespace Unicode { - -enum Direction { - LeftToRight = UnicodeCE::U_LEFT_TO_RIGHT, - RightToLeft = UnicodeCE::U_RIGHT_TO_LEFT, - EuropeanNumber = UnicodeCE::U_EUROPEAN_NUMBER, - EuropeanNumberSeparator = UnicodeCE::U_EUROPEAN_NUMBER_SEPARATOR, - EuropeanNumberTerminator = UnicodeCE::U_EUROPEAN_NUMBER_TERMINATOR, - ArabicNumber = UnicodeCE::U_ARABIC_NUMBER, - CommonNumberSeparator = UnicodeCE::U_COMMON_NUMBER_SEPARATOR, - BlockSeparator = UnicodeCE::U_BLOCK_SEPARATOR, - SegmentSeparator = UnicodeCE::U_SEGMENT_SEPARATOR, - WhiteSpaceNeutral = UnicodeCE::U_WHITE_SPACE_NEUTRAL, - OtherNeutral = UnicodeCE::U_OTHER_NEUTRAL, - LeftToRightEmbedding = UnicodeCE::U_LEFT_TO_RIGHT_EMBEDDING, - LeftToRightOverride = UnicodeCE::U_LEFT_TO_RIGHT_OVERRIDE, - RightToLeftArabic = UnicodeCE::U_RIGHT_TO_LEFT_ARABIC, - RightToLeftEmbedding = UnicodeCE::U_RIGHT_TO_LEFT_EMBEDDING, - RightToLeftOverride = UnicodeCE::U_RIGHT_TO_LEFT_OVERRIDE, - PopDirectionalFormat = UnicodeCE::U_POP_DIRECTIONAL_FORMAT, - NonSpacingMark = UnicodeCE::U_DIR_NON_SPACING_MARK, - BoundaryNeutral = UnicodeCE::U_BOUNDARY_NEUTRAL -}; - -enum DecompositionType { - DecompositionNone = UnicodeCE::U_DT_NONE, - DecompositionCanonical = UnicodeCE::U_DT_CANONICAL, - DecompositionCompat = UnicodeCE::U_DT_COMPAT, - DecompositionCircle = UnicodeCE::U_DT_CIRCLE, - DecompositionFinal = UnicodeCE::U_DT_FINAL, - DecompositionFont = UnicodeCE::U_DT_FONT, - DecompositionFraction = UnicodeCE::U_DT_FRACTION, - DecompositionInitial = UnicodeCE::U_DT_INITIAL, - DecompositionIsolated = UnicodeCE::U_DT_ISOLATED, - DecompositionMedial = UnicodeCE::U_DT_MEDIAL, - DecompositionNarrow = UnicodeCE::U_DT_NARROW, - DecompositionNoBreak = UnicodeCE::U_DT_NOBREAK, - DecompositionSmall = UnicodeCE::U_DT_SMALL, - DecompositionSquare = UnicodeCE::U_DT_SQUARE, - DecompositionSub = UnicodeCE::U_DT_SUB, - DecompositionSuper = UnicodeCE::U_DT_SUPER, - DecompositionVertical = UnicodeCE::U_DT_VERTICAL, - DecompositionWide = UnicodeCE::U_DT_WIDE -}; - -enum CharCategory { - NoCategory = 0, - Other_NotAssigned = TO_MASK(UnicodeCE::U_GENERAL_OTHER_TYPES), - Letter_Uppercase = TO_MASK(UnicodeCE::U_UPPERCASE_LETTER), - Letter_Lowercase = TO_MASK(UnicodeCE::U_LOWERCASE_LETTER), - Letter_Titlecase = TO_MASK(UnicodeCE::U_TITLECASE_LETTER), - Letter_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_LETTER), - Letter_Other = TO_MASK(UnicodeCE::U_OTHER_LETTER), - - Mark_NonSpacing = TO_MASK(UnicodeCE::U_NON_SPACING_MARK), - Mark_Enclosing = TO_MASK(UnicodeCE::U_ENCLOSING_MARK), - Mark_SpacingCombining = TO_MASK(UnicodeCE::U_COMBINING_SPACING_MARK), - - Number_DecimalDigit = TO_MASK(UnicodeCE::U_DECIMAL_DIGIT_NUMBER), - Number_Letter = TO_MASK(UnicodeCE::U_LETTER_NUMBER), - Number_Other = TO_MASK(UnicodeCE::U_OTHER_NUMBER), - - Separator_Space = TO_MASK(UnicodeCE::U_SPACE_SEPARATOR), - Separator_Line = TO_MASK(UnicodeCE::U_LINE_SEPARATOR), - Separator_Paragraph = TO_MASK(UnicodeCE::U_PARAGRAPH_SEPARATOR), - - Other_Control = TO_MASK(UnicodeCE::U_CONTROL_CHAR), - Other_Format = TO_MASK(UnicodeCE::U_FORMAT_CHAR), - Other_PrivateUse = TO_MASK(UnicodeCE::U_PRIVATE_USE_CHAR), - Other_Surrogate = TO_MASK(UnicodeCE::U_SURROGATE), - - Punctuation_Dash = TO_MASK(UnicodeCE::U_DASH_PUNCTUATION), - Punctuation_Open = TO_MASK(UnicodeCE::U_START_PUNCTUATION), - Punctuation_Close = TO_MASK(UnicodeCE::U_END_PUNCTUATION), - Punctuation_Connector = TO_MASK(UnicodeCE::U_CONNECTOR_PUNCTUATION), - Punctuation_Other = TO_MASK(UnicodeCE::U_OTHER_PUNCTUATION), - - Symbol_Math = TO_MASK(UnicodeCE::U_MATH_SYMBOL), - Symbol_Currency = TO_MASK(UnicodeCE::U_CURRENCY_SYMBOL), - Symbol_Modifier = TO_MASK(UnicodeCE::U_MODIFIER_SYMBOL), - Symbol_Other = TO_MASK(UnicodeCE::U_OTHER_SYMBOL), - - Punctuation_InitialQuote = TO_MASK(UnicodeCE::U_INITIAL_PUNCTUATION), - Punctuation_FinalQuote = TO_MASK(UnicodeCE::U_FINAL_PUNCTUATION) -}; - -CharCategory category(unsigned int); - -bool isSpace(UChar); -bool isLetter(UChar); -bool isPrintableChar(UChar); -bool isUpper(UChar); -bool isLower(UChar); -bool isPunct(UChar); -bool isDigit(UChar); -bool isAlphanumeric(UChar); -inline bool isSeparatorSpace(UChar c) { return category(c) == Separator_Space; } -inline bool isHighSurrogate(UChar c) { return (c & 0xfc00) == 0xd800; } -inline bool isLowSurrogate(UChar c) { return (c & 0xfc00) == 0xdc00; } - -UChar toLower(UChar); -UChar toUpper(UChar); -UChar foldCase(UChar); -UChar toTitleCase(UChar); -int toLower(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError); -int toUpper(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError); -int foldCase(UChar* result, int resultLength, const UChar* source, int sourceLength, bool* isError); - -int digitValue(UChar); - -UChar mirroredChar(UChar32); -unsigned char combiningClass(UChar32); -DecompositionType decompositionType(UChar32); -Direction direction(UChar32); -inline bool isArabicChar(UChar32 c) -{ - return c >= 0x0600 && c <= 0x06FF; -} - -inline bool hasLineBreakingPropertyComplexContext(UChar32) -{ - return false; // FIXME: implement! -} - -inline int umemcasecmp(const UChar* a, const UChar* b, int len) -{ - for (int i = 0; i < len; ++i) { - UChar c1 = foldCase(a[i]); - UChar c2 = foldCase(b[i]); - if (c1 != c2) - return c1 - c2; - } - return 0; -} - -inline UChar32 surrogateToUcs4(UChar high, UChar low) -{ - return (UChar32(high) << 10) + low - 0x35fdc00; -} - -} // namespace Unicode -} // namespace WTF - -#endif // WTF_UnicodeWinCE_h diff --git a/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp b/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp deleted file mode 100644 index f69162a67..000000000 --- a/Source/JavaScriptCore/wtf/url/api/ParsedURL.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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. - * - * 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 "ParsedURL.h" - -#if USE(WTFURL) - -#include "URLComponent.h" -#include "URLParser.h" - -namespace WTF { - -ParsedURL::ParsedURL(const String& urlString) - : m_spec(urlString) -{ - // FIXME: Handle non-standard URLs. - if (urlString.isEmpty()) - return; - URLParser<UChar>::parseStandardURL(urlString.characters(), urlString.length(), m_segments); -} - -ParsedURL ParsedURL::isolatedCopy() const -{ - ParsedURL copy; - copy.m_segments = this->m_segments; - copy.m_spec = URLString(this->m_spec.string().isolatedCopy()); - return copy; -} - -String ParsedURL::scheme() const -{ - return segment(m_segments.scheme); -} - -String ParsedURL::username() const -{ - return segment(m_segments.username); -} - -String ParsedURL::password() const -{ - return segment(m_segments.password); -} - -String ParsedURL::host() const -{ - return segment(m_segments.host); -} - -String ParsedURL::port() const -{ - return segment(m_segments.port); -} - -String ParsedURL::path() const -{ - return segment(m_segments.path); -} - -String ParsedURL::query() const -{ - return segment(m_segments.query); -} - -String ParsedURL::fragment() const -{ - return segment(m_segments.fragment); -} - -String ParsedURL::baseAsString() const -{ - // FIXME: Add WTFURL Implementation. - return String(); -} - -String ParsedURL::segment(const URLComponent& component) const -{ - ASSERT(isValid()); - - if (!component.isValid()) - return String(); - - String segment = m_spec.string().substring(component.begin(), component.length()); - ASSERT_WITH_MESSAGE(!segment.isEmpty(), "A valid URL component should not be empty."); - return segment; -} - -} - -#endif // USE(WTFURL) diff --git a/Source/JavaScriptCore/wtf/url/api/ParsedURL.h b/Source/JavaScriptCore/wtf/url/api/ParsedURL.h deleted file mode 100644 index 2bb3330cf..000000000 --- a/Source/JavaScriptCore/wtf/url/api/ParsedURL.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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. - * - * 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 ParsedURL_h -#define ParsedURL_h - -#if USE(WTFURL) - -#include <wtf/url/api/URLString.h> -#include <wtf/url/src/URLSegments.h> - -namespace WTF { - -class URLComponent; - -// ParsedURL represents a valid URL decomposed by components. -class ParsedURL { -public: - // FIXME: Add a method for parsing non-canonicalized URLs. - ParsedURL() { }; - WTF_EXPORT_PRIVATE explicit ParsedURL(const String&); - - WTF_EXPORT_PRIVATE ParsedURL isolatedCopy() const; - - bool isValid() const { return !m_spec.string().isEmpty(); } - - // Return a URL component or a null String if the component is undefined for the URL. - WTF_EXPORT_PRIVATE String scheme() const; - WTF_EXPORT_PRIVATE String username() const; - WTF_EXPORT_PRIVATE String password() const; - WTF_EXPORT_PRIVATE String host() const; - WTF_EXPORT_PRIVATE String port() const; - WTF_EXPORT_PRIVATE String path() const; - WTF_EXPORT_PRIVATE String query() const; - WTF_EXPORT_PRIVATE String fragment() const; - - WTF_EXPORT_PRIVATE String baseAsString() const; - - URLString spec() { return m_spec; } - -private: - inline String segment(const URLComponent&) const; - - URLString m_spec; - URLSegments m_segments; -}; - -} - -#endif // USE(WTFURL) - -#endif diff --git a/Source/JavaScriptCore/wtf/url/src/RawURLBuffer.h b/Source/JavaScriptCore/wtf/url/src/RawURLBuffer.h deleted file mode 100644 index 59a7f18af..000000000 --- a/Source/JavaScriptCore/wtf/url/src/RawURLBuffer.h +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef RawURLBuffer_h -#define RawURLBuffer_h - -#if USE(WTFURL) - -#include "URLBuffer.h" - -namespace WTF { - -// Simple implementation of the URLBuffer using new[]. This class -// also supports a static buffer so if it is allocated on the stack, most -// URLs can be canonicalized with no heap allocations. -template<typename CharacterType, int inlineCapacity = 1024> -class RawURLBuffer : public URLBuffer<CharacterType> { -public: - RawURLBuffer() : URLBuffer<CharacterType>() - { - this->m_buffer = m_inlineBuffer; - this->m_capacity = inlineCapacity; - } - - virtual ~RawURLBuffer() - { - if (this->m_buffer != m_inlineBuffer) - delete[] this->m_buffer; - } - - virtual void resize(int size) - { - CharacterType* newBuffer = new CharacterType[size]; - memcpy(newBuffer, this->m_buffer, sizeof(CharacterType) * (this->m_length < size ? this->m_length : size)); - if (this->m_buffer != m_inlineBuffer) - delete[] this->m_buffer; - this->m_buffer = newBuffer; - this->m_capacity = size; - } - -protected: - CharacterType m_inlineBuffer[inlineCapacity]; -}; - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // RawURLBuffer_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLBuffer.h b/Source/JavaScriptCore/wtf/url/src/URLBuffer.h deleted file mode 100644 index 84a4f85c2..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLBuffer.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef URLBuffer_h -#define URLBuffer_h - -#if USE(WTFURL) - -namespace WTF { - -// Base class for the canonicalizer output, this maintains a buffer and -// supports simple resizing and append operations on it. -// -// It is VERY IMPORTANT that no virtual function calls be made on the common -// code path. We only have two virtual function calls, the destructor and a -// resize function that is called when the existing buffer is not big enough. -// The derived class is then in charge of setting up our buffer which we will -// manage. -template<typename CharacterType> -class URLBuffer { -public: - URLBuffer() : m_buffer(0), m_capacity(0), m_length(0) { } - virtual ~URLBuffer() { } - - // Implemented to resize the buffer. This function should update the buffer - // pointer to point to the new buffer, and any old data up to |m_length| in - // the buffer must be copied over. - // - // The new size must be larger than m_capacity. - virtual void resize(int) = 0; - - inline char at(int offset) const { return m_buffer[offset]; } - inline void set(int offset, CharacterType ch) - { - // FIXME: Add ASSERT(offset < length()); - m_buffer[offset] = ch; - } - - // Returns the current capacity of the buffer. The length() is the number of - // characters that have been declared to be written, but the capacity() is - // the number that can be written without reallocation. If the caller must - // write many characters at once, it can make sure there is enough capacity, - // write the data, then use setLength() to declare the new length(). - int capacity() const { return m_capacity; } - int length() const { return m_length; } - - // The output will NOT be 0-terminated. Call length() to get the length. - const CharacterType* data() const { return m_buffer; } - CharacterType* data() { return m_buffer; } - - // Shortens the URL to the new length. Used for "backing up" when processing - // relative paths. This can also be used if an external function writes a lot - // of data to the buffer (when using the "Raw" version below) beyond the end, - // to declare the new length. - void setLength(int length) - { - // FIXME: Add ASSERT(length < capacity()); - m_length = length; - } - - // This is the most performance critical function, since it is called for - // every character. - void append(CharacterType ch) - { - // In VC2005, putting this common case first speeds up execution - // dramatically because this branch is predicted as taken. - if (m_length < m_capacity) { - m_buffer[m_length] = ch; - ++m_length; - return; - } - - if (!grow(1)) - return; - - m_buffer[m_length] = ch; - ++m_length; - } - - void append(const CharacterType* str, int strLength) - { - if (m_length + strLength > m_capacity) { - if (!grow(m_length + strLength - m_capacity)) - return; - } - for (int i = 0; i < strLength; i++) - m_buffer[m_length + i] = str[i]; - m_length += strLength; - } - -protected: - // Returns true if the buffer could be resized, false on OOM. - bool grow(int minimumAdditionalCapacity) - { - static const int minimumCapacity = 16; - int newCapacity = m_capacity ? m_capacity : minimumCapacity; - do { - if (newCapacity >= (1 << 30)) // Prevent overflow below. - return false; - newCapacity *= 2; - } while (newCapacity < m_capacity + minimumAdditionalCapacity); - resize(newCapacity); - return true; - } - - CharacterType* m_buffer; - int m_capacity; - int m_length; // Used characters in the buffer. -}; - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLBuffer_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.cpp b/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.cpp deleted file mode 100644 index f56e7207c..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.cpp +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" -#include "URLCharacterTypes.h" - -#if USE(WTFURL) - -namespace WTF { - -const unsigned char URLCharacterTypes::characterTypeTable[0x100] = { - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x00 - 0x0f - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x10 - 0x1f - InvalidCharacter, // 0x20 ' ' (escape spaces in queries) - QueryCharacter | UserInfoCharacter, // 0x21 ! - InvalidCharacter, // 0x22 " - InvalidCharacter, // 0x23 # (invalid in query since it marks the ref) - QueryCharacter | UserInfoCharacter, // 0x24 $ - QueryCharacter | UserInfoCharacter, // 0x25 % - QueryCharacter | UserInfoCharacter, // 0x26 & - QueryCharacter | UserInfoCharacter, // 0x27 ' - QueryCharacter | UserInfoCharacter, // 0x28 ( - QueryCharacter | UserInfoCharacter, // 0x29 ) - QueryCharacter | UserInfoCharacter, // 0x2a * - QueryCharacter | UserInfoCharacter, // 0x2b + - QueryCharacter | UserInfoCharacter, // 0x2c , - QueryCharacter | UserInfoCharacter, // 0x2d - - QueryCharacter | UserInfoCharacter | IPv4Character, // 0x2e . - QueryCharacter, // 0x2f / - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x30 0 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x31 1 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x32 2 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x33 3 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x34 4 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x35 5 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x36 6 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter | OctalCharacter, // 0x37 7 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x38 8 - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter | DecimalCharacter, // 0x39 9 - QueryCharacter, // 0x3a : - QueryCharacter, // 0x3b ; - InvalidCharacter, // 0x3c < - QueryCharacter, // 0x3d = - InvalidCharacter, // 0x3e > - QueryCharacter, // 0x3f ? - QueryCharacter, // 0x40 @ - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x41 A - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x42 B - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x43 C - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x44 D - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x45 E - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x46 F - QueryCharacter | UserInfoCharacter, // 0x47 G - QueryCharacter | UserInfoCharacter, // 0x48 H - QueryCharacter | UserInfoCharacter, // 0x49 I - QueryCharacter | UserInfoCharacter, // 0x4a J - QueryCharacter | UserInfoCharacter, // 0x4b K - QueryCharacter | UserInfoCharacter, // 0x4c L - QueryCharacter | UserInfoCharacter, // 0x4d M - QueryCharacter | UserInfoCharacter, // 0x4e N - QueryCharacter | UserInfoCharacter, // 0x4f O - QueryCharacter | UserInfoCharacter, // 0x50 P - QueryCharacter | UserInfoCharacter, // 0x51 Q - QueryCharacter | UserInfoCharacter, // 0x52 R - QueryCharacter | UserInfoCharacter, // 0x53 S - QueryCharacter | UserInfoCharacter, // 0x54 T - QueryCharacter | UserInfoCharacter, // 0x55 U - QueryCharacter | UserInfoCharacter, // 0x56 V - QueryCharacter | UserInfoCharacter, // 0x57 W - QueryCharacter | UserInfoCharacter | IPv4Character, // 0x58 X - QueryCharacter | UserInfoCharacter, // 0x59 Y - QueryCharacter | UserInfoCharacter, // 0x5a Z - QueryCharacter, // 0x5b [ - QueryCharacter, // 0x5c '\' - QueryCharacter, // 0x5d ] - QueryCharacter, // 0x5e ^ - QueryCharacter | UserInfoCharacter, // 0x5f _ - QueryCharacter, // 0x60 ` - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x61 a - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x62 b - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x63 c - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x64 d - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x65 e - QueryCharacter | UserInfoCharacter | IPv4Character | HexCharacter, // 0x66 f - QueryCharacter | UserInfoCharacter, // 0x67 g - QueryCharacter | UserInfoCharacter, // 0x68 h - QueryCharacter | UserInfoCharacter, // 0x69 i - QueryCharacter | UserInfoCharacter, // 0x6a j - QueryCharacter | UserInfoCharacter, // 0x6b k - QueryCharacter | UserInfoCharacter, // 0x6c l - QueryCharacter | UserInfoCharacter, // 0x6d m - QueryCharacter | UserInfoCharacter, // 0x6e n - QueryCharacter | UserInfoCharacter, // 0x6f o - QueryCharacter | UserInfoCharacter, // 0x70 p - QueryCharacter | UserInfoCharacter, // 0x71 q - QueryCharacter | UserInfoCharacter, // 0x72 r - QueryCharacter | UserInfoCharacter, // 0x73 s - QueryCharacter | UserInfoCharacter, // 0x74 t - QueryCharacter | UserInfoCharacter, // 0x75 u - QueryCharacter | UserInfoCharacter, // 0x76 v - QueryCharacter | UserInfoCharacter, // 0x77 w - QueryCharacter | UserInfoCharacter | IPv4Character, // 0x78 x - QueryCharacter | UserInfoCharacter, // 0x79 y - QueryCharacter | UserInfoCharacter, // 0x7a z - QueryCharacter, // 0x7b { - QueryCharacter, // 0x7c | - QueryCharacter, // 0x7d } - QueryCharacter | UserInfoCharacter, // 0x7e ~ - InvalidCharacter, // 0x7f - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x80 - 0x8f - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0x90 - 0x9f - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xa0 - 0xaf - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xb0 - 0xbf - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xc0 - 0xcf - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xd0 - 0xdf - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xe0 - 0xef - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, - InvalidCharacter, InvalidCharacter, InvalidCharacter, InvalidCharacter, // 0xf0 - 0xff -}; - -} - -#endif // USE(WTFURL) diff --git a/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.h b/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.h deleted file mode 100644 index 6edb98ca2..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLCharacterTypes.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef URLCharacterTypes_h -#define URLCharacterTypes_h - -#if USE(WTFURL) - -namespace WTF { - -class URLCharacterTypes { -public: - static inline bool isQueryChar(unsigned char c) { return isCharOfType(c, QueryCharacter); } - static inline bool isIPv4Char(unsigned char c) { return isCharOfType(c, IPv4Character); } - static inline bool isHexChar(unsigned char c) { return isCharOfType(c, HexCharacter); } - -private: - enum CharTypes { - InvalidCharacter = 0, - QueryCharacter = 1 << 0, - UserInfoCharacter = 1 << 1, - IPv4Character = 1 << 2, - HexCharacter = 1 << 3, - DecimalCharacter = 1 << 4, - OctalCharacter = 1 << 5, - }; - - static const unsigned char characterTypeTable[0x100]; - - static inline bool isCharOfType(unsigned char c, CharTypes type) - { - return !!(characterTypeTable[c] & type); - } -}; - -} - -#endif // USE(WTFURL) - -#endif // URLCharacterTypes_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLComponent.h b/Source/JavaScriptCore/wtf/url/src/URLComponent.h deleted file mode 100644 index 747a80b80..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLComponent.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef URLComponent_h -#define URLComponent_h - -#if USE(WTFURL) - -namespace WTF { - -// Represents a substring for URL parsing. -class URLComponent { -public: - URLComponent() : m_begin(0), m_length(-1) { } - URLComponent(int begin, int length) : m_begin(begin), m_length(length) { } - - // Helper that returns a component created with the given begin and ending - // points. The ending point is non-inclusive. - static inline URLComponent fromRange(int begin, int end) - { - return URLComponent(begin, end - begin); - } - - // Returns true if this component is valid, meaning the length is given. Even - // valid components may be empty to record the fact that they exist. - bool isValid() const { return m_length != -1; } - - bool isNonEmpty() const { return m_length > 0; } - bool isEmptyOrInvalid() const { return m_length <= 0; } - - void reset() - { - m_begin = 0; - m_length = -1; - } - - bool operator==(const URLComponent& other) const { return m_begin == other.m_begin && m_length == other.m_length; } - - int begin() const { return m_begin; } - void setBegin(int begin) { m_begin = begin; } - - int length() const { return m_length; } - void setLength(int length) { m_length = length; } - - int end() const { return m_begin + m_length; } - -private: - int m_begin; // Byte offset in the string of this component. - int m_length; // Will be -1 if the component is unspecified. -}; - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLComponent_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLEscape.cpp b/Source/JavaScriptCore/wtf/url/src/URLEscape.cpp deleted file mode 100644 index 5acdcde24..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLEscape.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#include "config.h" -#include "URLEscape.h" - -#if USE(WTFURL) - -namespace WTF { - -const char hexCharacterTable[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', -}; - -} - -#endif // USE(WTFURL) diff --git a/Source/JavaScriptCore/wtf/url/src/URLEscape.h b/Source/JavaScriptCore/wtf/url/src/URLEscape.h deleted file mode 100644 index e010012a3..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLEscape.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef URLEscape_h -#define URLEscape_h - -#if USE(WTFURL) - -#include "URLBuffer.h" - -namespace WTF { - -extern const char hexCharacterTable[16]; - -template<typename InChar, typename OutChar> -inline void appendURLEscapedCharacter(InChar ch, URLBuffer<OutChar>& buffer) -{ - buffer.append('%'); - buffer.append(hexCharacterTable[ch >> 4]); - buffer.append(hexCharacterTable[ch & 0xf]); -} - -} - -#endif // USE(WTFURL) - -#endif diff --git a/Source/JavaScriptCore/wtf/url/src/URLParser.h b/Source/JavaScriptCore/wtf/url/src/URLParser.h deleted file mode 100644 index 01f738cf3..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLParser.h +++ /dev/null @@ -1,579 +0,0 @@ -/* Based on nsURLParsers.cc from Mozilla - * ------------------------------------- - * Copyright (C) 1998 Netscape Communications Corporation. - * - * Other contributors: - * Darin Fisher (original author) - * - * 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.1 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 - * - * Alternatively, the contents of this file may be used under the terms - * of either the Mozilla Public License Version 1.1, found at - * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public - * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html - * (the "GPL"), in which case the provisions of the MPL or the GPL are - * applicable instead of those above. If you wish to allow use of your - * version of this file only under the terms of one of those two - * licenses (the MPL or the GPL) and not to allow others to use your - * version of this file under the LGPL, indicate your decision by - * deletingthe provisions above and replace them with the notice and - * other provisions required by the MPL or the GPL, as the case may be. - * If you do not delete the provisions above, a recipient may use your - * version of this file under any of the LGPL, the MPL or the GPL. - */ - -#ifndef URLParser_h -#define URLParser_h - -#include "URLComponent.h" -#include "URLSegments.h" - -#if USE(WTFURL) - -namespace WTF { - -template<typename CharacterType> -class URLParser { -public: - enum SpecialPort { - UnspecifiedPort = -1, - InvalidPort = -2, - }; - - // This handles everything that may be an authority terminator, including - // backslash. For special backslash handling see parseAfterScheme. - static bool isPossibleAuthorityTerminator(CharacterType ch) - { - return isURLSlash(ch) || ch == '?' || ch == '#' || ch == ';'; - } - - // Given an already-identified auth section, breaks it into its constituent - // parts. The port number will be parsed and the resulting integer will be - // filled into the given *port variable, or -1 if there is no port number - // or it is invalid. - static void parseAuthority(const CharacterType* spec, const URLComponent& auth, URLComponent& username, URLComponent& password, URLComponent& host, URLComponent& port) - { - // FIXME: add ASSERT(auth.isValid()); // We should always get an authority. - if (!auth.length()) { - username.reset(); - password.reset(); - host.reset(); - port.reset(); - return; - } - - // Search backwards for @, which is the separator between the user info - // and the server info. RFC 3986 forbids @ from occuring in auth, but - // someone might include it in a password unescaped. - int i = auth.begin() + auth.length() - 1; - while (i > auth.begin() && spec[i] != '@') - --i; - - if (spec[i] == '@') { - // Found user info: <user-info>@<server-info> - parseUserInfo(spec, URLComponent(auth.begin(), i - auth.begin()), username, password); - parseServerInfo(spec, URLComponent::fromRange(i + 1, auth.begin() + auth.length()), host, port); - } else { - // No user info, everything is server info. - username.reset(); - password.reset(); - parseServerInfo(spec, auth, host, port); - } - } - - static bool extractScheme(const CharacterType* spec, int specLength, URLComponent& scheme) - { - // Skip leading whitespace and control characters. - int begin = 0; - while (begin < specLength && shouldTrimFromURL(spec[begin])) - begin++; - if (begin == specLength) - return false; // Input is empty or all whitespace. - - // Find the first colon character. - for (int i = begin; i < specLength; i++) { - if (spec[i] == ':') { - scheme = URLComponent::fromRange(begin, i); - return true; - } - } - return false; // No colon found: no scheme - } - - // Fills in all members of the URLSegments structure (except for the - // scheme) for standard URLs. - // - // |spec| is the full spec being parsed, of length |specLength|. - // |afterScheme| is the character immediately following the scheme (after - // the colon) where we'll begin parsing. - static void parseAfterScheme(const CharacterType* spec, int specLength, int afterScheme, URLSegments& parsed) - { - int numberOfSlashes = consecutiveSlashes(spec, afterScheme, specLength); - int afterSlashes = afterScheme + numberOfSlashes; - - // First split into two main parts, the authority (username, password, - // host, and port) and the full path (path, query, and reference). - URLComponent authority; - URLComponent fullPath; - - // Found "//<some data>", looks like an authority section. Treat - // everything from there to the next slash (or end of spec) to be the - // authority. Note that we ignore the number of slashes and treat it as - // the authority. - int authEnd = nextAuthorityTerminator(spec, afterSlashes, specLength); - authority = URLComponent(afterSlashes, authEnd - afterSlashes); - - if (authEnd == specLength) // No beginning of path found. - fullPath = URLComponent(); - else // Everything starting from the slash to the end is the path. - fullPath = URLComponent(authEnd, specLength - authEnd); - - // Now parse those two sub-parts. - parseAuthority(spec, authority, parsed.username, parsed.password, parsed.host, parsed.port); - parsePath(spec, fullPath, parsed.path, parsed.query, parsed.fragment); - } - - // The main parsing function for standard URLs. Standard URLs have a scheme, - // host, path, etc. - static void parseStandardURL(const CharacterType* spec, int specLength, URLSegments& parsed) - { - // FIXME: add ASSERT(specLength >= 0); - - // Strip leading & trailing spaces and control characters. - int begin = 0; - trimURL(spec, begin, specLength); - - int afterScheme; - if (extractScheme(spec, specLength, parsed.scheme)) - afterScheme = parsed.scheme.end() + 1; // Skip past the colon. - else { - // Say there's no scheme when there is a colon. We could also say - // that everything is the scheme. Both would produce an invalid - // URL, but this way seems less wrong in more cases. - parsed.scheme.reset(); - afterScheme = begin; - } - parseAfterScheme(spec, specLength, afterScheme, parsed); - } - - static void parsePath(const CharacterType* spec, const URLComponent& path, URLComponent& filepath, URLComponent& query, URLComponent& fragment) - { - // path = [/]<segment1>/<segment2>/<...>/<segmentN>;<param>?<query>#<fragment> - - // Special case when there is no path. - if (!path.isValid()) { - filepath.reset(); - query.reset(); - fragment.reset(); - return; - } - // FIXME: add ASSERT(path.length() > 0); // We should never have 0 length paths. - - // Search for first occurrence of either ? or #. - int pathEnd = path.begin() + path.length(); - - int querySeparator = -1; // Index of the '?' - int refSeparator = -1; // Index of the '#' - for (int i = path.begin(); i < pathEnd; i++) { - switch (spec[i]) { - case '?': - if (querySeparator < 0) - querySeparator = i; - break; - case '#': - refSeparator = i; - i = pathEnd; // Break out of the loop. - break; - default: - break; - } - } - - // Markers pointing to the character after each of these corresponding - // components. The code below works from the end back to the beginning, - // and will update these indices as it finds components that exist. - int fileEnd, queryEnd; - - // Fragment: from the # to the end of the path. - if (refSeparator >= 0) { - fileEnd = refSeparator; - queryEnd = refSeparator; - fragment = URLComponent::fromRange(refSeparator + 1, pathEnd); - } else { - fileEnd = pathEnd; - queryEnd = pathEnd; - fragment.reset(); - } - - // Query fragment: everything from the ? to the next boundary (either - // the end of the path or the fragment fragment). - if (querySeparator >= 0) { - fileEnd = querySeparator; - query = URLComponent::fromRange(querySeparator + 1, queryEnd); - } else - query.reset(); - - // File path: treat an empty file path as no file path. - if (fileEnd != path.begin()) - filepath = URLComponent::fromRange(path.begin(), fileEnd); - else - filepath.reset(); - } - - // Initializes a path URL which is merely a scheme followed by a path. - // Examples include "about:foo" and "javascript:alert('bar');" - static void parsePathURL(const CharacterType* spec, int specLength, URLSegments& parsed) - { - // Get the non-path and non-scheme parts of the URL out of the way, we - // never use them. - parsed.username.reset(); - parsed.password.reset(); - parsed.host.reset(); - parsed.port.reset(); - parsed.query.reset(); - parsed.fragment.reset(); - - // Strip leading & trailing spaces and control characters. - // FIXME: Perhaps this is unnecessary? - int begin = 0; - trimURL(spec, begin, specLength); - - // Handle empty specs or ones that contain only whitespace or control - // chars. - if (begin == specLength) { - parsed.scheme.reset(); - parsed.path.reset(); - return; - } - - // Extract the scheme, with the path being everything following. We also - // handle the case where there is no scheme. - if (extractScheme(&spec[begin], specLength - begin, parsed.scheme)) { - // Offset the results since we gave extractScheme a substring. - parsed.scheme.setBegin(parsed.scheme.begin() + begin); - - // For compatibility with the standard URL parser, we treat no path - // as -1, rather than having a length of 0 (we normally wouldn't - // care so much for these non-standard URLs). - if (parsed.scheme.end() == specLength - 1) - parsed.path.reset(); - else - parsed.path = URLComponent::fromRange(parsed.scheme.end() + 1, specLength); - } else { - // No scheme found, just path. - parsed.scheme.reset(); - parsed.path = URLComponent::fromRange(begin, specLength); - } - } - - static void parseMailtoURL(const CharacterType* spec, int specLength, URLSegments& parsed) - { - // FIXME: add ASSERT(specLength >= 0); - - // Get the non-path and non-scheme parts of the URL out of the way, we - // never use them. - parsed.username.reset(); - parsed.password.reset(); - parsed.host.reset(); - parsed.port.reset(); - parsed.fragment.reset(); - parsed.query.reset(); // May use this; reset for convenience. - - // Strip leading & trailing spaces and control characters. - int begin = 0; - trimURL(spec, begin, specLength); - - // Handle empty specs or ones that contain only whitespace or control - // chars. - if (begin == specLength) { - parsed.scheme.reset(); - parsed.path.reset(); - return; - } - - int pathBegin = -1; - int pathEnd = -1; - - // Extract the scheme, with the path being everything following. We also - // handle the case where there is no scheme. - if (extractScheme(&spec[begin], specLength - begin, parsed.scheme)) { - // Offset the results since we gave extractScheme a substring. - parsed.scheme.setBegin(parsed.scheme.begin() + begin); - - if (parsed.scheme.end() != specLength - 1) { - pathBegin = parsed.scheme.end() + 1; - pathEnd = specLength; - } - } else { - // No scheme found, just path. - parsed.scheme.reset(); - pathBegin = begin; - pathEnd = specLength; - } - - // Split [pathBegin, pathEnd) into a path + query. - for (int i = pathBegin; i < pathEnd; ++i) { - if (spec[i] == '?') { - parsed.query = URLComponent::fromRange(i + 1, pathEnd); - pathEnd = i; - break; - } - } - - // For compatibility with the standard URL parser, treat no path as - // -1, rather than having a length of 0 - if (pathBegin == pathEnd) - parsed.path.reset(); - else - parsed.path = URLComponent::fromRange(pathBegin, pathEnd); - } - - static int parsePort(const CharacterType* spec, const URLComponent& component) - { - // Easy success case when there is no port. - const int maxDigits = 5; - if (component.isEmptyOrInvalid()) - return UnspecifiedPort; - - URLComponent nonZeroDigits(component.end(), 0); - for (int i = 0; i < component.length(); ++i) { - if (spec[component.begin() + i] != '0') { - nonZeroDigits = URLComponent::fromRange(component.begin() + i, component.end()); - break; - } - } - if (!nonZeroDigits.length()) - return 0; // All digits were 0. - - if (nonZeroDigits.length() > maxDigits) - return InvalidPort; - - int port = 0; - for (int i = 0; i < nonZeroDigits.length(); ++i) { - CharacterType ch = spec[nonZeroDigits.begin() + i]; - if (!isPortDigit(ch)) - return InvalidPort; - port *= 10; - port += static_cast<char>(ch) - '0'; - } - if (port > 65535) - return InvalidPort; - return port; - } - - static void extractFileName(const CharacterType* spec, const URLComponent& path, URLComponent& fileName) - { - // Handle empty paths: they have no file names. - if (path.isEmptyOrInvalid()) { - fileName.reset(); - return; - } - - // Search backwards for a parameter, which is a normally unused field - // in a URL delimited by a semicolon. We parse the parameter as part of - // the path, but here, we don't want to count it. The last semicolon is - // the parameter. - int fileEnd = path.end(); - for (int i = path.end() - 1; i > path.begin(); --i) { - if (spec[i] == ';') { - fileEnd = i; - break; - } - } - - // Now search backwards from the filename end to the previous slash - // to find the beginning of the filename. - for (int i = fileEnd - 1; i >= path.begin(); --i) { - if (isURLSlash(spec[i])) { - // File name is everything following this character to the end - fileName = URLComponent::fromRange(i + 1, fileEnd); - return; - } - } - - // No slash found, this means the input was degenerate (generally paths - // will start with a slash). Let's call everything the file name. - fileName = URLComponent::fromRange(path.begin(), fileEnd); - } - - static bool extractQueryKeyValue(const CharacterType* spec, URLComponent& query, URLComponent& key, URLComponent& value) - { - if (query.isEmptyOrInvalid()) - return false; - - int start = query.begin(); - int current = start; - int end = query.end(); - - // We assume the beginning of the input is the beginning of the "key" - // and we skip to the end of it. - key.setBegin(current); - while (current < end && spec[current] != '&' && spec[current] != '=') - ++current; - key.setLength(current - key.begin()); - - // Skip the separator after the key (if any). - if (current < end && spec[current] == '=') - ++current; - - // Find the value part. - value.setBegin(current); - while (current < end && spec[current] != '&') - ++current; - value.setLength(current - value.begin()); - - // Finally skip the next separator if any - if (current < end && spec[current] == '&') - ++current; - - // Save the new query - query = URLComponent::fromRange(current, end); - return true; - } - -// FIXME: This should be protected or private. -public: - // We treat slashes and backslashes the same for IE compatibility. - static inline bool isURLSlash(CharacterType ch) - { - return ch == '/' || ch == '\\'; - } - - // Returns true if we should trim this character from the URL because it is - // a space or a control character. - static inline bool shouldTrimFromURL(CharacterType ch) - { - return ch <= ' '; - } - - // Given an already-initialized begin index and end index (the index after - // the last CharacterType in spec), this shrinks the range to eliminate - // "should-be-trimmed" characters. - static inline void trimURL(const CharacterType* spec, int& begin, int& end) - { - // Strip leading whitespace and control characters. - while (begin < end && shouldTrimFromURL(spec[begin])) - ++begin; - - // Strip trailing whitespace and control characters. We need the >i - // test for when the input string is all blanks; we don't want to back - // past the input. - while (end > begin && shouldTrimFromURL(spec[end - 1])) - --end; - } - - // Counts the number of consecutive slashes starting at the given offset - // in the given string of the given length. - static inline int consecutiveSlashes(const CharacterType *string, int beginOffset, int stringLength) - { - int count = 0; - while (beginOffset + count < stringLength && isURLSlash(string[beginOffset + count])) - ++count; - return count; - } - -private: - // URLParser cannot be constructed. - URLParser(); - - // Returns true if the given character is a valid digit to use in a port. - static inline bool isPortDigit(CharacterType ch) - { - return ch >= '0' && ch <= '9'; - } - - // Returns the offset of the next authority terminator in the input starting - // from startOffset. If no terminator is found, the return value will be equal - // to specLength. - static int nextAuthorityTerminator(const CharacterType* spec, int startOffset, int specLength) - { - for (int i = startOffset; i < specLength; i++) { - if (isPossibleAuthorityTerminator(spec[i])) - return i; - } - return specLength; // Not found. - } - - static void parseUserInfo(const CharacterType* spec, const URLComponent& user, URLComponent& username, URLComponent& password) - { - // Find the first colon in the user section, which separates the - // username and password. - int colonOffset = 0; - while (colonOffset < user.length() && spec[user.begin() + colonOffset] != ':') - ++colonOffset; - - if (colonOffset < user.length()) { - // Found separator: <username>:<password> - username = URLComponent(user.begin(), colonOffset); - password = URLComponent::fromRange(user.begin() + colonOffset + 1, user.begin() + user.length()); - } else { - // No separator, treat everything as the username - username = user; - password = URLComponent(); - } - } - - static void parseServerInfo(const CharacterType* spec, const URLComponent& serverInfo, URLComponent& host, URLComponent& port) - { - if (!serverInfo.length()) { - // No server info, host name is empty. - host.reset(); - port.reset(); - return; - } - - // If the host starts with a left-bracket, assume the entire host is an - // IPv6 literal. Otherwise, assume none of the host is an IPv6 literal. - // This assumption will be overridden if we find a right-bracket. - // - // Our IPv6 address canonicalization code requires both brackets to - // exist, but the ability to locate an incomplete address can still be - // useful. - int ipv6Terminator = spec[serverInfo.begin()] == '[' ? serverInfo.end() : -1; - int colon = -1; - - // Find the last right-bracket, and the last colon. - for (int i = serverInfo.begin(); i < serverInfo.end(); i++) { - switch (spec[i]) { - case ']': - ipv6Terminator = i; - break; - case ':': - colon = i; - break; - default: - break; - } - } - - if (colon > ipv6Terminator) { - // Found a port number: <hostname>:<port> - host = URLComponent::fromRange(serverInfo.begin(), colon); - if (!host.length()) - host.reset(); - port = URLComponent::fromRange(colon + 1, serverInfo.end()); - } else { - // No port: <hostname> - host = serverInfo; - port.reset(); - } - } -}; - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLParser_h diff --git a/Source/JavaScriptCore/wtf/url/src/URLQueryCanonicalizer.h b/Source/JavaScriptCore/wtf/url/src/URLQueryCanonicalizer.h deleted file mode 100644 index 467c497fd..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLQueryCanonicalizer.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 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: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -#ifndef URLQueryCanonicalizer_h -#define URLQueryCanonicalizer_h - -#if USE(WTFURL) - -#include "RawURLBuffer.h" -#include "URLBuffer.h" -#include "URLCharacterTypes.h" -#include "URLComponent.h" -#include "URLEscape.h" - -namespace WTF { - -template<typename InChar, typename OutChar, void convertCharset(const InChar*, int length, URLBuffer<char>&)> -class URLQueryCanonicalizer { -public: - static void canonicalize(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer, URLComponent& resultQuery) - { - if (query.length() < 0) { - resultQuery = URLComponent(); - return; - } - - buffer->append('?'); - resultQuery.setBegin(buffer->length()); - convertToQueryEncoding(spec, query, buffer); - resultQuery.setLength(buffer->length() - resultQuery.begin()); - } - -private: - static bool isAllASCII(const InChar* spec, const URLComponent& query) - { - int end = query.end(); - for (int i = query.begin(); i < end; ++i) { - if (static_cast<unsigned>(spec[i]) >= 0x80) - return false; - } - return true; - } - -#ifndef NDEBUG - static bool isRaw8Bit(const InChar* source, int length) - { - for (int i = source; i < length; ++i) { - if (source[i] & 0xFF != source[i]) - return false; - } - return true; - } -#endif - - static void appendRaw8BitQueryString(const InChar* source, int length, URLBuffer<OutChar>* buffer) - { - ASSERT(isRaw8Bit(source, length)); - for (int i = 0; i < length; ++i) { - if (!URLCharacterTypes::isQueryChar(source[i])) - appendURLEscapedCharacter(static_cast<unsigned char>(source[i]), buffer); - else - buffer->append(static_cast<char>(source[i])); - } - } - - static void convertToQueryEncoding(const InChar* spec, const URLComponent& query, URLBuffer<OutChar>& buffer) - { - if (isAllASCII(spec, query)) { - appendRaw8BitQueryString(&spec[query.begin()], query.length(), buffer); - return; - } - - RawURLBuffer<char, 1024> convertedQuery; - convertCharset(spec, query, convertedQuery); - appendRaw8BitQueryString(convertedQuery.data(), convertedQuery.length(), buffer); - } -}; - -} - -#endif // USE(WTFURL) - -#endif diff --git a/Source/JavaScriptCore/wtf/url/src/URLSegments.cpp b/Source/JavaScriptCore/wtf/url/src/URLSegments.cpp deleted file mode 100644 index 182b0d45b..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLSegments.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* Based on nsURLParsers.cc from Mozilla - * ------------------------------------- - * Copyright (C) 1998 Netscape Communications Corporation. - * - * Other contributors: - * Darin Fisher (original author) - * - * 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.1 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 - * - * Alternatively, the contents of this file may be used under the terms - * of either the Mozilla Public License Version 1.1, found at - * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public - * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html - * (the "GPL"), in which case the provisions of the MPL or the GPL are - * applicable instead of those above. If you wish to allow use of your - * version of this file only under the terms of one of those two - * licenses (the MPL or the GPL) and not to allow others to use your - * version of this file under the LGPL, indicate your decision by - * deletingthe provisions above and replace them with the notice and - * other provisions required by the MPL or the GPL, as the case may be. - * If you do not delete the provisions above, a recipient may use your - * version of this file under any of the LGPL, the MPL or the GPL. - */ - -#include "config.h" -#include "URLSegments.h" - -#if USE(WTFURL) - -namespace WTF { - -int URLSegments::length() const -{ - if (fragment.isValid()) - return fragment.end(); - return charactersBefore(Fragment, false); -} - -int URLSegments::charactersBefore(ComponentType type, bool includeDelimiter) const -{ - if (type == Scheme) - return scheme.begin(); - - int current = 0; - if (scheme.isValid()) - current = scheme.end() + 1; // Advance over the ':' at the end of the scheme. - - if (username.isValid()) { - if (type <= Username) - return username.begin(); - current = username.end() + 1; // Advance over the '@' or ':' at the end. - } - - if (password.isValid()) { - if (type <= Password) - return password.begin(); - current = password.end() + 1; // Advance over the '@' at the end. - } - - if (host.isValid()) { - if (type <= Host) - return host.begin(); - current = host.end(); - } - - if (port.isValid()) { - if (type < Port || (type == Port && includeDelimiter)) - return port.begin() - 1; // Back over delimiter. - if (type == Port) - return port.begin(); // Don't want delimiter counted. - current = port.end(); - } - - if (path.isValid()) { - if (type <= Path) - return path.begin(); - current = path.end(); - } - - if (query.isValid()) { - if (type < Query || (type == Query && includeDelimiter)) - return query.begin() - 1; // Back over delimiter. - if (type == Query) - return query.begin(); // Don't want delimiter counted. - current = query.end(); - } - - if (fragment.isValid()) { - if (type == Fragment && !includeDelimiter) - return fragment.begin(); // Back over delimiter. - - // When there is a fragment and we get here, the component we wanted was before - // this and not found, so we always know the beginning of the fragment is right. - return fragment.begin() - 1; // Don't want delimiter counted. - } - - return current; -} - -} // namespace WTF - -#endif // USE(WTFURL) diff --git a/Source/JavaScriptCore/wtf/url/src/URLSegments.h b/Source/JavaScriptCore/wtf/url/src/URLSegments.h deleted file mode 100644 index 64d0619b8..000000000 --- a/Source/JavaScriptCore/wtf/url/src/URLSegments.h +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2007, Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -#ifndef URLSegments_h -#define URLSegments_h - -#include "URLComponent.h" - -#if USE(WTFURL) - -namespace WTF { - -// A structure that holds the identified parts of an input URL. This structure -// does NOT store the URL itself. The caller will have to store the URL text -// and its corresponding Parsed structure separately. -class URLSegments { -public: - // Identifies different components. - enum ComponentType { - Scheme, - Username, - Password, - Host, - Port, - Path, - Query, - Fragment, - }; - - URLSegments() { } - - // Returns the length of the URL (the end of the last component). - // - // Note that for some invalid, non-canonical URLs, this may not be the length - // of the string. For example "http://": the parsed structure will only - // contain an entry for the four-character scheme, and it doesn't know about - // the "://". For all other last-components, it will return the real length. - int length() const; - - // Returns the number of characters before the given component if it exists, - // or where the component would be if it did exist. This will return the - // string length if the component would be appended to the end. - // - // Note that this can get a little funny for the port, query, and fragment - // components which have a delimiter that is not counted as part of the - // component. The |includeDelimiter| flag controls if you want this counted - // as part of the component or not when the component exists. - // - // This example shows the difference between the two flags for two of these - // delimited components that is present (the port and query) and one that - // isn't (the reference). The components that this flag affects are marked - // with a *. - // 0 1 2 - // 012345678901234567890 - // Example input: http://foo:80/?query - // include_delim=true, ...=false ("<-" indicates different) - // Scheme: 0 0 - // Username: 5 5 - // Password: 5 5 - // Host: 7 7 - // *Port: 10 11 <- - // Path: 13 13 - // *Query: 14 15 <- - // *Fragment: 20 20 - // - int charactersBefore(ComponentType, bool includeDelimiter) const; - - // Each component excludes the related delimiters and has a length of -1 - // if that component is absent but 0 if the component exists but is empty. - URLComponent scheme; - URLComponent username; - URLComponent password; - URLComponent host; - URLComponent port; - URLComponent path; - URLComponent query; - URLComponent fragment; -}; - -} // namespace WTF - -#endif // USE(WTFURL) - -#endif // URLSegments_h diff --git a/Source/JavaScriptCore/wtf/win/MainThreadWin.cpp b/Source/JavaScriptCore/wtf/win/MainThreadWin.cpp deleted file mode 100644 index ee3a27377..000000000 --- a/Source/JavaScriptCore/wtf/win/MainThreadWin.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2009 Torch Mobile 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. - */ - -#include "config.h" -#include "MainThread.h" - -#include "Assertions.h" -#include "Threading.h" -#if !OS(WINCE) -#include <windows.h> -#endif - -namespace WTF { - -static HWND threadingWindowHandle; -static UINT threadingFiredMessage; -const LPCWSTR kThreadingWindowClassName = L"ThreadingWindowClass"; - -LRESULT CALLBACK ThreadingWindowWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - if (message == threadingFiredMessage) - dispatchFunctionsFromMainThread(); - else - return DefWindowProc(hWnd, message, wParam, lParam); - return 0; -} - -void initializeMainThreadPlatform() -{ - if (threadingWindowHandle) - return; - - HWND hWndParent = 0; -#if OS(WINCE) - WNDCLASS wcex; - memset(&wcex, 0, sizeof(WNDCLASS)); -#else - WNDCLASSEX wcex; - memset(&wcex, 0, sizeof(WNDCLASSEX)); - wcex.cbSize = sizeof(WNDCLASSEX); -#endif - wcex.lpfnWndProc = ThreadingWindowWndProc; - wcex.lpszClassName = kThreadingWindowClassName; -#if OS(WINCE) - RegisterClass(&wcex); -#else - RegisterClassEx(&wcex); - hWndParent = HWND_MESSAGE; -#endif - - threadingWindowHandle = CreateWindow(kThreadingWindowClassName, 0, 0, - CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hWndParent, 0, 0, 0); - threadingFiredMessage = RegisterWindowMessage(L"com.apple.WebKit.MainThreadFired"); - - initializeCurrentThreadInternal("Main Thread"); -} - -void scheduleDispatchFunctionsOnMainThread() -{ - ASSERT(threadingWindowHandle); - PostMessage(threadingWindowHandle, threadingFiredMessage, 0, 0); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/win/OwnPtrWin.cpp b/Source/JavaScriptCore/wtf/win/OwnPtrWin.cpp deleted file mode 100644 index 67a32ff77..000000000 --- a/Source/JavaScriptCore/wtf/win/OwnPtrWin.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007 Apple Inc. All rights reserved. - * Copyright (C) 2008, 2009 Torch Mobile, 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. - * - * 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 "OwnPtr.h" - -#include <windows.h> - -namespace WTF { - -void deleteOwnedPtr(HBITMAP ptr) -{ - if (ptr) - DeleteObject(ptr); -} - -void deleteOwnedPtr(HBRUSH ptr) -{ - if (ptr) - DeleteObject(ptr); -} - -void deleteOwnedPtr(HDC ptr) -{ - if (ptr) - DeleteDC(ptr); -} - -void deleteOwnedPtr(HFONT ptr) -{ - if (ptr) - DeleteObject(ptr); -} - -void deleteOwnedPtr(HPALETTE ptr) -{ - if (ptr) - DeleteObject(ptr); -} - -void deleteOwnedPtr(HPEN ptr) -{ - if (ptr) - DeleteObject(ptr); -} - -void deleteOwnedPtr(HRGN ptr) -{ - if (ptr) - DeleteObject(ptr); -} - -} diff --git a/Source/JavaScriptCore/wtf/wince/FastMallocWinCE.h b/Source/JavaScriptCore/wtf/wince/FastMallocWinCE.h deleted file mode 100644 index 3601249cf..000000000 --- a/Source/JavaScriptCore/wtf/wince/FastMallocWinCE.h +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. - * Copyright (C) 2007-2009 Torch Mobile, Inc. All rights reserved - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public License - * along with this library; see the file COPYING.LIB. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#ifndef WTF_FastMallocWinCE_h -#define WTF_FastMallocWinCE_h - -#include <new.h> - -#ifdef __cplusplus -#include <new> -#include <wtf/wince/MemoryManager.h> -extern "C" { -#endif - -void* fastMalloc(size_t n); -void* fastCalloc(size_t n_elements, size_t element_size); -void fastFree(void* p); -void* fastRealloc(void* p, size_t n); -void* fastZeroedMalloc(size_t n); -// These functions return 0 if an allocation fails. -void* tryFastMalloc(size_t n); -void* tryFastZeroedMalloc(size_t n); -void* tryFastCalloc(size_t n_elements, size_t element_size); -void* tryFastRealloc(void* p, size_t n); -char* fastStrDup(const char*); - -#ifndef NDEBUG -void fastMallocForbid(); -void fastMallocAllow(); -#endif - -#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC - -#define malloc(n) fastMalloc(n) -#define calloc(n_elements, element_size) fastCalloc(n_elements, element_size) -#define realloc(p, n) fastRealloc(p, n) -#define free(p) fastFree(p) -#define strdup(p) fastStrDup(p) - -#else - -#define strdup(p) _strdup(p) - -#endif - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus -#if !defined(USE_SYSTEM_MALLOC) || !USE_SYSTEM_MALLOC -static inline void* __cdecl operator new(size_t s) { return fastMalloc(s); } -static inline void __cdecl operator delete(void* p) { fastFree(p); } -static inline void* __cdecl operator new[](size_t s) { return fastMalloc(s); } -static inline void __cdecl operator delete[](void* p) { fastFree(p); } -static inline void* operator new(size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); } -static inline void operator delete(void* p, const std::nothrow_t&) throw() { fastFree(p); } -static inline void* operator new[](size_t s, const std::nothrow_t&) throw() { return fastMalloc(s); } -static inline void operator delete[](void* p, const std::nothrow_t&) throw() { fastFree(p); } -#endif - -namespace WTF { - // This defines a type which holds an unsigned integer and is the same - // size as the minimally aligned memory allocation. - typedef unsigned long long AllocAlignmentInteger; - - namespace Internal { - enum AllocType { // Start with an unusual number instead of zero, because zero is common. - AllocTypeMalloc = 0x375d6750, // Encompasses fastMalloc, fastZeroedMalloc, fastCalloc, fastRealloc. - AllocTypeClassNew, // Encompasses class operator new from FastAllocBase. - AllocTypeClassNewArray, // Encompasses class operator new[] from FastAllocBase. - AllocTypeFastNew, // Encompasses fastNew. - AllocTypeFastNewArray, // Encompasses fastNewArray. - AllocTypeNew, // Encompasses global operator new. - AllocTypeNewArray // Encompasses global operator new[]. - }; - } - - -#if ENABLE(FAST_MALLOC_MATCH_VALIDATION) - - // Malloc validation is a scheme whereby a tag is attached to an - // allocation which identifies how it was originally allocated. - // This allows us to verify that the freeing operation matches the - // allocation operation. If memory is allocated with operator new[] - // but freed with free or delete, this system would detect that. - // In the implementation here, the tag is an integer prepended to - // the allocation memory which is assigned one of the AllocType - // enumeration values. An alternative implementation of this - // scheme could store the tag somewhere else or ignore it. - // Users of FastMalloc don't need to know or care how this tagging - // is implemented. - - namespace Internal { - - // Return the AllocType tag associated with the allocated block p. - inline AllocType fastMallocMatchValidationType(const void* p) - { - const AllocAlignmentInteger* type = static_cast<const AllocAlignmentInteger*>(p) - 1; - return static_cast<AllocType>(*type); - } - - // Return the address of the AllocType tag associated with the allocated block p. - inline AllocAlignmentInteger* fastMallocMatchValidationValue(void* p) - { - return reinterpret_cast<AllocAlignmentInteger*>(static_cast<char*>(p) - sizeof(AllocAlignmentInteger)); - } - - // Set the AllocType tag to be associaged with the allocated block p. - inline void setFastMallocMatchValidationType(void* p, AllocType allocType) - { - AllocAlignmentInteger* type = static_cast<AllocAlignmentInteger*>(p) - 1; - *type = static_cast<AllocAlignmentInteger>(allocType); - } - - // Handle a detected alloc/free mismatch. By default this calls CRASH(). - void fastMallocMatchFailed(void* p); - - } // namespace Internal - - // This is a higher level function which is used by FastMalloc-using code. - inline void fastMallocMatchValidateMalloc(void* p, Internal::AllocType allocType) - { - if (!p) - return; - - Internal::setFastMallocMatchValidationType(p, allocType); - } - - // This is a higher level function which is used by FastMalloc-using code. - inline void fastMallocMatchValidateFree(void* p, Internal::AllocType allocType) - { - if (!p) - return; - - if (Internal::fastMallocMatchValidationType(p) != allocType) - Internal::fastMallocMatchFailed(p); - Internal::setFastMallocMatchValidationType(p, Internal::AllocTypeMalloc); // Set it to this so that fastFree thinks it's OK. - } - -#else - - inline void fastMallocMatchValidateMalloc(void*, Internal::AllocType) - { - } - - inline void fastMallocMatchValidateFree(void*, Internal::AllocType) - { - } - -#endif - -} // namespace WTF - -#endif - -#endif // WTF_FastMallocWinCE_h diff --git a/Source/JavaScriptCore/wtf/wince/MemoryManager.cpp b/Source/JavaScriptCore/wtf/wince/MemoryManager.cpp deleted file mode 100644 index 81d4f805b..000000000 --- a/Source/JavaScriptCore/wtf/wince/MemoryManager.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2008-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 "MemoryManager.h" - -#undef malloc -#undef calloc -#undef realloc -#undef free -#undef strdup -#undef _strdup -#undef VirtualAlloc -#undef VirtualFree - -#include <malloc.h> -#include <windows.h> - -namespace WTF { - -MemoryManager* memoryManager() -{ - static MemoryManager mm; - return &mm; -} - -MemoryManager::MemoryManager() -: m_allocationCanFail(false) -{ -} - -MemoryManager::~MemoryManager() -{ -} - -HBITMAP MemoryManager::createCompatibleBitmap(HDC hdc, int width, int height) -{ - return ::CreateCompatibleBitmap(hdc, width, height); -} - -HBITMAP MemoryManager::createDIBSection(const BITMAPINFO* pbmi, void** ppvBits) -{ - return ::CreateDIBSection(0, pbmi, DIB_RGB_COLORS, ppvBits, 0, 0); -} - -void* MemoryManager::m_malloc(size_t size) -{ - return malloc(size); -} - -void* MemoryManager::m_calloc(size_t num, size_t size) -{ - return calloc(num, size); -} - -void* MemoryManager::m_realloc(void* p, size_t size) -{ - return realloc(p, size); -} - -void MemoryManager::m_free(void* p) -{ - return free(p); -} - -bool MemoryManager::resizeMemory(void*, size_t) -{ - return false; -} - -void* MemoryManager::allocate64kBlock() -{ - return VirtualAlloc(0, 65536, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); -} - -void MemoryManager::free64kBlock(void* p) -{ - VirtualFree(p, 65536, MEM_RELEASE); -} - -bool MemoryManager::onIdle(DWORD& timeLimitMs) -{ - return false; -} - -LPVOID MemoryManager::virtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect) -{ - return ::VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect); -} - -BOOL MemoryManager::virtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType) -{ - return ::VirtualFree(lpAddress, dwSize, dwFreeType); -} - - -#if defined(USE_SYSTEM_MALLOC) && USE_SYSTEM_MALLOC - -void *fastMalloc(size_t n) { return malloc(n); } -void *fastCalloc(size_t n_elements, size_t element_size) { return calloc(n_elements, element_size); } -void fastFree(void* p) { return free(p); } -void *fastRealloc(void* p, size_t n) { return realloc(p, n); } - -#else - -void *fastMalloc(size_t n) { return MemoryManager::m_malloc(n); } -void *fastCalloc(size_t n_elements, size_t element_size) { return MemoryManager::m_calloc(n_elements, element_size); } -void fastFree(void* p) { return MemoryManager::m_free(p); } -void *fastRealloc(void* p, size_t n) { return MemoryManager::m_realloc(p, n); } - -#endif - -#ifndef NDEBUG -void fastMallocForbid() {} -void fastMallocAllow() {} -#endif - -void* fastZeroedMalloc(size_t n) -{ - void* p = fastMalloc(n); - if (p) - memset(p, 0, n); - return p; -} - -TryMallocReturnValue tryFastMalloc(size_t n) -{ - MemoryAllocationCanFail canFail; - return fastMalloc(n); -} - -TryMallocReturnValue tryFastZeroedMalloc(size_t n) -{ - MemoryAllocationCanFail canFail; - return fastZeroedMalloc(n); -} - -TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size) -{ - MemoryAllocationCanFail canFail; - return fastCalloc(n_elements, element_size); -} - -TryMallocReturnValue tryFastRealloc(void* p, size_t n) -{ - MemoryAllocationCanFail canFail; - return fastRealloc(p, n); -} - -char* fastStrDup(const char* str) -{ - return _strdup(str); -} - -}
\ No newline at end of file diff --git a/Source/JavaScriptCore/wtf/wince/MemoryManager.h b/Source/JavaScriptCore/wtf/wince/MemoryManager.h deleted file mode 100644 index f405612df..000000000 --- a/Source/JavaScriptCore/wtf/wince/MemoryManager.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2008-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. - */ - -#pragma once - -#include <winbase.h> - -typedef struct HBITMAP__* HBITMAP; -typedef struct HDC__* HDC; -typedef void *HANDLE; -typedef struct tagBITMAPINFO BITMAPINFO; - -namespace WTF { - - class MemoryManager { - public: - MemoryManager(); - ~MemoryManager(); - - bool allocationCanFail() const { return m_allocationCanFail; } - void setAllocationCanFail(bool c) { m_allocationCanFail = c; } - - static HBITMAP createCompatibleBitmap(HDC hdc, int width, int height); - static HBITMAP createDIBSection(const BITMAPINFO* pbmi, void** ppvBits); - static void* m_malloc(size_t size); - static void* m_calloc(size_t num, size_t size); - static void* m_realloc(void* p, size_t size); - static void m_free(void*); - static bool resizeMemory(void* p, size_t newSize); - static void* allocate64kBlock(); - static void free64kBlock(void*); - static bool onIdle(DWORD& timeLimitMs); - static LPVOID virtualAlloc(LPVOID lpAddress, DWORD dwSize, DWORD flAllocationType, DWORD flProtect); - static BOOL virtualFree(LPVOID lpAddress, DWORD dwSize, DWORD dwFreeType); - - private: - friend MemoryManager* memoryManager(); - - bool m_allocationCanFail; - }; - - MemoryManager* memoryManager(); - - class MemoryAllocationCanFail { - public: - MemoryAllocationCanFail() : m_old(memoryManager()->allocationCanFail()) { memoryManager()->setAllocationCanFail(true); } - ~MemoryAllocationCanFail() { memoryManager()->setAllocationCanFail(m_old); } - private: - bool m_old; - }; - - class MemoryAllocationCannotFail { - public: - MemoryAllocationCannotFail() : m_old(memoryManager()->allocationCanFail()) { memoryManager()->setAllocationCanFail(false); } - ~MemoryAllocationCannotFail() { memoryManager()->setAllocationCanFail(m_old); } - private: - bool m_old; - }; -} - -using WTF::MemoryManager; -using WTF::memoryManager; -using WTF::MemoryAllocationCanFail; -using WTF::MemoryAllocationCannotFail; diff --git a/Source/JavaScriptCore/wtf/wx/MainThreadWx.cpp b/Source/JavaScriptCore/wtf/wx/MainThreadWx.cpp deleted file mode 100644 index e1d15c96f..000000000 --- a/Source/JavaScriptCore/wtf/wx/MainThreadWx.cpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2007 Kevin Ollivier - * - * 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" -#include "MainThread.h" - -#include <wx/defs.h> -#include <wx/app.h> -#include <wx/event.h> - -const wxEventType wxEVT_CALL_AFTER = wxNewEventType(); - -class wxCallAfter : public wxEvtHandler -{ -public: - wxCallAfter() - : wxEvtHandler() - { - wxTheApp->Connect(-1, -1, wxEVT_CALL_AFTER, wxCommandEventHandler(wxCallAfter::OnCallback)); - wxCommandEvent event(wxEVT_CALL_AFTER); - wxPostEvent(wxTheApp, event); - } - - void OnCallback(wxCommandEvent& event) - { - WTF::dispatchFunctionsFromMainThread(); - } -}; - -namespace WTF { - -void initializeMainThreadPlatform() -{ -} - -void scheduleDispatchFunctionsOnMainThread() -{ - wxCallAfter(); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/wtf/wx/StringWx.cpp b/Source/JavaScriptCore/wtf/wx/StringWx.cpp deleted file mode 100644 index d5f6c578a..000000000 --- a/Source/JavaScriptCore/wtf/wx/StringWx.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2007 Vaclav Slavik, Kevin Ollivier <kevino@theolliviers.com> - * - * 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" - -// The wx headers must come first in this case, because the wtf/text headers -// import windows.h, and we need to allow the wx headers to set its configuration -// first. -#include <wx/defs.h> -#include <wx/string.h> - -#include <wtf/text/CString.h> -#include <wtf/text/WTFString.h> - -namespace WTF { - -String::String(const wxString& wxstr) -{ -#if !wxUSE_UNICODE - #error "This code only works in Unicode build of wxWidgets" -#endif - -#if SIZEOF_WCHAR_T == 2 - - const UChar* str = wxstr.wc_str(); - const size_t len = wxstr.length(); - -#else // SIZEOF_WCHAR_T == 4 - - // NB: we can't simply use wxstr.mb_str(wxMBConvUTF16()) here because - // the number of characters in UTF-16 encoding of the string may differ - // from the number of UTF-32 values and we can't get the length from - // returned buffer: - -#if defined(wxUSE_UNICODE_UTF8) && wxUSE_UNICODE_UTF8 - // in wx3's UTF8 mode, wc_str() returns a buffer, not raw pointer - wxWCharBuffer wideString(wxstr.wc_str()); -#else - const wxChar *wideString = wxstr.wc_str(); -#endif - size_t wideLength = wxstr.length(); - - wxMBConvUTF16 conv; - - const size_t utf16bufLen = conv.FromWChar(0, 0, wideString, wideLength); - wxCharBuffer utf16buf(utf16bufLen); - - const UChar* str = (const UChar*)utf16buf.data(); - size_t len = conv.FromWChar(utf16buf.data(), utf16bufLen, wideString, wideLength) / 2; - -#endif // SIZEOF_WCHAR_T == 2 - - m_impl = StringImpl::create(str, len); - -} - -String::operator wxString() const -{ - return wxString(utf8().data(), wxConvUTF8); -} - -} // namespace WTF diff --git a/Source/JavaScriptCore/yarr/Yarr.h b/Source/JavaScriptCore/yarr/Yarr.h index 57a3846c0..d393e9fa9 100644 --- a/Source/JavaScriptCore/yarr/Yarr.h +++ b/Source/JavaScriptCore/yarr/Yarr.h @@ -63,9 +63,6 @@ enum YarrCharSize { Char16 }; -JS_EXPORT_PRIVATE PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*); -JS_EXPORT_PRIVATE unsigned interpret(BytecodePattern*, const UString& input, unsigned start, unsigned length, unsigned* output); - } } // namespace JSC::Yarr #endif // Yarr_h diff --git a/Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.cpp b/Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.cpp new file mode 100644 index 000000000..7bb3d08eb --- /dev/null +++ b/Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.cpp @@ -0,0 +1,463 @@ +/* + * Copyright (C) 2012 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. + */ + +// DO NOT EDIT! - this file autogenerated by YarrCanonicalizeUCS2.js + +#include "config.h" +#include "YarrCanonicalizeUCS2.h" + +namespace JSC { namespace Yarr { + +#include <stdint.h> + +uint16_t ucs2CharacterSet0[] = { 0x01c4u, 0x01c5u, 0x01c6u, 0 }; +uint16_t ucs2CharacterSet1[] = { 0x01c7u, 0x01c8u, 0x01c9u, 0 }; +uint16_t ucs2CharacterSet2[] = { 0x01cau, 0x01cbu, 0x01ccu, 0 }; +uint16_t ucs2CharacterSet3[] = { 0x01f1u, 0x01f2u, 0x01f3u, 0 }; +uint16_t ucs2CharacterSet4[] = { 0x0392u, 0x03b2u, 0x03d0u, 0 }; +uint16_t ucs2CharacterSet5[] = { 0x0395u, 0x03b5u, 0x03f5u, 0 }; +uint16_t ucs2CharacterSet6[] = { 0x0398u, 0x03b8u, 0x03d1u, 0 }; +uint16_t ucs2CharacterSet7[] = { 0x0345u, 0x0399u, 0x03b9u, 0x1fbeu, 0 }; +uint16_t ucs2CharacterSet8[] = { 0x039au, 0x03bau, 0x03f0u, 0 }; +uint16_t ucs2CharacterSet9[] = { 0x00b5u, 0x039cu, 0x03bcu, 0 }; +uint16_t ucs2CharacterSet10[] = { 0x03a0u, 0x03c0u, 0x03d6u, 0 }; +uint16_t ucs2CharacterSet11[] = { 0x03a1u, 0x03c1u, 0x03f1u, 0 }; +uint16_t ucs2CharacterSet12[] = { 0x03a3u, 0x03c2u, 0x03c3u, 0 }; +uint16_t ucs2CharacterSet13[] = { 0x03a6u, 0x03c6u, 0x03d5u, 0 }; +uint16_t ucs2CharacterSet14[] = { 0x1e60u, 0x1e61u, 0x1e9bu, 0 }; + +static const size_t UCS2_CANONICALIZATION_SETS = 15; +uint16_t* characterSetInfo[UCS2_CANONICALIZATION_SETS] = { + ucs2CharacterSet0, + ucs2CharacterSet1, + ucs2CharacterSet2, + ucs2CharacterSet3, + ucs2CharacterSet4, + ucs2CharacterSet5, + ucs2CharacterSet6, + ucs2CharacterSet7, + ucs2CharacterSet8, + ucs2CharacterSet9, + ucs2CharacterSet10, + ucs2CharacterSet11, + ucs2CharacterSet12, + ucs2CharacterSet13, + ucs2CharacterSet14, +}; + +const size_t UCS2_CANONICALIZATION_RANGES = 364; +UCS2CanonicalizationRange rangeInfo[UCS2_CANONICALIZATION_RANGES] = { + { 0x0000u, 0x0040u, 0x0000u, CanonicalizeUnique }, + { 0x0041u, 0x005au, 0x0020u, CanonicalizeRangeLo }, + { 0x005bu, 0x0060u, 0x0000u, CanonicalizeUnique }, + { 0x0061u, 0x007au, 0x0020u, CanonicalizeRangeHi }, + { 0x007bu, 0x00b4u, 0x0000u, CanonicalizeUnique }, + { 0x00b5u, 0x00b5u, 0x0009u, CanonicalizeSet }, + { 0x00b6u, 0x00bfu, 0x0000u, CanonicalizeUnique }, + { 0x00c0u, 0x00d6u, 0x0020u, CanonicalizeRangeLo }, + { 0x00d7u, 0x00d7u, 0x0000u, CanonicalizeUnique }, + { 0x00d8u, 0x00deu, 0x0020u, CanonicalizeRangeLo }, + { 0x00dfu, 0x00dfu, 0x0000u, CanonicalizeUnique }, + { 0x00e0u, 0x00f6u, 0x0020u, CanonicalizeRangeHi }, + { 0x00f7u, 0x00f7u, 0x0000u, CanonicalizeUnique }, + { 0x00f8u, 0x00feu, 0x0020u, CanonicalizeRangeHi }, + { 0x00ffu, 0x00ffu, 0x0079u, CanonicalizeRangeLo }, + { 0x0100u, 0x012fu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0130u, 0x0131u, 0x0000u, CanonicalizeUnique }, + { 0x0132u, 0x0137u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0138u, 0x0138u, 0x0000u, CanonicalizeUnique }, + { 0x0139u, 0x0148u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x0149u, 0x0149u, 0x0000u, CanonicalizeUnique }, + { 0x014au, 0x0177u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0178u, 0x0178u, 0x0079u, CanonicalizeRangeHi }, + { 0x0179u, 0x017eu, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x017fu, 0x017fu, 0x0000u, CanonicalizeUnique }, + { 0x0180u, 0x0180u, 0x00c3u, CanonicalizeRangeLo }, + { 0x0181u, 0x0181u, 0x00d2u, CanonicalizeRangeLo }, + { 0x0182u, 0x0185u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0186u, 0x0186u, 0x00ceu, CanonicalizeRangeLo }, + { 0x0187u, 0x0188u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x0189u, 0x018au, 0x00cdu, CanonicalizeRangeLo }, + { 0x018bu, 0x018cu, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x018du, 0x018du, 0x0000u, CanonicalizeUnique }, + { 0x018eu, 0x018eu, 0x004fu, CanonicalizeRangeLo }, + { 0x018fu, 0x018fu, 0x00cau, CanonicalizeRangeLo }, + { 0x0190u, 0x0190u, 0x00cbu, CanonicalizeRangeLo }, + { 0x0191u, 0x0192u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x0193u, 0x0193u, 0x00cdu, CanonicalizeRangeLo }, + { 0x0194u, 0x0194u, 0x00cfu, CanonicalizeRangeLo }, + { 0x0195u, 0x0195u, 0x0061u, CanonicalizeRangeLo }, + { 0x0196u, 0x0196u, 0x00d3u, CanonicalizeRangeLo }, + { 0x0197u, 0x0197u, 0x00d1u, CanonicalizeRangeLo }, + { 0x0198u, 0x0199u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x019au, 0x019au, 0x00a3u, CanonicalizeRangeLo }, + { 0x019bu, 0x019bu, 0x0000u, CanonicalizeUnique }, + { 0x019cu, 0x019cu, 0x00d3u, CanonicalizeRangeLo }, + { 0x019du, 0x019du, 0x00d5u, CanonicalizeRangeLo }, + { 0x019eu, 0x019eu, 0x0082u, CanonicalizeRangeLo }, + { 0x019fu, 0x019fu, 0x00d6u, CanonicalizeRangeLo }, + { 0x01a0u, 0x01a5u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x01a6u, 0x01a6u, 0x00dau, CanonicalizeRangeLo }, + { 0x01a7u, 0x01a8u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x01a9u, 0x01a9u, 0x00dau, CanonicalizeRangeLo }, + { 0x01aau, 0x01abu, 0x0000u, CanonicalizeUnique }, + { 0x01acu, 0x01adu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x01aeu, 0x01aeu, 0x00dau, CanonicalizeRangeLo }, + { 0x01afu, 0x01b0u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x01b1u, 0x01b2u, 0x00d9u, CanonicalizeRangeLo }, + { 0x01b3u, 0x01b6u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x01b7u, 0x01b7u, 0x00dbu, CanonicalizeRangeLo }, + { 0x01b8u, 0x01b9u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x01bau, 0x01bbu, 0x0000u, CanonicalizeUnique }, + { 0x01bcu, 0x01bdu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x01beu, 0x01beu, 0x0000u, CanonicalizeUnique }, + { 0x01bfu, 0x01bfu, 0x0038u, CanonicalizeRangeLo }, + { 0x01c0u, 0x01c3u, 0x0000u, CanonicalizeUnique }, + { 0x01c4u, 0x01c6u, 0x0000u, CanonicalizeSet }, + { 0x01c7u, 0x01c9u, 0x0001u, CanonicalizeSet }, + { 0x01cau, 0x01ccu, 0x0002u, CanonicalizeSet }, + { 0x01cdu, 0x01dcu, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x01ddu, 0x01ddu, 0x004fu, CanonicalizeRangeHi }, + { 0x01deu, 0x01efu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x01f0u, 0x01f0u, 0x0000u, CanonicalizeUnique }, + { 0x01f1u, 0x01f3u, 0x0003u, CanonicalizeSet }, + { 0x01f4u, 0x01f5u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x01f6u, 0x01f6u, 0x0061u, CanonicalizeRangeHi }, + { 0x01f7u, 0x01f7u, 0x0038u, CanonicalizeRangeHi }, + { 0x01f8u, 0x021fu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0220u, 0x0220u, 0x0082u, CanonicalizeRangeHi }, + { 0x0221u, 0x0221u, 0x0000u, CanonicalizeUnique }, + { 0x0222u, 0x0233u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0234u, 0x0239u, 0x0000u, CanonicalizeUnique }, + { 0x023au, 0x023au, 0x2a2bu, CanonicalizeRangeLo }, + { 0x023bu, 0x023cu, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x023du, 0x023du, 0x00a3u, CanonicalizeRangeHi }, + { 0x023eu, 0x023eu, 0x2a28u, CanonicalizeRangeLo }, + { 0x023fu, 0x0240u, 0x2a3fu, CanonicalizeRangeLo }, + { 0x0241u, 0x0242u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x0243u, 0x0243u, 0x00c3u, CanonicalizeRangeHi }, + { 0x0244u, 0x0244u, 0x0045u, CanonicalizeRangeLo }, + { 0x0245u, 0x0245u, 0x0047u, CanonicalizeRangeLo }, + { 0x0246u, 0x024fu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0250u, 0x0250u, 0x2a1fu, CanonicalizeRangeLo }, + { 0x0251u, 0x0251u, 0x2a1cu, CanonicalizeRangeLo }, + { 0x0252u, 0x0252u, 0x2a1eu, CanonicalizeRangeLo }, + { 0x0253u, 0x0253u, 0x00d2u, CanonicalizeRangeHi }, + { 0x0254u, 0x0254u, 0x00ceu, CanonicalizeRangeHi }, + { 0x0255u, 0x0255u, 0x0000u, CanonicalizeUnique }, + { 0x0256u, 0x0257u, 0x00cdu, CanonicalizeRangeHi }, + { 0x0258u, 0x0258u, 0x0000u, CanonicalizeUnique }, + { 0x0259u, 0x0259u, 0x00cau, CanonicalizeRangeHi }, + { 0x025au, 0x025au, 0x0000u, CanonicalizeUnique }, + { 0x025bu, 0x025bu, 0x00cbu, CanonicalizeRangeHi }, + { 0x025cu, 0x025fu, 0x0000u, CanonicalizeUnique }, + { 0x0260u, 0x0260u, 0x00cdu, CanonicalizeRangeHi }, + { 0x0261u, 0x0262u, 0x0000u, CanonicalizeUnique }, + { 0x0263u, 0x0263u, 0x00cfu, CanonicalizeRangeHi }, + { 0x0264u, 0x0264u, 0x0000u, CanonicalizeUnique }, + { 0x0265u, 0x0265u, 0xa528u, CanonicalizeRangeLo }, + { 0x0266u, 0x0267u, 0x0000u, CanonicalizeUnique }, + { 0x0268u, 0x0268u, 0x00d1u, CanonicalizeRangeHi }, + { 0x0269u, 0x0269u, 0x00d3u, CanonicalizeRangeHi }, + { 0x026au, 0x026au, 0x0000u, CanonicalizeUnique }, + { 0x026bu, 0x026bu, 0x29f7u, CanonicalizeRangeLo }, + { 0x026cu, 0x026eu, 0x0000u, CanonicalizeUnique }, + { 0x026fu, 0x026fu, 0x00d3u, CanonicalizeRangeHi }, + { 0x0270u, 0x0270u, 0x0000u, CanonicalizeUnique }, + { 0x0271u, 0x0271u, 0x29fdu, CanonicalizeRangeLo }, + { 0x0272u, 0x0272u, 0x00d5u, CanonicalizeRangeHi }, + { 0x0273u, 0x0274u, 0x0000u, CanonicalizeUnique }, + { 0x0275u, 0x0275u, 0x00d6u, CanonicalizeRangeHi }, + { 0x0276u, 0x027cu, 0x0000u, CanonicalizeUnique }, + { 0x027du, 0x027du, 0x29e7u, CanonicalizeRangeLo }, + { 0x027eu, 0x027fu, 0x0000u, CanonicalizeUnique }, + { 0x0280u, 0x0280u, 0x00dau, CanonicalizeRangeHi }, + { 0x0281u, 0x0282u, 0x0000u, CanonicalizeUnique }, + { 0x0283u, 0x0283u, 0x00dau, CanonicalizeRangeHi }, + { 0x0284u, 0x0287u, 0x0000u, CanonicalizeUnique }, + { 0x0288u, 0x0288u, 0x00dau, CanonicalizeRangeHi }, + { 0x0289u, 0x0289u, 0x0045u, CanonicalizeRangeHi }, + { 0x028au, 0x028bu, 0x00d9u, CanonicalizeRangeHi }, + { 0x028cu, 0x028cu, 0x0047u, CanonicalizeRangeHi }, + { 0x028du, 0x0291u, 0x0000u, CanonicalizeUnique }, + { 0x0292u, 0x0292u, 0x00dbu, CanonicalizeRangeHi }, + { 0x0293u, 0x0344u, 0x0000u, CanonicalizeUnique }, + { 0x0345u, 0x0345u, 0x0007u, CanonicalizeSet }, + { 0x0346u, 0x036fu, 0x0000u, CanonicalizeUnique }, + { 0x0370u, 0x0373u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0374u, 0x0375u, 0x0000u, CanonicalizeUnique }, + { 0x0376u, 0x0377u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0378u, 0x037au, 0x0000u, CanonicalizeUnique }, + { 0x037bu, 0x037du, 0x0082u, CanonicalizeRangeLo }, + { 0x037eu, 0x0385u, 0x0000u, CanonicalizeUnique }, + { 0x0386u, 0x0386u, 0x0026u, CanonicalizeRangeLo }, + { 0x0387u, 0x0387u, 0x0000u, CanonicalizeUnique }, + { 0x0388u, 0x038au, 0x0025u, CanonicalizeRangeLo }, + { 0x038bu, 0x038bu, 0x0000u, CanonicalizeUnique }, + { 0x038cu, 0x038cu, 0x0040u, CanonicalizeRangeLo }, + { 0x038du, 0x038du, 0x0000u, CanonicalizeUnique }, + { 0x038eu, 0x038fu, 0x003fu, CanonicalizeRangeLo }, + { 0x0390u, 0x0390u, 0x0000u, CanonicalizeUnique }, + { 0x0391u, 0x0391u, 0x0020u, CanonicalizeRangeLo }, + { 0x0392u, 0x0392u, 0x0004u, CanonicalizeSet }, + { 0x0393u, 0x0394u, 0x0020u, CanonicalizeRangeLo }, + { 0x0395u, 0x0395u, 0x0005u, CanonicalizeSet }, + { 0x0396u, 0x0397u, 0x0020u, CanonicalizeRangeLo }, + { 0x0398u, 0x0398u, 0x0006u, CanonicalizeSet }, + { 0x0399u, 0x0399u, 0x0007u, CanonicalizeSet }, + { 0x039au, 0x039au, 0x0008u, CanonicalizeSet }, + { 0x039bu, 0x039bu, 0x0020u, CanonicalizeRangeLo }, + { 0x039cu, 0x039cu, 0x0009u, CanonicalizeSet }, + { 0x039du, 0x039fu, 0x0020u, CanonicalizeRangeLo }, + { 0x03a0u, 0x03a0u, 0x000au, CanonicalizeSet }, + { 0x03a1u, 0x03a1u, 0x000bu, CanonicalizeSet }, + { 0x03a2u, 0x03a2u, 0x0000u, CanonicalizeUnique }, + { 0x03a3u, 0x03a3u, 0x000cu, CanonicalizeSet }, + { 0x03a4u, 0x03a5u, 0x0020u, CanonicalizeRangeLo }, + { 0x03a6u, 0x03a6u, 0x000du, CanonicalizeSet }, + { 0x03a7u, 0x03abu, 0x0020u, CanonicalizeRangeLo }, + { 0x03acu, 0x03acu, 0x0026u, CanonicalizeRangeHi }, + { 0x03adu, 0x03afu, 0x0025u, CanonicalizeRangeHi }, + { 0x03b0u, 0x03b0u, 0x0000u, CanonicalizeUnique }, + { 0x03b1u, 0x03b1u, 0x0020u, CanonicalizeRangeHi }, + { 0x03b2u, 0x03b2u, 0x0004u, CanonicalizeSet }, + { 0x03b3u, 0x03b4u, 0x0020u, CanonicalizeRangeHi }, + { 0x03b5u, 0x03b5u, 0x0005u, CanonicalizeSet }, + { 0x03b6u, 0x03b7u, 0x0020u, CanonicalizeRangeHi }, + { 0x03b8u, 0x03b8u, 0x0006u, CanonicalizeSet }, + { 0x03b9u, 0x03b9u, 0x0007u, CanonicalizeSet }, + { 0x03bau, 0x03bau, 0x0008u, CanonicalizeSet }, + { 0x03bbu, 0x03bbu, 0x0020u, CanonicalizeRangeHi }, + { 0x03bcu, 0x03bcu, 0x0009u, CanonicalizeSet }, + { 0x03bdu, 0x03bfu, 0x0020u, CanonicalizeRangeHi }, + { 0x03c0u, 0x03c0u, 0x000au, CanonicalizeSet }, + { 0x03c1u, 0x03c1u, 0x000bu, CanonicalizeSet }, + { 0x03c2u, 0x03c3u, 0x000cu, CanonicalizeSet }, + { 0x03c4u, 0x03c5u, 0x0020u, CanonicalizeRangeHi }, + { 0x03c6u, 0x03c6u, 0x000du, CanonicalizeSet }, + { 0x03c7u, 0x03cbu, 0x0020u, CanonicalizeRangeHi }, + { 0x03ccu, 0x03ccu, 0x0040u, CanonicalizeRangeHi }, + { 0x03cdu, 0x03ceu, 0x003fu, CanonicalizeRangeHi }, + { 0x03cfu, 0x03cfu, 0x0008u, CanonicalizeRangeLo }, + { 0x03d0u, 0x03d0u, 0x0004u, CanonicalizeSet }, + { 0x03d1u, 0x03d1u, 0x0006u, CanonicalizeSet }, + { 0x03d2u, 0x03d4u, 0x0000u, CanonicalizeUnique }, + { 0x03d5u, 0x03d5u, 0x000du, CanonicalizeSet }, + { 0x03d6u, 0x03d6u, 0x000au, CanonicalizeSet }, + { 0x03d7u, 0x03d7u, 0x0008u, CanonicalizeRangeHi }, + { 0x03d8u, 0x03efu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x03f0u, 0x03f0u, 0x0008u, CanonicalizeSet }, + { 0x03f1u, 0x03f1u, 0x000bu, CanonicalizeSet }, + { 0x03f2u, 0x03f2u, 0x0007u, CanonicalizeRangeLo }, + { 0x03f3u, 0x03f4u, 0x0000u, CanonicalizeUnique }, + { 0x03f5u, 0x03f5u, 0x0005u, CanonicalizeSet }, + { 0x03f6u, 0x03f6u, 0x0000u, CanonicalizeUnique }, + { 0x03f7u, 0x03f8u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x03f9u, 0x03f9u, 0x0007u, CanonicalizeRangeHi }, + { 0x03fau, 0x03fbu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x03fcu, 0x03fcu, 0x0000u, CanonicalizeUnique }, + { 0x03fdu, 0x03ffu, 0x0082u, CanonicalizeRangeHi }, + { 0x0400u, 0x040fu, 0x0050u, CanonicalizeRangeLo }, + { 0x0410u, 0x042fu, 0x0020u, CanonicalizeRangeLo }, + { 0x0430u, 0x044fu, 0x0020u, CanonicalizeRangeHi }, + { 0x0450u, 0x045fu, 0x0050u, CanonicalizeRangeHi }, + { 0x0460u, 0x0481u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0482u, 0x0489u, 0x0000u, CanonicalizeUnique }, + { 0x048au, 0x04bfu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x04c0u, 0x04c0u, 0x000fu, CanonicalizeRangeLo }, + { 0x04c1u, 0x04ceu, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x04cfu, 0x04cfu, 0x000fu, CanonicalizeRangeHi }, + { 0x04d0u, 0x0527u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x0528u, 0x0530u, 0x0000u, CanonicalizeUnique }, + { 0x0531u, 0x0556u, 0x0030u, CanonicalizeRangeLo }, + { 0x0557u, 0x0560u, 0x0000u, CanonicalizeUnique }, + { 0x0561u, 0x0586u, 0x0030u, CanonicalizeRangeHi }, + { 0x0587u, 0x109fu, 0x0000u, CanonicalizeUnique }, + { 0x10a0u, 0x10c5u, 0x1c60u, CanonicalizeRangeLo }, + { 0x10c6u, 0x1d78u, 0x0000u, CanonicalizeUnique }, + { 0x1d79u, 0x1d79u, 0x8a04u, CanonicalizeRangeLo }, + { 0x1d7au, 0x1d7cu, 0x0000u, CanonicalizeUnique }, + { 0x1d7du, 0x1d7du, 0x0ee6u, CanonicalizeRangeLo }, + { 0x1d7eu, 0x1dffu, 0x0000u, CanonicalizeUnique }, + { 0x1e00u, 0x1e5fu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x1e60u, 0x1e61u, 0x000eu, CanonicalizeSet }, + { 0x1e62u, 0x1e95u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x1e96u, 0x1e9au, 0x0000u, CanonicalizeUnique }, + { 0x1e9bu, 0x1e9bu, 0x000eu, CanonicalizeSet }, + { 0x1e9cu, 0x1e9fu, 0x0000u, CanonicalizeUnique }, + { 0x1ea0u, 0x1effu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x1f00u, 0x1f07u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f08u, 0x1f0fu, 0x0008u, CanonicalizeRangeHi }, + { 0x1f10u, 0x1f15u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f16u, 0x1f17u, 0x0000u, CanonicalizeUnique }, + { 0x1f18u, 0x1f1du, 0x0008u, CanonicalizeRangeHi }, + { 0x1f1eu, 0x1f1fu, 0x0000u, CanonicalizeUnique }, + { 0x1f20u, 0x1f27u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f28u, 0x1f2fu, 0x0008u, CanonicalizeRangeHi }, + { 0x1f30u, 0x1f37u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f38u, 0x1f3fu, 0x0008u, CanonicalizeRangeHi }, + { 0x1f40u, 0x1f45u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f46u, 0x1f47u, 0x0000u, CanonicalizeUnique }, + { 0x1f48u, 0x1f4du, 0x0008u, CanonicalizeRangeHi }, + { 0x1f4eu, 0x1f50u, 0x0000u, CanonicalizeUnique }, + { 0x1f51u, 0x1f51u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f52u, 0x1f52u, 0x0000u, CanonicalizeUnique }, + { 0x1f53u, 0x1f53u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f54u, 0x1f54u, 0x0000u, CanonicalizeUnique }, + { 0x1f55u, 0x1f55u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f56u, 0x1f56u, 0x0000u, CanonicalizeUnique }, + { 0x1f57u, 0x1f57u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f58u, 0x1f58u, 0x0000u, CanonicalizeUnique }, + { 0x1f59u, 0x1f59u, 0x0008u, CanonicalizeRangeHi }, + { 0x1f5au, 0x1f5au, 0x0000u, CanonicalizeUnique }, + { 0x1f5bu, 0x1f5bu, 0x0008u, CanonicalizeRangeHi }, + { 0x1f5cu, 0x1f5cu, 0x0000u, CanonicalizeUnique }, + { 0x1f5du, 0x1f5du, 0x0008u, CanonicalizeRangeHi }, + { 0x1f5eu, 0x1f5eu, 0x0000u, CanonicalizeUnique }, + { 0x1f5fu, 0x1f5fu, 0x0008u, CanonicalizeRangeHi }, + { 0x1f60u, 0x1f67u, 0x0008u, CanonicalizeRangeLo }, + { 0x1f68u, 0x1f6fu, 0x0008u, CanonicalizeRangeHi }, + { 0x1f70u, 0x1f71u, 0x004au, CanonicalizeRangeLo }, + { 0x1f72u, 0x1f75u, 0x0056u, CanonicalizeRangeLo }, + { 0x1f76u, 0x1f77u, 0x0064u, CanonicalizeRangeLo }, + { 0x1f78u, 0x1f79u, 0x0080u, CanonicalizeRangeLo }, + { 0x1f7au, 0x1f7bu, 0x0070u, CanonicalizeRangeLo }, + { 0x1f7cu, 0x1f7du, 0x007eu, CanonicalizeRangeLo }, + { 0x1f7eu, 0x1fafu, 0x0000u, CanonicalizeUnique }, + { 0x1fb0u, 0x1fb1u, 0x0008u, CanonicalizeRangeLo }, + { 0x1fb2u, 0x1fb7u, 0x0000u, CanonicalizeUnique }, + { 0x1fb8u, 0x1fb9u, 0x0008u, CanonicalizeRangeHi }, + { 0x1fbau, 0x1fbbu, 0x004au, CanonicalizeRangeHi }, + { 0x1fbcu, 0x1fbdu, 0x0000u, CanonicalizeUnique }, + { 0x1fbeu, 0x1fbeu, 0x0007u, CanonicalizeSet }, + { 0x1fbfu, 0x1fc7u, 0x0000u, CanonicalizeUnique }, + { 0x1fc8u, 0x1fcbu, 0x0056u, CanonicalizeRangeHi }, + { 0x1fccu, 0x1fcfu, 0x0000u, CanonicalizeUnique }, + { 0x1fd0u, 0x1fd1u, 0x0008u, CanonicalizeRangeLo }, + { 0x1fd2u, 0x1fd7u, 0x0000u, CanonicalizeUnique }, + { 0x1fd8u, 0x1fd9u, 0x0008u, CanonicalizeRangeHi }, + { 0x1fdau, 0x1fdbu, 0x0064u, CanonicalizeRangeHi }, + { 0x1fdcu, 0x1fdfu, 0x0000u, CanonicalizeUnique }, + { 0x1fe0u, 0x1fe1u, 0x0008u, CanonicalizeRangeLo }, + { 0x1fe2u, 0x1fe4u, 0x0000u, CanonicalizeUnique }, + { 0x1fe5u, 0x1fe5u, 0x0007u, CanonicalizeRangeLo }, + { 0x1fe6u, 0x1fe7u, 0x0000u, CanonicalizeUnique }, + { 0x1fe8u, 0x1fe9u, 0x0008u, CanonicalizeRangeHi }, + { 0x1feau, 0x1febu, 0x0070u, CanonicalizeRangeHi }, + { 0x1fecu, 0x1fecu, 0x0007u, CanonicalizeRangeHi }, + { 0x1fedu, 0x1ff7u, 0x0000u, CanonicalizeUnique }, + { 0x1ff8u, 0x1ff9u, 0x0080u, CanonicalizeRangeHi }, + { 0x1ffau, 0x1ffbu, 0x007eu, CanonicalizeRangeHi }, + { 0x1ffcu, 0x2131u, 0x0000u, CanonicalizeUnique }, + { 0x2132u, 0x2132u, 0x001cu, CanonicalizeRangeLo }, + { 0x2133u, 0x214du, 0x0000u, CanonicalizeUnique }, + { 0x214eu, 0x214eu, 0x001cu, CanonicalizeRangeHi }, + { 0x214fu, 0x215fu, 0x0000u, CanonicalizeUnique }, + { 0x2160u, 0x216fu, 0x0010u, CanonicalizeRangeLo }, + { 0x2170u, 0x217fu, 0x0010u, CanonicalizeRangeHi }, + { 0x2180u, 0x2182u, 0x0000u, CanonicalizeUnique }, + { 0x2183u, 0x2184u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x2185u, 0x24b5u, 0x0000u, CanonicalizeUnique }, + { 0x24b6u, 0x24cfu, 0x001au, CanonicalizeRangeLo }, + { 0x24d0u, 0x24e9u, 0x001au, CanonicalizeRangeHi }, + { 0x24eau, 0x2bffu, 0x0000u, CanonicalizeUnique }, + { 0x2c00u, 0x2c2eu, 0x0030u, CanonicalizeRangeLo }, + { 0x2c2fu, 0x2c2fu, 0x0000u, CanonicalizeUnique }, + { 0x2c30u, 0x2c5eu, 0x0030u, CanonicalizeRangeHi }, + { 0x2c5fu, 0x2c5fu, 0x0000u, CanonicalizeUnique }, + { 0x2c60u, 0x2c61u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x2c62u, 0x2c62u, 0x29f7u, CanonicalizeRangeHi }, + { 0x2c63u, 0x2c63u, 0x0ee6u, CanonicalizeRangeHi }, + { 0x2c64u, 0x2c64u, 0x29e7u, CanonicalizeRangeHi }, + { 0x2c65u, 0x2c65u, 0x2a2bu, CanonicalizeRangeHi }, + { 0x2c66u, 0x2c66u, 0x2a28u, CanonicalizeRangeHi }, + { 0x2c67u, 0x2c6cu, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x2c6du, 0x2c6du, 0x2a1cu, CanonicalizeRangeHi }, + { 0x2c6eu, 0x2c6eu, 0x29fdu, CanonicalizeRangeHi }, + { 0x2c6fu, 0x2c6fu, 0x2a1fu, CanonicalizeRangeHi }, + { 0x2c70u, 0x2c70u, 0x2a1eu, CanonicalizeRangeHi }, + { 0x2c71u, 0x2c71u, 0x0000u, CanonicalizeUnique }, + { 0x2c72u, 0x2c73u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x2c74u, 0x2c74u, 0x0000u, CanonicalizeUnique }, + { 0x2c75u, 0x2c76u, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x2c77u, 0x2c7du, 0x0000u, CanonicalizeUnique }, + { 0x2c7eu, 0x2c7fu, 0x2a3fu, CanonicalizeRangeHi }, + { 0x2c80u, 0x2ce3u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0x2ce4u, 0x2ceau, 0x0000u, CanonicalizeUnique }, + { 0x2cebu, 0x2ceeu, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0x2cefu, 0x2cffu, 0x0000u, CanonicalizeUnique }, + { 0x2d00u, 0x2d25u, 0x1c60u, CanonicalizeRangeHi }, + { 0x2d26u, 0xa63fu, 0x0000u, CanonicalizeUnique }, + { 0xa640u, 0xa66du, 0x0000u, CanonicalizeAlternatingAligned }, + { 0xa66eu, 0xa67fu, 0x0000u, CanonicalizeUnique }, + { 0xa680u, 0xa697u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0xa698u, 0xa721u, 0x0000u, CanonicalizeUnique }, + { 0xa722u, 0xa72fu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0xa730u, 0xa731u, 0x0000u, CanonicalizeUnique }, + { 0xa732u, 0xa76fu, 0x0000u, CanonicalizeAlternatingAligned }, + { 0xa770u, 0xa778u, 0x0000u, CanonicalizeUnique }, + { 0xa779u, 0xa77cu, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0xa77du, 0xa77du, 0x8a04u, CanonicalizeRangeHi }, + { 0xa77eu, 0xa787u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0xa788u, 0xa78au, 0x0000u, CanonicalizeUnique }, + { 0xa78bu, 0xa78cu, 0x0000u, CanonicalizeAlternatingUnaligned }, + { 0xa78du, 0xa78du, 0xa528u, CanonicalizeRangeHi }, + { 0xa78eu, 0xa78fu, 0x0000u, CanonicalizeUnique }, + { 0xa790u, 0xa791u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0xa792u, 0xa79fu, 0x0000u, CanonicalizeUnique }, + { 0xa7a0u, 0xa7a9u, 0x0000u, CanonicalizeAlternatingAligned }, + { 0xa7aau, 0xff20u, 0x0000u, CanonicalizeUnique }, + { 0xff21u, 0xff3au, 0x0020u, CanonicalizeRangeLo }, + { 0xff3bu, 0xff40u, 0x0000u, CanonicalizeUnique }, + { 0xff41u, 0xff5au, 0x0020u, CanonicalizeRangeHi }, + { 0xff5bu, 0xffffu, 0x0000u, CanonicalizeUnique }, +}; + +const size_t LATIN_CANONICALIZATION_RANGES = 20; +LatinCanonicalizationRange latinRangeInfo[LATIN_CANONICALIZATION_RANGES] = { + { 0x0000u, 0x0040u, 0x0000u, CanonicalizeLatinSelf }, + { 0x0041u, 0x005au, 0x0000u, CanonicalizeLatinMask0x20 }, + { 0x005bu, 0x0060u, 0x0000u, CanonicalizeLatinSelf }, + { 0x0061u, 0x007au, 0x0000u, CanonicalizeLatinMask0x20 }, + { 0x007bu, 0x00bfu, 0x0000u, CanonicalizeLatinSelf }, + { 0x00c0u, 0x00d6u, 0x0000u, CanonicalizeLatinMask0x20 }, + { 0x00d7u, 0x00d7u, 0x0000u, CanonicalizeLatinSelf }, + { 0x00d8u, 0x00deu, 0x0000u, CanonicalizeLatinMask0x20 }, + { 0x00dfu, 0x00dfu, 0x0000u, CanonicalizeLatinSelf }, + { 0x00e0u, 0x00f6u, 0x0000u, CanonicalizeLatinMask0x20 }, + { 0x00f7u, 0x00f7u, 0x0000u, CanonicalizeLatinSelf }, + { 0x00f8u, 0x00feu, 0x0000u, CanonicalizeLatinMask0x20 }, + { 0x00ffu, 0x00ffu, 0x0000u, CanonicalizeLatinSelf }, + { 0x0100u, 0x0177u, 0x0000u, CanonicalizeLatinInvalid }, + { 0x0178u, 0x0178u, 0x00ffu, CanonicalizeLatinOther }, + { 0x0179u, 0x039bu, 0x0000u, CanonicalizeLatinInvalid }, + { 0x039cu, 0x039cu, 0x00b5u, CanonicalizeLatinOther }, + { 0x039du, 0x03bbu, 0x0000u, CanonicalizeLatinInvalid }, + { 0x03bcu, 0x03bcu, 0x00b5u, CanonicalizeLatinOther }, + { 0x03bdu, 0xffffu, 0x0000u, CanonicalizeLatinInvalid }, +}; + +} } // JSC::Yarr + diff --git a/Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.h b/Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.h new file mode 100644 index 000000000..be0ead43d --- /dev/null +++ b/Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.h @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2012 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 YarrCanonicalizeUCS2_H +#define YarrCanonicalizeUCS2_H + +#include <stdint.h> +#include <wtf/unicode/Unicode.h> + +namespace JSC { namespace Yarr { + +// This set of data (autogenerated using YarrCanonicalizeUCS2.js into YarrCanonicalizeUCS2.cpp) +// provides information for each UCS2 code point as to the set of code points that it should +// match under the ES5.1 case insensitive RegExp matching rules, specified in 15.10.2.8. +enum UCS2CanonicalizationType { + CanonicalizeUnique, // No canonically equal values, e.g. 0x0. + CanonicalizeSet, // Value indicates a set in characterSetInfo. + CanonicalizeRangeLo, // Value is positive delta to pair, E.g. 0x41 has value 0x20, -> 0x61. + CanonicalizeRangeHi, // Value is positive delta to pair, E.g. 0x61 has value 0x20, -> 0x41. + CanonicalizeAlternatingAligned, // Aligned consequtive pair, e.g. 0x1f4,0x1f5. + CanonicalizeAlternatingUnaligned, // Unaligned consequtive pair, e.g. 0x241,0x242. +}; +struct UCS2CanonicalizationRange { uint16_t begin, end, value, type; }; +extern const size_t UCS2_CANONICALIZATION_RANGES; +extern uint16_t* characterSetInfo[]; +extern UCS2CanonicalizationRange rangeInfo[]; + +// This table is similar to the full rangeInfo table, however this maps from UCS2 codepoints to +// the set of Latin1 codepoints that could match. +enum LatinCanonicalizationType { + CanonicalizeLatinSelf, // This character is in the Latin1 range, but has no canonical equivalent in the range. + CanonicalizeLatinMask0x20, // One of a pair of characters, under the mask 0x20. + CanonicalizeLatinOther, // This character is not in the Latin1 range, but canonicalizes to another that is. + CanonicalizeLatinInvalid, // Cannot match against Latin1 input. +}; +struct LatinCanonicalizationRange { uint16_t begin, end, value, type; }; +extern const size_t LATIN_CANONICALIZATION_RANGES; +extern LatinCanonicalizationRange latinRangeInfo[]; + +// This searches in log2 time over ~364 entries, so should typically result in 8 compares. +inline UCS2CanonicalizationRange* rangeInfoFor(UChar ch) +{ + UCS2CanonicalizationRange* info = rangeInfo; + size_t entries = UCS2_CANONICALIZATION_RANGES; + + while (true) { + size_t candidate = entries >> 1; + UCS2CanonicalizationRange* candidateInfo = info + candidate; + if (ch < candidateInfo->begin) + entries = candidate; + else if (ch <= candidateInfo->end) + return candidateInfo; + else { + info = candidateInfo + 1; + entries -= (candidate + 1); + } + } +} + +// Should only be called for characters that have one canonically matching value. +inline UChar getCanonicalPair(UCS2CanonicalizationRange* info, UChar ch) +{ + ASSERT(ch >= info->begin && ch <= info->end); + switch (info->type) { + case CanonicalizeRangeLo: + return ch + info->value; + case CanonicalizeRangeHi: + return ch - info->value; + case CanonicalizeAlternatingAligned: + return ch ^ 1; + case CanonicalizeAlternatingUnaligned: + return ((ch - 1) ^ 1) + 1; + default: + ASSERT_NOT_REACHED(); + } + ASSERT_NOT_REACHED(); + return 0; +} + +// Returns true if no other UCS2 codepoint can match this value. +inline bool isCanonicallyUnique(UChar ch) +{ + return rangeInfoFor(ch)->type == CanonicalizeUnique; +} + +// Returns true if values are equal, under the canonicalization rules. +inline bool areCanonicallyEquivalent(UChar a, UChar b) +{ + UCS2CanonicalizationRange* info = rangeInfoFor(a); + switch (info->type) { + case CanonicalizeUnique: + return a == b; + case CanonicalizeSet: { + for (uint16_t* set = characterSetInfo[info->value]; (a = *set); ++set) { + if (a == b) + return true; + } + return false; + } + case CanonicalizeRangeLo: + return (a == b) || (a + info->value == b); + case CanonicalizeRangeHi: + return (a == b) || (a - info->value == b); + case CanonicalizeAlternatingAligned: + return (a | 1) == (b | 1); + case CanonicalizeAlternatingUnaligned: + return ((a - 1) | 1) == ((b - 1) | 1); + } + + ASSERT_NOT_REACHED(); + return false; +} + +} } // JSC::Yarr + +#endif diff --git a/Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.js b/Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.js new file mode 100644 index 000000000..00361dd46 --- /dev/null +++ b/Source/JavaScriptCore/yarr/YarrCanonicalizeUCS2.js @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2012 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. + */ + +// See ES 5.1, 15.10.2.8 +function canonicalize(ch) +{ + var u = String.fromCharCode(ch).toUpperCase(); + if (u.length > 1) + return ch; + var cu = u.charCodeAt(0); + if (ch >= 128 && cu < 128) + return ch; + return cu; +} + +var MAX_UCS2 = 0xFFFF; +var MAX_LATIN = 0xFF; + +var groupedCanonically = []; +// Pass 1: populate groupedCanonically - this is mapping from canonicalized +// values back to the set of character code that canonicalize to them. +for (var i = 0; i <= MAX_UCS2; ++i) { + var ch = canonicalize(i); + if (!groupedCanonically[ch]) + groupedCanonically[ch] = []; + groupedCanonically[ch].push(i); +} + +var typeInfo = []; +var latinTypeInfo = []; +var characterSetInfo = []; +// Pass 2: populate typeInfo & characterSetInfo. For every character calculate +// a typeInfo value, described by the types above, and a value payload. +for (cu in groupedCanonically) { + // The set of characters that canonicalize to cu + var characters = groupedCanonically[cu]; + + // If there is only one, it is unique. + if (characters.length == 1) { + typeInfo[characters[0]] = "CanonicalizeUnique:0"; + latinTypeInfo[characters[0]] = characters[0] <= MAX_LATIN ? "CanonicalizeLatinSelf:0" : "CanonicalizeLatinInvalid:0"; + continue; + } + + // Sort the array. + characters.sort(function(x,y){return x-y;}); + + // If there are more than two characters, create an entry in characterSetInfo. + if (characters.length > 2) { + for (i in characters) + typeInfo[characters[i]] = "CanonicalizeSet:" + characterSetInfo.length; + characterSetInfo.push(characters); + + if (characters[1] <= MAX_LATIN) + throw new Error("sets with more than one latin character not supported!"); + if (characters[0] <= MAX_LATIN) { + for (i in characters) + latinTypeInfo[characters[i]] = "CanonicalizeLatinOther:" + characters[0]; + latinTypeInfo[characters[0]] = "CanonicalizeLatinSelf:0"; + } else { + for (i in characters) + latinTypeInfo[characters[i]] = "CanonicalizeLatinInvalid:0"; + } + + continue; + } + + // We have a pair, mark alternating ranges, otherwise track whether this is the low or high partner. + var lo = characters[0]; + var hi = characters[1]; + var delta = hi - lo; + if (delta == 1) { + var type = lo & 1 ? "CanonicalizeAlternatingUnaligned:0" : "CanonicalizeAlternatingAligned:0"; + typeInfo[lo] = type; + typeInfo[hi] = type; + } else { + typeInfo[lo] = "CanonicalizeRangeLo:" + delta; + typeInfo[hi] = "CanonicalizeRangeHi:" + delta; + } + + if (lo > MAX_LATIN) { + latinTypeInfo[lo] = "CanonicalizeLatinInvalid:0"; + latinTypeInfo[hi] = "CanonicalizeLatinInvalid:0"; + } else if (hi > MAX_LATIN) { + latinTypeInfo[lo] = "CanonicalizeLatinSelf:0"; + latinTypeInfo[hi] = "CanonicalizeLatinOther:" + lo; + } else { + if (delta != 0x20 || lo & 0x20) + throw new Error("pairs of latin characters that don't mask with 0x20 not supported!"); + latinTypeInfo[lo] = "CanonicalizeLatinMask0x20:0"; + latinTypeInfo[hi] = "CanonicalizeLatinMask0x20:0"; + } +} + +var rangeInfo = []; +// Pass 3: coallesce types into ranges. +for (var end = 0; end <= MAX_UCS2; ++end) { + var begin = end; + var type = typeInfo[end]; + while (end < MAX_UCS2 && typeInfo[end + 1] == type) + ++end; + rangeInfo.push({begin:begin, end:end, type:type}); +} + +var latinRangeInfo = []; +// Pass 4: coallesce latin-1 types into ranges. +for (var end = 0; end <= MAX_UCS2; ++end) { + var begin = end; + var type = latinTypeInfo[end]; + while (end < MAX_UCS2 && latinTypeInfo[end + 1] == type) + ++end; + latinRangeInfo.push({begin:begin, end:end, type:type}); +} + + +// Helper function to convert a number to a fixed width hex representation of a C uint16_t. +function hex(x) +{ + var s = Number(x).toString(16); + while (s.length < 4) + s = 0 + s; + return "0x" + s + "u"; +} + +var copyright = ( + "/*" + "\n" + + " * Copyright (C) 2012 Apple Inc. All rights reserved." + "\n" + + " *" + "\n" + + " * Redistribution and use in source and binary forms, with or without" + "\n" + + " * modification, are permitted provided that the following conditions" + "\n" + + " * are met:" + "\n" + + " * 1. Redistributions of source code must retain the above copyright" + "\n" + + " * notice, this list of conditions and the following disclaimer." + "\n" + + " * 2. Redistributions in binary form must reproduce the above copyright" + "\n" + + " * notice, this list of conditions and the following disclaimer in the" + "\n" + + " * documentation and/or other materials provided with the distribution." + "\n" + + " *" + "\n" + + " * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY" + "\n" + + " * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE" + "\n" + + " * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR" + "\n" + + " * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR" + "\n" + + " * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL," + "\n" + + " * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO," + "\n" + + " * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR" + "\n" + + " * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY" + "\n" + + " * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT" + "\n" + + " * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE" + "\n" + + " * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. " + "\n" + + " */"); + +print(copyright); +print(); +print("// DO NOT EDIT! - this file autogenerated by YarrCanonicalizeUCS2.js"); +print(); +print('#include "config.h"'); +print('#include "YarrCanonicalizeUCS2.h"'); +print(); +print("namespace JSC { namespace Yarr {"); +print(); +print("#include <stdint.h>"); +print(); + +for (i in characterSetInfo) { + var characters = "" + var set = characterSetInfo[i]; + for (var j in set) + characters += hex(set[j]) + ", "; + print("uint16_t ucs2CharacterSet" + i + "[] = { " + characters + "0 };"); +} +print(); +print("static const size_t UCS2_CANONICALIZATION_SETS = " + characterSetInfo.length + ";"); +print("uint16_t* characterSetInfo[UCS2_CANONICALIZATION_SETS] = {"); +for (i in characterSetInfo) +print(" ucs2CharacterSet" + i + ","); +print("};"); +print(); +print("const size_t UCS2_CANONICALIZATION_RANGES = " + rangeInfo.length + ";"); +print("UCS2CanonicalizationRange rangeInfo[UCS2_CANONICALIZATION_RANGES] = {"); +for (i in rangeInfo) { + var info = rangeInfo[i]; + var typeAndValue = info.type.split(':'); + print(" { " + hex(info.begin) + ", " + hex(info.end) + ", " + hex(typeAndValue[1]) + ", " + typeAndValue[0] + " },"); +} +print("};"); +print(); +print("const size_t LATIN_CANONICALIZATION_RANGES = " + latinRangeInfo.length + ";"); +print("LatinCanonicalizationRange latinRangeInfo[LATIN_CANONICALIZATION_RANGES] = {"); +for (i in latinRangeInfo) { + var info = latinRangeInfo[i]; + var typeAndValue = info.type.split(':'); + print(" { " + hex(info.begin) + ", " + hex(info.end) + ", " + hex(typeAndValue[1]) + ", " + typeAndValue[0] + " },"); +} +print("};"); +print(); +print("} } // JSC::Yarr"); +print(); + diff --git a/Source/JavaScriptCore/yarr/YarrInterpreter.cpp b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp index 743f16048..ba10171bf 100644 --- a/Source/JavaScriptCore/yarr/YarrInterpreter.cpp +++ b/Source/JavaScriptCore/yarr/YarrInterpreter.cpp @@ -29,6 +29,7 @@ #include "UString.h" #include "Yarr.h" +#include "YarrCanonicalizeUCS2.h" #include <wtf/BumpPointerAllocator.h> #include <wtf/DataLog.h> #include <wtf/text/CString.h> @@ -41,6 +42,7 @@ using namespace WTF; namespace JSC { namespace Yarr { +template<typename CharType> class Interpreter { public: struct ParenthesesDisjunctionContext; @@ -169,55 +171,9 @@ public: allocatorPool = allocatorPool->dealloc(context); } - // This class is a placeholder for future character iterator, current - // proposed name StringConstCharacterIterator. - class CharAccess { - public: - CharAccess(const UString& s) - { - if (s.is8Bit()) { - m_charSize = Char8; - m_ptr.ptr8 = s.characters8(); - } else { - m_charSize = Char16; - m_ptr.ptr16 = s.characters16(); - } - } - - CharAccess(const LChar* ptr) - : m_charSize(Char8) - { - m_ptr.ptr8 = ptr; - } - - CharAccess(const UChar* ptr) - : m_charSize(Char16) - { - m_ptr.ptr16 = ptr; - } - - ~CharAccess() - { - } - - inline UChar operator[](unsigned index) - { - if (m_charSize == Char8) - return m_ptr.ptr8[index]; - return m_ptr.ptr16[index]; - } - - private: - union { - const LChar* ptr8; - const UChar* ptr16; - } m_ptr; - YarrCharSize m_charSize; - }; - class InputStream { public: - InputStream(const UString& input, unsigned start, unsigned length) + InputStream(const CharType* input, unsigned start, unsigned length) : input(input) , pos(start) , length(length) @@ -331,7 +287,7 @@ public: } private: - CharAccess input; + const CharType* input; unsigned pos; unsigned length; }; @@ -383,15 +339,22 @@ public: if (pattern->m_ignoreCase) { for (unsigned i = 0; i < matchSize; ++i) { - int ch = input.reread(matchBegin + i); + int oldCh = input.reread(matchBegin + i); + int ch = input.readChecked(negativeInputOffset + matchSize - i); - int lo = Unicode::toLower(ch); - int hi = Unicode::toUpper(ch); + if (oldCh == ch) + continue; - if ((lo != hi) ? (!checkCasedCharacter(lo, hi, negativeInputOffset + matchSize - i)) : (!checkCharacter(ch, negativeInputOffset + matchSize - i))) { - input.uncheckInput(matchSize); - return false; - } + // The definition for canonicalize (see ES 5.1, 15.10.2.8) means that + // unicode values are never allowed to match against ascii ones. + if (isASCII(oldCh) || isASCII(ch)) { + if (toASCIIUpper(oldCh) == toASCIIUpper(ch)) + continue; + } else if (areCanonicallyEquivalent(oldCh, ch)) + continue; + + input.uncheckInput(matchSize); + return false; } } else { for (unsigned i = 0; i < matchSize; ++i) { @@ -1481,7 +1444,7 @@ public: return output[0]; } - Interpreter(BytecodePattern* pattern, unsigned* output, const UString input, unsigned start, unsigned length) + Interpreter(BytecodePattern* pattern, unsigned* output, const CharType* input, unsigned length, unsigned start) : pattern(pattern) , output(output) , input(input, start, length) @@ -1971,18 +1934,31 @@ PassOwnPtr<BytecodePattern> byteCompile(YarrPattern& pattern, BumpPointerAllocat return ByteCompiler(pattern).compile(allocator); } -unsigned interpret(BytecodePattern* bytecode, const UString& input, unsigned start, unsigned length, unsigned* output) +unsigned interpret(BytecodePattern* bytecode, const UString& input, unsigned start, unsigned* output) +{ + if (input.is8Bit()) + return Interpreter<LChar>(bytecode, output, input.characters8(), input.length(), start).interpret(); + return Interpreter<UChar>(bytecode, output, input.characters16(), input.length(), start).interpret(); +} + +unsigned interpret(BytecodePattern* bytecode, const LChar* input, unsigned length, unsigned start, unsigned* output) +{ + return Interpreter<LChar>(bytecode, output, input, length, start).interpret(); +} + +unsigned interpret(BytecodePattern* bytecode, const UChar* input, unsigned length, unsigned start, unsigned* output) { - return Interpreter(bytecode, output, input, start, length).interpret(); + return Interpreter<UChar>(bytecode, output, input, length, start).interpret(); } -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoPatternCharacter) == (YarrStackSpaceForBackTrackInfoPatternCharacter * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoPatternCharacter); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoCharacterClass) == (YarrStackSpaceForBackTrackInfoCharacterClass * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoCharacterClass); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoBackReference) == (YarrStackSpaceForBackTrackInfoBackReference * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoBackReference); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoAlternative) == (YarrStackSpaceForBackTrackInfoAlternative * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoAlternative); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheticalAssertion) == (YarrStackSpaceForBackTrackInfoParentheticalAssertion * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheticalAssertion); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParenthesesOnce) == (YarrStackSpaceForBackTrackInfoParenthesesOnce * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParenthesesOnce); -COMPILE_ASSERT(sizeof(Interpreter::BackTrackInfoParentheses) == (YarrStackSpaceForBackTrackInfoParentheses * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheses); +// These should be the same for both UChar & LChar. +COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoPatternCharacter) == (YarrStackSpaceForBackTrackInfoPatternCharacter * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoPatternCharacter); +COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoCharacterClass) == (YarrStackSpaceForBackTrackInfoCharacterClass * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoCharacterClass); +COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoBackReference) == (YarrStackSpaceForBackTrackInfoBackReference * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoBackReference); +COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoAlternative) == (YarrStackSpaceForBackTrackInfoAlternative * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoAlternative); +COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoParentheticalAssertion) == (YarrStackSpaceForBackTrackInfoParentheticalAssertion * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheticalAssertion); +COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoParenthesesOnce) == (YarrStackSpaceForBackTrackInfoParenthesesOnce * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParenthesesOnce); +COMPILE_ASSERT(sizeof(Interpreter<UChar>::BackTrackInfoParentheses) == (YarrStackSpaceForBackTrackInfoParentheses * sizeof(uintptr_t)), CheckYarrStackSpaceForBackTrackInfoParentheses); } } diff --git a/Source/JavaScriptCore/yarr/YarrInterpreter.h b/Source/JavaScriptCore/yarr/YarrInterpreter.h index 4bb1efc50..4ecd69eca 100644 --- a/Source/JavaScriptCore/yarr/YarrInterpreter.h +++ b/Source/JavaScriptCore/yarr/YarrInterpreter.h @@ -375,6 +375,11 @@ private: Vector<CharacterClass*> m_userCharacterClasses; }; +JS_EXPORT_PRIVATE PassOwnPtr<BytecodePattern> byteCompile(YarrPattern&, BumpPointerAllocator*); +JS_EXPORT_PRIVATE unsigned interpret(BytecodePattern*, const UString& input, unsigned start, unsigned* output); +unsigned interpret(BytecodePattern*, const LChar* input, unsigned length, unsigned start, unsigned* output); +unsigned interpret(BytecodePattern*, const UChar* input, unsigned length, unsigned start, unsigned* output); + } } // namespace JSC::Yarr #endif // YarrInterpreter_h diff --git a/Source/JavaScriptCore/yarr/YarrJIT.cpp b/Source/JavaScriptCore/yarr/YarrJIT.cpp index 2269792ec..60519ebd8 100644 --- a/Source/JavaScriptCore/yarr/YarrJIT.cpp +++ b/Source/JavaScriptCore/yarr/YarrJIT.cpp @@ -29,6 +29,7 @@ #include <wtf/ASCIICType.h> #include "LinkBuffer.h" #include "Yarr.h" +#include "YarrCanonicalizeUCS2.h" #if ENABLE(YARR_JIT) @@ -36,6 +37,7 @@ using namespace WTF; namespace JSC { namespace Yarr { +template<YarrJITCompileMode compileMode> class YarrGenerator : private MacroAssembler { friend void jitCompile(JSGlobalData*, YarrCodeBlock& jitObject, const UString& pattern, unsigned& numSubpatterns, const char*& error, bool ignoreCase, bool multiline); @@ -49,6 +51,7 @@ class YarrGenerator : private MacroAssembler { static const RegisterID regT1 = ARMRegisters::r6; static const RegisterID returnRegister = ARMRegisters::r0; + static const RegisterID returnRegister2 = ARMRegisters::r1; #elif CPU(MIPS) static const RegisterID input = MIPSRegisters::a0; static const RegisterID index = MIPSRegisters::a1; @@ -59,6 +62,7 @@ class YarrGenerator : private MacroAssembler { static const RegisterID regT1 = MIPSRegisters::t5; static const RegisterID returnRegister = MIPSRegisters::v0; + static const RegisterID returnRegister2 = MIPSRegisters::v1; #elif CPU(SH4) static const RegisterID input = SH4Registers::r4; static const RegisterID index = SH4Registers::r5; @@ -69,6 +73,7 @@ class YarrGenerator : private MacroAssembler { static const RegisterID regT1 = SH4Registers::r1; static const RegisterID returnRegister = SH4Registers::r0; + static const RegisterID returnRegister2 = SH4Registers::r1; #elif CPU(X86) static const RegisterID input = X86Registers::eax; static const RegisterID index = X86Registers::edx; @@ -79,6 +84,7 @@ class YarrGenerator : private MacroAssembler { static const RegisterID regT1 = X86Registers::esi; static const RegisterID returnRegister = X86Registers::eax; + static const RegisterID returnRegister2 = X86Registers::edx; #elif CPU(X86_64) static const RegisterID input = X86Registers::edi; static const RegisterID index = X86Registers::esi; @@ -89,6 +95,7 @@ class YarrGenerator : private MacroAssembler { static const RegisterID regT1 = X86Registers::ebx; static const RegisterID returnRegister = X86Registers::eax; + static const RegisterID returnRegister2 = X86Registers::edx; #endif void optimizeAlternative(PatternAlternative* alternative) @@ -262,10 +269,10 @@ class YarrGenerator : private MacroAssembler { // For case-insesitive compares, non-ascii characters that have different // upper & lower case representations are converted to a character class. - ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || (Unicode::toLower(ch) == Unicode::toUpper(ch))); + ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || isCanonicallyUnique(ch)); if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) { - or32(TrustedImm32(32), character); - ch = Unicode::toLower(ch); + or32(TrustedImm32(0x20), character); + ch |= 0x20; } return branch32(NotEqual, character, Imm32(ch)); @@ -304,6 +311,65 @@ class YarrGenerator : private MacroAssembler { jump(Address(stackPointerRegister, frameLocation * sizeof(void*))); } + void initCallFrame() + { + unsigned callFrameSize = m_pattern.m_body->m_callFrameSize; + if (callFrameSize) + subPtr(Imm32(callFrameSize * sizeof(void*)), stackPointerRegister); + } + void removeCallFrame() + { + unsigned callFrameSize = m_pattern.m_body->m_callFrameSize; + if (callFrameSize) + addPtr(Imm32(callFrameSize * sizeof(void*)), stackPointerRegister); + } + + // Used to record subpatters, should only be called if compileMode is IncludeSubpatterns. + void setSubpatternStart(RegisterID reg, unsigned subpattern) + { + ASSERT(subpattern); + // FIXME: should be able to ASSERT(compileMode == IncludeSubpatterns), but then this function is conditionally NORETURN. :-( + store32(reg, Address(output, (subpattern << 1) * sizeof(int))); + } + void setSubpatternEnd(RegisterID reg, unsigned subpattern) + { + ASSERT(subpattern); + // FIXME: should be able to ASSERT(compileMode == IncludeSubpatterns), but then this function is conditionally NORETURN. :-( + store32(reg, Address(output, ((subpattern << 1) + 1) * sizeof(int))); + } + void clearSubpatternStart(unsigned subpattern) + { + ASSERT(subpattern); + // FIXME: should be able to ASSERT(compileMode == IncludeSubpatterns), but then this function is conditionally NORETURN. :-( + store32(TrustedImm32(-1), Address(output, (subpattern << 1) * sizeof(int))); + } + + // We use one of three different strategies to track the start of the current match, + // while matching. + // 1) If the pattern has a fixed size, do nothing! - we calculate the value lazily + // at the end of matching. This is irrespective of compileMode, and in this case + // these methods should never be called. + // 2) If we're compiling IncludeSubpatterns, 'output' contains a pointer to an output + // vector, store the match start in the output vector. + // 3) If we're compiling MatchOnly, 'output' is unused, store the match start directly + // in this register. + void setMatchStart(RegisterID reg) + { + ASSERT(!m_pattern.m_body->m_hasFixedSize); + if (compileMode == IncludeSubpatterns) + store32(reg, output); + else + move(reg, output); + } + void getMatchStart(RegisterID reg) + { + ASSERT(!m_pattern.m_body->m_hasFixedSize); + if (compileMode == IncludeSubpatterns) + load32(output, reg); + else + move(output, reg); + } + enum YarrOpCode { // These nodes wrap body alternatives - those in the main disjunction, // rather than subpatterns or assertions. These are chained together in @@ -685,9 +751,9 @@ class YarrGenerator : private MacroAssembler { // For case-insesitive compares, non-ascii characters that have different // upper & lower case representations are converted to a character class. - ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || (Unicode::toLower(ch) == Unicode::toUpper(ch))); + ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || isCanonicallyUnique(ch)); - if ((m_pattern.m_ignoreCase) && (isASCIIAlpha(ch))) + if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) ignoreCaseMask |= 32; for (numberCharacters = 1; numberCharacters < maxCharactersAtOnce && nextOp->m_op == OpTerm; ++numberCharacters, nextOp = &m_ops[opIndex + numberCharacters]) { @@ -713,7 +779,7 @@ class YarrGenerator : private MacroAssembler { // For case-insesitive compares, non-ascii characters that have different // upper & lower case representations are converted to a character class. - ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(currentCharacter) || (Unicode::toLower(currentCharacter) == Unicode::toUpper(currentCharacter))); + ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(currentCharacter) || isCanonicallyUnique(currentCharacter)); allCharacters |= (currentCharacter << shiftAmount); @@ -728,12 +794,12 @@ class YarrGenerator : private MacroAssembler { return; case 2: { BaseIndex address(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar)); - load16(address, character); + load16Unaligned(address, character); break; } case 3: { BaseIndex highAddress(input, index, TimesOne, (startTermPosition - m_checked) * sizeof(LChar)); - load16(highAddress, character); + load16Unaligned(highAddress, character); if (ignoreCaseMask) or32(Imm32(ignoreCaseMask), character); op.m_jumps.append(branch32(NotEqual, character, Imm32((allCharacters & 0xffff) | ignoreCaseMask))); @@ -790,10 +856,10 @@ class YarrGenerator : private MacroAssembler { // For case-insesitive compares, non-ascii characters that have different // upper & lower case representations are converted to a character class. - ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || (Unicode::toLower(ch) == Unicode::toUpper(ch))); + ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || isCanonicallyUnique(ch)); if (m_pattern.m_ignoreCase && isASCIIAlpha(ch)) { - or32(TrustedImm32(32), character); - ch = Unicode::toLower(ch); + or32(TrustedImm32(0x20), character); + ch |= 0x20; } op.m_jumps.append(branch32(NotEqual, character, Imm32(ch))); @@ -1029,7 +1095,6 @@ class YarrGenerator : private MacroAssembler { m_backtrackingState.link(this); - Label backtrackBegin(this); loadFromFrame(term->frameLocation, countRegister); nonGreedyFailures.append(atEndOfInput()); @@ -1068,11 +1133,8 @@ class YarrGenerator : private MacroAssembler { JumpList saveStartIndex; JumpList foundEndingNewLine; - if (m_pattern.m_body->m_hasFixedSize) { - move(index, matchPos); - sub32(Imm32(m_checked), matchPos); - } else - load32(Address(output), matchPos); + ASSERT(!m_pattern.m_body->m_hasFixedSize); + getMatchStart(matchPos); saveStartIndex.append(branchTest32(Zero, matchPos)); Label findBOLLoop(this); @@ -1092,7 +1154,8 @@ class YarrGenerator : private MacroAssembler { if (!m_pattern.m_multiline && term->anchors.bolAnchor) op.m_jumps.append(branchTest32(NonZero, matchPos)); - store32(matchPos, Address(output)); + ASSERT(!m_pattern.m_body->m_hasFixedSize); + setMatchStart(matchPos); move(index, matchPos); @@ -1314,8 +1377,7 @@ class YarrGenerator : private MacroAssembler { // If we get here, the prior alternative matched - return success. // Adjust the stack pointer to remove the pattern's frame. - if (m_pattern.m_body->m_callFrameSize) - addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister); + removeCallFrame(); // Load appropriate values into the return register and the first output // slot, and return. In the case of pattern with a fixed size, we will @@ -1325,10 +1387,14 @@ class YarrGenerator : private MacroAssembler { move(index, returnRegister); if (priorAlternative->m_minimumSize) sub32(Imm32(priorAlternative->m_minimumSize), returnRegister); - store32(returnRegister, output); + if (compileMode == IncludeSubpatterns) + store32(returnRegister, output); } else - load32(Address(output), returnRegister); - store32(index, Address(output, 4)); + getMatchStart(returnRegister); + if (compileMode == IncludeSubpatterns) + store32(index, Address(output, 4)); + move(index, returnRegister2); + generateReturn(); // This is the divide between the tail of the prior alternative, above, and @@ -1511,17 +1577,16 @@ class YarrGenerator : private MacroAssembler { // FIXME: could avoid offsetting this value in JIT code, apply // offsets only afterwards, at the point the results array is // being accessed. - if (term->capture()) { - int offsetId = term->parentheses.subpatternId << 1; + if (term->capture() && compileMode == IncludeSubpatterns) { int inputOffset = term->inputPosition - m_checked; if (term->quantityType == QuantifierFixedCount) inputOffset -= term->parentheses.disjunction->m_minimumSize; if (inputOffset) { move(index, indexTemporary); add32(Imm32(inputOffset), indexTemporary); - store32(indexTemporary, Address(output, offsetId * sizeof(int))); + setSubpatternStart(indexTemporary, term->parentheses.subpatternId); } else - store32(index, Address(output, offsetId * sizeof(int))); + setSubpatternStart(index, term->parentheses.subpatternId); } break; } @@ -1547,15 +1612,14 @@ class YarrGenerator : private MacroAssembler { // FIXME: could avoid offsetting this value in JIT code, apply // offsets only afterwards, at the point the results array is // being accessed. - if (term->capture()) { - int offsetId = (term->parentheses.subpatternId << 1) + 1; + if (term->capture() && compileMode == IncludeSubpatterns) { int inputOffset = term->inputPosition - m_checked; if (inputOffset) { move(index, indexTemporary); add32(Imm32(inputOffset), indexTemporary); - store32(indexTemporary, Address(output, offsetId * sizeof(int))); + setSubpatternEnd(indexTemporary, term->parentheses.subpatternId); } else - store32(index, Address(output, offsetId * sizeof(int))); + setSubpatternEnd(index, term->parentheses.subpatternId); } // If the parentheses are quantified Greedy then add a label to jump back @@ -1645,9 +1709,9 @@ class YarrGenerator : private MacroAssembler { } case OpMatchFailed: - if (m_pattern.m_body->m_callFrameSize) - addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister); - move(TrustedImm32(-1), returnRegister); + removeCallFrame(); + move(TrustedImmPtr((void*)WTF::notFound), returnRegister); + move(TrustedImm32(0), returnRegister2); generateReturn(); break; } @@ -1742,14 +1806,14 @@ class YarrGenerator : private MacroAssembler { // If the pattern size is not fixed, then store the start index, for use if we match. if (!m_pattern.m_body->m_hasFixedSize) { if (alternative->m_minimumSize == 1) - store32(index, Address(output)); + setMatchStart(index); else { move(index, regT0); if (alternative->m_minimumSize) sub32(Imm32(alternative->m_minimumSize - 1), regT0); else add32(TrustedImm32(1), regT0); - store32(regT0, Address(output)); + setMatchStart(regT0); } } @@ -1835,7 +1899,7 @@ class YarrGenerator : private MacroAssembler { // disjunction is 0, e.g. /a*|b/). if (needsToUpdateMatchStart && alternative->m_minimumSize == 1) { // index is already incremented by 1, so just store it now! - store32(index, Address(output)); + setMatchStart(index); needsToUpdateMatchStart = false; } @@ -1859,11 +1923,11 @@ class YarrGenerator : private MacroAssembler { if (needsToUpdateMatchStart) { if (!m_pattern.m_body->m_minimumSize) - store32(index, Address(output)); + setMatchStart(index); else { move(index, regT0); sub32(Imm32(m_pattern.m_body->m_minimumSize), regT0); - store32(regT0, Address(output)); + setMatchStart(regT0); } } @@ -1885,9 +1949,9 @@ class YarrGenerator : private MacroAssembler { // run any matches, and need to return a failure state from JIT code. matchFailed.link(this); - if (m_pattern.m_body->m_callFrameSize) - addPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister); - move(TrustedImm32(-1), returnRegister); + removeCallFrame(); + move(TrustedImmPtr((void*)WTF::notFound), returnRegister); + move(TrustedImm32(0), returnRegister2); generateReturn(); break; } @@ -2054,12 +2118,12 @@ class YarrGenerator : private MacroAssembler { ASSERT(term->quantityCount == 1); // We only need to backtrack to thispoint if capturing or greedy. - if (term->capture() || term->quantityType == QuantifierGreedy) { + if ((term->capture() && compileMode == IncludeSubpatterns) || term->quantityType == QuantifierGreedy) { m_backtrackingState.link(this); // If capturing, clear the capture (we only need to reset start). - if (term->capture()) - store32(TrustedImm32(-1), Address(output, (term->parentheses.subpatternId << 1) * sizeof(int))); + if (term->capture() && compileMode == IncludeSubpatterns) + clearSubpatternStart(term->parentheses.subpatternId); // If Greedy, jump to the end. if (term->quantityType == QuantifierGreedy) { @@ -2449,9 +2513,11 @@ class YarrGenerator : private MacroAssembler { loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), input); loadPtr(Address(X86Registers::ebp, 3 * sizeof(void*)), index); loadPtr(Address(X86Registers::ebp, 4 * sizeof(void*)), length); - loadPtr(Address(X86Registers::ebp, 5 * sizeof(void*)), output); + if (compileMode == IncludeSubpatterns) + loadPtr(Address(X86Registers::ebp, 5 * sizeof(void*)), output); #else - loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output); + if (compileMode == IncludeSubpatterns) + loadPtr(Address(X86Registers::ebp, 2 * sizeof(void*)), output); #endif #elif CPU(ARM) push(ARMRegisters::r4); @@ -2460,7 +2526,8 @@ class YarrGenerator : private MacroAssembler { #if CPU(ARM_TRADITIONAL) push(ARMRegisters::r8); // scratch register #endif - move(ARMRegisters::r3, output); + if (compileMode == IncludeSubpatterns) + move(ARMRegisters::r3, output); #elif CPU(SH4) push(SH4Registers::r11); push(SH4Registers::r13); @@ -2510,18 +2577,20 @@ public: generateEnter(); Jump hasInput = checkInput(); - move(TrustedImm32(-1), returnRegister); + move(TrustedImmPtr((void*)WTF::notFound), returnRegister); + move(TrustedImm32(0), returnRegister2); generateReturn(); hasInput.link(this); - for (unsigned i = 0; i < m_pattern.m_numSubpatterns + 1; ++i) - store32(TrustedImm32(-1), Address(output, (i << 1) * sizeof(int))); + if (compileMode == IncludeSubpatterns) { + for (unsigned i = 0; i < m_pattern.m_numSubpatterns + 1; ++i) + store32(TrustedImm32(-1), Address(output, (i << 1) * sizeof(int))); + } if (!m_pattern.m_body->m_hasFixedSize) - store32(index, Address(output)); + setMatchStart(index); - if (m_pattern.m_body->m_callFrameSize) - subPtr(Imm32(m_pattern.m_body->m_callFrameSize * sizeof(void*)), stackPointerRegister); + initCallFrame(); // Compile the pattern to the internal 'YarrOp' representation. opCompileBody(m_pattern.m_body); @@ -2539,10 +2608,18 @@ public: // Link & finalize the code. LinkBuffer linkBuffer(*globalData, this, REGEXP_CODE_ID); m_backtrackingState.linkDataLabels(linkBuffer); - if (m_charSize == Char8) - jitObject.set8BitCode(linkBuffer.finalizeCode()); - else - jitObject.set16BitCode(linkBuffer.finalizeCode()); + + if (compileMode == MatchOnly) { + if (m_charSize == Char8) + jitObject.set8BitCodeMatchOnly(linkBuffer.finalizeCode()); + else + jitObject.set16BitCodeMatchOnly(linkBuffer.finalizeCode()); + } else { + if (m_charSize == Char8) + jitObject.set8BitCode(linkBuffer.finalizeCode()); + else + jitObject.set16BitCode(linkBuffer.finalizeCode()); + } jitObject.setFallBack(m_shouldFallBack); } @@ -2576,9 +2653,12 @@ private: BacktrackingState m_backtrackingState; }; -void jitCompile(YarrPattern& pattern, YarrCharSize charSize, JSGlobalData* globalData, YarrCodeBlock& jitObject) +void jitCompile(YarrPattern& pattern, YarrCharSize charSize, JSGlobalData* globalData, YarrCodeBlock& jitObject, YarrJITCompileMode mode) { - YarrGenerator(pattern, charSize).compile(globalData, jitObject); + if (mode == MatchOnly) + YarrGenerator<MatchOnly>(pattern, charSize).compile(globalData, jitObject); + else + YarrGenerator<IncludeSubpatterns>(pattern, charSize).compile(globalData, jitObject); } }} diff --git a/Source/JavaScriptCore/yarr/YarrJIT.h b/Source/JavaScriptCore/yarr/YarrJIT.h index 38ae76cc4..71928e73c 100644 --- a/Source/JavaScriptCore/yarr/YarrJIT.h +++ b/Source/JavaScriptCore/yarr/YarrJIT.h @@ -29,7 +29,8 @@ #if ENABLE(YARR_JIT) #include "JSGlobalData.h" -#include "MacroAssembler.h" +#include "MacroAssemblerCodeRef.h" +#include "MatchResult.h" #include "UString.h" #include "Yarr.h" #include "YarrPattern.h" @@ -48,8 +49,17 @@ class ExecutablePool; namespace Yarr { class YarrCodeBlock { - typedef int (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL; - typedef int (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL; +#if CPU(X86_64) + typedef MatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL; + typedef MatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL; + typedef MatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL; + typedef MatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL; +#else + typedef EncodedMatchResult (*YarrJITCode8)(const LChar* input, unsigned start, unsigned length, int* output) YARR_CALL; + typedef EncodedMatchResult (*YarrJITCode16)(const UChar* input, unsigned start, unsigned length, int* output) YARR_CALL; + typedef EncodedMatchResult (*YarrJITCodeMatchOnly8)(const LChar* input, unsigned start, unsigned length) YARR_CALL; + typedef EncodedMatchResult (*YarrJITCodeMatchOnly16)(const UChar* input, unsigned start, unsigned length) YARR_CALL; +#endif public: YarrCodeBlock() @@ -63,43 +73,67 @@ public: void setFallBack(bool fallback) { m_needFallBack = fallback; } bool isFallBack() { return m_needFallBack; } + bool has8BitCode() { return m_ref8.size(); } bool has16BitCode() { return m_ref16.size(); } - void set8BitCode(MacroAssembler::CodeRef ref) { m_ref8 = ref; } - void set16BitCode(MacroAssembler::CodeRef ref) { m_ref16 = ref; } + void set8BitCode(MacroAssemblerCodeRef ref) { m_ref8 = ref; } + void set16BitCode(MacroAssemblerCodeRef ref) { m_ref16 = ref; } - int execute(const LChar* input, unsigned start, unsigned length, int* output) + bool has8BitCodeMatchOnly() { return m_matchOnly8.size(); } + bool has16BitCodeMatchOnly() { return m_matchOnly16.size(); } + void set8BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly8 = matchOnly; } + void set16BitCodeMatchOnly(MacroAssemblerCodeRef matchOnly) { m_matchOnly16 = matchOnly; } + + MatchResult execute(const LChar* input, unsigned start, unsigned length, int* output) { ASSERT(has8BitCode()); - return reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output); + return MatchResult(reinterpret_cast<YarrJITCode8>(m_ref8.code().executableAddress())(input, start, length, output)); } - int execute(const UChar* input, unsigned start, unsigned length, int* output) + MatchResult execute(const UChar* input, unsigned start, unsigned length, int* output) { ASSERT(has16BitCode()); - return reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output); + return MatchResult(reinterpret_cast<YarrJITCode16>(m_ref16.code().executableAddress())(input, start, length, output)); } + + MatchResult execute(const LChar* input, unsigned start, unsigned length) + { + ASSERT(has8BitCodeMatchOnly()); + return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly8>(m_matchOnly8.code().executableAddress())(input, start, length)); + } + + MatchResult execute(const UChar* input, unsigned start, unsigned length) + { + ASSERT(has16BitCodeMatchOnly()); + return MatchResult(reinterpret_cast<YarrJITCodeMatchOnly16>(m_matchOnly16.code().executableAddress())(input, start, length)); + } + #if ENABLE(REGEXP_TRACING) void *getAddr() { return m_ref.code().executableAddress(); } #endif + void clear() + { + m_ref8 = MacroAssemblerCodeRef(); + m_ref16 = MacroAssemblerCodeRef(); + m_matchOnly8 = MacroAssemblerCodeRef(); + m_matchOnly16 = MacroAssemblerCodeRef(); + m_needFallBack = false; + } + private: - MacroAssembler::CodeRef m_ref8; - MacroAssembler::CodeRef m_ref16; + MacroAssemblerCodeRef m_ref8; + MacroAssemblerCodeRef m_ref16; + MacroAssemblerCodeRef m_matchOnly8; + MacroAssemblerCodeRef m_matchOnly16; bool m_needFallBack; }; -void jitCompile(YarrPattern&, YarrCharSize, JSGlobalData*, YarrCodeBlock& jitObject); - -inline int execute(YarrCodeBlock& jitObject, const LChar* input, unsigned start, unsigned length, int* output) -{ - return jitObject.execute(input, start, length, output); -} - -inline int execute(YarrCodeBlock& jitObject, const UChar* input, unsigned start, unsigned length, int* output) -{ - return jitObject.execute(input, start, length, output); -} +enum YarrJITCompileMode { + MatchOnly, + IncludeSubpatterns +}; +void jitCompile(YarrPattern&, YarrCharSize, JSGlobalData*, YarrCodeBlock& jitObject, YarrJITCompileMode = IncludeSubpatterns); } } // namespace JSC::Yarr diff --git a/Source/JavaScriptCore/yarr/YarrPattern.cpp b/Source/JavaScriptCore/yarr/YarrPattern.cpp index f0d10e624..bbda9c526 100644 --- a/Source/JavaScriptCore/yarr/YarrPattern.cpp +++ b/Source/JavaScriptCore/yarr/YarrPattern.cpp @@ -28,6 +28,7 @@ #include "YarrPattern.h" #include "Yarr.h" +#include "YarrCanonicalizeUCS2.h" #include "YarrParser.h" #include <wtf/Vector.h> @@ -66,32 +67,43 @@ public: void putChar(UChar ch) { + // Handle ascii cases. if (ch <= 0x7f) { if (m_isCaseInsensitive && isASCIIAlpha(ch)) { addSorted(m_matches, toASCIIUpper(ch)); addSorted(m_matches, toASCIILower(ch)); } else addSorted(m_matches, ch); - } else { - UChar upper, lower; - if (m_isCaseInsensitive && ((upper = Unicode::toUpper(ch)) != (lower = Unicode::toLower(ch)))) { - addSorted(m_matchesUnicode, upper); - addSorted(m_matchesUnicode, lower); - } else - addSorted(m_matchesUnicode, ch); + return; } - } - // returns true if this character has another case, and 'ch' is the upper case form. - static inline bool isUnicodeUpper(UChar ch) - { - return ch != Unicode::toLower(ch); + // Simple case, not a case-insensitive match. + if (!m_isCaseInsensitive) { + addSorted(m_matchesUnicode, ch); + return; + } + + // Add multiple matches, if necessary. + UCS2CanonicalizationRange* info = rangeInfoFor(ch); + if (info->type == CanonicalizeUnique) + addSorted(m_matchesUnicode, ch); + else + putUnicodeIgnoreCase(ch, info); } - // returns true if this character has another case, and 'ch' is the lower case form. - static inline bool isUnicodeLower(UChar ch) + void putUnicodeIgnoreCase(UChar ch, UCS2CanonicalizationRange* info) { - return ch != Unicode::toUpper(ch); + ASSERT(m_isCaseInsensitive); + ASSERT(ch > 0x7f); + ASSERT(ch >= info->begin && ch <= info->end); + ASSERT(info->type != CanonicalizeUnique); + if (info->type == CanonicalizeSet) { + for (uint16_t* set = characterSetInfo[info->value]; (ch = *set); ++set) + addSorted(m_matchesUnicode, ch); + } else { + addSorted(m_matchesUnicode, ch); + addSorted(m_matchesUnicode, getCanonicalPair(info, ch)); + } } void putRange(UChar lo, UChar hi) @@ -108,36 +120,59 @@ public: addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a')); } } - if (hi >= 0x80) { - uint32_t unicodeCurr = std::max(lo, (UChar)0x80); - addSortedRange(m_rangesUnicode, unicodeCurr, hi); - - if (m_isCaseInsensitive) { - while (unicodeCurr <= hi) { - // If the upper bound of the range (hi) is 0xffff, the increments to - // unicodeCurr in this loop may take it to 0x10000. This is fine - // (if so we won't re-enter the loop, since the loop condition above - // will definitely fail) - but this does mean we cannot use a UChar - // to represent unicodeCurr, we must use a 32-bit value instead. - ASSERT(unicodeCurr <= 0xffff); - - if (isUnicodeUpper(unicodeCurr)) { - UChar lowerCaseRangeBegin = Unicode::toLower(unicodeCurr); - UChar lowerCaseRangeEnd = lowerCaseRangeBegin; - while ((++unicodeCurr <= hi) && isUnicodeUpper(unicodeCurr) && (Unicode::toLower(unicodeCurr) == (lowerCaseRangeEnd + 1))) - lowerCaseRangeEnd++; - addSortedRange(m_rangesUnicode, lowerCaseRangeBegin, lowerCaseRangeEnd); - } else if (isUnicodeLower(unicodeCurr)) { - UChar upperCaseRangeBegin = Unicode::toUpper(unicodeCurr); - UChar upperCaseRangeEnd = upperCaseRangeBegin; - while ((++unicodeCurr <= hi) && isUnicodeLower(unicodeCurr) && (Unicode::toUpper(unicodeCurr) == (upperCaseRangeEnd + 1))) - upperCaseRangeEnd++; - addSortedRange(m_rangesUnicode, upperCaseRangeBegin, upperCaseRangeEnd); - } else - ++unicodeCurr; - } + if (hi <= 0x7f) + return; + + lo = std::max(lo, (UChar)0x80); + addSortedRange(m_rangesUnicode, lo, hi); + + if (!m_isCaseInsensitive) + return; + + UCS2CanonicalizationRange* info = rangeInfoFor(lo); + while (true) { + // Handle the range [lo .. end] + UChar end = std::min<UChar>(info->end, hi); + + switch (info->type) { + case CanonicalizeUnique: + // Nothing to do - no canonical equivalents. + break; + case CanonicalizeSet: { + UChar ch; + for (uint16_t* set = characterSetInfo[info->value]; (ch = *set); ++set) + addSorted(m_matchesUnicode, ch); + break; } - } + case CanonicalizeRangeLo: + addSortedRange(m_rangesUnicode, lo + info->value, end + info->value); + break; + case CanonicalizeRangeHi: + addSortedRange(m_rangesUnicode, lo - info->value, end - info->value); + break; + case CanonicalizeAlternatingAligned: + // Use addSortedRange since there is likely an abutting range to combine with. + if (lo & 1) + addSortedRange(m_rangesUnicode, lo - 1, lo - 1); + if (!(end & 1)) + addSortedRange(m_rangesUnicode, end + 1, end + 1); + break; + case CanonicalizeAlternatingUnaligned: + // Use addSortedRange since there is likely an abutting range to combine with. + if (!(lo & 1)) + addSortedRange(m_rangesUnicode, lo - 1, lo - 1); + if (end & 1) + addSortedRange(m_rangesUnicode, end + 1, end + 1); + break; + } + + if (hi == end) + return; + + ++info; + lo = info->begin; + }; + } CharacterClass* charClass() @@ -280,12 +315,21 @@ public: { // We handle case-insensitive checking of unicode characters which do have both // cases by handling them as if they were defined using a CharacterClass. - if (m_pattern.m_ignoreCase && !isASCII(ch) && (Unicode::toUpper(ch) != Unicode::toLower(ch))) { - atomCharacterClassBegin(); - atomCharacterClassAtom(ch); - atomCharacterClassEnd(); - } else + if (!m_pattern.m_ignoreCase || isASCII(ch)) { + m_alternative->m_terms.append(PatternTerm(ch)); + return; + } + + UCS2CanonicalizationRange* info = rangeInfoFor(ch); + if (info->type == CanonicalizeUnique) { m_alternative->m_terms.append(PatternTerm(ch)); + return; + } + + m_characterClassConstructor.putUnicodeIgnoreCase(ch, info); + CharacterClass* newCharacterClass = m_characterClassConstructor.charClass(); + m_pattern.m_userCharacterClasses.append(newCharacterClass); + m_alternative->m_terms.append(PatternTerm(newCharacterClass, false)); } void atomBuiltInCharacterClass(BuiltInCharacterClassID classID, bool invert) diff --git a/Source/JavaScriptCore/yarr/yarr.pri b/Source/JavaScriptCore/yarr/yarr.pri index c2634864f..623098fd3 100644 --- a/Source/JavaScriptCore/yarr/yarr.pri +++ b/Source/JavaScriptCore/yarr/yarr.pri @@ -7,7 +7,12 @@ SOURCES += \ $$PWD/YarrInterpreter.cpp \ $$PWD/YarrPattern.cpp \ - $$PWD/YarrSyntaxChecker.cpp + $$PWD/YarrSyntaxChecker.cpp \ + $$PWD/YarrCanonicalizeUCS2.cpp # For UString.h -v8: INCLUDEPATH += $$PWD/../runtime +v8 { + INCLUDEPATH += \ + $$PWD/.. \ + $$PWD/../runtime +} |